Browse Source

Fixed PM and related formalisms/algorithms: reachability starts running
fine

Yentl Van Tendeloo 8 years ago
parent
commit
2bd562bb6a

+ 9 - 10
core/core_algorithm.alc

@@ -200,7 +200,6 @@ Element function get_full_model(model_id : String):
 	Element m
 	Element all_links
 	String choice
-	log("Getting full model!")
 
 	choice = get_instanceOf_link(model_id)
 
@@ -213,8 +212,7 @@ Element function get_full_model(model_id : String):
 		dict_add(m, "metamodel", m)
 	else:
 		dict_add(m, "metamodel", get_full_model(readAssociationDestination(core, choice)))
-
-	log("Finished!")
+		
 	return m!
 
 Integer function get_relation_to_model(user_id : String, model_id : String):
@@ -478,9 +476,11 @@ Boolean function enact_action(pm : Element, element : String, prefix : String, u
 	String type_name
 	String exact_type
 	Element trace_links
+	Element output_mms
 
 	inputs = create_node()
 	outputs = create_node()
+	output_mms = create_node()
 
 	// TODO use the prefix for data locations (in model write/read in MvC)
 
@@ -496,6 +496,7 @@ Boolean function enact_action(pm : Element, element : String, prefix : String, u
 		// As there are no inheritance relations between full models, we can just read out the typename
 		type_name = read_attribute(pm, elem, "type")
 		dict_add(inputs, type_name, string_join(prefix, read_attribute(pm, elem, "name")))
+	log("Inputs: " + dict_to_string(inputs))
 
 	// Find all outputs and their types (i.e., key)
 	log("Read all producers of " + element)
@@ -507,6 +508,8 @@ Boolean function enact_action(pm : Element, element : String, prefix : String, u
 		type_name = read_attribute(pm, elem, "type")
 		log("Type name: " + type_name)
 		dict_add(outputs, type_name, string_join(prefix, read_attribute(pm, elem, "name")))
+		dict_add(output_mms, type_name, get_full_model(get_model_id(type_name)))
+	log("Outputs: " + dict_to_string(outputs))
 
 	exact_type = read_type(core, transformation_id)
 	log("Exact type: " + exact_type)
@@ -519,9 +522,6 @@ Boolean function enact_action(pm : Element, element : String, prefix : String, u
 		//		3) Perform the transformation on the merged model
 		//		4) Split the resulting model based on the target formalisms
 		//
-		// There is one exception: if the target model is bound to a source model, that model is overwritten
-		// This allows for some optimizations when it is a simple in-place transformation (skip model copy, join, and split)
-		// First check for this exception, as it is much faster
 		Element input_model
 		Element schedule_model
 		String trace_link_id
@@ -618,7 +618,8 @@ Boolean function enact_action(pm : Element, element : String, prefix : String, u
 		// 2) Execute action language model
 		func = get_func_AL_model(get_full_model(transformation_id))
 		log("Ready to execute: " + cast_e2s(func))
-		result = func(inputs)
+
+		result = func(inputs, output_mms)
 		log("Result: " + cast_e2s(result))
 
 		// 3) Split output dictionary back to seperate models
@@ -686,6 +687,7 @@ Boolean function enact_action(pm : Element, element : String, prefix : String, u
 				split_off_model = model_split(merged_model, get_full_model(desired_metamodel_id), key + "/")
 
 				// Check if the destination model already exists
+				log("Writing output to " + cast_v2s(outputs[key]))
 				if (get_model_id(outputs[key]) == ""):
 					// New model
 					model_create(split_off_model, outputs[key], user_id, desired_metamodel_id, "Model")
@@ -972,9 +974,6 @@ Void function user_function_skip_init(user_id : String):
 							//		3) Perform the transformation on the merged model
 							//		4) Split the resulting model based on the target formalisms
 							//
-							// There is one exception: if the target model is bound to a source model, that model is overwritten
-							// This allows for some optimizations when it is a simple in-place transformation (skip model copy, join, and split)
-							// First check for this exception, as it is much faster
 							Element input_model
 							Element schedule_model
 							String trace_link_id

+ 1 - 0
integration/code/pm_pn_reachability.mvc

@@ -19,6 +19,7 @@ ProcessModel combo_reach {
         type = "PetriNet"
     }
     Data reachability_graph {
+        name = "reachability"
         type = "ReachabilityGraph"
     }
 

+ 32 - 16
integration/code/reachability.alc

@@ -11,7 +11,7 @@ Element function reachability_graph(params : Element, output_mms : Element):
 	Element transition_vectors_produce
 	Element transition_vectors_consume
 	Element all_transitions
-	Element vector
+	Element all_transitions_original
 	Element tv
 	Element links
 	Element mappings
@@ -33,63 +33,77 @@ Element function reachability_graph(params : Element, output_mms : Element):
 
 	result = create_node()
 	out_model = instantiate_model(output_mms["ReachabilityGraph"])
-	in_model = params["PetriNets"]
+	in_model = params["PetriNet"]
+	log("Got in_model: " + cast_e2s(in_model))
+	log("Params: " + dict_to_string(params))
+	log("Params: " + cast_e2s(in_model))
+	log("Keys in type: " + set_to_string(dict_keys(in_model["metamodel"]["model"])))
 
 	// Create a dictionary representation for each transition
 	transition_vectors_produce = create_node()
 	transition_vectors_consume = create_node()
 	all_transitions = allInstances(in_model, "Transition")
+	log("Got all transitions: " + set_to_string(all_transitions))
 	while (read_nr_out(all_transitions) > 0):
 		transition = set_pop(all_transitions)
-		name = read_attribute(in_model, transition, "name")
-		vector = create_node()
 
 		tv = create_node()
-		dict_add(transition_vectors_consume, name, tv)
 		links = allIncomingAssociationInstances(in_model, transition, "P2T")
+		log("All links: " + set_to_string(links))
 		while (read_nr_out(links) > 0):
 			link = set_pop(links)
 			name = reverseKeyLookup(in_model["model"], read_edge_src(in_model["model"][link]))
 			link_weight = read_attribute(in_model, link, "weight")
 			dict_add(tv, name, link_weight)
+		dict_add(transition_vectors_consume, transition, tv)
+		log("Consume OK: " + dict_to_string(transition_vectors_consume[transition]))
 
 		tv = create_node()
-		dict_add(transition_vectors_produce, name, tv)
 		links = allOutgoingAssociationInstances(in_model, transition, "T2P")
 		while (read_nr_out(links) > 0):
 			link = set_pop(links)
 			name = reverseKeyLookup(in_model["model"], read_edge_dst(in_model["model"][link]))
 			link_weight = read_attribute(in_model, link, "weight")
 			dict_add(tv, name, link_weight)
+		dict_add(transition_vectors_produce, transition, tv)
+		log("Produce OK: " + dict_to_string(transition_vectors_produce[transition]))
 
+	log("Ready for work!")
 	workset = create_node()
 
 	all_places = allInstances(in_model, "Place")
+	log("All places: " + set_to_string(all_places))
 	dict_repr = create_node()
 	while (read_nr_out(all_places) > 0):
 		place = set_pop(all_places)
-		dict_add(dict_repr, read_attribute(in_model, place, "name"), read_attribute(in_model, place, "tokens"))
+		dict_add(dict_repr, place, read_attribute(in_model, place, "tokens"))
+
+	log("Representation of first state: " + dict_to_string(dict_repr))
 
 	set_add(workset, dict_repr)
 	mappings = create_node()
 
+	log("Start!")
+	all_transitions_original = allInstances(in_model, "Transition")
 	while (read_nr_out(workset) > 0):
 		dict_repr = set_pop(workset)
+
 		// TODO check if dict_repr is already in the set of reachable states
-		set_add(reachable_states, dict_repr)
 
 		// Compute how the PN behaves with this specific state
 		// For this, we fetch all transitions and check if they are enabled
-		all_transitions = allInstances(in_model, "Transition")
+		all_transitions = set_copy(all_transitions_original)
 		while (read_nr_out(all_transitions) > 0):
-			name = set_pop(all_transitions)
-			keys = dict_keys(transition_vectors_consume[name])
+			transition = set_pop(all_transitions)
+			log("Compute if possible for " + transition)
+			keys = dict_keys(transition_vectors_consume[transition])
 			possible = True
+			log("Read keys")
 			while (read_nr_out(keys) > 0):
 				key = set_pop(keys)
 
 				// Compare the values in the state with those consumed by the transition
-				if (integer_lt(dict_repr[key], transition_vectors_consume[name][key])):
+				if (integer_lt(dict_repr[key], transition_vectors_consume[transition][key])):
 					// Impossible transition, so discard this one
 					possible = False
 					break!
@@ -97,14 +111,16 @@ Element function reachability_graph(params : Element, output_mms : Element):
 			if (possible):
 				dict_repr = dict_copy(dict_repr)
 				// Transition can execute, so compute and add the new state based on the consume/produce vectors
-				keys = dict_keys(transition_vectors_consume[name])
+				keys = dict_keys(transition_vectors_consume[transition])
+				log("Deduct")
 				while (read_nr_out(keys) > 0):
 					key = set_pop(keys)
-					dict_overwrite(dict_repr, key, integer_subtraction(dict_repr[key], transition_vectors_consume[name][key]))
-				keys = dict_keys(transition_vectors_produce[name])
+					dict_overwrite(dict_repr, key, integer_subtraction(dict_repr[key], transition_vectors_consume[transition][key]))
+				keys = dict_keys(transition_vectors_produce[transition])
+				log("Increment")
 				while (read_nr_out(keys) > 0):
 					key = set_pop(keys)
-					dict_overwrite(dict_repr, key, integer_addition(dict_repr[key], transition_vectors_produce[name][key]))
+					dict_overwrite(dict_repr, key, integer_addition(dict_repr[key], transition_vectors_produce[transition][key]))
 
 				// Add the target to workset
 				set_add(workset, dict_repr)

+ 2 - 0
integration/code/reachabilitygraph_print.mvc

@@ -17,6 +17,7 @@ ReachabilityGraph_RAM reachabilitygraph_print {
                     label = "0"
                     action = $
                         Void function action(model : Element, name : String, mapping : Element):
+                            log("State action")
                             Element dict_values
                             Element all_values
                             dict_values = create_node()
@@ -55,6 +56,7 @@ ReachabilityGraph_RAM reachabilitygraph_print {
                     label = "2"
                     action = $
                         Void function action(model : Element, name : String, mapping : Element):
+                            log("Transition action")
                             output((((cast_v2s(mapping["0"]) + " --[") + cast_v2s(read_attribute(model, name, "name"))) + "]--> ") + cast_v2s(mapping["1"]))
                             return!
                         $

+ 4 - 0
integration/test_mvc.py

@@ -1954,6 +1954,10 @@ class TestModelverseCore(unittest.TestCase):
                         "p2t",
                         "p1",
                         "t1",
+                    "attr_add",
+                        "p2t",
+                        "weight",
+                        1,
                     "exit",
                 "model_list",
             ],