Forráskód Böngészése

Added simplified Env_to_PN algorithm (in AL)

Yentl Van Tendeloo 8 éve
szülő
commit
d9cac21762
1 módosított fájl, 187 hozzáadás és 0 törlés
  1. 187 0
      models/environment_to_EPN.alc

+ 187 - 0
models/environment_to_EPN.alc

@@ -0,0 +1,187 @@
+// Pseudo-code
+//    assumption: Activities all have duration (e.g., 0 for parallel)
+//    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_PW"]
+
+	// 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!