pn.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. from uuid import UUID
  2. from state.base import State
  3. from services.bottom.V0 import Bottom
  4. from services.primitives.integer_type import Integer
  5. from services.primitives.string_type import String
  6. import re
  7. class PN:
  8. """
  9. Implements services for the petri nets LTM.
  10. Implementation is done in terms of services provided by LTM-bottom.
  11. Implementation is very similar to that in scd.py, which has more extensive comments
  12. """
  13. def __init__(self, model: UUID, state: State):
  14. ltm_pn_id = state.read_dict(state.read_root(), "PN")
  15. self.ltm_pn = UUID(state.read_value(ltm_pn_id))
  16. self.model = model
  17. self.bottom = Bottom(state)
  18. def create_place(self, name: str, tokens: int):
  19. """
  20. Creates a place element.
  21. Args:
  22. name: name of the place
  23. Returns:
  24. Nothing.
  25. """
  26. # instantiate Place class
  27. place_node = self.bottom.create_node() # create place node
  28. self.bottom.create_edge(self.model, place_node, name) # attach to model
  29. morph_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "P") # retrieve type
  30. self.bottom.create_edge(place_node, morph_node, "Morphism") # create morphism link
  31. # instantiate name attribute
  32. name_model = self.bottom.create_node()
  33. String(name_model, self.bottom.state).create(name)
  34. name_node = self.bottom.create_node(str(name_model))
  35. self.bottom.create_edge(self.model, name_node, f"{name}.n")
  36. name_link = self.bottom.create_edge(place_node, name_node)
  37. self.bottom.create_edge(self.model, name_link, f"{name}.n_link")
  38. ltm_pn_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "String")
  39. ltm_pn_link, = self.bottom.read_outgoing_elements(self.ltm_pn, "P_n")
  40. self.bottom.create_edge(name_node, ltm_pn_node, "Morphism")
  41. self.bottom.create_edge(name_link, ltm_pn_link, "Morphism")
  42. # instantiate tokens attribute
  43. tokens_model = self.bottom.create_node()
  44. Integer(tokens_model, self.bottom.state).create(tokens)
  45. tokens_node = self.bottom.create_node(str(tokens_model))
  46. self.bottom.create_edge(self.model, tokens_node, f"{name}.t")
  47. tokens_link = self.bottom.create_edge(place_node, tokens_node)
  48. self.bottom.create_edge(self.model, tokens_link, f"{name}.t_link")
  49. ltm_pn_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "Integer")
  50. ltm_pn_link, = self.bottom.read_outgoing_elements(self.ltm_pn, "P_t")
  51. self.bottom.create_edge(tokens_node, ltm_pn_node, "Morphism")
  52. self.bottom.create_edge(tokens_link, ltm_pn_link, "Morphism")
  53. def create_transition(self, name: str):
  54. """
  55. Creates a transition element.
  56. Args:
  57. name: name of the transition
  58. Returns:
  59. Nothing.
  60. """
  61. # instantiate Transition class
  62. transition_node = self.bottom.create_node() # create transition node
  63. self.bottom.create_edge(self.model, transition_node, name) # attach to model
  64. morph_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "T") # retrieve type
  65. self.bottom.create_edge(transition_node, morph_node, "Morphism") # create morphism link
  66. # instantiate name attribute
  67. name_model = self.bottom.create_node()
  68. String(name_model, self.bottom.state).create(name)
  69. name_node = self.bottom.create_node(str(name_model))
  70. self.bottom.create_edge(self.model, name_node, f"{name}.name")
  71. name_link = self.bottom.create_edge(transition_node, name_node)
  72. self.bottom.create_edge(self.model, name_link, f"{name}.name_link")
  73. ltm_pn_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "String")
  74. ltm_pn_link, = self.bottom.read_outgoing_elements(self.ltm_pn, "T_name")
  75. self.bottom.create_edge(name_node, ltm_pn_node, "Morphism")
  76. self.bottom.create_edge(name_link, ltm_pn_link, "Morphism")
  77. def create_p2t(self, place: str, transition: str, weight: int):
  78. """
  79. Creates a place to transition link.
  80. Args:
  81. place: source of the link
  82. transition: target of the link
  83. weight: weight of the link
  84. Returns:
  85. Nothing.
  86. """
  87. # create p2t link + morphism links
  88. edge = self.bottom.create_edge(
  89. *self.bottom.read_outgoing_elements(self.model, place),
  90. *self.bottom.read_outgoing_elements(self.model, transition),
  91. )
  92. self.bottom.create_edge(self.model, edge, f"{place}_to_{transition}") # attach to model
  93. morph_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "P2T") # retrieve type
  94. self.bottom.create_edge(edge, morph_node, "Morphism") # create morphism link
  95. # weight attribute
  96. weight_model = self.bottom.create_node()
  97. Integer(weight_model, self.bottom.state).create(weight)
  98. weight_node = self.bottom.create_node(str(weight_model))
  99. self.bottom.create_edge(self.model, weight_node, f"{place}_to_{transition}.weight")
  100. weight_link = self.bottom.create_edge(edge, weight_node)
  101. self.bottom.create_edge(self.model, weight_link, f"{place}_to_{transition}.weight_link")
  102. scd_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "Integer")
  103. scd_link, = self.bottom.read_outgoing_elements(self.ltm_pn, "P2T_weight")
  104. self.bottom.create_edge(weight_node, scd_node, "Morphism")
  105. self.bottom.create_edge(weight_link, scd_link, "Morphism")
  106. def create_t2p(self, transition: str, place: str, weight: int):
  107. """
  108. Creates a transition to place link.
  109. Args:
  110. transition: source of the link
  111. place: target of the link
  112. weight: weight of the link
  113. Returns:
  114. Nothing.
  115. """
  116. # create t2p link + morphism links
  117. edge = self.bottom.create_edge(
  118. *self.bottom.read_outgoing_elements(self.model, transition),
  119. *self.bottom.read_outgoing_elements(self.model, place),
  120. )
  121. self.bottom.create_edge(self.model, edge, f"{transition}_to_{place}") # attach to model
  122. morph_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "T2P") # retrieve type
  123. self.bottom.create_edge(edge, morph_node, "Morphism") # create morphism link
  124. # weight attribute
  125. weight_model = self.bottom.create_node()
  126. Integer(weight_model, self.bottom.state).create(weight)
  127. weight_node = self.bottom.create_node(str(weight_model))
  128. self.bottom.create_edge(self.model, weight_node, f"{transition}_to_{place}.weight")
  129. weight_link = self.bottom.create_edge(edge, weight_node)
  130. self.bottom.create_edge(self.model, weight_link, f"{transition}_to_{place}.weight_link")
  131. scd_node, = self.bottom.read_outgoing_elements(self.ltm_pn, "Integer")
  132. scd_link, = self.bottom.read_outgoing_elements(self.ltm_pn, "T2P_weight")
  133. self.bottom.create_edge(weight_node, scd_node, "Morphism")
  134. self.bottom.create_edge(weight_link, scd_link, "Morphism")
  135. def list_elements(self):
  136. """
  137. Lists elements in the model.
  138. Returns:
  139. A list of elements in alphabetical order.
  140. """
  141. pn_names = {}
  142. for key in self.bottom.read_keys(self.ltm_pn):
  143. element, = self.bottom.read_outgoing_elements(self.ltm_pn, key)
  144. pn_names[element] = key
  145. unsorted = []
  146. for key in self.bottom.read_keys(self.model):
  147. element, = self.bottom.read_outgoing_elements(self.model, key)
  148. element_types = self.bottom.read_outgoing_elements(element, "Morphism")
  149. type_model_elements = self.bottom.read_outgoing_elements(self.ltm_pn)
  150. element_type_node, = [e for e in element_types if e in type_model_elements]
  151. unsorted.append((key, pn_names[element_type_node]))
  152. for elem in sorted(unsorted, key=lambda e: e[0]):
  153. print("{} : {}".format(*elem))
  154. def delete_element(self, name: str):
  155. """
  156. Deletes an element from the model.
  157. Args:
  158. name: name of the element to delete
  159. Returns:
  160. Nothing.
  161. """
  162. keys = self.bottom.read_keys(self.model)
  163. r = re.compile(r"{}\..*".format(name))
  164. to_delete = list(filter(r.match, keys))
  165. for key in to_delete:
  166. # TODO: find way to solve memory leak, primitive models are not deleted this way
  167. node, = self.bottom.read_outgoing_elements(self.model, label=key)
  168. self.bottom.delete_element(node)
  169. def to_bottom(self):
  170. # already implemented in terms of LTM bottom
  171. pass
  172. def from_bottom(self):
  173. # already implemented in terms of LTM bottom
  174. pass