-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Automaton __iter__ for enumerating accepted language? #79
Comments
@caleb531 for DFA/NFAs, I think there are algorithms for this based on treating the transitions as a graph and doing graph search (or similar algorithms). I'll have to look through some books to see if they explicitly describe something like this, but here's a stackoverflow post describing something similar: As for the other automation, I'm not sure about PDAs, but for TMs even checking whether a TM accepts any string (let alone enumeration of all of them) is undecidable (equivalent to the halting problem). EDIT: Now that I think about it, this problem boils down to traversing edges of a graph in lexicographic order and outputting the string corresponding to the current path. Then on the next yield statement, compute the next such string (like BFS but no need for a visited set). |
I think I have some code for this already written. I'll take a look tomorrow. |
Decided to look at it before I go to bed. def count_words_of_length(self, k):
"""
Counts the number of words of length k in the language represented by the DFA
"""
return self._count_words_of_length(self.initial_state, k)
def _count_words_of_length(self, state, k):
"""
Counts words of length k assuming state is the initial state
"""
if k == 0:
return 1 if state in self.final_states else 0
return sum(self._count_words_of_length(self.transitions[state][symbol], k-1) for symbol in self.input_symbols)
def words_of_length(self, k):
"""
Generates all words of length k in the language represented by the DFA
"""
for word in self._words_of_length(self.initial_state, k):
yield word
def _words_of_length(self, state, k):
"""
Generator for accepted words of length k assuming state is the initial state
"""
if k == 0:
if state in self.final_states:
yield ''
return
for symbol in self.input_symbols:
for word in self._words_of_length(self.transitions[state][symbol], k-1):
yield symbol + word For Should we implement |
@Tagl Great that you already have a starting implementation for this! The only issue we might run into is efficiency, since recursion in Python is very slow. Since this algorithm needs to store the results anyway, do you think that this could be done iteratively with a dictionary of results? I think doing the len as the cardinality of the language is a cool idea. I think it may be better to raise a specialized exception in that case. What do you think @caleb531 ? |
I also dig the idea of using |
Yes, converting to doing it iteratively is no problem at all since the transitions if the DP are simple. It was one of the optimizations I had in mind. |
Thoughts on adding |
@Tagl I think it would make more sense for |
I personally prefer doing |
@Tagl I agree, I think that |
@Tagl Oh, I see now. Because this whole conversation is about |
@eliotwrobson @Tagl But it will be important that |
Please take a look at the implementation. Changed to iterative, calculates the entire level for length |
DPDA we should be able to do. Non-determinism makes things a bit trickier. I can implement the same kind of logic to NFA but the generation will essentially involve partial or full tracking of powersets like |
@Tagl If the NFA string generation involves tracking powersets, I'm not really sure that it's worth the effort to do for NFAs directly, if users can just determinize and use the existing DFA functions. It seems overall pretty impractical. |
@eliotwrobson So with all the recent discussion around automata ultimately being representations of finite languages, it got me thinking:
What if we implemented an
__iter__
method that produced each string in that automaton's accepted language? My thought it we could generate one string at a time viayield
, and leave it up to the user if they want to convert the automaton to alist
orset
. Ideally, we could start with DFAs/NFAs, and then explore if a similar algorithm is possible with PDAs and TMs.How difficult do you think this would be to implement from an algorithmic perspective? Initially, my thought is generating all permutations of the machine's input symbols, then filter that set down to only those accepted via
accepts_input
.Although the number of iterations could be enormous, so maybe we could filter that set further by analyzing transition symbols from the initial state (first character) and final states (possible last characters). But I'm curious if there is an approach that isn't so brute-force.
The text was updated successfully, but these errors were encountered: