def test_loop_path(): a = Automaton() a.addTransition(0, 0, ord('a')) assert not a.findPath() a.setAccepting(0) assert [ord('a')] == a.findPath()
def test_createFromLtlFormula(env: Env): ltl = LTL.not_(LTL.globally(LTL.future(LTL.var("p")))) automaton = env.automatonService.createFromLtl_formula(ltl) reference = Automaton() reference.addTransition(0, 0, LTL.t()) notP = LTL.not_(LTL.var("p")) reference.addTransition(0, 1, notP) reference.addTransition(1, 1, notP) reference.setAccepting(1) reference.initialState = 0 assert reference == automaton
def saveAsDot(self, graph: Automaton, file_str: str) -> None: with open(file_str, 'w') as writer: print("digraph G {", file=writer) print("\trankdir = LR;", file=writer) for k, v in graph.automaton.items(): nodeId = k succesors = v shape = "" if graph.isAccepting(nodeId): shape = "doublecircle" else: shape = "circle" print("\t" + L.PREFIX + str(nodeId) + "[shape=\"" + shape + "\"];", file=writer) for k, v in succesors.items(): symbol = k next_ = v for nextId in next_: print("\t" + L.PREFIX + str(nodeId) + " -> " + L.PREFIX + str(nextId) + "[label=\"" + str(symbol) + "\"]", file=writer) print("}", file=writer)
def map_(self, input_: Automaton, mapper: types.FunctionType) -> Automaton: output_ = Automaton() for nodeId, successors in input_.automaton.items(): for a, v in successors.items(): b = mapper(a) for nextId in v: output_.addTransition(nodeId, nextId, b) for nodeId in input_.acceptingSet: output_.setAccepting(nodeId) output_.initialState = input_.initialState return output_
def test_simpleIntersectionTest(env: Env): log.info("intersection test") an = 2 bn = 4 a = Automaton() b = Automaton() a.addTransition(0, 1, 0) a.addTransition(1, 0, 1) curr = 0 for i in range(bn - 1): b.addTransition(i, i + 1, curr) curr = 1 - curr b.addTransition(3, 0, 1) a.setAccepting(0) b.setAccepting(1) c = env.automatonService.intersect(a, b, MyIntersector()) path = c.findPath() ref = [] curr = 0 for i in range(len(path)): ref.append(curr) curr = 1 - curr assert path == ref
def test_tailed_path(): log.info('lasso test') n = 10 a = Automaton() for i in range(n - 1): a.addTransition(i, i + 1, i) a.addTransition(n - 1, n / 2, n - 1) a.setAccepting(n / 2 - 1) assert not a.findPath() a.setAccepting(n / 2 + 1) act = a.findPath() assert list(range(n)) == act
def createFromLtl_str(self, ltl: str) -> Automaton: states = self.createStateListFromLtl(ltl) ids = itertools.count() idMap = defaultdict(lambda: next(ids)) automaton = Automaton() for state in states: nodeId = idMap[state.name] if self.isAcceptance(state.name): automaton.setAccepting(nodeId) if self.isInit(state.name): automaton.initialState = nodeId for transition in state.transitions: nextId = idMap[transition.stateName] formula = transition.expression automaton.addTransition(nodeId, nextId, formula) if self.isAcceptance(transition.stateName): automaton.setAccepting(nextId) if self.isInit(transition.stateName): automaton.initialState = nextId for nodeId in automaton.nodes: if len(automaton.get(nodeId)) == 0: automaton.addTransition(nodeId, nodeId, LTL.t()) return automaton
def intersect(self, a: Automaton, b: Automaton, intersector) -> Automaton: c = Automaton() tr = dict() # Build all transitions for i, iState in a.automaton.items(): for j, jState in b.automaton.items(): for iSymbol in iState.keys(): for jSymbol in jState.keys(): t = intersector.intersect(iSymbol, jSymbol) if t is None: continue for is_ in iState.get(iSymbol): for js in jState.get(jSymbol): c.addTransition( self.convert(i, j, 0, tr), self.convert(is_, js, 1 if a.isAccepting(i) else 0, tr), t) c.addTransition( self.convert(i, j, 1, tr), self.convert(is_, js, 0 if a.isAccepting(j) else 1, tr), t) # Accepting set of the new automaton for accB in b.acceptingSet: for i in a.automaton.keys(): c.setAccepting(self.convert(i, accB, 1, tr)) c.initialState = self.convert(a.initialState, b.initialState, 0, tr) return c
def createFromDiagram(self, diagram) -> Automaton: widgetMap = {w['id']: w for w in diagram.widget} successors = dict() for widget in diagram.widget: if widget['type'] == L.L_WIDGET_STATE: if not hasattr(widget.attributes, 'incoming'): continue for incoming in widget.attributes.incoming: prev = widgetMap.get(incoming['id']) if prev['type'] == L.L_WIDGET_TRANSITION: successors.update({incoming['id']: widget['id']}) else: raise IllegalStateException('IllegalStateException') automaton = Automaton() ids = itertools.count(10000) initId = None for widget in diagram.widget: if widget['type'] == L.L_WIDGET_STATE: stateNode = int(widget['id']) if State.INITIAL == int(widget.attributes.type.cdata): if initId is None: initId = next(ids) automaton.initialState = initId stateEdge = self.createFormulaFromState(widget) automaton.addTransition(initId, stateNode, stateEdge) if not hasattr(widget.attributes, 'outgoing'): continue for outgoing in widget.attributes.outgoing: next_ = widgetMap.get(outgoing['id']) if next_['type'] == L.L_WIDGET_TRANSITION: # event eventEdge = self.createFormulaFromEvent( next_.attributes.event) eventNodeId = next(ids) automaton.addTransition(stateNode, eventNodeId, eventEdge) lastNodeId = eventNodeId # actions if hasattr(next_.attributes, 'action'): for action in next_.attributes.action: actionEdge = self.createFormulaFromActions_action( action) actionNodeId = next(ids) automaton.addTransition( lastNodeId, actionNodeId, actionEdge) lastNodeId = actionNodeId # next state successorId = successors.get(outgoing['id']) nextState = widgetMap.get(successorId) nextNode = int(nextState['id']) nextEdge = self.createFormulaFromState(nextState) automaton.addTransition(lastNodeId, nextNode, nextEdge) else: raise IllegalStateException('IllegalStateException2') for nodeId in automaton.nodes: automaton.setAccepting(nodeId) if len(automaton.get(nodeId)) == 0: automaton.addTransition(nodeId, nodeId, LTL.t()) return automaton