pypharm 1.2.10__py3-none-any.whl → 1.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,7 @@ import random
2
2
  import numpy as np
3
3
  from operator import attrgetter
4
4
  from math import ceil, cos, sin
5
+ from multiprocessing import shared_memory
5
6
 
6
7
 
7
8
  class Individual:
@@ -350,7 +351,7 @@ class Country:
350
351
 
351
352
  class CountriesAlgorithm:
352
353
 
353
- def __init__(self, f, Xmin, Xmax, M, N, n, p, m, k, l, ep, tmax, printing=False):
354
+ def __init__(self, f, Xmin, Xmax, M, N, n, p, m, k, l, ep, tmax, printing=False, memory_list=None):
354
355
  self.f = f
355
356
  self.Xmin = Xmin
356
357
  self.Xmax = Xmax
@@ -363,6 +364,7 @@ class CountriesAlgorithm:
363
364
  self.tmax = tmax
364
365
  self.countries = []
365
366
  self.printing = printing
367
+ self.memory_list = memory_list
366
368
  for i in range(M):
367
369
  self.countries.append(Country(self.Xmin, self.Xmax, N, self.f))
368
370
 
@@ -372,6 +374,8 @@ class CountriesAlgorithm:
372
374
  trade = 0
373
375
  war = 0
374
376
  epedemic = 0
377
+ if self.memory_list is not None:
378
+ self.memory_list[0] = False
375
379
  while ti <= self.tmax:
376
380
  ti += 1
377
381
  for country in self.countries:
@@ -457,6 +461,12 @@ class CountriesAlgorithm:
457
461
  if self.printing:
458
462
  print(f"{ti}) Лучшее решение: {result.x} - {result.f}, Стран осталось: {len(self.countries)}, Движение/Обмен/Войны/Эпидемии: {motion}/{trade}/{war}/{epedemic}")
459
463
  print(f"Общее количество особей: {sum([len(country.population) for country in self.countries])}")
464
+
465
+ if self.memory_list is not None:
466
+ self.memory_list[0] = ti
467
+ for i in range(len(result.x)):
468
+ self.memory_list[i + 1] = float(result.x[i])
469
+ self.memory_list[-1] = float(result.f)
460
470
  return (result.x, result.f, False, ti)
461
471
 
462
472
 
PyPharm/models.py CHANGED
@@ -1,3 +1,5 @@
1
+ from multiprocessing import shared_memory
2
+
1
3
  import numpy as np
2
4
  from scipy.integrate import solve_ivp, RK45
3
5
  from scipy.integrate._ivp.rk import rk_step, SAFETY, MAX_FACTOR, MIN_FACTOR
@@ -16,7 +18,7 @@ class BaseCompartmentModel:
16
18
  _optim = False
17
19
  numba_option = False
18
20
 
19
- def __init__(self, configuration_matrix, outputs, volumes=None, numba_option=False):
21
+ def __init__(self, configuration_matrix, outputs, volumes=None, numba_option=False, use_shared_memory=False):
20
22
  """
21
23
  Базовая камерная модель для описания фармакокинетики системы
22
24
 
@@ -48,8 +50,18 @@ class BaseCompartmentModel:
48
50
  self.volumes_target_count = np.sum(self.volumes == None)
49
51
  self.last_result = None
50
52
  self.numba_option = numba_option
51
-
52
- def _сompartment_model(self, t, c):
53
+ self.use_shared_memory = use_shared_memory
54
+ if self.use_shared_memory:
55
+ self.memory_size = 2 + self.configuration_matrix_target_count + self.outputs_target_count + self.volumes_target_count
56
+ self.memory = shared_memory.ShareableList(self.memory_size * [None])
57
+ self.memory_name = self.memory.shm.name
58
+
59
+ def __del__(self):
60
+ if getattr(self, 'memory', None):
61
+ self.memory.shm.close()
62
+ self.memory.shm.unlink()
63
+
64
+ def _compartment_model(self, t, c):
53
65
  """
54
66
  Функция для расчета камерной модели
55
67
 
@@ -67,7 +79,7 @@ class BaseCompartmentModel:
67
79
 
68
80
  @staticmethod
69
81
  @njit
70
- def _numba_сompartment_model(t, c, configuration_matrix, outputs, volumes):
82
+ def _numba_compartment_model(t, c, configuration_matrix, outputs, volumes):
71
83
  """
72
84
  Функция для расчета камерной модели
73
85
 
@@ -110,7 +122,7 @@ class BaseCompartmentModel:
110
122
  c0 = np.array(c0)
111
123
  ts = [0, t_max]
112
124
  self.last_result = solve_ivp(
113
- fun=self._сompartment_model if not self.numba_option else lambda t, c: self._numba_сompartment_model(t, c, self.configuration_matrix.astype(np.float64), self.outputs.astype(np.float64), self.volumes.astype(np.float64)),
125
+ fun=self._compartment_model if not self.numba_option else lambda t, c: self._numba_compartment_model(t, c, self.configuration_matrix.astype(np.float64), self.outputs.astype(np.float64), self.volumes.astype(np.float64)),
114
126
  t_span=ts,
115
127
  y0=c0,
116
128
  max_step=max_step,
@@ -206,6 +218,7 @@ class BaseCompartmentModel:
206
218
  if method == 'country_optimization':
207
219
  CA = CountriesAlgorithm(
208
220
  f=f,
221
+ memory_list=getattr(self, 'memory', None),
209
222
  **kwargs
210
223
  )
211
224
  CA.start()
@@ -266,11 +279,19 @@ class MagicCompartmentModel(BaseCompartmentModel):
266
279
 
267
280
  need_magic_optimization = False
268
281
 
269
- def __init__(self, configuration_matrix, outputs, volumes=None, magic_coefficient=1, exclude_compartments=[], numba_option=False):
270
- super().__init__(configuration_matrix, outputs, volumes, numba_option)
282
+ def __init__(self, configuration_matrix, outputs, volumes=None, magic_coefficient=1, exclude_compartments=[], numba_option=False, use_shared_memory=False):
283
+ super().__init__(configuration_matrix, outputs, volumes, numba_option, use_shared_memory)
271
284
  self.magic_coefficient = magic_coefficient
272
285
  self.exclude_compartments = np.array(exclude_compartments)
273
286
  self.need_magic_optimization = self.magic_coefficient is None
287
+ if getattr(self, "memory", None):
288
+ self.memory.shm.close()
289
+ self.memory.shm.unlink()
290
+ self.memory_size += int(self.need_magic_optimization)
291
+ self.memory = shared_memory.ShareableList(
292
+ sequence=self.memory_size * [None]
293
+ )
294
+ self.memory_name = self.memory.shm.name
274
295
 
275
296
  def __call__(self, t_max, c0=None, d=None, compartment_number=None, max_step=0.01, t_eval=None):
276
297
  if not self._optim and not self.magic_coefficient:
@@ -301,12 +322,14 @@ class MagicCompartmentModel(BaseCompartmentModel):
301
322
  class ReleaseCompartmentModel(BaseCompartmentModel):
302
323
 
303
324
  need_v_release_optimization = False
325
+ release_parameters_target = None
326
+ release_parameters_target = None
304
327
 
305
328
  class ReleaseRK45(RK45):
306
329
 
307
330
  def __init__(self, fun, t0, y0, t_bound, release_function, compartment_number, c0, max_step=np.inf,
308
- rtol=1e-3, atol=1e-6, vectorized=False,
309
- first_step=None, **extraneous):
331
+ with_accumulate=False, accumulation_function=None, accumulation_type=1, rtol=1e-3, atol=1e-6, vectorized=False,
332
+ first_step=None, **extraneous):
310
333
  super().__init__(fun, t0, y0, t_bound, max_step=max_step,
311
334
  rtol=rtol, atol=atol, vectorized=vectorized,
312
335
  first_step=first_step, **extraneous)
@@ -314,15 +337,37 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
314
337
  self.compartment_number = compartment_number
315
338
  self.c0 = c0
316
339
  self.old_release_correction = 0
340
+ self.old_accumulation_correction = c0
341
+ self.with_accumulate = with_accumulate
342
+ self.accumulation_function = accumulation_function
343
+ self.accumulation_type = accumulation_type
317
344
 
318
345
  def _step_impl(self):
319
346
  result = super()._step_impl()
320
347
  release_correction = self.release_function(self.t, self.c0)
321
- self.y[self.compartment_number] += release_correction - self.old_release_correction
348
+ minus_accumulation = 0
349
+ if self.with_accumulate:
350
+ if self.accumulation_type == 1:
351
+ accumulation_correction = self.accumulation_function(self.t, self.c0 )
352
+ minus_accumulation = self.old_accumulation_correction - accumulation_correction
353
+ elif self.accumulation_type == 2:
354
+ coef_accumulation = self.accumulation_function(self.t, self.c0) / self.c0
355
+ plus_release = release_correction - self.old_release_correction
356
+ all_corrections = plus_release
357
+ if self.accumulation_type == 1:
358
+ if plus_release - minus_accumulation > 0:
359
+ all_corrections = plus_release - minus_accumulation
360
+ elif self.accumulation_type == 2:
361
+ all_corrections *= coef_accumulation
362
+ self.y[self.compartment_number] += all_corrections
322
363
  self.old_release_correction = release_correction
364
+ if self.with_accumulate and self.accumulation_type == 1:
365
+ self.old_accumulation_correction = accumulation_correction
323
366
  return result
324
367
 
325
- def __init__(self, v_release, release_parameters, release_compartment, release_function=None, *args, **kwargs):
368
+ def __init__(self, v_release, release_parameters, release_compartment,
369
+ release_function=None, with_accumulate=False, accumulation_function=None,
370
+ accumulation_parameters=[None], accumulation_type=1, *args, **kwargs):
326
371
  """
