Browse Source

algebraic loops seem to be solved semi-correctly now

Yentl Van Tendeloo 7 years ago
parent
commit
1a7d157c3f
3 changed files with 189 additions and 31 deletions
  1. 1 0
      models/dtcbd_simple.mvc
  2. 186 29
      models/dtcbd_simulate.alc
  3. 2 2
      models/live_modelling.py

+ 1 - 0
models/dtcbd_simple.mvc

@@ -16,3 +16,4 @@ Link (cte_x, adder) {}
 Link (adder, y) {}
 Link (adder, neg) {}
 Link (delay, z) {}
+Link (neg, adder) {}

+ 186 - 29
models/dtcbd_simulate.alc

@@ -5,6 +5,7 @@ include "conformance_scd.alh"
 include "io.alh"
 include "metamodels.alh"
 include "mini_modify.alh"
+include "utils.alh"
 
 Boolean function main(model : Element):
 	log("Start DTCBD simulation!")
@@ -50,20 +51,15 @@ Element function create_schedule(model : Element):
 	// Create nice graph first
 	Element nodes
 	Element successors
-	Element predecessors
 	String element_name
 	Element incoming_links
 	Element all_blocks
 
 	nodes = allInstances(model, "FullRuntime/Block")
-	successors = dict_create()
-	predecessors = dict_create()
+	successors = set_create()
 	while (set_len(nodes) > 0):
 		element_name = set_pop(nodes)
-		if (bool_not(dict_in(successors, element_name))):
-			dict_add(successors, element_name, create_node())
-		if (bool_not(dict_in(predecessors, element_name))):
-			dict_add(predecessors, element_name, create_node())
+		log("Block " + element_name + " : " + read_type(model, element_name))
 
 		if (is_nominal_instance(model, element_name, "FullRuntime/ICBlock")):
 			if (bool_not(is_physical_float(read_attribute(model, element_name, "last_in")))):
@@ -76,22 +72,27 @@ Element function create_schedule(model : Element):
 		while (set_len(incoming_links) > 0):
 			String source
 			source = readAssociationSource(model, set_pop(incoming_links))
-			if (bool_not(dict_in(successors, source))):
-				dict_add(successors, source, create_node())
-			set_add(successors[source], element_name)
-			set_add(predecessors[element_name], source)
-	
+			list_append(successors, create_tuple(source, element_name))
+			log("Found edge: " + source + " --> " + element_name)
+
 	Element values
 	values = create_node()
-	dict_add(values, "model", model)
-	dict_add(values, "S", create_node())
-	dict_add(values, "index", 0)
-	dict_add(values, "indices", create_node())
-	dict_add(values, "lowlink", create_node())
-	dict_add(values, "onStack", create_node())
-	dict_add(values, "successors", successors)
-	dict_add(values, "predecessors", predecessors)
-	dict_add(values, "SCC", create_node())
+	//dict_add(values, "model", model)
+	//dict_add(values, "S", create_node())
+	//dict_add(values, "index", 0)
+	//dict_add(values, "indices", create_node())
+	//dict_add(values, "lowlink", create_node())
+	//dict_add(values, "onStack", create_node())
+	//dict_add(values, "successors", successors)
+	//dict_add(values, "predecessors", predecessors)
+	//dict_add(values, "SCC", create_node())
+
+	dict_add(values, "edges", successors)
+	dict_add(values, "nodes", allInstances(model, "FullRuntime/Block"))
+	dict_add(values, "dfsCounter", 0)
+	dict_add(values, "orderNumber", dict_create())
+	dict_add(values, "visited_topSort", set_create())
+	dict_add(values, "unvisited_strongComp", set_create())
 
 	log("Toposort")
 	//nodes = get_topolist(values)
@@ -99,14 +100,147 @@ Element function create_schedule(model : Element):
 	//	log("Strong connect")
 	//	strongconnect(list_pop_final(nodes), values)
 
-	nodes = allInstances(model, "FullRuntime/Block")
-	while (set_len(nodes) > 0):
-		strongconnect(set_pop(nodes), values)
+	dict_overwrite(values, "SCC", strongComp(values))
+
+	//nodes = allInstances(model, "FullRuntime/Block")
+	//while (set_len(nodes) > 0):
+	//	strongconnect(set_pop(nodes), values)
 
 	log("OK")
 
 	return values["SCC"]!
 
