Module spatial.ltlf2dfa_nx
Expand source code
import re
import networkx as nx
from ltlf2dfa.base import MonaProgram
from ltlf2dfa.ltlf2dfa import invoke_mona, createMonafile
from ltlf2dfa.parser.ltlf import LTLfParser
# Dump a value from a file based on a regex passed in.
def get_value(text, regex, value_type=str):
pattern = re.compile(regex, re.MULTILINE)
results = pattern.search(text)
if results:
return value_type(results.group(1))
else:
print("Could not find the value {}, in the text provided".format(regex))
return value_type(0.0)
class LTLf2nxParser:
def __init__(self):
self.parser = LTLfParser()
self.formula = None
def parse_formula(self, formula_str):
self.formula = self.parser(formula_str)
def to_dot(self):
if self.formula is None:
print('<LTLf2ndParser.to_dot()> No formula parsed. Please parse a formula first using parse_formula(str)!')
return None
return self.formula.to_dfa()
def to_mona_output(self):
if self.formula is None:
print('<LTLf2ndParser.to_mona_output()> No formula parsed. Please parse a formula first using parse_formula(str)!')
return None
mona_p_string = MonaProgram(self.formula).mona_program()
createMonafile(mona_p_string)
mona = invoke_mona()
return mona
def to_nxgraph(self, name='MONA_DFA'):
if self.formula is None:
print('<LTLf2ndParser.to_nxgraph()> No formula parsed. Please parse a formula first using parse_formula(str)!')
return None
mona_output = self.to_mona_output()
g = nx.DiGraph()
g.graph['name'] = name
# if formula is unsatisfiable
if "Formula is unsatisfiable" in mona_output:
print('<LTLf2ndParser.to_nxgraph()> Formula is unsatisfiable, DFA not constructed!')
return None
if "DFA for formula with free variables:" not in mona_output:
print('<LTLf2ndParser.to_nxgraph()> an unexpected error occurred. Is MONA properly installed?')
return None
# atomic propositions
variables = get_value(mona_output, r'.*DFA for formula with free variables:[\s]*(.*?)\n.*', str)
g.graph['ap'] = variables.lower().split()
# accepting states
accepting_states = get_value(mona_output, r".*Accepting states:[\s]*(.*?)\n.*", str)
accepting_states = [
str(x.strip()) for x in accepting_states.split() if len(x.strip()) > 0
]
g.graph['acc'] = accepting_states
# edges and states
for line in mona_output.splitlines():
if line.startswith("State "):
orig_state = get_value(line, r".*State[\s]*(\d+):\s.*", str)
dest_state = get_value(line, r".*state[\s]*(\d+)[\s]*.*", str)
guard = get_value(line, r".*:[\s](.*?)[\s]->.*", str)
if g.has_edge(orig_state, dest_state):
g.edges[orig_state, dest_state]['guard'].append(guard)
else:
g.add_edge(orig_state, dest_state, guard=[guard])
# remove the don't care state 0
assert g.has_edge('0', '1')
assert len(list(g.successors('0'))) == 1
assert len(g.edges['0', '1']['guard']) == 1
assert all(c == 'X' for c in g.edges['0', '1']['guard'][0])
g.remove_node('0')
# initial state
g.graph['init'] = '1'
return g
Functions
def get_value(text, regex, value_type=builtins.str)
-
Expand source code
def get_value(text, regex, value_type=str): pattern = re.compile(regex, re.MULTILINE) results = pattern.search(text) if results: return value_type(results.group(1)) else: print("Could not find the value {}, in the text provided".format(regex)) return value_type(0.0)
Classes
class LTLf2nxParser
-
Expand source code
class LTLf2nxParser: def __init__(self): self.parser = LTLfParser() self.formula = None def parse_formula(self, formula_str): self.formula = self.parser(formula_str) def to_dot(self): if self.formula is None: print('<LTLf2ndParser.to_dot()> No formula parsed. Please parse a formula first using parse_formula(str)!') return None return self.formula.to_dfa() def to_mona_output(self): if self.formula is None: print('<LTLf2ndParser.to_mona_output()> No formula parsed. Please parse a formula first using parse_formula(str)!') return None mona_p_string = MonaProgram(self.formula).mona_program() createMonafile(mona_p_string) mona = invoke_mona() return mona def to_nxgraph(self, name='MONA_DFA'): if self.formula is None: print('<LTLf2ndParser.to_nxgraph()> No formula parsed. Please parse a formula first using parse_formula(str)!') return None mona_output = self.to_mona_output() g = nx.DiGraph() g.graph['name'] = name # if formula is unsatisfiable if "Formula is unsatisfiable" in mona_output: print('<LTLf2ndParser.to_nxgraph()> Formula is unsatisfiable, DFA not constructed!') return None if "DFA for formula with free variables:" not in mona_output: print('<LTLf2ndParser.to_nxgraph()> an unexpected error occurred. Is MONA properly installed?') return None # atomic propositions variables = get_value(mona_output, r'.*DFA for formula with free variables:[\s]*(.*?)\n.*', str) g.graph['ap'] = variables.lower().split() # accepting states accepting_states = get_value(mona_output, r".*Accepting states:[\s]*(.*?)\n.*", str) accepting_states = [ str(x.strip()) for x in accepting_states.split() if len(x.strip()) > 0 ] g.graph['acc'] = accepting_states # edges and states for line in mona_output.splitlines(): if line.startswith("State "): orig_state = get_value(line, r".*State[\s]*(\d+):\s.*", str) dest_state = get_value(line, r".*state[\s]*(\d+)[\s]*.*", str) guard = get_value(line, r".*:[\s](.*?)[\s]->.*", str) if g.has_edge(orig_state, dest_state): g.edges[orig_state, dest_state]['guard'].append(guard) else: g.add_edge(orig_state, dest_state, guard=[guard]) # remove the don't care state 0 assert g.has_edge('0', '1') assert len(list(g.successors('0'))) == 1 assert len(g.edges['0', '1']['guard']) == 1 assert all(c == 'X' for c in g.edges['0', '1']['guard'][0]) g.remove_node('0') # initial state g.graph['init'] = '1' return g
Methods
def parse_formula(self, formula_str)
-
Expand source code
def parse_formula(self, formula_str): self.formula = self.parser(formula_str)
def to_dot(self)
-
Expand source code
def to_dot(self): if self.formula is None: print('<LTLf2ndParser.to_dot()> No formula parsed. Please parse a formula first using parse_formula(str)!') return None return self.formula.to_dfa()
def to_mona_output(self)
-
Expand source code
def to_mona_output(self): if self.formula is None: print('<LTLf2ndParser.to_mona_output()> No formula parsed. Please parse a formula first using parse_formula(str)!') return None mona_p_string = MonaProgram(self.formula).mona_program() createMonafile(mona_p_string) mona = invoke_mona() return mona
def to_nxgraph(self, name='MONA_DFA')
-
Expand source code
def to_nxgraph(self, name='MONA_DFA'): if self.formula is None: print('<LTLf2ndParser.to_nxgraph()> No formula parsed. Please parse a formula first using parse_formula(str)!') return None mona_output = self.to_mona_output() g = nx.DiGraph() g.graph['name'] = name # if formula is unsatisfiable if "Formula is unsatisfiable" in mona_output: print('<LTLf2ndParser.to_nxgraph()> Formula is unsatisfiable, DFA not constructed!') return None if "DFA for formula with free variables:" not in mona_output: print('<LTLf2ndParser.to_nxgraph()> an unexpected error occurred. Is MONA properly installed?') return None # atomic propositions variables = get_value(mona_output, r'.*DFA for formula with free variables:[\s]*(.*?)\n.*', str) g.graph['ap'] = variables.lower().split() # accepting states accepting_states = get_value(mona_output, r".*Accepting states:[\s]*(.*?)\n.*", str) accepting_states = [ str(x.strip()) for x in accepting_states.split() if len(x.strip()) > 0 ] g.graph['acc'] = accepting_states # edges and states for line in mona_output.splitlines(): if line.startswith("State "): orig_state = get_value(line, r".*State[\s]*(\d+):\s.*", str) dest_state = get_value(line, r".*state[\s]*(\d+)[\s]*.*", str) guard = get_value(line, r".*:[\s](.*?)[\s]->.*", str) if g.has_edge(orig_state, dest_state): g.edges[orig_state, dest_state]['guard'].append(guard) else: g.add_edge(orig_state, dest_state, guard=[guard]) # remove the don't care state 0 assert g.has_edge('0', '1') assert len(list(g.successors('0'))) == 1 assert len(g.edges['0', '1']['guard']) == 1 assert all(c == 'X' for c in g.edges['0', '1']['guard'][0]) g.remove_node('0') # initial state g.graph['init'] = '1' return g