327
372
  Камерная модель с высвобождением для описания фармакокинетики системы
328
373
 
@@ -349,6 +394,24 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
349
394
  self.need_v_release_optimization = True
350
395
  self.release_compartment = release_compartment
351
396
  self.release_function = release_function
397
+ self.with_accumulate = with_accumulate
398
+ self.accumulation_type = accumulation_type
399
+
400
+ if self.with_accumulate:
401
+ self.accumulation_function = accumulation_function
402
+ self.accumulation_parameters = np.array(accumulation_parameters)
403
+ if np.any(self.accumulation_parameters == None):
404
+ self.accumulation_parameters_target = np.where(self.accumulation_parameters == None)
405
+ self.accumulation_parameters_target_count = np.sum(self.accumulation_parameters == None)
406
+
407
+ if getattr(self, "memory", None):
408
+ self.memory.shm.close()
409
+ self.memory.shm.unlink()
410
+ self.memory_size += self.release_parameters_target_count + int(self.need_v_release_optimization)
411
+ self.memory = shared_memory.ShareableList(
412
+ sequence=self.memory_size * [None]
413
+ )
414
+ self.memory_name = self.memory.shm.name
352
415
 
353
416
  def load_data_from_list(self, x):
354
417
  super().load_data_from_list(x)
@@ -357,6 +420,10 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
357
420
  self.release_parameters[self.release_parameters_target] = x[s:s + self.release_parameters_target_count]
358
421
  if self.need_v_release_optimization:
359
422
  self.v_release = x[s + self.release_parameters_target_count]
423
+ if self.with_accumulate:
424
+ if self.accumulation_parameters_target:
425
+ s += self.release_parameters_target_count + int(self.need_v_release_optimization)
426
+ self.accumulation_parameters[self.accumulation_parameters_target] = x[s:s + self.accumulation_parameters_target_count]
360
427
 
361
428
  def _default_release_function(self, t, c0):
362
429
  """
@@ -371,6 +438,19 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
371
438
  else:
372
439
  return self._default_release_function
373
440
 
441
+ def _default_accumulation_function(self, t, c0):
442
+ """
443
+ Функция для поправки на накопление
444
+ """
445
+ k, = self.accumulation_parameters
446
+ return c0 * np.exp(-k * t)
447
+
448
+ def get_accumulation_function(self):
449
+ if self.accumulation_function is not None:
450
+ return lambda t, c0: self.accumulation_function(t, c0, *self.accumulation_parameters)
451
+ else:
452
+ return self._default_accumulation_function
453
+
374
454
  def __call__(self, t_max, c0=None, d=None, max_step=0.01, t_eval=None, **kwargs):
375
455
  """
376
456
  Расчет кривых концентраций по фармакокинетической модели
@@ -395,9 +475,9 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
395
475
  ts = [0, t_max]
396
476
  y0 = np.zeros(self.outputs.shape)
