Quellcode durchsuchen

First version including the generation of the matrix for the SCC

Yentl Van Tendeloo vor 8 Jahren
Ursprung
Commit
c3cc0be024
1 geänderte Dateien mit 127 neuen und 3 gelöschten Zeilen
  1. 127 3
      integration/code/cbd_semantics.alc

+ 127 - 3
integration/code/cbd_semantics.alc

@@ -197,6 +197,129 @@ Element function list_pop(list : Element):
 String function readType(model : Element, name : String):
 	return reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], model["model"][name]))!
 
+Boolean function solve_scc(model : Element, scc : Element):
+	Element m
+	Integer i
+	Integer j
+	String block
+	String blocktype
+	Element incoming
+	String selected
+	Float constant
+	Element t
+
+	// Construct the matrix first, with as many rows as there are variables
+	// Number of columns is 1 higher
+	i = 0
+	m = create_node()
+	while (i < read_nr_out(scc)):
+		j = 0
+		t = create_node()
+		while (j < (read_nr_out(scc) + 1)):
+			list_append(t, 0.0)
+			j = j + 1
+		list_append(m, t)
+		i = i + 1
+
+	log("Matrix ready!")
+	// Matrix initialized to 0.0
+	i = 0
+	while (i < read_nr_out(scc)):
+		log("Creating matrix row")
+		// First element of scc
+		block = cast_v2s(list_read(scc, i))
+		blocktype = readType(model, block)
+
+		// First write 1 in the current block
+		dict_overwrite(m[i], i, 1.0)
+
+		// Now check all blocks that are incoming
+		if (blocktype == "AdditionBlock"):
+			constant = 0.0
+		elif (blocktype == "MultiplyBlock"):
+			constant = 1.0
+		incoming = allIncomingAssociationInstances(model, block, "Link")
+
+		Integer index_to_write_constant
+		index_to_write_constant = -1
+		log("Iterating over incoming")
+		while (read_nr_out(incoming) > 0):
+			log("Iteration")
+			selected = readAssociationSource(model, set_pop(incoming))
+
+			if (set_in(scc, selected)):
+				// Part of the loop, so in the index of selected in scc
+				// Five options:
+				if (blocktype == "AdditionBlock"):
+					// 1) AdditionBlock
+					// Add the negative of this signal, which is as of yet unknown
+					// x = y + z --> x - y - z = 0
+					dict_overwrite(m[i], list_index_of(scc, selected), -1.0)
+				elif (blocktype == "MultiplyBlock"):
+					// 2) MultiplyBlock
+					if (index_to_write_constant != -1):
+						return False!
+					index_to_write_constant = list_index_of(scc, selected)
+				elif (blocktype == "NegatorBlock"):
+					// 3) NegatorBlock
+					// Add the positive of the signal, which is as of yet unknown
+					dict_overwrite(m[i], list_index_of(scc, selected), 1.0)
+				elif (blocktype == "DelayBlock"):
+					// 5) DelayBlock
+					// Just copies a single value
+					dict_overwrite(m[i], list_index_of(scc, selected), -1.0)
+				else:
+					// Block that cannot be handled
+					return False!
+			else:
+				// A constant, which we can assume is already computed and thus usable
+				if (blocktype == "AdditionBlock"):
+					constant = constant + v2f(read_attribute(model, selected, "signal"))
+					dict_overwrite(m[i], read_nr_out(scc), -constant)
+				elif (blocktype == "MultiplyBlock"):
+					constant = constant * v2f(read_attribute(model, selected, "signal"))
+					// Not written to constant part, as multiplies a variable
+
+				// Any other block is impossible:
+				// * Constant would never be part of a SCC
+				// * Delay would never get an incoming constant
+				// * Negation and Inverse only get 1 input, which is a variable in a loop
+				// * Integrator and Derivator never get an incoming constant
+
+		if (index_to_write_constant != -1):
+			dict_overwrite(m[i], index_to_write_constant, -constant)
+
+		i = i + 1
+
+	// Constructed a complete matrix, so we can start!
+	log("Constructed matrix to solve:")
+	log(matrix2string(m))
+
+	// Solve matrix now
+	eliminateGaussJordan(m)
+
+	// Now go over m and set signals for each element
+	// Assume that everything worked out...
+	i = 0
+	while (i < read_nr_out(m)):
+		block = scc[i]
+		unset_attribute(model, block, "signal")
+		instantiate_attribute(model, block, "signal", m[i][read_nr_out(scc)])
+		log((("Solved " + block) + " to ") + cast_v2s(m[i][read_nr_out(scc)]))
+		output((("SIM_PROBE " + cast_v2s(block)) + " ") + cast_v2s(m[i][read_nr_out(scc)]))
+
+	return True!
+
+Integer function list_index_of(lst : Element, elem : Element):
+	Integer i
+	i = 0
+	while (i < read_nr_out(lst)):
+		if (value_eq(list_read(lst, i), elem)):
+			return i!
+		else:
+			i = i + 1
+	return -1!
+
 Void function step_simulation(model : Element, schedule : Element):
 	String time
 	Float signal
@@ -221,9 +344,10 @@ Void function step_simulation(model : Element, schedule : Element):
 		i = i + 1
 
 		if (list_len(scc) > 1):
-			output("ALGEBRAIC_LOOP")
-			// TODO solve if possible
-			return !
+			log("Solving algebraic loop!")
+			if (bool_not(solve_scc(model, scc))):
+				output("ALGEBRAIC_LOOP")
+				return !
 		else:
 			block = set_pop(scc)