reachability.alc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. include "primitives.alh"
  2. include "modelling.alh"
  3. include "object_operations.alh"
  4. Element function reachability_graph(params : Element, output : Element):
  5. Element result
  6. Element model
  7. Element workset
  8. String state
  9. result = create_node()
  10. out_model = instantiate_node(output["ReachabilityGraph"])
  11. in_model = params["PetriNets"]
  12. // Create a dictionary representation for each transition
  13. transition_vectors_produce = create_node()
  14. transition_vectors_consume = create_node()
  15. all_transitions = allInstances(in_model, "Transition")
  16. while (read_nr_out(all_transitions) > 0):
  17. transition = set_pop(all_transitions)
  18. name = read_attribute(in_model, transition, "name")
  19. vector = create_node()
  20. tv = create_node()
  21. dict_add(transition_vectors_consume, name, tv)
  22. links = allIncomingAssociationInstances(in_model, transition, "P2T")
  23. while (read_nr_out(links) > 0):
  24. link = set_pop(links)
  25. name = reverseKeyLookup(in_model["model"], read_edge_src(in_model["model"][link]))
  26. link_weight = read_attribute(in_model, link, "weight")
  27. dict_add(tv, name, link_weight)
  28. tv = create_node()
  29. dict_add(transition_vectors_produce, name, tv)
  30. links = allOutgoingAssociationInstances(in_model, transition, "T2P")
  31. while (read_nr_out(links) > 0):
  32. link = set_pop(links)
  33. name = reverseKeyLookup(in_model["model"], read_edge_dst(in_model["model"][link]))
  34. link_weight = read_attribute(in_model, link, "weight")
  35. dict_add(tv, name, link_weight)
  36. workset = create_node()
  37. all_places = allInstances(in_model, "Place")
  38. dict_repr = create_node()
  39. while (read_nr_out(all_places) > 0):
  40. place = set_pop(all_places)
  41. dict_add(dict_repr, read_attribute(in_model, place, "name"), read_attribute(in_model, place, "tokens"))
  42. initial = 0
  43. set_add(workset, create_tuple(initial, dict_repr))
  44. mappings = create_node()
  45. while (read_nr_out(workset) > 0):
  46. dict_repr = set_pop(workset)
  47. // TODO check if dict_repr is already in the set of reachable states
  48. set_add(reachable_states, dict_repr)
  49. // Compute how the PN behaves with this specific state
  50. // For this, we fetch all transitions and check if they are enabled
  51. all_transitions = allInstances(in_model, "Transition")
  52. while (read_nr_out(all_transitions) > 0):
  53. name = set_pop(all_transitions)
  54. keys = dict_keys(transition_vectors_consume[name])
  55. possible = True
  56. while (read_nr_out(keys) > 0):
  57. key = set_pop(keys)
  58. // Compare the values in the state with those consumed by the transition
  59. if (dict_repr[key] < transition_vectors_consume[name][key]):
  60. // Impossible transition, so discard this one
  61. possible = False
  62. break!
  63. if (possible):
  64. dict_repr = dict_copy(work_unit[1])
  65. // Transition can execute, so compute and add the new state based on the consume/produce vectors
  66. keys = dict_keys(transition_vectors_consume[name])
  67. while (read_nr_out(keys) > 0):
  68. key = set_pop(keys)
  69. dict_overwrite(dict_repr, key, dict_repr[key] - transition_vectors_consume[name][key])
  70. keys = dict_keys(transition_vectors_produce[name])
  71. while (read_nr_out(keys) > 0):
  72. key = set_pop(keys)
  73. dict_overwrite(dict_repr, key, dict_repr[key] + transition_vectors_produce[name][key])
  74. // Add the target to workset
  75. set_add(workset, dict_repr)
  76. dict_add(result, "ReachabilityGraph", out_model)
  77. return result!