397
477
  self.last_result = solve_ivp(
398
- fun=self._сompartment_model if
478
+ fun=self._compartment_model if
399
479
  not self.numba_option
400
- else lambda t, c: self._numba_сompartment_model(t, c,
480
+ else lambda t, c: self._numba_compartment_model(t, c,
401
481
  self.configuration_matrix.astype(
402
482
  np.float64),
403
483
  self.outputs.astype(
@@ -411,6 +491,9 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
411
491
  method=self.ReleaseRK45,
412
492
  release_function=self.get_release_function(),
413
493
  compartment_number=self.release_compartment,
494
+ with_accumulate=self.with_accumulate,
495
+ accumulation_function=self.get_accumulation_function() if self.with_accumulate else None,
496
+ accumulation_type=self.accumulation_type,
414
497
  c0=c0
415
498
  )
416
499
  return self.last_result
@@ -438,13 +521,38 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
438
521
  )
439
522
  target_results = self.last_result.y[tuple(self.know_compartments), :]
440
523
  if metric == 'R2':
441
- return np.sum(np.sum(self.w * ((target_results - self.teoretic_y) ** 2), axis=1) / np.sum((self.teoretic_avg - self.teoretic_y) ** 2, axis=1))
524
+ plus = 0
525
+ if self.teoretic_realized is not None:
526
+ model_realized = c0 - self.get_release_function()(self.teoretic_x, c0)
527
+ if self.with_accumulate:
528
+ model_accumulation = self.get_accumulation_function()(self.teoretic_x, c0)
529
+ if self.accumulation_type == 1:
530
+ model_realized = model_accumulation - self.get_release_function()(self.teoretic_x, c0)
531
+ elif self.accumulation_type == 2:
532
+ accumulation_coeffs = model_accumulation / c0
533
+ model_realized = accumulation_coeffs * self.get_release_function()(self.teoretic_x, c0)
534
+ model_realized = model_accumulation - model_realized
535
+ plus = np.sum(((model_realized - self.teoretic_realized) ** 2) / ((self.teoretic_realized - self.teoretic_realized_avg) ** 2))
536
+ return plus + np.sum(np.sum(self.w * ((target_results - self.teoretic_y) ** 2), axis=1) / np.sum((self.teoretic_avg - self.teoretic_y) ** 2, axis=1))
442
537
  elif metric == 'norm':
443
- return np.linalg.norm(target_results - self.teoretic_y)
538
+ plus = 0
539
+ if self.teoretic_realized is not None:
540
+ model_realized = c0 - self.get_release_function()(self.teoretic_x, c0)
541
+ if self.with_accumulate:
542
+ model_accumulation = self.get_accumulation_function()(self.teoretic_x, c0)
543
+ if self.accumulation_type == 1:
544
+ model_realized = model_accumulation - self.get_release_function()(self.teoretic_x, c0)
545
+ elif self.accumulation_type == 2:
546
+ accumulation_coeffs = model_accumulation / c0
547
+ model_realized = accumulation_coeffs * self.get_release_function()(self.teoretic_x, c0)
548
+ model_realized = model_accumulation - model_realized
549
+ plus = np.linalg.norm(self.teoretic_realized - model_realized)
550
+ return plus + np.linalg.norm(target_results - self.teoretic_y)
444
551
  else:
445
552
  return np.sum(np.sum(self.w * ((target_results - self.teoretic_y) ** 2), axis=1) / np.sum((self.teoretic_avg - self.teoretic_y) ** 2, axis=1))
446
553
 
447
- def load_optimization_data(self, teoretic_x, teoretic_y, know_compartments, w = None, c0=None, d=None, compartment_number=None):
554
+ def load_optimization_data(self, teoretic_x, teoretic_y, know_compartments,
555
+ w = None, c0=None, d=None, compartment_number=None, teoretic_realized=None):
448
556
  """
449
557
  Функция загрузки в модель эксперементальных данных
450
558
 
@@ -460,6 +568,9 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
460
568
  """
461
569
  self.teoretic_x = np.array(teoretic_x)
462
570
  self.teoretic_y = np.array(teoretic_y)
571
+ self.teoretic_realized = np.array(teoretic_realized) if teoretic_realized is not None else teoretic_realized
572
+ if teoretic_realized is not None:
573
+ self.teoretic_realized_avg = np.average(self.teoretic_realized)
463
574
  self.know_compartments = know_compartments
464
575
  self.teoretic_avg = np.average(self.teoretic_y, axis=1)
465
576
  self.teoretic_avg = np.repeat(self.teoretic_avg, self.teoretic_x.size)
@@ -481,4 +592,8 @@ class ReleaseCompartmentModel(BaseCompartmentModel):
481
592
  if self.need_v_release_optimization:
482
593
  self.v_release = x[s:s + self.release_parameters_target_count + 1]
483
594
  self.need_v_release_optimization = False
595
+ if self.with_accumulate:
596
+ if self.accumulation_parameters_target:
597
+ s += self.release_parameters_target_count + int(self.need_v_release_optimization)
598
+ self.accumulation_parameters[self.accumulation_parameters_target] = x[s:s + self.accumulation_parameters_target_count]
484
599
  return x
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypharm
3
- Version: 1.2.10
3
+ Version: 1.3.1
4
4
  Summary: Module for solving pharmacokinetic problems
5
5
  Home-page: https://github.com/Krash13/PyPharm
6
6
  Author: Krash13
@@ -207,6 +207,22 @@ plt.show()
207
207
  в таком случае, искомое нужно просто задать как None. Тогда вектор неизвестных это
208
208
  x = [configuration_matrix (неизвестные), outputs(неизвестные), volumes(неизвестные), release_parameters(неизвестные), v_release]
209
209
 
210
+
211
+ **6) Использование shared_memory**
212
+
213
+ Начиная с версии 1.3.0, вы можете использовать **shared_memory** для получения текущих данных
214
+ оптимизации. Имя нужного вам участка памяти хранится в поле **memory_name**.
215
+
216
+ ```python
217
+ from multiprocessing import shared_memory
218
+
219
+ c = shared_memory.ShareableList(name='<your model.memory_name>')
220
+ print(c)
221
+ # ShareableList([4, 3.5192100752465563, 1.4158559227257506, 1.7264077213115414, 0.008336751860551, 0.2549196311342251, 0.5160375718404234, 6.915499993374695, 2.944744649331201, 0.5, 1.907294741996761], name='wnsm_0c50aa90')
222
+ ```
223
+
224
+ Данные хранятся в формате списка [текущая_итерация, x0, ... , xn, f], работает только для алгоритма country_optimization.
225
+
210
226
  **ENG documentation**
211
227
  ----------
212
228
 
@@ -397,3 +413,17 @@ The release_parameters and v_release parameters can be optimized
397
413
  in this case, you just need to set the desired value as None. Then the vector of unknowns is
398
414
  x = [configuration_matrix (unknown), outputs(unknown), volumes(unknown), release_parameters(unknown), v_release]
399
415
 
416
+ **6) Using shared_memory**
417
+
418
+ Since version 1.3.0, you can use **shared_memory** to get current data
419
+ optimization. The name of the memory location you need is stored in the **memory_name** field.
420
+ ```python
421
+ from multiprocessing import shared_memory
422
+
423
+ c = shared_memory.ShareableList(name='<your model.memory_name>')
424
+ print(c)
425
+ # ShareableList([4, 3.5192100752465563, 1.4158559227257506, 1.7264077213115414, 0.008336751860551, 0.2549196311342251, 0.5160375718404234, 6.915499993374695, 2.944744649331201, 0.5, 1.907294741996761], name='wnsm_0c50aa90')
426
+ ```
427
+
428
+ The data is stored in list format [current_iteration, x0, ... , xn, f], works only for the country_optimization algorithm.
429
+
@@ -0,0 +1,8 @@
1
+ PyPharm/__init__.py,sha256=hxhMRlWpLMARQV-ZNYkmvhQ9gCYI18an75vlySWjA6s,90
2
+ PyPharm/country_optimization.py,sha256=WsjfAWAWbxRnUUfBiMi1VatCSVbru7F1_G6kQBRVyA0,20452
3
+ PyPharm/country_optimization_v2.py,sha256=3d2mt15DXdr1V3soIJS51xuCv6uzH8pirah1RnI5--8,13156
4
+ PyPharm/models.py,sha256=i02m8P-R256qbt8oMyB6XccgFoFlx5NnuYk5-nRQYVQ,31145
5
+ pypharm-1.3.1.dist-info/METADATA,sha256=SsNyNCtLgb4s92-PF_wWTOJze9_9j-3uzae3QmEFboA,14464
6
+ pypharm-1.3.1.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
7
+ pypharm-1.3.1.dist-info/top_level.txt,sha256=yybfSkKw8q1G3aEcnlfVL7_L9ufGFSAYZnpc7q6oYJk,8
8
+ pypharm-1.3.1.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- PyPharm/__init__.py,sha256=hxhMRlWpLMARQV-ZNYkmvhQ9gCYI18an75vlySWjA6s,90
2
- PyPharm/country_optimization.py,sha256=nbg5kuJcOhMMfPR0_1O8KUzyqHApUcnqgs_I2I0Z1Gs,20008
3
- PyPharm/country_optimization_v2.py,sha256=3d2mt15DXdr1V3soIJS51xuCv6uzH8pirah1RnI5--8,13156
4
- PyPharm/models.py,sha256=6loQuWoPjSAAzHlERF6Bszjh7iyasX8RMe-cqbq4Fws,24228
5
- pypharm-1.2.10.dist-info/METADATA,sha256=pAZ6OkaCelCdBSf3LHKdE8dU3_WAbqHqwPjcFhZsuz0,12911
6
- pypharm-1.2.10.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
7
- pypharm-1.2.10.dist-info/top_level.txt,sha256=yybfSkKw8q1G3aEcnlfVL7_L9ufGFSAYZnpc7q6oYJk,8
8
- pypharm-1.2.10.dist-info/RECORD,,