Browse Source

Updated set_difference to a pre-compiled

Yentl Van Tendeloo 5 years ago
parent
commit
0c014a84c6

+ 20 - 19
bootstrap/conformance_finding.alc

@@ -14,34 +14,35 @@ Boolean function find_type_mapping(model : Element):
 	Element tm
 	Element elems
 	String elem
+	Element diff
 
 	tm = get_type_mapping_as_dict(model)
 
-	// 1) remove elements from type mapping that are not in the model or metamodel
-	elems = dict_keys(tm)
+	// 1a) remove elements from type mapping that are not in the model
+	Element reverse
+	reverse = make_reverse_dictionary_multi(tm)
+	elems = dict_keys(reverse)
+	diff = set_difference(elems, dict_keys(model["metamodel"]["model"]))
 
-	if (set_len(elems) > 1000):
-		// For now, we give up as this takes too much time...
-		return True!
+	while (set_len(diff) > 0):
+		elems = reverse[set_pop(diff)]
+		while (set_len(elems) > 0):
+			dict_delete(tm, set_pop(elems))
 
+	// 1b) remove elements from type mapping that are not in the model
+	elems = dict_keys(tm)
 	if (bool_not(set_equality(elems, dict_keys(model["model"])))):
 		// First do a simplified check to see which ones are known to be there
-		while (set_len(elems) > 0):
-			log("Remaining " + cast_string(set_len(elems)))
-			elem = set_pop(elems)
-			if (bool_not(dict_in(model["model"], elem))):
-				// Remove the key, as the model does not contain the element anymore
-				dict_delete(tm, elem)
-			else:
-				if (bool_not(dict_in(model["metamodel"]["model"], tm[elem]))):
-					// Remove the key, as the metamodel does not contain the type anymore
-					dict_delete(tm, elem)
-	else:
-		log("Skipped " + cast_string(set_len(elems)))
-		
+		diff = set_difference(elems, dict_keys(model["model"]))
+
+		while (set_len(diff) > 0):
+			elem = set_pop(diff)
+			dict_delete(tm, elem)
+	
 	// 2) find a mapping based on the current partial mapping, but only if it is not yet complete
 	// TODO this must be expanded for other things than trivial metamodels!
-	if (dict_len(model["model"]) > dict_len(tm)):
+	//if (dict_len(model["model"]) > dict_len(tm)):
+	if (set_len(set_difference(dict_keys(model["model"]), dict_keys(tm))) > 0):
 		// TODO for now, this only returns something for a simple case, where the MM has one edge, and one node
 		//      and it makes the assumption that SCD is the M3 level...
 

+ 18 - 3
bootstrap/semi_primitives.alc

@@ -385,9 +385,24 @@ Element function make_reverse_dictionary(dict : Element):
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
 		value = cast_id(dict[key])
-		if (dict_in(reverse, value)):
-			dict_delete(reverse, value)
-		dict_add(reverse, value, key)
+		dict_overwrite(reverse, value, key)
+
+	return reverse!
+
+Element function make_reverse_dictionary_multi(dict : Element):
+	Element keys
+	Element reverse
+	String key
+	String value
+
+	reverse = dict_create()
+	keys = dict_keys(dict)
+	while (set_len(keys) > 0):
+		key = set_pop(keys)
+		value = cast_string(dict[key])
+		if (bool_not(dict_in(reverse, value))):
+			dict_add(reverse, value, set_create())
+		set_add(reverse[value], key)
 
 	return reverse!
 

+ 1 - 0
interface/HUTN/includes/primitives.alh

@@ -113,6 +113,7 @@ Element function create_tuple(a : Element, b : Element)
 Void function dict_overwrite(a : Element, b : Element, c : Element)
 Void function set_merge(sa : Element, sb : Element)
 Element function make_reverse_dictionary(dict : Element)
+Element function make_reverse_dictionary_multi(dict : Element)
 Element function set_create()
 Element function list_create()
 Element function dict_create()

+ 35 - 0
kernel/modelverse_kernel/compiled.py

@@ -135,11 +135,37 @@ def has_value(a, **remainder):
 
 def make_reverse_dictionary(a, **remainder):
     reverse, = yield [("CN", [])]
+
+    if "id" not in a:
+        yield [("RETURN", [{'id': reverse}])]
+
     key_nodes, = yield [("RDK", [a['id']])]
     values = yield [("RDN", [a['id'], i]) for i in key_nodes]
     yield [("CD", [reverse, str(v), k]) for k, v in zip(key_nodes, values)]
     yield [("RETURN", [{'id': reverse}])]
 
+def make_reverse_dictionary_multi(a, **remainder):
+    reverse, keys = yield [("CN", []), ("RDK", [a['id']])]
+
+    if "id" not in a:
+        yield [("RETURN", [{'id': reverse}])]
+
+    values = yield [("RDN", [a['id'], i]) for i in keys]
+    keys = yield [("RV", [i]) for i in keys]
+    values = yield [("RV", [i]) for i in values]
+
+    ndict = {}
+    for k, v in zip(keys, values):
+        ndict.setdefault(v, set()).add(k)
+
+    n = yield [("CN", []) for _ in ndict]
+    for k in ndict:
+        set_node = n.pop()
+        yield [("CD", [reverse, k, set_node])]
+        yield [("CD", [set_node, v, set_node]) for v in ndict[k]]
+
+    yield [("RETURN", [{'id': reverse}])]
+
 def dict_eq(a, b, **remainder):
     key_nodes, = yield [("RDK", [a['id']])]
     key_values = yield [("RV", [i]) for i in key_nodes]
@@ -462,3 +488,12 @@ def set_equality(a, b, **remainder):
     keys_b = yield [("RV", [i]) for i in keys_b]
     print("Check equality for # " + str(len(keys_a) + len(keys_b)))
     yield [("RETURN", [{'value': keys_a == keys_b}])]
+
+def set_difference(a, b, **remainder):
+    keys_a, keys_b = yield [("RDK", [a["id"]]), ("RDK", [b["id"]])]
+    keys_a = yield [("RV", [i]) for i in keys_a]
+    keys_b = yield [("RV", [i]) for i in keys_b]
+    result = set(keys_a) - set(keys_b)
+    res, = yield [("CN", [])]
+    yield [("CD", [res, v, res]) for v in result]
+    yield [("RETURN", [{'id': res}])]