-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcell2.py
358 lines (304 loc) · 15.9 KB
/
cell2.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
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# coding: utf8
#import scipy.stats
import numpy
import copy
import pickle #загружаем и сохраняем данные
import matplotlib as plt
from mpl_toolkits.mplot3d import Axes3D
from numpy import arange
from matplotlib.mlab import griddata
def move(a,b,i): #перемещение из одного списка в другой
a.append(i)
b.remove(i)
def event(ks = 1, ls = 1, l1 = 1, l0 = 1, gap = 7, t = 0):
w0 = numpy.random.weibull(1)*l0
w1 = numpy.random.weibull(1)*l1
ws = numpy.random.weibull(ks)*ls
# if t == 0:
# print ('-----------------------')
# print ('.'+str(w0)+'>'+str(ws)+'t='+str(t))
if w0 > ws: # если время до деление меньше, то возвращаем его + задержку
return gap + t + ws #
else: # если время до перехода в фазу сна меньше,
# то ставим в качестве задержки время до перехода и время в фазе сна
# и вызываем рекурсию
k = event(t = w0 + w1 + t, ks = ks, ls = ls, l1 = l1, l0 = l0, gap = gap)
return k
class cell:
""" Класс клетка.
Умеет
выдавать решение на следующую итерацию:
делится,
умирать (и вот вопрос, что с ней происходит, когда она умирает)
возвращать
Есть реальный вариант наследовать этому: https://pypi.python.org/pypi/bintrees/2.0.1
Бинарное дерево можно использовать как структуру данных в клоне, и хранить в клетке только информацию о количестве делений
а историю и время хранить в Клоне, в нодах дерева. Ожнако это не нужно пока нет проблемы с памятью
и тут немного о Вейбуле и рисовании http://stackoverflow.com/questions/17481672/fitting-a-weibull-distribution-using-scipy
"""
def __init__(self, s=None):
self.action_list = [] #вектор событий с данной клеткой
self.time_list = [] #вектор последовательности времени до событий
if s == None:
p = programm()
self.s = p.makeDict()
else:
self.s = s
def action(self):
act = []
act.append(self.s['l1']*numpy.random.weibull(self.s['a1'])) #разыгрывем время до ближайших событий
act.append(self.s['l2']*numpy.random.weibull(self.s['a2'])) #разыгрывем время до ближайших событий
i = numpy.argmin(act) #определяем какое из событий таки ближайшее
self.time_list.append(act[i]) #прицепляем минимальный элемент
self.action_list.append(i) #прицепляем минимальный элемент -- номер события
return i #возвращаем идентификатор события
def getCumTime(self):
return sum(self.time_list)
def tst():
print ("test")
class clone:
""" для дуплицирования объектов используется http://pymotw.com/2/copy/ """
def __init__(self, s=None):
self.live_cells = []
self.cell_arch = []
self.live_cells.append(cell(s))
self.actions=[]
self.track = []
def tik(self):
for i in self.live_cells:
act = i.action()
self.actions.append(act)
if act == 0:
self.live_cells.append(copy.deepcopy(i))
if act == 1:
move(self.cell_arch, self.live_cells, i)
self.track.append(len(self))
def NTiks(self, n):
for i in range(n):
self.tik()
def do(self):
while self.isAlive():
self.tik()
if self.getProductValue()>1000:
break
def __len__(self): #getCloneValue:
return len(self.live_cells)
def getProductValue(self):
return len(self.cell_arch)
def isAlive(self):
if len(self) == 0:
return False
else: return True
class core:
def __init__(self):
self.CurClone = clone()
self.track = []
def newClone(self,s):
self.CurClone = clone(s)
def iterate(self,n,s=None):
self.product = []
self.result = []
for i in range(n):
self.newClone(s)
self.CurClone.do()
self.product.append(self.CurClone.getProductValue()) #прицепляем объем продукта
self.result.append(self.CurClone.isAlive()) #прицепляем исход запуска клона
self.track.append(self.CurClone.track)
def plotTracks(self):
for i in self.track:
plt.pyplot.plot(i)
plt.show()
def GetMeanRes(self):
return numpy.mean(self.result)
def GetMedRes(self):
return numpy.median(self.result)
def GetMeanProd(self):
return numpy.mean(self.product)
def GetMedProd(self):
return numpy.median(self.product)
class programm:
"""
Программа вычислений.
iter -- количество итераций для каждой точки
element -- вектор словарей -- задание на эксперимент
Видимо структура объекта такая, до первого запуска операции push,
которая загоняет словарь в стек, мы можем добавлять атрибуты,
после этого мы блокируем объект. Кроме того надо написать модули сохранения и извлечения словарей.
После обработки программы каждое задание становилтся экспериментом,
т.е. дополняется результатами. После этого мы должны мочь его так же сохранить
self.dict.keys() -- значения ключей
для присвоения нового атрибута используем
p.dict['имя']=значение
НЕ ИСПОЛЬЗУЕМ, ИНАЧЕ БЛОКИРОВКА НЕ БУДЕТ РАБОТАТЬ
Внимание вопрос: как сохранять объекты?
есть масса вариантов,
----> во первых pickle как стандартная библиотека сохранения и извлечения объектов.
пока реализуем этот самый простой вариант. Тем более, что
плюсы
нативность
минусы
читается только питоном же
Проблемы:
все отлично читается и сохраняется, за исключением того, что загрузка самого себя вещь странная.
весьма вероятно, что она не будет работать.
А сохранять только словарь из всего объекта не правильно, т.к. кроме словаря у меня имеется несколько объектов с важной информацией
ВОТ И ДУМАЙ...
Решение: Оказывается Pickleзация объекта происходит через сохранение
(внимание!) СЛОВАРЯ __dict__ в котором хранятся переменные объекта.
Что мне собственно и нужно. Пишем метод для сохранения и извлечения __dict__
Работать будет так. Если нужно загрузить словарь, то создаем пустой объект
и запускаем метод Load. ВАЖНО сделать предупреждение, что существующий
метод обнуляется
во вторых CSV
плюсы
читаемость SASом
читаемость и редактируемость руками
минусы
ненативность
в третьих XML
плюсы
минусы
в четвертых JSON
плюсы
минусы
по теме:
чтение и запись словаря в текстовый файл
http://stackoverflow.com/questions/11026959/python-writing-dict-to-txt-file-and-reading-dict-from-txt-file
"""
def __init__(self,itr = 100):
self.element = []
self.block = False
self.itr = itr
self.dict = {'a1':1,'a2':1,'l1':1,'l2':1}
self.isCalc = False
def chPrec(self, n):
self.isCalc = False
self.itr = n
def push(self):
self.block = True
self.element.append(copy.deepcopy(self.dict))
def addAttr(self, name, value):
""" Добавление атрибута к словарю """
if self.block:
print ('attempt rejected')
else:
self.dict[name]=value
def chAttr(self,name, value):
if name in self.dict.keys():
self.dict[name]=value
else:
print ('No such name')
def keys(self): return self.dict.keys()
def makeDict(self, a1=1,a2=1,l1=1,l2=1):
return self.dict
# высокоуровневые операции по формированию
def makeGrid(self, name1, start1, stop1, step1, name2, start2, stop2, step2):
self.isCalc = False
if name1 in self.dict.keys() and name2 in self.dict.keys():
a = arange(start1, stop1, step1)
b = arange(start2, stop2, step2)
for j in a:
for i in b:
self.chAttr(name1,j)
self.chAttr(name2,i)
self.push()
else:
print ('No such name. Grid creation aborted')
# [[[self.addDict(i),k] for i in range(4)] for k in range(4)]
def makeVec(self, name, start, stop, step):
self.isCalc = False
if name in self.dict.keys():
a = arange(start, stop, step)
for i in a:
self.chAttr(name,i)
self.push()
else:
print ('No such name')
# Подсистема сохранения и извлечения программы эксперимента
def save(self,name):
if self.isCalc:
with open(name + '.rst', 'wb') as f:
pickle.dump(self.__dict__, f,2)
else:
with open(name + '.dic', 'wb') as f:
pickle.dump(self.__dict__, f,2)
def load(self,name):
with open(name, 'rb') as f:
loaded_dict = pickle.load(f)
f.close()
self.__dict__.update(loaded_dict)
class experiment:
"""
Объект эксперимент
задачи: написать инициализацию по словарю
написать вытакивалку имен параметров и результатов
ВАЖНО!!!
По факту система выполнения действий является ассинхронной (т.е. мы выполняем события не в хронологическом порядке),
в связи с чем мы не можем выполнять взаимодействия и обратные связи.
Для избежания этой проблемы необходимо создать централизованый стек (с сортировкой после каждого пуша)
он должен принадлежать к обработчику, быть единым для всех клонов.
Т.е. операцию итерирования мы изымаем из ведения клона. Может быть клон вобще должен быть атрибутом клетки, и не более
НО ЭТО ПОЗЖЕ...
"""
def __init__(self, p = None):
self.c = core()
if p == None:
self.p = programm()
else:
self.p = p
def setDict(self,p):
self.p = p
def do(self):
'''
Запускаем расчет по выбраному словарю
Аргументов не требуется
'''
print('Start calculating: /n')
self.p.isCalc=True
i = 0
for s in self.p.element:
i=i+1
print("calculating " + str(i) + ' from ' + str(len(self.p.element)))
print s
self.c.iterate(self.p.itr,s)
s['MeanRes'] = self.c.GetMeanRes()
s['MedRes'] = self.c.GetMedRes()
s['MeanProd'] = self.c.GetMeanProd()
s['MedProd'] = self.c.GetMedProd()
def plot(self, resName, param1, param2 = None, t = 'p'):
'''
Если 1 параметр передается, то рисуется 2D график, если два, то 3D
Для интерполяции неструктурированых данных (кои дефакто мы и имеем, хотя это не совсем так)
надо использовать функцию from matplotlib.mlab import griddata.
Например как тут: http://matplotlib.org/examples/pylab_examples/griddata_demo.html
Размерность сетки интерполяции мб такой же как и у данных
'''
# сначала надо вытащить из словаря итерируемые значения
#if resName = 'all'
if not self.p.isCalc:
print('ATTENTION, object is unCalc')
if param2 == None:
y = [self.p.element[i][resName] for i in range(len(self.p.element))]
x = [self.p.element[i][param1] for i in range(len(self.p.element))]
plt.pyplot.plot(x, y, 'yo-')
plt.pyplot.show()
else:
z = [self.p.element[i][resName] for i in range(len(self.p.element))]
x = [self.p.element[i][param1] for i in range(len(self.p.element))]
y = [self.p.element[i][param2] for i in range(len(self.p.element))]
fig = plt.pyplot.figure()
axes = Axes3D(fig)
axes.set_xlabel(param1)
axes.set_ylabel(param2)
axes.set_zlabel(resName)
axes.scatter3D(x,y,z, c=z)
# xi = numpy.linspace(0,1,100)
# yi = numpy.linspace(0,1,100)
# grid the data.
# zi = griddata(x,y,z,xi,yi,interp='linear')
# axes.plot_wireframe(x, y, z)
# axes.plot_surface(xi,yi,zi)
# plt.pyplot.colorbar()
#axes.plot(x,y,z)
#axes.plot_wireframe(x, y, z)
fig.show()