Commit db0183d8 authored by VIGNET Pierre's avatar VIGNET Pierre
Browse files

[cmd] Small refactoring; Update/set doc; Fix typos; doc recursive func for cond parsing

parent 748af5d0
......@@ -402,7 +402,7 @@ def low_graph_info(model_file, centralities):
# valid paths from conditions.
front_places = get_frontier_places(transitions_1, all_places_1)
front_places_str = " ".join(front_places)
LOGGER.debug("Frontier places 1: " + front_places_str)
LOGGER.info("Frontier places 1: %s", front_places_str)
# Build graphs & get networkx object
# We give all events in the model as a list of steps
......
......@@ -57,13 +57,13 @@ def build_graph(solution, steps, transitions):
- Inhibition edge: red
- Activation edge: green
:param arg1: Frontier places.
:param arg2: List of steps (with events in each step).
:param arg3: A dictionnary of events as keys, and transitions as values
:param solution: Frontier places.
:param steps: List of steps (with events in each step).
:param transitions: A dictionnary of events as keys, and transitions as values
(see get_transitions()).
:type arg1: <str>
:type arg2: <list <list>>
:type arg3: <dict <list <tuple <str>, <str>, <dict <str>: <str>>>>
:type solution: <str>
:type steps: <list <list>>
:type transitions: <dict <list <tuple <str>, <str>, <dict <str>: <str>>>>
:return:
- Networkx graph object.
- Nodes corresponding to transitions with conditions.
......@@ -103,7 +103,7 @@ def build_graph(solution, steps, transitions):
# Color nodes
# Since we explore all possible paths for each condition,
# some edges are rewrited multiple times.
# some edges are rewritten multiple times.
# => included edges between origin <=> transition node
# These edges must be grey while, edges between a node that is
# only in a condition and a transition node must be green.
......@@ -120,77 +120,76 @@ def build_graph(solution, steps, transitions):
for trans in step_event:
attributes = trans[2]
ori = trans[0]
ext = trans[1]
event = attributes['label'].split('[')[0]
ori, ext, attributes = trans
# If there is a condition formula associated to this clock
if attributes['condition'] != '':
# Add the transition as node
# PS: There may be a rewrite of an identical node here,
# networkx will do the merge later, but the conditions
# will not be preserved. Only the last condition is kept.
transition_nodes.append(
(
event,
{
'name': attributes['label'], # Trick for Cytoscape
'color': 'blue',
'condition': attributes['condition'], # Partial cond (cf above)
}
)
)
# Is there a condition formula associated to this clock ?
if not attributes['condition']:
# No => Normal edges
edges.append(trans)
continue
# Origin => transition node
edges_with_cond.append(
(
ori, event,
{
'label': ori + '-' + event,
}
)
)
event = attributes['label'].split('[')[0]
# Transition node => ext
edges_with_cond.append(
(
event, ext,
{
'label': event + '-' + ext,
}
)
# Add the transition as node
# PS: There may be a rewrite of an identical node here,
# networkx will do the merge later, but the conditions
# will not be preserved. Only the last condition is kept.
transition_nodes.append(
(
event,
{
'name': attributes['label'], # Trick for Cytoscape
'color': 'blue',
'condition': attributes['condition'], # Partial cond (cf above)
}
)
# Add all transitions to nodes linked via the condition
valid_paths = parse_condition(
attributes['condition'],
all_nodes,
inhibitors_nodes # Set in place by parse_condition
)
# Origin => transition node
edges_with_cond.append(
(
ori, event,
{
'label': ori + '-' + event,
}
)
)
# Transition node => ext
edges_with_cond.append(
(
event, ext,
{
'label': event + '-' + ext,
}
)
for i, path in enumerate(valid_paths):
for node in path:
edges_in_cond.append(
(
node, event,
{
'label': '{} ({})'.format(
event,
i
),
#'label': '{} [{}] ({})'.format(
# event,
# ', '.join(path),
# i
#), #node + '-' + event,
'color': color_map(node), # Set edge color
}
)
)
# Add all transitions to nodes linked via the condition
valid_paths = parse_condition(
attributes['condition'],
all_nodes,
inhibitors_nodes # Modified in place
)
for i, path in enumerate(valid_paths):
for node in path:
edges_in_cond.append(
(
node, event,
{
'label': '{} ({})'.format(
event,
i
),
#'label': '{} [{}] ({})'.format(
# event,
# ', '.join(path),
# i
#), #node + '-' + event,
'color': color_map(node), # Set edge color
}
)
else:
# Normal edges
edges.append(trans)
)
# Get & make all needed edges ##############################################
......@@ -208,7 +207,7 @@ def build_graph(solution, steps, transitions):
all_transitions = \
(transitions[step_event] for step_event in it.chain(*steps))
transitions_ori_ext = \
(tuple((ori, ext)) for ori, ext, _ in it.chain(*all_transitions))
((ori, ext) for ori, ext, _ in it.chain(*all_transitions))
except KeyError:
LOGGER.error("/!\One event is not in the given model file... Please check it.")
raise
......
......@@ -230,13 +230,13 @@ def get_places_from_condition(condition):
# symb_tab = tvi.tab_symb
# cond_sexpr = compile_cond(condition, symb_tab, err)
# inhibitors_nodes = set()
# possible_paths = rec(cond_sexpr, inhibitors_nodes)
# possible_paths = decompile_condition(cond_sexpr, inhibitors_nodes)
# return set(it.chain(*possible_paths))
# Replace parentheses first to make spaces in the string
# As operators are followed or preceded by parentheses, we can detect them
# without false positives (operator string inside an entity name)
replacement = ["(", ")", " and ", " or ", " not "]
replacement = ("(", ")", " and ", " or ", " not ")
for operator in replacement:
condition = condition.replace(operator, " ")
......@@ -290,17 +290,13 @@ def parse_event(event):
"Your expression type is not yet supported..."
)
# def filterSigExpression(listOfExpr):
# return [filterSigExpression(expr) for expr in listOfExpr]
LOGGER.debug("parse_event: %s", event)
# Error Reporter
err = Reporter()
tvi = TableVisitor(err)
symb_tab = tvi.tab_symb
reporter = Reporter()
tvi = TableVisitor(reporter)
# Get tree object from event string
event_sexpr = compile_event(event, symb_tab, True, err)[0]
event_sexpr = compile_event(event, tvi.tab_symb, True, reporter)[0]
# Filter when events
g = (filterSigExpression(expr) for expr in treeToExprDefaultsList(event_sexpr))
......@@ -329,19 +325,18 @@ def parse_condition(condition, all_nodes, inhibitors_nodes):
LOGGER.debug("parse_condition: %s", condition)
# Error Reporter
err = Reporter()
tvi = TableVisitor(err)
reporter = Reporter()
tvi = TableVisitor(reporter)
# Link the lexer to the model allows to avoid error in Reporter
# like: "-> dec -> Undeclared event or state"
# In practice this is time consuming and useless for what we want to do
# parser = MakeModelFromXmlFile(BIO_MOLDELS_DIR +
# "Whole NCI-PID database translated into CADBIOM formalism(and).bcx")
# parser.model.accept(tvi)
symb_tab = tvi.tab_symb
# Get tree object from condition string
cond_sexpr = compile_cond(condition, symb_tab, err)
cond_sexpr = compile_cond(condition, tvi.tab_symb, reporter)
# Get all possible paths from the condition
possible_paths = rec(cond_sexpr, inhibitors_nodes)
possible_paths = decompile_condition(cond_sexpr, inhibitors_nodes)
# Prune possible paths according to:
# - Inhibitor nodes that must be removed because they will never
......@@ -379,34 +374,7 @@ def parse_condition(condition, all_nodes, inhibitors_nodes):
return valid_paths
from cadbiom.models.guard_transitions.analyser.ana_visitors import SigExpIdCollectVisitor
# condition expressions contains only node ident
icv = SigExpIdCollectVisitor()
lst1 = cond_sexpr.accept(icv)
print(cond_sexpr)
print(type(cond_sexpr))
print(dir(cond_sexpr))
print("LISTE", lst1)
# <class 'cadbiom.models.biosignal.sig_expr.SigSyncBinExpr'>
# 'accept', 'get_signals', 'get_ultimate_signals', 'is_bot', 'is_clock',
# 'is_const', 'is_const_false', 'is_ident', 'left_h', 'operator', 'right_h', 'test_equal']
print(cond_sexpr.get_signals())
# print(cond_sexpr.get_ultimate_signals())
print("LEFT", cond_sexpr.left_h)
print("OPERATOR", cond_sexpr.operator)
print("RIGHT", cond_sexpr.right_h)
# ret = treeToTab(cond_sexpr)
# [set([('((formule', True)])]
# print("treeToTab", ret)
# print(type(ret))
# print(dir(ret))
def rec(tree, inhibitors_nodes):
def decompile_condition(tree, inhibitors_nodes):
"""Recursive function to decompile conditions
:param tree:
......@@ -423,26 +391,34 @@ def rec(tree, inhibitors_nodes):
('C', 'v', ('D', '^', 'E'))
)
))
"""
# print("TREE", tree, type(tree), dir(tree))
:param inhibitors_nodes: Set of inhibitors
:type tree: <expression>
:type inhibitors_nodes: <set>
:return: List of valid paths composed of entities (except inhibitors).
Inhibitors are added to `inhibitors_nodes`.
"""
# print("TREE", tree, type(tree), dir(tree))
if isinstance(tree, str): # terminal node
path = [tree]
solutions = [path]
return solutions
if isinstance(tree, SigNotExpr):
# tree.operand: the entity, type: SigIdentExpr
LOGGER.debug("NOT OPERAND: %s, %s", tree.operand, type(tree.operand))
#LOGGER.debug("NOT OPERAND: %s, %s", tree.operand, type(tree.operand))
try:
current_inhibitors = get_places_from_condition(tree.operand.__str__())
current_inhibitors = get_places_from_condition(str(tree.operand))
inhibitors_nodes.update(current_inhibitors)
LOGGER.debug("INHIBITORS found: %s", current_inhibitors)
#LOGGER.debug("INHIBITORS found: %s", current_inhibitors)
# SigIdentExpr if name attr
path = [tree.operand.name]
solutions = [path]
return solutions
except AttributeError:
# Capture operands without "name" attribute (expression other than SigIdentExpr)
tree = tree.operand
if isinstance(tree, SigIdentExpr):
......@@ -450,28 +426,17 @@ def rec(tree, inhibitors_nodes):
solutions = [path]
return solutions
lch = tree.left_h
# Bin expression or similar (2 expressions linked with a logical operator)
op = tree.operator
rch = tree.right_h
# print('OZCJSH:', lch, op, rch, sep='\t\t')
lpaths = rec(lch, inhibitors_nodes)
rpaths = rec(rch, inhibitors_nodes)
# print('VFUENK:', lpaths, rpaths)
lpaths = decompile_condition(tree.left_h, inhibitors_nodes)
rpaths = decompile_condition(tree.right_h, inhibitors_nodes)
if op == 'or': # or
# ret = [*lpaths, *rpaths]
ret = list(it.chain(lpaths, rpaths))
# print('RET:', ret)
return ret
else: # and
assert op == 'and'
# print(list(it.product(lpaths, rpaths)))
# raw_input('test')
ret = list(l + r for l, r in it.product(lpaths, rpaths))
# print('RET:', ret)
return ret
return list(it.chain(lpaths, rpaths))
# and
assert op == 'and'
return list(l + r for l, r in it.product(lpaths, rpaths))
################################################################################
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment