reachability.alc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. include "primitives.alh"
  2. include "modelling.alh"
  3. include "object_operations.alh"
  4. Element function reachability_graph(params : Element, output_mms : Element):
  5. Element result
  6. Element model
  7. Element workset
  8. Element out_model
  9. Element in_model
  10. Element transition_vectors_produce
  11. Element transition_vectors_consume
  12. Element all_transitions
  13. Element all_transitions_original
  14. Element tv
  15. Element links
  16. Element mappings
  17. Element reachable_states
  18. Element keys
  19. String transition
  20. String state
  21. String name
  22. String link
  23. String place
  24. String key
  25. Integer link_weight
  26. Integer initial
  27. Integer state_id
  28. Boolean possible
  29. Element all_places
  30. Element dict_repr
  31. Element work_unit
  32. result = create_node()
  33. out_model = instantiate_model(output_mms["ReachabilityGraph"])
  34. in_model = params["PetriNet"]
  35. log("Got in_model: " + cast_e2s(in_model))
  36. log("Params: " + dict_to_string(params))
  37. log("Params: " + cast_e2s(in_model))
  38. log("Keys in type: " + set_to_string(dict_keys(in_model["metamodel"]["model"])))
  39. // Create a dictionary representation for each transition
  40. transition_vectors_produce = create_node()
  41. transition_vectors_consume = create_node()
  42. all_transitions = allInstances(in_model, "Transition")
  43. log("Got all transitions: " + set_to_string(all_transitions))
  44. while (read_nr_out(all_transitions) > 0):
  45. transition = set_pop(all_transitions)
  46. tv = create_node()
  47. links = allIncomingAssociationInstances(in_model, transition, "P2T")
  48. log("All links: " + set_to_string(links))
  49. while (read_nr_out(links) > 0):
  50. link = set_pop(links)
  51. name = reverseKeyLookup(in_model["model"], read_edge_src(in_model["model"][link]))
  52. link_weight = read_attribute(in_model, link, "weight")
  53. dict_add(tv, name, link_weight)
  54. dict_add(transition_vectors_consume, transition, tv)
  55. log("Consume OK: " + dict_to_string(transition_vectors_consume[transition]))
  56. tv = create_node()
  57. links = allOutgoingAssociationInstances(in_model, transition, "T2P")
  58. while (read_nr_out(links) > 0):
  59. link = set_pop(links)
  60. name = reverseKeyLookup(in_model["model"], read_edge_dst(in_model["model"][link]))
  61. link_weight = read_attribute(in_model, link, "weight")
  62. dict_add(tv, name, link_weight)
  63. dict_add(transition_vectors_produce, transition, tv)
  64. log("Produce OK: " + dict_to_string(transition_vectors_produce[transition]))
  65. log("Ready for work!")
  66. workset = create_node()
  67. all_places = allInstances(in_model, "Place")
  68. log("All places: " + set_to_string(all_places))
  69. dict_repr = create_node()
  70. while (read_nr_out(all_places) > 0):
  71. place = set_pop(all_places)
  72. dict_add(dict_repr, place, read_attribute(in_model, place, "tokens"))
  73. log("Representation of first state: " + dict_to_string(dict_repr))
  74. set_add(workset, dict_repr)
  75. mappings = create_node()
  76. log("Start!")
  77. all_transitions_original = allInstances(in_model, "Transition")
  78. while (read_nr_out(workset) > 0):
  79. dict_repr = set_pop(workset)
  80. // TODO check if dict_repr is already in the set of reachable states
  81. // Compute how the PN behaves with this specific state
  82. // For this, we fetch all transitions and check if they are enabled
  83. all_transitions = set_copy(all_transitions_original)
  84. while (read_nr_out(all_transitions) > 0):
  85. transition = set_pop(all_transitions)
  86. log("Compute if possible for " + transition)
  87. keys = dict_keys(transition_vectors_consume[transition])
  88. possible = True
  89. log("Read keys")
  90. while (read_nr_out(keys) > 0):
  91. key = set_pop(keys)
  92. // Compare the values in the state with those consumed by the transition
  93. if (integer_lt(dict_repr[key], transition_vectors_consume[transition][key])):
  94. // Impossible transition, so discard this one
  95. possible = False
  96. break!
  97. if (possible):
  98. dict_repr = dict_copy(dict_repr)
  99. // Transition can execute, so compute and add the new state based on the consume/produce vectors
  100. keys = dict_keys(transition_vectors_consume[transition])
  101. log("Deduct")
  102. while (read_nr_out(keys) > 0):
  103. key = set_pop(keys)
  104. dict_overwrite(dict_repr, key, integer_subtraction(dict_repr[key], transition_vectors_consume[transition][key]))
  105. keys = dict_keys(transition_vectors_produce[transition])
  106. log("Increment")
  107. while (read_nr_out(keys) > 0):
  108. key = set_pop(keys)
  109. dict_overwrite(dict_repr, key, integer_addition(dict_repr[key], transition_vectors_produce[transition][key]))
  110. // Add the target to workset
  111. set_add(workset, dict_repr)
  112. dict_add(result, "ReachabilityGraph", out_model)
  113. return result!