+Void function topSort(values : Element):
+	Element nodes_copy
+	String node
+
+	// for node in graph:
+	//     node.visited = False
+	dict_overwrite(values, "visited_topSort", set_create())
+
+	// for node in graph:
+	//     if not node.visited:
+	//          dfsLabelling(node)
+	nodes_copy = set_copy(values["nodes"])
+	while (set_len(nodes_copy) > 0):
+		node = set_pop(nodes_copy)
+		if (bool_not(set_in(values["visited_topSort"], node))):
+			dfsLabelling(values, node)
+
+	return!
+
+Element function get_successors(values : Element, node : String, key : String):
+	Element edges
+	Element result
+	String edge
+
+	result = set_create()
+	edges = list_copy(values[key])
+	while (list_len(edges) > 0):
+		edge = list_pop_final(edges)
+		if (cast_string(edge[0]) == node):
+			set_add(result, edge[1])
+
+	return result!
+
+Void function dfsLabelling(values : Element, node : String):
+	Element successors
+	String successor
+
+	// if not node.visited
+	if (bool_not(set_in(values["visited_topSort"], node))):
+		// node.visited = True
+		set_add(values["visited_topSort"], node)
+
+		// for neighbour in node.out_neighbours:
+		//     dfsLabelling(neighbour, graph)
+		successors = get_successors(values, node, "edges")
+		while (set_len(successors) > 0):
+			successor = set_pop(successors)
+			dfsLabelling(values, successor)
+
+		// node.orderNumber = dfsCounter
+		dict_overwrite(values["orderNumber"], node, values["dfsCounter"])
+
+		// dfsCounter += 1
+		dict_overwrite(values, "dfsCounter", cast_integer(values["dfsCounter"]) + 1)
+
+	return !
+
+Element function dfsCollect(values : Element, start_node : String):
+	Element result
+	String successor
+	Element successors
+
+	result = set_create()
+
+	// if not node.visited
+	if (set_in(values["unvisited_strongComp"], start_node)):
+		list_append(result, start_node)
+		// node.visited = True
+		set_remove(values["unvisited_strongComp"], start_node)
+
+		// for neighbour in node.out_neighbours:
+		//     dfsLabelling(neighbour, graph)
+		successors = get_successors(values, start_node, "rev_edges")
+		while (set_len(successors) > 0):
+			successor = set_pop(successors)
+			list_extend(result, dfsCollect(values, successor))
+
+	return result!
+
+String function highest_orderNumber(values : Element):
+	Integer max
+	String max_element
+	Element search
+	String elem
+
+	max = -1
+	search = set_copy(values["unvisited_strongComp"])
+	while (set_len(search) > 0):
+		elem = set_pop(search)
+		if (cast_integer(values["orderNumber"][elem]) > max):
+			max = values["orderNumber"][elem]
+			max_element = elem
+		
+	return max_element!
+
+Element function reverse_edges(edges : Element):
+	Element result
+	Element elem
+
+	result = list_create()
+	edges = list_copy(edges)
+	while (list_len(edges) > 0):
+		elem = list_pop_final(edges)
+		list_append(result, create_tuple(elem[1], elem[0]))
+	return result!
+
+Element function strongComp(values : Element):
+	Element graph
+	Element sccs
+	String start_node
+	Element strong_components
+	Element component
+
+	sccs = list_create()
+
+	topSort(values)
+
+	dict_overwrite(values, "unvisited_strongComp", set_copy(values["nodes"]))
+
+	dict_overwrite(values, "rev_edges", reverse_edges(values["edges"]))
+	strong_components = list_create()
+
+	while (set_len(values["unvisited_strongComp"]) > 0):
+		start_node = highest_orderNumber(values)
+
+		component = dfsCollect(values, start_node)
+		list_append(sccs, component)
+		log("Got strong component: " + list_to_string(component))
+
+	return sccs!
+
 Element function get_topolist(values : Element):
 	Element result
 	Element predecessors
@@ -137,41 +271,64 @@ Integer function min(a : Integer, b : Integer):
 		return b!
 
 Void function strongconnect(v : String, values : Element):
+	// if (v.index is undefined) then
+	//    strongconnect(V)
 	if (dict_in(values["indices"], v)):
 		return!
 
+	// v.index := index
 	dict_overwrite(values["indices"], v, values["index"])
+	// v.lowlink := indwx
 	dict_overwrite(values["lowlink"], v, values["index"])
+	// index := index + 1
 	dict_overwrite(values, "index", cast_integer(values["index"]) + 1)
 
+	// S.push(v)
 	list_append(values["S"], v)
+	// v.onStack := true
 	dict_overwrite(values["onStack"], v, True)
 	
 	Element successors
 	String w
 	successors = values["successors"][v]
 	while (set_len(successors) > 0):
+		// for each (v, w) in E do
 		w = set_pop(successors)
+		// if (w.index is undefined) then
 		if (bool_not(dict_in(values["indices"], w))):
+			// strongconnect(w)
 			strongconnect(w, values)
+			// v.lowlink := min(v.lowlink, w.lowlink)
 			dict_overwrite(values["lowlink"], v, min(values["lowlink"][v], values["lowlink"][w]))
 		elif (dict_in(values["onStack"], w)):
+			// else if (w.onStack)
 			if (values["onStack"][w]):
+				// v.lowlink := min(v.lowlink, w.index)
 				dict_overwrite(values["lowlink"], v, min(values["lowlink"][v], values["indices"][w]))
 	
+	// if (v.lowlink == v.index) then
 	if (value_eq(values["lowlink"][v], values["indices"][v])):
 		Element scc
+		// Start a new strongly connected component
 		scc = create_node()
 		// It will always differ now
+		// w := S.pop()
 		w = list_pop_final(values["S"])
-		list_append(scc, w)
+		// w.onStack = false
 		dict_overwrite(values["onStack"], w, False)
+		// add w to current strongly connected component
+		list_append(scc, w)
+		// while w != v
 		while (w != v):
+			// w := S.pop()
 			w = list_pop_final(values["S"])
-			list_append(scc, w)
+			// w.onStack = false
 			dict_overwrite(values["onStack"], w, False)
+			// add w to current strongly connected component
+			list_append(scc, w)
+		// output the current strongly connected component
 		list_insert(values["SCC"], scc, 0)
-
+		log("Found new SCC: " + list_to_string(scc))
 	return!
 
 Boolean function solve_scc(model : Element, scc : Element):
@@ -214,14 +371,14 @@ Boolean function solve_scc(model : Element, scc : Element):
 		elif (blocktype == "FullRuntime/MultiplyBlock"):
 			constant = 1.0
 
-		incoming = allIncomingAssociationInstances(model, block, "Link")
+		incoming = allIncomingAssociationInstances(model, block, "FullRuntime/Link")
 
 		Integer index_to_write_constant
 		index_to_write_constant = -1
 		while (read_nr_out(incoming) > 0):
 			selected = readAssociationSource(model, set_pop(incoming))
 
-			if (set_in(scc, selected)):
+			if (list_in(scc, selected)):
 				// Part of the loop, so in the index of selected in scc
 				// Five options:
 				if (blocktype == "FullRuntime/AdditionBlock"):

+ 2 - 2
models/live_modelling.py

@@ -5,7 +5,6 @@ from modelverse import *
 init()
 login("admin", "admin")
 
-"""
 ### live modelling DTCBD
 
 model_add("formalisms/DTCBD/Design_MM", "formalisms/SimpleClassDiagrams", open("models/dtcbd_design.mvc", 'r').read())
@@ -29,8 +28,8 @@ transformation_add_AL({"FullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, {"Full
 transformation_add_AL({}, {}, "models/DTCBD/restartSim", open("models/cbd_restartSim.alc", 'r').read())
 
 model_add("models/live_modelling_DTCBD", "formalisms/ProcessModel", open("models/pm_live_DTCBD.mvc", 'r').read())
-"""
 
+"""
 ### live modelling CTCBD
 
 model_add("formalisms/CTCBD/Design_MM", "formalisms/SimpleClassDiagrams", open("models/ctcbd_design.mvc", 'r').read())
@@ -54,6 +53,7 @@ transformation_add_AL({"FullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, {"Full
 transformation_add_AL({}, {}, "models/DTCBD/restartSim", open("models/cbd_restartSim.alc", 'r').read())
 
 model_add("models/live_modelling_CTCBD", "formalisms/ProcessModel", open("models/pm_live_CTCBD.mvc", 'r').read())
+"""
 
 """
 ### live modelling FSA