Skip to content

Commit

Permalink
Merge 13aaf95 into b36d726
Browse files Browse the repository at this point in the history
  • Loading branch information
khoda81 committed Jun 6, 2023
2 parents b36d726 + 13aaf95 commit 42950d0
Show file tree
Hide file tree
Showing 13 changed files with 570 additions and 288 deletions.
23 changes: 0 additions & 23 deletions .coveragerc

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
with:
python-version: "3.11"

- name: Install graphviz
run: sudo apt-get install graphviz
- name: Setup Graphviz
uses: ts-graphviz/setup-graphviz@v1

- name: Install dependencies
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install graphviz
run: sudo apt-get install graphviz
- name: Setup Graphviz
uses: ts-graphviz/setup-graphviz@v1

- name: Install dependencies
run: |
Expand Down
72 changes: 33 additions & 39 deletions automata/fa/dfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@
Iterable,
Iterator,
List,
Literal,
Mapping,
Optional,
Set,
Tuple,
Type,
TypeVar,
cast,
)

import networkx as nx
from pydot import Dot, Edge, Node
from typing_extensions import Self

import automata.base.exceptions as exceptions
Expand Down Expand Up @@ -332,7 +329,7 @@ def minify(self, retain_names: bool = False) -> Self:
Create a minimal DFA which accepts the same inputs as this DFA.
First, non-reachable states are removed.
Then, similiar states are merged using Hopcroft's Algorithm.
Then, similar states are merged using Hopcroft's Algorithm.
retain_names: If True, merged states retain names.
If False, new states will be named 0, ..., n-1.
"""
Expand Down Expand Up @@ -807,7 +804,7 @@ def predecessors(
*,
strict: bool = True,
key: Optional[Callable[[Any], Any]] = None,
) -> Iterable[str]:
) -> Generator[str, None, None]:
"""
Generates all strings that come before the input string
in lexicographical order.
Expand Down Expand Up @@ -845,7 +842,7 @@ def successors(
strict: bool = True,
key: Optional[Callable[[Any], Any]] = None,
reverse: bool = False,
) -> Iterable[str]:
) -> Generator[str, None, None]:
"""
Generates all strings that come after the input string in
lexicographical order. Passing in None will generate all words. If
Expand Down Expand Up @@ -906,7 +903,7 @@ def successors(
)
# Traverse to child if candidate is viable
if candidate_state in coaccessible_nodes:
state_stack.append(cast(str, candidate_state))
state_stack.append(candidate_state)
char_stack.append(cast(str, candidate))
candidate = first_symbol
else:
Expand Down Expand Up @@ -1553,38 +1550,35 @@ def get_name_original(states: FrozenSet[DFAStateT]) -> DFAStateT:
final_states=dfa_final_states,
)

def show_diagram(self, path=None):
def iter_transitions(
self,
) -> Generator[Tuple[DFAStateT, DFAStateT, str], None, None]:
return (
(from_, to_, symbol)
for from_, lookup in self.transitions.items()
for symbol, to_ in lookup.items()
)

def _get_input_path(
self, input_str
) -> Tuple[List[Tuple[DFAStateT, DFAStateT, DFASymbolT]], bool]:
"""
Creates the graph associated with this DFA
Calculate the path taken by input.
Args:
input_str (str): The input string to run on the DFA.
Returns:
tuple[list[tuple[DFAStateT, DFAStateT, DFASymbolT], bool]]: A list
of all transitions taken in each step and a boolean indicating
whether the DFA accepted the input.
"""
# Nodes are set of states

graph = Dot(graph_type="digraph", rankdir="LR")
nodes = {}
for state in self.states:
if state == self.initial_state:
# color start state with green
if state in self.final_states:
initial_state_node = Node(
state, style="filled", peripheries=2, fillcolor="#66cc33"
)
else:
initial_state_node = Node(
state, style="filled", fillcolor="#66cc33"
)
nodes[state] = initial_state_node
graph.add_node(initial_state_node)
else:
if state in self.final_states:
state_node = Node(state, peripheries=2)
else:
state_node = Node(state)
nodes[state] = state_node
graph.add_node(state_node)
# adding edges
for from_state, lookup in self.transitions.items():
for to_label, to_state in lookup.items():
graph.add_edge(Edge(nodes[from_state], nodes[to_state], label=to_label))
if path:
graph.write_png(path)
return graph
state_history = list(self.read_input_stepwise(input_str, ignore_rejection=True))
path = list(zip(state_history, state_history[1:], input_str))

last_state = state_history[-1] if state_history else self.initial_state
accepted = last_state in self.final_states

return path, accepted
Loading

0 comments on commit 42950d0

Please sign in to comment.