simulation.py 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import collections
  2. from synergine2.utils import initialize_subject
  3. class Simulation(object):
  4. def __init__(self):
  5. self.collections = collections.defaultdict(list)
  6. self._subjects = None
  7. @property
  8. def subjects(self):
  9. return self._subjects
  10. @subjects.setter
  11. def subjects(self, value: 'Subjects'):
  12. if not isinstance(value, Subjects):
  13. raise Exception('Simulation.subjects must be Subjects type')
  14. self._subjects = value
  15. class Subject(object):
  16. collections = []
  17. behaviours_classes = []
  18. def __init__(self, simulation: Simulation):
  19. self.id = id(self) # We store object id because it's lost between process
  20. self.simulation = simulation
  21. self.behaviours = {}
  22. self.mechanisms = {}
  23. for collection in self.collections:
  24. self.simulation.collections[collection].append(self)
  25. initialize_subject(
  26. simulation=simulation,
  27. subject=self,
  28. )
  29. class Subjects(list):
  30. """
  31. TODO: Manage other list methods
  32. """
  33. def __init__(self, *args, **kwargs):
  34. self.simulation = kwargs.pop('simulation')
  35. self.removes = []
  36. self.adds = []
  37. self.track_changes = False
  38. super().__init__(*args, **kwargs)
  39. def remove(self, value: Subject):
  40. # Remove from subjects list
  41. super().remove(value)
  42. # Remove from collections
  43. for collection_name in value.collections:
  44. self.simulation.collections[collection_name].remove(value)
  45. # Add to removed listing
  46. if self.track_changes:
  47. self.removes.append(value)
  48. def append(self, p_object):
  49. # Add to subjects list
  50. super().append(p_object)
  51. # Add to adds list
  52. if self.track_changes:
  53. self.adds.append(p_object)
  54. class Mechanism(object):
  55. def __init__(
  56. self,
  57. simulation: Simulation,
  58. subject: Subject,
  59. ):
  60. self.simulation = simulation
  61. self.subject = subject
  62. def run(self):
  63. raise NotImplementedError()
  64. class Event(object):
  65. def __init__(self, *args, **kwargs):
  66. pass
  67. class Behaviour(object):
  68. def __init__(
  69. self,
  70. simulation: Simulation,
  71. subject: Subject,
  72. ):
  73. self.simulation = simulation
  74. self.subject = subject
  75. def run(self, data):
  76. """
  77. Method called in subprocess.
  78. If return equivalent to False, behaviour produce nothing.
  79. If return equivalent to True, action bahaviour method
  80. will be called with these data
  81. Note: Returned data will be transfered from sub processes.
  82. Prefer scalar types.
  83. """
  84. raise NotImplementedError()
  85. def action(self, data) -> [Event]:
  86. """
  87. Method called in main process
  88. Return value will be give to terminals
  89. """
  90. raise NotImplementedError()