diff --git a/NodeLibrary.py b/NodeLibrary.py index fc6e6bd..0928433 100644 --- a/NodeLibrary.py +++ b/NodeLibrary.py @@ -77,6 +77,9 @@ def node_manipulator(self, node: DiagramNode) -> None: ###################################################################################### class SyncType(NodeType): + def __init__(self): + self.stop = False + def type_string(self) -> str: return "sync" @@ -435,3 +438,6 @@ def synchronization(self, tokens: Sequence[Dict], sync: Sequence[Dict], node: Di node.loog += tokens return (tokens, []) + + +###################################################################################### diff --git a/Tests/TTT_maor.flow b/Tests/TTT_maor.flow index e222b95..d6ee289 100644 --- a/Tests/TTT_maor.flow +++ b/Tests/TTT_maor.flow @@ -58,6 +58,21 @@ Tie = 'game over in tie' wa3 [type=waitall, waitall="AllButOne(path ,X)", at= 'toblock'] rq3 [type=sync, req="[O(toblock)]", width=200,priority = 7] +###################################################################################### +#fork + st4 -> wa4 -> rq4; + wt4; + + st4 [type=start, initial="[{'fork' : fork , 'defend' : defend} for (fork,defend) in [([4,1,2],[7,3])] ]", width=400]; + wa4 [type=waitall, waitall="AllButOne(fork ,O)", at= 'toFork'] + rq4 [type=sync, req="[O(toFork)]", width=200,priority = 6] + wt4 [type=sync, wait="[X(d) for d in defend]", width=200] + group { + wa4; + rq4; + wt4; + } + ###################################################################################### #WinChecker @@ -120,6 +135,7 @@ Tie = 'game over in tie' rqX1[type = sync , req="[X(i)]"] ###################################################################################### + # For debugging class hidden [color = none, style = none, textcolor = white]; stt -> listener -> logger -> listener [style = "none"]; diff --git a/Tests/TTT_maor.png b/Tests/TTT_maor.png index 706ab26..1cbeecc 100644 Binary files a/Tests/TTT_maor.png and b/Tests/TTT_maor.png differ diff --git a/Tests/TTT_maor_run/1.png b/Tests/TTT_maor_run/1.png index 744a6c2..9955584 100644 Binary files a/Tests/TTT_maor_run/1.png and b/Tests/TTT_maor_run/1.png differ diff --git a/Tests/TTT_maor_run/2.png b/Tests/TTT_maor_run/2.png index 1789aa3..8d2a433 100644 Binary files a/Tests/TTT_maor_run/2.png and b/Tests/TTT_maor_run/2.png differ diff --git a/Tests/group_test.flow b/Tests/group_test.flow index b6d69ad..dfd733c 100644 --- a/Tests/group_test.flow +++ b/Tests/group_test.flow @@ -1,7 +1,7 @@ blockdiag { st -> req1 -> req2; - st -> wt1; - wt2 -> req3; + st -> wt2; + wt1 -> req3; st [type=start]; req1 [type=sync, req="['1']"]; @@ -14,8 +14,8 @@ blockdiag { group { req1; req2; - wt1; wt2; + wt1; } diff --git a/Tests/group_test.png b/Tests/group_test.png new file mode 100644 index 0000000..4a33438 Binary files /dev/null and b/Tests/group_test.png differ diff --git a/Tests/testLiat.py b/Tests/testLiat.py deleted file mode 100644 index f79eb2e..0000000 --- a/Tests/testLiat.py +++ /dev/null @@ -1,32 +0,0 @@ -import matplotlib.pyplot as plt -import numpy as np -import scipy.stats -from sympy import * -from sympy.stats import Normal, E, Expectation, where -from sympy.abc import x - - -def d2aExpctation(thresholds, levels): - levels = len(thresholds) - - X1 = Normal('X1', 0, 1) - X2 = Normal('X2', 0, 1) - - print(E(X1 + X2, X1 < 10).simplify() ) - - print("thresholds=", thresholds) - arr = [(i, x <= thresholds[i]) for i in range(levels)] + [(levels, True)] - a2d = Lambda(x, Piecewise(*arr)) - - print(a2d) - for i in range(2 * levels - 1): - print(i, "-->") - if i==0: - print("\t", E(X1 + X2, And(Le(X1,thresholds[0]), Le(X2, thresholds[0]))).evalf(2)) - elif i==1: - print("\t", E(X1 + X2, (X1 < thresholds[0] and X2 < thresholds[1] and X2 > thresholds[0]) or (X2 < thresholds[0] and X1 < thresholds[1] and X1 > thresholds[0])).evalf(2)) - else: - print("\t", E(X1 + X2, Eq(a2d(X1) + a2d(X2), i)).evalf(2)) - - -d2aExpctation([-1.1, 0, 1.1], 0) \ No newline at end of file diff --git a/flow.py b/flow.py index d9ed325..68492d2 100644 --- a/flow.py +++ b/flow.py @@ -38,20 +38,50 @@ node_types = (StartType(), SyncType(), LoopType(), PassType(), PermutationType(), JoinType(), WaitForSetType(), LoggerType(), WaitAll()) +global _id +_id = 0 + def traverse_nodes(n): if not hasattr(n, 'nodes'): yield n else: - # TODO: Group for nn in n.nodes: # Add nn.group = n ? yield from traverse_nodes(nn) +def traverse_nodes_group(n): + if not hasattr(n, 'nodes'): + pass + else: + for nn in n.nodes: + # Add nn.group = n ? + yield from traverse_nodes_group(nn) + if type(nn) is NodeGroup: + yield nn + + +def get_group_nodes(g): + n = [n for n in g.nodes] + for e in g.edges: + if e.node2 in n: + n.remove(e.node2) + yield e.node2 + gr = g + while gr is not diagram and len(nodes) != 0: + gr = g.group + for e in gr.edges: + if e.node2 in n: + n.remove(e.node2) + yield e.node2 + + def setup_diagram(diagram): global nodes + global nodes_group nodes = [n for n in traverse_nodes(diagram)] + nodes_group = [n for n in traverse_nodes_group(diagram)] for n in nodes: n.pred = [] @@ -60,9 +90,19 @@ def setup_diagram(diagram): if nt.type_string() == n.type: n.node_type = nt nt.node_manipulator(n) + break if n.node_type is None: raise AttributeError("Unknown type '" + n.type + "'") + for g in nodes_group: + g.stop_group = False + g.conn_nodes = [n for n in get_group_nodes(g)] + g.groupStop = set(g.nodes) - set(g.conn_nodes) + for cn in g.conn_nodes: + if not hasattr(cn, "stop_nodes"): + cn.stop_nodes = [] + for sn in g.groupStop: + cn.stop_nodes.append(sn) build_predessessors_field(diagram) print_diagram(diagram, sys.argv[1]) @@ -104,10 +144,36 @@ def print_state(terminal_output=True): def step_to_next_state(diagram): + global _id tmp, changed = {}, False for n in nodes: - tmp[n] = [t for pn, p in n.pred for t in - pn.node_type.transformation(pn.tokens, pn, p)] + n.node_type.keep(n.tokens, n) + if n not in tmp.keys(): + tmp[n] = [] + for pn, p in n.pred: + trans = [t for t in pn.node_type.transformation(pn.tokens, pn, p)] + if pn.group != n.group: + if hasattr(n, "stop_nodes"): + for sn in n.stop_nodes: + if sn not in tmp.keys(): + tmp[sn] = [] + for t in trans: + if "ID" not in t.keys(): + t["ID"] = _id + _id += 1 + tmp[sn].extend(trans) + tmp[n].extend(trans) + + tmp[n].extend(n.node_type.keep(n.tokens, n)) + + # for g in nodes_group: + # for n in g.conn_nodes: + # for t in n.tokens + n.sync: + # for sn in g.groupStop: + # if t["ID"] not in [tt["ID"] for tt in (sn.tokens + sn.sync)]: + # if t in n.tokens: + # n.tokens.remove(t) + # elif t in n.sync: + # n.sync.remove(t) for n in nodes: tmp[n], n.sync = n.node_type.synchronization(tmp[n], n.sync, n) @@ -115,6 +181,15 @@ def step_to_next_state(diagram): changed = True n.tokens = tmp[n] + for g in nodes_group: + for n in g.conn_nodes: + for t in n.tokens + n.sync: + for sn in g.groupStop: + if t["ID"] not in [tt["ID"] for tt in (sn.tokens + sn.sync)]: + if t in n.tokens: + n.tokens.remove(t) + elif t in n.sync: + n.sync.remove(t) return changed @@ -133,7 +208,7 @@ def select_event(diagram): if diagram.event_selection_mechanism == 'random': pass elif diagram.event_selection_mechanism == 'priority': - if len(candidates)>0: + if len(candidates) > 0: p = max(candidates, key=lambda e: int(e[1]))[1] candidates = [e for e in candidates if e[1] == p] else: @@ -142,7 +217,7 @@ def select_event(diagram): if len(candidates) == 0: raise EndOfRunException() - + return random.choice(candidates)[0] @@ -174,10 +249,10 @@ def run_diagram(diagram): while True: while step_to_next_state(diagram): print_state() - + e = select_event(diagram) print("*** Event:", e, "***") - + wake_up_tokens(diagram, e) except EndOfRunException: pass