Procházet zdrojové kódy

Fixed CBD semantics (without algebraic loops!)

Yentl Van Tendeloo před 8 roky
rodič
revize
dd2a7f4c48

binární
bootstrap/bootstrap.m.gz


+ 5 - 6
bootstrap/modelling.alc

@@ -172,11 +172,11 @@ Void function instantiate_attribute(model : Element, element : String, attribute
 		log("Could not find attribute " + cast_v2s(attribute_name))
 		return!
 		
-	if (set_in_node(model["model"], value)):
-		attr_name = reverseKeyLookup(model["model"], value)
-	else:
-		attr_name = model_add_value(model, (element + ".") + attribute_name, value)
-		retype(model, attr_name, reverseKeyLookup(model["metamodel"]["model"], read_edge_dst(model["metamodel"]["model"][attr_type])))
+	// Make a copy of the value, as it is likely that this value is reused later on
+	value = create_value(value)
+
+	attr_name = model_add_value(model, (element + ".") + attribute_name, value)
+	retype(model, attr_name, reverseKeyLookup(model["metamodel"]["model"], read_edge_dst(model["metamodel"]["model"][attr_type])))
 	instantiate_link(model, attr_type, "", element, attr_name)
 
 	return!
@@ -234,7 +234,6 @@ Void function unset_attribute(model : Element, element : String, attribute : Str
 	String attr_type
 	Element attr_links
 	String attr_link
-	log((("Unsetting attribute " + attribute) + " of element ") + element)
 	
 	attr_type = find_attribute_type(model, element, attribute)
 	attr_links = allOutgoingAssociationInstances(model, element, attr_type)

+ 1 - 0
integration/code/cbd_design.mvc

@@ -61,6 +61,7 @@ CausalBlockDiagrams_Design my_CBD{
     Link(b, c){}
     Link(c, d){}
     InitialCondition(a, d){}
+    Link(d, c){}
 }
 
 export my_CBD to models/my_CBD

+ 20 - 30
integration/code/cbd_semantics.alc

@@ -38,12 +38,8 @@ Element function translate_to_runtime(design_model : Element):
 	String time
 	Element all_attributes
 
-	log("Translating to runtime model!")
-
-	log("Creating empty runtime model")
 	runtime_model = instantiate_model(import_node("models/CausalBlockDiagrams_Runtime"))
 
-	log("Converting blocks")
 	all_blocks = allInstances(design_model, "Block")
 	while (list_len(all_blocks) > 0):
 		element_name = set_pop(all_blocks)
@@ -54,41 +50,30 @@ Element function translate_to_runtime(design_model : Element):
 		elif (mm_type_name == "DelayBlock"):
 			instantiate_attribute(runtime_model, element_name, "memory", 0.0)
 		instantiate_attribute(runtime_model, element_name, "signal", 0.0)
-		log("    Converted block " + element_name)
 
 	// Don't merge this together with the block conversion, as the destination block might not exist yet!
-	log("Relinking blocks")
 	all_links = allInstances(design_model, "Link")
 	while (read_nr_out(all_links) > 0):
 		element_name = set_pop(all_links)
 		src = reverseKeyLookup(design_model["model"], read_edge_src(design_model["model"][element_name]))
 		dst = reverseKeyLookup(design_model["model"], read_edge_dst(design_model["model"][element_name]))
 		instantiate_link(runtime_model, "Link", element_name, src, dst)
-		log((("    Relinked blocks " + src) + " and ") + dst)
 
-	log("Resetting initial conditions")
 	all_links = allInstances(design_model, "InitialCondition")
 	while (read_nr_out(all_links) > 0):
 		element_name = set_pop(all_links)
 		src = reverseKeyLookup(design_model["model"], read_edge_src(design_model["model"][element_name]))
 		dst = reverseKeyLookup(design_model["model"], read_edge_dst(design_model["model"][element_name]))
 		instantiate_link(runtime_model, "InitialCondition", element_name, src, dst)
-		log("    Reset IC of " + dst)
 
-	log("Creating schedule at time = 0")
 	create_schedule(runtime_model, True)
 
-	log("Creating schedule at time > 0")
 	create_schedule(runtime_model, False)
 
-	log("Solving loops (TODO)")
-
-	log("Creating simulation time")
 	time = instantiate_node(runtime_model, "Time", "time")
 	instantiate_attribute(runtime_model, time, "current_time", 0)
 	instantiate_attribute(runtime_model, time, "termination_time", 100)
 
-	log("DONE!")
 	return runtime_model!
 
 Void function create_schedule(model : Element, is_time_zero : Boolean):
@@ -196,6 +181,7 @@ Void function step_simulation(model : Element):
 	String elem
 	String blocktype
 	String output_string
+	Element delay_blocks
 
 	time = "time"
 	if (cast_s2i(cast_v2s(read_attribute(model, time, "current_time"))) == 0):
@@ -203,6 +189,7 @@ Void function step_simulation(model : Element):
 	else:
 		schedule = "schedule_run"
 
+	delay_blocks = create_node()
 	output_string = "("
 	while (read_nr_out(allOutgoingAssociationInstances(model, schedule, "LinkedBlock")) > 0):
 		block = readAssociationDestination(model, set_pop(allOutgoingAssociationInstances(model, schedule, "LinkedBlock")))
@@ -235,27 +222,28 @@ Void function step_simulation(model : Element):
 				selected = readAssociationSource(model, set_pop(incoming))
 				signal = float_division(1.0, cast_s2f(cast_v2s(read_attribute(model, selected, "signal"))))
 		elif (blocktype == "DelayBlock"):
-			// TODO this is very broken...
-			if (schedule == "schedule_init"):
+			if (cast_s2i(cast_v2s(read_attribute(model, time, "current_time"))) == 0):
 				incoming = allIncomingAssociationInstances(model, block, "InitialCondition")
 				while (read_nr_out(incoming) > 0):
 					selected = readAssociationSource(model, set_pop(incoming))
 					signal = cast_s2f(cast_v2s(read_attribute(model, selected, "signal")))
-					log("Read signal from initial condition: " + cast_v2s(signal))
 			else:
 				signal = read_attribute(model, block, "memory")
-
-			// Update memory
-			incoming = allIncomingAssociationInstances(model, block, "Link")
-			while (read_nr_out(incoming) > 0):
-				selected = readAssociationSource(model, set_pop(incoming))
-			unset_attribute(model, block, "memory")
-			instantiate_attribute(model, block, "memory", cast_s2f(cast_v2s(read_attribute(model, selected, "signal"))))
+			set_add(delay_blocks, block)
 
 		unset_attribute(model, block, "signal")
 		instantiate_attribute(model, block, "signal", signal)
 		output_string = output_string + (((block + " = ") + cast_v2s(signal)) + "; ")
 	output_string = output_string + ")"
+	
+	while (read_nr_out(delay_blocks) > 0):
+		block = set_pop(delay_blocks)
+		// Update memory
+		incoming = allIncomingAssociationInstances(model, block, "Link")
+		while (read_nr_out(incoming) > 0):
+			selected = readAssociationSource(model, set_pop(incoming))
+			unset_attribute(model, block, "memory")
+			instantiate_attribute(model, block, "memory", cast_s2f(cast_v2s(read_attribute(model, selected, "signal"))))
 
 	// Increase simulation time
 	Integer new_time
@@ -274,11 +262,6 @@ Void function set_termination_time(model : Element):
 Void function execute_cbd(model : Element):
 	String verify_result
 	model = translate_to_runtime(model)
-	verify_result = conformance_scd(model)
-	if (verify_result != "OK"):
-		output("Error constructing conforming runtime model: " + verify_result)
-		return!
-	
 	output("Runtime model constructed OK!")
 
 	String cmd
@@ -303,6 +286,7 @@ Void function execute_cbd(model : Element):
 				//output("  modify  -- live modelling: modify model structure")
 				output("  list    -- list blocks and connections")
 				output("  exit    -- select another model")
+				output("  verify  -- verify the runtime model")
 			else:
 				output("  pause   -- pause simulation")
 			output("  help    -- this information")
@@ -326,6 +310,12 @@ Void function execute_cbd(model : Element):
 				running = True
 			elif (cmd == "exit"):
 				return!
+			elif (cmd == "verify"):
+				verify_result = conformance_scd(model)
+				if (verify_result != "OK"):
+					output("Error in runtime model: " + verify_result)
+				else:
+					output("Runtime model OK!")
 			else:
 				output("Did not understand command!")
 				output("Use 'help' for a list of available options")

+ 1 - 1
integration/code/pn_interface.alc

@@ -249,7 +249,7 @@ Element function model_loaded(model : Element):
 				if (dict_in(model["metamodel"]["model"], typename)):
 					// OK, do the retyping
 					// First try removing the previous type if it exists
-					dict_delete(model["type_mapping"], model["model"][elementname])
+					dict_delete_node(model["type_mapping"], model["model"][elementname])
 					// Now add the new type
 					dict_add(model["type_mapping"], model["model"][elementname], model["metamodel"]["model"][typename])
 					output("Retyped!")

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

@@ -34,6 +34,7 @@ String function cast_v2s(a: Element)
 String function cast_id2s(a: Element) 
 Element function dict_add(a: Element, b: Element, c: Element)
 Element function dict_delete(a: Element, b: Element)
+Element function dict_delete_node(a: Element, b: Element)
 Element function dict_read(a: Element, b: Element) 
 Element function dict_read_edge(a: Element, b: Element) 
 Element function dict_read_node(a: Element, b: Element) 

+ 12 - 3
kernel/modelverse_kernel/primitives.py

@@ -258,11 +258,20 @@ def dict_add(a, b, c, **remainder):
     raise PrimitiveFinished(a)
 
 def dict_delete(a, b, **remainder):
+    b_value, = yield [("RV", [b])]
+    edge, = yield [("RDE", [a, b_value])]
+    if edge is None:
+        print("Failed dict_delete for value %s!" % b_value)
+        keys, = yield [("RDK", [a])]
+        keys = yield [("RV", [i]) for i in keys]
+        print("Keys: " + str(keys))
+    yield [("DE", [edge])]
+    raise PrimitiveFinished(a)
+
+def dict_delete_node(a, b, **remainder):
     edge, = yield [("RDNE", [a, b])]
     if edge is None:
-        # This exact node isn't in this dictionary, so delete everything matching the value instead
-        b_value, = yield [("RV", [b])]
-        edge, = yield [("RDE", [a, b_value])]
+        print("Failed dict_delete_node!")
     yield [("DE", [edge])]
     raise PrimitiveFinished(a)
 

+ 6 - 1
state/modelverse_state/main.py

@@ -162,6 +162,11 @@ class ModelverseState(object):
             return (None, status.FAIL_CDICT_TARGET)
         if not self.is_valid_datavalue(data):
             return (None, status.FAIL_CDICT_OOB)
+        if (type(data) == float and data == 0.0):
+            print("Got dictionary with value 0.0")
+            print(locals())
+            print(self.values.get(destination, destination))
+            raise Exception()
         n = self.create_nodevalue(data)[0]
         e = self.create_edge(source, destination)[0]
         self.create_edge(e, n)
@@ -249,7 +254,7 @@ class ModelverseState(object):
                     # Found a match
                     # Now get the target of the original link
                     if found is not None:
-                        print("Duplicate key on value: %s (%s <-> %s)!" % (v, found, e1))
+                        print("Duplicate key on value: %s : %s (%s <-> %s)!" % (v, type(v), found, e1))
                         return (None, status.FAIL_RDICTE_AMBIGUOUS)
                     found = e1
                     self.cache.setdefault(node, {})[value] = e1