|
@@ -1,186 +0,0 @@
|
|
|
-// Pseudo-code
|
|
|
-// TODO: add link to the ports of the boundary
|
|
|
-// TODO: update MM to reflect the new changes to the structure (everything is an Activity with a Next link, and everything has a duration)
|
|
|
-
|
|
|
-// init_place = new_place()
|
|
|
-// branches = [(init_place, [(0, topmost_model)]]
|
|
|
-// while branches:
|
|
|
-// prev, options = branches.pop()
|
|
|
-// nr = find_min_time(options)
|
|
|
-// time, cur = options.pop(nr)
|
|
|
-//
|
|
|
-// if type(cur) == "Event":
|
|
|
-// // Just add the current node and augment the duration for the next one
|
|
|
-// prev_model = new_element(cur)
|
|
|
-// if (cur.next != None):
|
|
|
-// options.append((time + cur.next.duration, cur.next))
|
|
|
-// branches.append((prev_model, options))
|
|
|
-// else:
|
|
|
-// // recurse upwards until we can follow a link
|
|
|
-// elem = containee(cur)
|
|
|
-// while elem.next_activity == None and containee(elem) != None:
|
|
|
-// elem = containee(elem)
|
|
|
-// if containee(elem) == None:
|
|
|
-// // finished this branch
|
|
|
-// continue!
|
|
|
-// else:
|
|
|
-// cur = elem.next_activity
|
|
|
-// options.append((time + elem.duration, cur.next))
|
|
|
-// branches.append((prev_model, options))
|
|
|
-// elif type(cur) == "Sequence":
|
|
|
-// options.append((time + first.duration, cur.first))
|
|
|
-// branches.append((prev_model, options))
|
|
|
-// elif type(cur) == "Parallel":
|
|
|
-// // Add all starts of the parallel as potential next one
|
|
|
-// // But keep the previous source, as we only expanded
|
|
|
-// for next in cur.start_nodes:
|
|
|
-// options.append((time + next.duration, next))
|
|
|
-// branches.append((prev, options))
|
|
|
-// elif type(cur) == "Alternative":
|
|
|
-// // Expand into new branches, but keep the options as is (add the individual options though)
|
|
|
-// for next in cur.start_nodes:
|
|
|
-// options.append((time + next.duration, next))
|
|
|
-// // Don't rewrite the source, as we effectively want to branch out from this node
|
|
|
-// branches.append(prev, options)
|
|
|
-
|
|
|
-include "primitives.alh"
|
|
|
-include "modelling.alh"
|
|
|
-include "object_operations.alh"
|
|
|
-
|
|
|
-Element function env_to_EPN(params : Element, output_mms : Element):
|
|
|
- Element result
|
|
|
- Element out_model
|
|
|
- Element in_model
|
|
|
- String init_place
|
|
|
- String current_activity
|
|
|
- Element branches
|
|
|
- Element options
|
|
|
- Element branch
|
|
|
- String previous_place
|
|
|
- Integer i
|
|
|
- Integer cnt
|
|
|
- Integer min_time
|
|
|
- Integer index_min_time
|
|
|
- Element option
|
|
|
- Integer current_time
|
|
|
- String new_transition
|
|
|
- String new_model
|
|
|
- Element containers
|
|
|
- Element new_options
|
|
|
- Element inner_elements
|
|
|
- Element entry
|
|
|
- String type
|
|
|
- String prev_model
|
|
|
- String element
|
|
|
-
|
|
|
- result = create_node()
|
|
|
- out_model = instantiate_model(output_mms["Encapsulated_PetriNet"])
|
|
|
- in_model = params["environment"]
|
|
|
-
|
|
|
- // Create the initial place
|
|
|
- init_place = instantiate_node(out_model, "Place", "")
|
|
|
- instantiate_attribute(out_model, init_place, "tokens", 1)
|
|
|
-
|
|
|
- // Set current element to the TopActivity, which will be expanded
|
|
|
- current_activity = set_pop(allInstances(in_model, "TopActivity"))
|
|
|
-
|
|
|
- // Initialize the data structure with the current element and initial place
|
|
|
- branches = create_node()
|
|
|
- options = create_node()
|
|
|
- list_append(options, create_tuple(0, current_activity))
|
|
|
- set_add(branches, create_tuple(init_place, options))
|
|
|
-
|
|
|
- // Keep going as long as there are branches to resolve
|
|
|
- while (read_nr_out(branches) > 0):
|
|
|
- // Still a branch, so pick one at random
|
|
|
- branch = set_pop(branches)
|
|
|
- previous_place = branch[0]
|
|
|
- options = branch[1]
|
|
|
-
|
|
|
- // Find the index of the option with the lowest time (first element of tuple)
|
|
|
- i = 0
|
|
|
- cnt = list_len(options)
|
|
|
- min_time = 9999999
|
|
|
- index_min_time = -1
|
|
|
- while (i < cnt):
|
|
|
- entry = list_read(options, i)
|
|
|
- if (integer_lt(entry[0], min_time)):
|
|
|
- min_time = entry[0]
|
|
|
- index_min_time = i
|
|
|
- i = i + 1
|
|
|
-
|
|
|
- // Pop the minimal option
|
|
|
- option = list_pop(options, index_min_time)
|
|
|
- current_time = option[0]
|
|
|
- current_activity = option[1]
|
|
|
-
|
|
|
- // Figure out the type
|
|
|
- type = read_type(in_model, current_activity)
|
|
|
-
|
|
|
- // Now branch based on the type
|
|
|
- if (type == "Event"):
|
|
|
- // Process an event: update the PN and go to the next activity
|
|
|
- new_transition = instantiate_node(out_model, "Transition", "")
|
|
|
- new_model = instantiate_node(out_model, "Place", "")
|
|
|
- instantiate_link(out_model, "P2T", "", prev_model, new_transition)
|
|
|
- instantiate_link(out_model, "T2P", "", new_transition, new_model)
|
|
|
-
|
|
|
- // Check if there is a Next to this Event, meaning another event
|
|
|
- if (read_nr_out(allOutgoingAssociationInstances(in_model, current_activity, "Next")) > 0):
|
|
|
- // We have a Next, so just push that next event on the options
|
|
|
- current_activity = set_pop(allAssociationDestinations(in_model, current_activity, "Next"))
|
|
|
- list_append(options, create_tuple(integer_addition(current_time, read_attribute(in_model, current_activity, "duration")), current_activity))
|
|
|
- set_add(branches, create_tuple(new_model, options))
|
|
|
- else:
|
|
|
- // No Next in this node, so we recurse up until one of these elements does have a next (or we reach the top)
|
|
|
- while (read_nr_out(allOutgoingAssociationInstances(in_model, current_activity, "Next")) == 0):
|
|
|
- // Recurse up
|
|
|
- containers = allAssociationOrigins(in_model, current_activity, "Contains")
|
|
|
- if (read_nr_out(containers) == 1):
|
|
|
- current_activity = set_pop(containers)
|
|
|
- elif (read_nr_out(containers) == 0):
|
|
|
- // No more containers, so at top element
|
|
|
- break!
|
|
|
- if (read_nr_out(containers) == 0):
|
|
|
- // Nothing left to do, so clear up this branch, but continue with the others
|
|
|
- continue!
|
|
|
- else:
|
|
|
- // Found a node with a Next link: we follow it
|
|
|
- current_activity = set_pop(allAssociationDestinations(in_model, current_activity, "Next"))
|
|
|
- list_append(options, create_tuple(integer_addition(current_time, read_attribute(in_model, current_activity, "duration")), current_activity))
|
|
|
- set_add(branches, create_tuple(new_model, options))
|
|
|
-
|
|
|
- elif (type == "Sequence"):
|
|
|
- // Process a sequence: just move the current option to the enclosing activity
|
|
|
- inner_elements = allAssociationDestinations(in_model, current_activity, "Contains")
|
|
|
- while (read_nr_out(inner_elements) > 0):
|
|
|
- element = set_pop(inner_elements)
|
|
|
- if (read_nr_out(allIncomingAssociationInstances(in_model, element, "Next")) == 0):
|
|
|
- current_activity = element
|
|
|
- break!
|
|
|
- // current_activity now contains the inner element to execute
|
|
|
- list_append(options, create_tuple(integer_addition(current_time, read_attribute(in_model, current_activity, "duration")), current_activity))
|
|
|
- // keep the current branch alive, as everything is updated by reference
|
|
|
- set_add(branches, branch)
|
|
|
-
|
|
|
- elif (type == "Parallel"):
|
|
|
- // Process a parallel: create new options for each containing element
|
|
|
- inner_elements = allAssociationDestinations(in_model, current_activity, "Contains")
|
|
|
- while (read_nr_out(inner_elements) > 0):
|
|
|
- current_activity = set_pop(inner_elements)
|
|
|
- // current_activity now contains the inner element to execute in parallel (an option)
|
|
|
- list_append(options, create_tuple(integer_addition(current_time, read_attribute(in_model, current_activity, "duration")), current_activity))
|
|
|
- // keep the current branch alive, as everything is updated by reference
|
|
|
- set_add(branches, branch)
|
|
|
-
|
|
|
- elif (type == "Alternative"):
|
|
|
- inner_elements = allAssociationDestinations(in_model, current_activity, "Contains")
|
|
|
- while (read_nr_out(inner_elements) > 0):
|
|
|
- current_activity = set_pop(inner_elements)
|
|
|
- // current_activity now contains the inner element to execute in alternative branches (a branch)
|
|
|
- new_options = set_copy(options)
|
|
|
- list_append(options, create_tuple(integer_addition(current_time, read_attribute(in_model, current_activity, "duration")), current_activity))
|
|
|
- set_add(branches, create_tuple(previous_place, new_options))
|
|
|
-
|
|
|
- dict_add(result, "Encapsulated_PetriNet", out_model)
|
|
|
- return result!
|