reachability.alc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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 vector
  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["PetriNets"]
  35. // Create a dictionary representation for each transition
  36. transition_vectors_produce = create_node()
  37. transition_vectors_consume = create_node()
  38. all_transitions = allInstances(in_model, "Transition")
  39. while (read_nr_out(all_transitions) > 0):
  40. transition = set_pop(all_transitions)
  41. name = read_attribute(in_model, transition, "name")
  42. vector = create_node()
  43. tv = create_node()
  44. dict_add(transition_vectors_consume, name, tv)
  45. links = allIncomingAssociationInstances(in_model, transition, "P2T")
  46. while (read_nr_out(links) > 0):
  47. link = set_pop(links)
  48. name = reverseKeyLookup(in_model["model"], read_edge_src(in_model["model"][link]))
  49. link_weight = read_attribute(in_model, link, "weight")
  50. dict_add(tv, name, link_weight)
  51. tv = create_node()
  52. dict_add(transition_vectors_produce, name, tv)
  53. links = allOutgoingAssociationInstances(in_model, transition, "T2P")
  54. while (read_nr_out(links) > 0):
  55. link = set_pop(links)
  56. name = reverseKeyLookup(in_model["model"], read_edge_dst(in_model["model"][link]))
  57. link_weight = read_attribute(in_model, link, "weight")
  58. dict_add(tv, name, link_weight)
  59. workset = create_node()
  60. all_places = allInstances(in_model, "Place")
  61. dict_repr = create_node()
  62. while (read_nr_out(all_places) > 0):
  63. place = set_pop(all_places)
  64. dict_add(dict_repr, read_attribute(in_model, place, "name"), read_attribute(in_model, place, "tokens"))
  65. set_add(workset, dict_repr)
  66. mappings = create_node()
  67. while (read_nr_out(workset) > 0):
  68. dict_repr = set_pop(workset)
  69. // TODO check if dict_repr is already in the set of reachable states
  70. set_add(reachable_states, dict_repr)
  71. // Compute how the PN behaves with this specific state
  72. // For this, we fetch all transitions and check if they are enabled
  73. all_transitions = allInstances(in_model, "Transition")
  74. while (read_nr_out(all_transitions) > 0):
  75. name = set_pop(all_transitions)
  76. keys = dict_keys(transition_vectors_consume[name])
  77. possible = True
  78. while (read_nr_out(keys) > 0):
  79. key = set_pop(keys)
  80. // Compare the values in the state with those consumed by the transition
  81. if (integer_lt(dict_repr[key], transition_vectors_consume[name][key])):
  82. // Impossible transition, so discard this one
  83. possible = False
  84. break!
  85. if (possible):
  86. dict_repr = dict_copy(dict_repr)
  87. // Transition can execute, so compute and add the new state based on the consume/produce vectors
  88. keys = dict_keys(transition_vectors_consume[name])
  89. while (read_nr_out(keys) > 0):
  90. key = set_pop(keys)
  91. dict_overwrite(dict_repr, key, integer_subtraction(dict_repr[key], transition_vectors_consume[name][key]))
  92. keys = dict_keys(transition_vectors_produce[name])
  93. while (read_nr_out(keys) > 0):
  94. key = set_pop(keys)
  95. dict_overwrite(dict_repr, key, integer_addition(dict_repr[key], transition_vectors_produce[name][key]))
  96. // Add the target to workset
  97. set_add(workset, dict_repr)
  98. dict_add(result, "ReachabilityGraph", out_model)
  99. return result!