caleb531 / automata Goto Github PK
View Code? Open in Web Editor NEWA Python library for simulating finite automata, pushdown automata, and Turing machines
Home Page: https://caleb531.github.io/automata/
License: MIT License
A Python library for simulating finite automata, pushdown automata, and Turing machines
Home Page: https://caleb531.github.io/automata/
License: MIT License
When transforming the automata to code, the value I get back is an error.
A symbol transition is adjacent to a lambda transition for this DPDA
Here is the code at paste.org
https://www.paste.org/118004
(something to clarify:
In this case, g,-/- is the same as g,2/_
Why this happend? i'm very sure that the automata is correct
Hi,
First of all congratulations for the library. I didn't find a way how to insert same symbol to a different state. Let's assume this automata for example:
So in this case with the state is in q0
, when receiving 1
could be at q0
or q1
. I think that the data structure to declare transitions is not ready for this use case because a dict in python can not have same key with different values. I guess the data structure should change to a list more or less like this:
transitions={
'q0': [ {'1': 'q0'}, {'1': 'q1'}, {'2': 'q1'} ],
'q1': [ {'2': 'q0'} ]
}
Thanks
In looking at the current regex parser, it seems like it could be made significantly faster with a more robust implementation (i.e. use specialized classes to reduce overhead when applying the NFA creation operations). We're working on a fast regex parser for our course (since we need to parse large regexes). Would there be interest in adapting a version for integration with this library?
DFAs have show diagram.
Expected NFAs an other machinces to have similar funtionality.
Right now the input symbols has to be a proper subset of the tape symbols (link below). But in our case we would like to have the input equal the allowed tape symbols.
This worked for us locally
def _read_input_symbol_subset(self):
if not (self.input_symbols <= self.tape_symbols):
raise exceptions.MissingSymbolError(
'The set of tape symbols is missing symbols from the input '
'symbol set ({})'.format(
self.tape_symbols - self.input_symbols))
https://github.com/caleb531/automata/blob/main/automata/tm/tm.py#L14
@caleb531 I don't if this is a real issue.
@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 via yield
, and leave it up to the user if they want to convert the automaton to a list
or set
. 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.
I found the following bug:
nfa._add_new_state introduces integers into the set of states.
Current code is:
def _add_new_state(state_set, start=0):
"""Adds new state to the state set and returns it"""
new_state = start
while new_state in state_set:
new_state += 1
state_set.add(new_state)
return new_state
which could be fixed, for example, in this way:
def _add_new_state(state_set, start=0):
"""Adds new state to the state set and returns it"""
new_state = start
while str(new_state) in state_set:
new_state += 1
state_set.add(str(new_state))
return str(new_state)
EDIT: this bugfix actually runs into other problems later - this is just an idea
This can lead to logic problems later. For example the following code fails:
from automata.fa.dfa import DFA
from automata.fa.nfa import NFA
A = NFA(
states={'0', '1'},
input_symbols={'0'},
transitions={'0': {'0': {'1'}}, '1': {'0': {'1'}}},
initial_state='0',
final_states={'1'}
)
print(A.reverse().states)
B = DFA.from_nfa(A.reverse())
assert(A.accepts_input('00')==B.accepts_input('00'))
I am very new to automata and have been learning a lot recently having this library has made things so much more fun and interactive for me, so I want to say thanks for all the hard work you all have put into this library.
I am trying to implement an NPDA, and I have struggled to configure the transitions properly. I have reviewed the palindrome example you all have on the doc page. Still, because it was not something I had initially visualized as a state diagram, I am having trouble connecting things in such a way that I can implement my own. If someone could maybe take a few minutes to explain how this simple PDA would be implemented, that would be very helpful to me, and I am sure I could then understand them enough to start doing my own properly. The PDA is a simple a^nb^n, n >=0.
Hello,
The documentation says "retain_names=False" is default,
but in the code, it's actually "retain_names=True".
@Tagl I am getting pretty close to releasing v7 (hooray!). However, I noticed that there was a slight drop in code coverage with the introduction of DFA.random_word()
. Since you implemented that method, I wanted to ask for your help in covering that additional case.
From what I can tell, the outer loop never runs for more than one iteration (either that, or it never completes without a break). In your tests, you seem to be testing high-enough values of k
, so I suspect the real gap may be not testing random_word()
with a partial DFA (i.e. allow_partial=True
). But I could certainly be wrong. 😅
I would appreciate any help you can offer. Screenshots are provided below.
HTML coverage report (locally):
Coveralls Report (link)
Using the PDA library, I get a code error with reference to transitions. "The automaton entered a configuration for which no transition is defined (q0, a, 0)".
(Attached code in paste.org)
https://www.paste.org/117966
Image of the PDA I made at https://automatonsimulator.com
When I run pip install automata-lib==5.0.0
, I get the following error message:
ERROR: Could not find a version that satisfies the requirement automata-lib==5.0.0 (from versions: 5.0.0.macosx-10.15-x86_64, 1.0.0.post1, 1.0.0.post2, 1.0.0.post3, 1.0.0.post4, 2.0.0, 2.0.1, 2.1.0, 3.0.0, 3.1.0, 3.1.0.post1, 4.0.0, 4.0.0.post1)
ERROR: No matching distribution found for automata-lib==5.0.0
I was trying to optimize some code of mine using the library (billions of DFA operations) so I ran a profiler and saw a lot of time was spent doing unions, specifically in PartitionRefinement.refine, cross product graph creation and then what surprised me was the __init__
function. And half of the time was due to validation.
I think validation should be optional, so the user could pass in validate=False
as a keyword argument when the user is a 100% sure that the construction is valid.
Thoughts on this?
I propose adding the functionality to define transition rules which are a logical combination of the input symbols, like:
from automata.fa.dfa import DFA
dfa = DFA(
states={'q0', 'q1'},
input_symbols={'x', 'y'},
transitions={
'q0': {'x': 'q0', '!x': 'q1'}, # go to q1 if neg x
'q1': {'x & y': 'q0', 'y': 'q1'} # go to q1 if x and y
},
initial_state='q0',
final_states={'q1'}
)
print(dfa.read_input('!xy(x & y)')) # produces q0
One idea for implementation would be to use parser generator libraries such as the good old PLY or its new refreshed version, SLY.
@eliotwrobson Just opening an issue to follow up on our discussion about PDAStack
(and friends), and the best way to refactor that to be cleaner without compromising the behavior/efficiency.
For reference, here is a link to our original comment thread.
The __eq__
function in the DFA class uses the symmetric difference between both DFAs, which is an O(n^2) time algorithm (and requires creating an auxiliary DFA). The Hopcroft-Karp algorithm doesn't require creating the auxiliary data structures, but requires the use of a union find. I think it's possible to copy in the code from a generic Python Union-Find, but the networkx
package has an implementation. Is it too much to introduce this dependency? Any generic union find should work.
Hi im traying to build a program that let you introduce your own NFA and transform it to DFA.
I would like to recive some advice
So I would like to know what would be the best option for TRANSITIONS user input.
(In the case where the symbol is repeated)
I have someting like this but it doesn't work, cause how dicts works.
In a while:
transitions_aux ={
input('State?: '): { input('value: '): set(input('transitionState:').split()) },
}
transitions.update(transitions_aux)
Should the user be ask just for a string instead?
Sorry for bad english.
hey i ve getting this error while using "nfa.accepts_input(my_input_str)" in my project , i tried the same structure of the automata in a seperate file and it functionned properly , im wondering if anyone could guide me a little to figure out what to fix ( or at least the scenarios that may lead to this error thanks!
here's my project link
https://github.com/maryembenali/automata.git
automata.base.exceptions.InvalidStateError: end state q for transition on q0 is not valid
Hello,
Thank you for your work and very nice library.
If ever you get the time, would it be possible to implement the conversion NFA <-> Regular expression ?
The direction Regex -> NFA is easy, the other one more annoying. A good reference is "Introduction to the Theory of Computation" by Sisper, chapter 1, definition 1.64 for the concept of "generalised nondeterministic finite automaton" which is useful in the conversion NFA -> Regex.
Thank you very much again,
Tristan
@eliotwrobson I want to run something by you that I've been mulling over for the past week.
When you integrated networkx
into the library back in ed1cdff, you added logic to precompute+cache the lambda closures for an NFA (via self._lambda_closure_dict
). Previously, these lambda closures were (arguably excessively) computed on the fly when reading input via my NFA._get_lambda_closure
method.
Given the performance/efficiency consequences of my previous approach, I very much appreciate your contribution here (enough so that I am planning to expose this dictionary as part of the public API, as you may have noticed in my recent commits to develop
).
However, your changes do introduce an interesting dilemma. You see, before Automata v6 was released with your precomputed lambda closure logic, NFA instances could be mutated without consequence just like every other Automaton
instance in the library.
But now that lambda_closures
(a derived attribute, in database terms) is in the picture, the NFA instance could end up in a situation where the user updates states
, transitions
, and/or input_symbols
, leaving lambda_closures
stale.
As I see it, there are three solutions to this stale lambda_closures
situation if we want NFAs to remain fully mutable:
We watch for changes to states
, input_symbols
, and transitions
(which is a nested structure) and automatically recompute lambda_closures
when any of the aforementioned attributes change; this is the ideal solution, but not sure how feasible it is to implement
We require the user to explicitly recompute the lambda closures (via some public method) when they choose to mutate the NFA. This is not my favorite approach, as the precomputing of lambda closures is really an implementation detail the user should not be concerned with. But it would balance implementation simplicity with performance.
We revert to caching nothing and computing the lambda closures on the fly when reading input; naturally, this would re-introduce a significant performance consequence, especially if you want to read many input strings with the same NFA instance
Of course, if we make NFAs fully immutable, then this problem goes away, and we don't need to worry about recomputing lambda_closures
post-instantiation.
So far, my blurb above is focused primarily on NFAs, but I think it opens up a larger question about whether any automaton should be a mutable structure, or whether it should be immutable. My ultimate aim for this library is to have a consistent and friendly API that makes working with these data structures pleasant and practical. And right now, NFAs are inconsistent with the rest of the Automaton sub-types because NFAs have some additional internal state (i.e. lambda_closures
) which must be managed.
Therefore, I will sum up my musings with a few questions regarding your own use of this library:
@abhinavsinha-adrino @Tagl If you guys happen to have a moment, I would love any feedback you have as well. This library isn't any good if it doesn't serve real-world use cases for working with these machines.
Much thanks in advance,
Caleb
@abhinavsinha-adrino I'm starting to wonder if I misunderstood the purpose of GNFAs when I suggested that we subclass GNFA from NFA. Let me explain the context:
I was trying to write a test for GNFA just now to verify that GNFA.read_input_stepwise()
operates as expected. However, I was encountering one error after another in trying to accomplish this. I then realized that, because GNFAs can have non-state values (i.e. regex strings and None
) in the transition map, maybe it doesn't make sense to use methods like read_input_stepwise
on a GNFA.
This then made me wonder if it was a mistake to subclass GNFA
from NFA
, since it seems like there could be a whole bunch of methods (like read_input_stepwise
) that either would fail or just wouldn't make sense to have available on GNFA
.
What do you think? Given what you know about Automata theory and the purpose of GNFAs, would it make sense to have functional methods like GNFA.read_input_stepwise
? Would it make more sense semantically to subclass GNFA
from FA
instead of NFA
?
I would like to have operations like these implemented within the library. The most common operations used are probably:
Another useful operation would be checking for equivalence of two DFAs.
If an equivalence check is added should the eq method be overloaded with the equivalence check?
I'd like to open a discussion on what additional operations could be added to the library.
I have implementations for all the listed operations in mind and I have already written code for the first three so I'll gladly add these operations myself.
@caleb531 was poking around online and found this blog post talking about constructing NFAs that recognize words within a given edit distance of a target word, along with some other cool utilites: http://blog.notdot.net/2010/07/Damn-Cool-Algorithms-Levenshtein-Automata
I think it could potentially be easy to integrate some of these ideas as well, since the blog post provides worked out examples (that could be used as tests) and code implementing these in Python (that should be easy to adapt). What do you think?
EDIT:
After more googling I guess this is like a thing or something, because here's two more blog posts implementing faster algorithms (in Python!):
https://julesjacobs.com/2015/06/17/disqus-levenshtein-simple-and-fast.html
https://fulmicoton.com/posts/levenshtein/
Hi!
Would you consider implementing the Visual Automata wrapper directly into automata-lib and deprecating Visual Automata?
Is there a specific reason why quantifiers for regular expressions are not supported? (so things like a{2,10}
) If there is no specific reason, would you be open to a PR that implements it?
Also, what do you think of adding a special regex shuffle operator? This would be very handy to express languages like "all permutations of a,b,c". My proposal would be to use the ~
character and implement a separate parser for that
Creating this issue to look into the semantics of the allow_partial flag.
See: #125 for the motivation
Hello,
Thanks for your work on this library! I've been using it as part of the backend for a course I'm TAing. For our purposes, we're working on adding type hints (which can be checked with mypy) to the library. We think this makes the code more readable, and easier to tell what certain functions do. Would there be interest in including these changes in this project? I'd be happy to put up a pull request once we're done.
Best,
Eliot
@eliotwrobson Another thought for you:
Since I don't know when #129 is going to be finished, I was thinking: it might be nice to backport the black configuration out of your PR into a separate PR to be merged into develop
branch. Then I could commit to the feature branch in #129 and run black on the modified files so that they wouldn't conflict with your type hints branch anyway.
In other words, if we can add configuration for black to the develop
branch, and apply it to all Python files on develop
, and apply it to all files in the open PRs, then we're all on the same page, and we won't have to worry about formatting conflicts ever again. This would also enable us to re-add the CI job sooner.
Thoughts?
Is there a way to specify the empty string as part of regexes? For example, Python's built-in re.compile allows expressions like '()'
or '|'
, but the parser in this library throws an error on both.
from automata.fa.nfa import NFA
nfa = NFA(
states={0},
input_symbols={'0'},
transitions={0: {}},
initial_state=0,
final_states=set()
)
print(nfa.accepts_input(''))
I would expect this to print False
, because the NFA has no accepting states. Instead, it throws this error:
File "/usr/local/lib/python3.8/site-packages/automata/base/automaton.py", line 41, in accepts_input
self.read_input(input_str)
File "/usr/local/lib/python3.8/site-packages/automata/base/automaton.py", line 34, in read_input
for config in validation_generator:
File "/usr/local/lib/python3.8/site-packages/automata/fa/nfa.py", line 120, in read_input_stepwise
self._check_for_input_rejection(current_states)
File "/usr/local/lib/python3.8/site-packages/automata/fa/nfa.py", line 104, in _check_for_input_rejection
', '.join(current_states)))
TypeError: sequence item 0: expected str instance, int found
Would it be possible to replace ', '.join(current_states)
with ', '.join(str(state) for state in current_states)
, or something along those lines?
I'm using version 5.0.0.
I have a generated DFA that essentially models a room and 2 persons, 0 and 1. The states are labeled "L-XY" where L is the distance from the initial state, X is 0 or 1 depending whether person 0 is in the room, and Y same for person 1. The edges are labeled "xE" or "xL" depending on whether person x enters or leaves the room. When I minify this DFA, I get a one state DFA instead of a four state DFA (0 in the room or not, 1 in the room or not). Code included below.
=============================
from automata.fa.dfa import DFA
xstates = { "0-00", "1-01", "1-10", "2-00", "2-11", "2-00", "3-10", "3-01", "4-00", "errr" }
xinitial = "0-00"
xfinal = set()
xsymbols = { "0E", "0L", "1E", "1L" }
xtransitions = {
"0-00": { "1E": "1-01", "0E": "1-10", "0L": "errr", "1L": "errr" },
"1-01": { "1L": "2-00", "0E": "2-11", "1E": "errr", "0L": "errr" },
"1-10": { "0L": "2-00", "1E": "2-11", "0E": "errr", "1L": "errr" },
"2-00": { "1E": "1-01", "0E": "3-10", "1L": "errr", "0L": "errr" },
"2-11": { "1L": "3-10", "0L": "3-01", "1E": "errr", "0E": "errr" },
"2-00": { "0E": "1-10", "1E": "3-01", "0L": "errr", "1L": "errr" },
"3-10": { "1E": "2-11", "0L": "4-00", "1L": "errr", "0E": "errr" },
"3-01": { "0E": "2-11", "1L": "4-00", "0L": "errr", "1E": "errr" },
"4-00": { "0E": "3-10", "1E": "3-01", "0L": "errr", "1L": "errr" },
"errr": { "0E": "errr", "1E": "errr", "0L": "errr", "1L": "errr" }
}
dfa = DFA(
states=xstates,
input_symbols=xsymbols,
transitions=xtransitions,
initial_state=xinitial,
final_states=xfinal
)
m = dfa.minify()
assert len(m.states) == 4, len(m.states)
@eliotwrobson So you probably recall that I recently added an Automaton.attributes()
method to retrieve all the public (non-underscore-prefixed) attributes on an Automaton instance, inspired by @Tagl's recent PR. However, I find the current name a little ambiguous, since some members that are technically considered attributes are excluded from the resulting dict
.
Here are some alternative ideas I have, mostly based on the observation that every public Automaton attribute also appears to be an input parameter to its respective __init__
:
parameters
input_parameters
input_params
I'm also considering if this would be better as a @property
rather than a method. I like the brevity of omitting any verbiage, but on the flip side, want to property communicate that this method isn't an input parameter in itself.
Thoughts?
I have made a method to transform an ε-NFA to an NFA, or eliminating lambda/epsilon if you will.
Since this is a step in the process of transforming an ε-NFA to DFA, I thought it could be nice to include it in this project?
0 1 λ
→*q0 ∅ q1 q2
q1 {*q0,q2} q2 ∅
q2 ∅ ∅ ∅
transforms to:
0 1
→*q0 ∅ q1
q1 {*q0,q2} q2
q2 ∅ ∅
Thanks for the awesome library!
I think that there might be a bug for DFA.from_nfa
. When the initial state has epsilon transition, the initial states for the NFA do not include other DFA states that can be reached from the DFA initial state via epsilon transition.
Here is a script that I tested:
···
nfa = NFA(
states={'q0', 'q1', 'q2'},
input_symbols={'a', 'b'},
transitions={
'q0': {'': {'q2'}},
'q1': {'a': {'q1'}},
'q2': {'a': {'q1'}}
},
initial_state='q0',
final_states={'q1'}
)
print("NFA: {}".format(nfa.read_input('a')))
dfa = DFA.from_nfa(nfa) # returns an equivalent DFA
print("DFA: ")
print("Initial State: {}".format(dfa.initial_state))
print(dfa.read_input('a') )
···
And here is the output:
NFA: {'q1'}
DFA:
Initial State: {q0}
Traceback (most recent call last):
File "nfa.py", line 23, in <module>
print(dfa.read_input('a') )
File "/usr/local/lib/python3.6/site-packages/automata/base/automaton.py", line 34, in read_input
for config in validation_generator:
File "/usr/local/lib/python3.6/site-packages/automata/fa/dfa.py", line 105, in read_input_stepwise
self._check_for_input_rejection(current_state)
File "/usr/local/lib/python3.6/site-packages/automata/fa/dfa.py", line 89, in _check_for_input_rejection
current_state))
automata.base.exceptions.RejectionException: the DFA stopped on a non-final state ({})
When I studied Automata Theory (and in the literature), the transition function for a DFA could be partial, this is, that there could be some states which do not have an associated transition for a symbol in the alphabet.
In my particular case, I was trying to get this automata:
But, as I said, some states do not have an associated transition for a symbol (take for example state b). This, in principle, accomplishes the DFA restrictions since there is no state such that for a symbol in the alphabet there is more than one associated transition.
When trying to obtain the above DFA using the transition function:
{
'': {'a': 'a', 'b': 'b'},
'a': {'b': 'ab', 'a': 'aa'},
'b': {'b': 'bb'},
'aa': {'a': 'aa', 'b': 'ab'},
'bb': {'a': 'ba'},
'ab': {'b': 'bb'},
'ba': {'a': 'aa'}
}
I get an exception:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/guillermh/.local/lib/python3.9/site-packages/automata/fa/dfa.py", line 23, in __init__
self.validate()
File "/home/guillermh/.local/lib/python3.9/site-packages/automata/fa/dfa.py", line 67, in validate
self._validate_transitions(start_state, paths)
File "/home/guillermh/.local/lib/python3.9/site-packages/automata/fa/dfa.py", line 59, in _validate_transitions
self._validate_transition_missing_symbols(start_state, paths)
File "/home/guillermh/.local/lib/python3.9/site-packages/automata/fa/dfa.py", line 29, in _validate_transition_missing_symbols
raise exceptions.MissingSymbolError(
automata.base.exceptions.MissingSymbolError: state b is missing transitions for symbol a
I think there is a method _validate_transition_missing_symbols
in automata.fa.dfa
which is the culprit of this thing.
I would make a pull request but right now I haven't got the time to learn how to implement and run tests and testing code coverage (I'm pretty novice in contributing tasks).
But I opened this issue in order to notify about the possible misconception about the formalities of DFA.
Thank you beforehand!
My next focus was gonna be a little bit on DPDAs. I've started implementing enumeration and iteration.
Are there any specific operations that you're particularly interested in prioritizing?
Some of them may not have any known efficient algorithm (regularity of language) or may even be undecidable (although that's more common for the nondeterministic version).
@caleb531 @eliotwrobson
Some ideas:
So the API documentation reorg (#98 and #99) is complete—great! But as I look through the API documentation, I realize that there is a lot of text to sift through between each block of code.
@Tagl @eliotwrobson What do you think about adding an examples/
directory with Python files that demonstrate the code needed to perform the most common DFA/etc. operations. Since the API is so large at this point, we would probably need to be selective about what use cases we plan to demonstrate.
One option is that we could make each example built around a real-world use case. For example:
# examples/reading_input_from_cli.py
from automata.fa.dfa import DFA
# DFA which matches all binary strings ending in an odd number of '1's
my_dfa = DFA(
states={'q0', 'q1', 'q2'},
input_symbols={'0', '1'},
transitions={
'q0': {'0': 'q0', '1': 'q1'},
'q1': {'0': 'q0', '1': 'q2'},
'q2': {'0': 'q2', '1': 'q1'}
},
initial_state='q0',
final_states={'q1'}
)
try:
while True:
if my_dfa.accepts_input(input('Please enter your input: ')):
print('Accepted')
else:
print('Rejected')
except KeyboardInterrupt:
print('')
Another option is that we could make each example a sort of rapid-fire walkthrough of the different things you can do. For example:
# examples/dfa_reading_input.py
from automata.fa.dfa import DFA
# DFA which matches all binary strings ending in an odd number of '1's
my_dfa = DFA(
states={'q0', 'q1', 'q2'},
input_symbols={'0', '1'},
transitions={
'q0': {'0': 'q0', '1': 'q1'},
'q1': {'0': 'q0', '1': 'q2'},
'q2': {'0': 'q2', '1': 'q1'}
},
initial_state='q0',
final_states={'q1'}
)
my_dfa.read_input('001') # returns a final state (e.g. 'q1')
my_dfa.read_input('001!') # raises RejectionException
# loop over each state of the DFA as you read input
for state in my_dfa.read_input_stepwise('00111'):
print(state)
# etc.
We may also need to be careful of adding too many examples, such that it becomes an additional maintenance burden on top of the existing API documentation. But it might be helpful for beginners. I'm a bit ambivalent—what do you think?
@caleb531 I think by mistake I wrote NFA.to_regex()
but this function is not there, instead NFA.from_regex(regex)
is there. For converting NFA to regex, one has to convert NFA to GNFA and then GNFA to regex.
Very sorry for this.
I am new to contributing, so I ask beforehand this time.
I would like to have more visual representation of transitions. I have been working a lot with this library now, and I am wondering if some of these features should be implemented in the source code? I don't want to work on it if it is not of interest :)
DPDAs can accept when the stack is empty or a final state has been reached (assuming that all input has been read).
The related code is DPDA._check_for_input_rejection
which is basically this:
if current_state not in self.final_states and stack:
raise exceptions.RejectionException()
This leads to the problem that when the DPDA accepts via final state, it will also accept if the stack is empty after reading a given input, even when no final state has been reached.
I would prefer specifying whether a DPDA accepts either via empty stack or via final state.
(This can probably be deducted by looking at whether self.final_states
is empty but I'm not so sure about that.)
GNFA.to_regex seems to give wrong results sometimes. For example, the following code:
from automata.fa.dfa import DFA
from automata.fa.nfa import NFA
from automata.fa.gnfa import GNFA
nfa = NFA.from_regex('a*')
dfa = DFA.from_nfa(nfa)
gnfa = GNFA.from_dfa(dfa)
print(gnfa.to_regex())
prints a single-character string *
, which is not a valid regex.
if I in the code put to read '' in the stack, the input will replace what there is in te stack or the input will be on the top with no replacing of what it is in the stack?
@eliotwrobson Per your brief comment from #112:
Currently, only alphanumeric characters are supported in the regex parsing here (which I'm now realizing is kindof a breaking change from v6, whoops). But I think some way of adding escape characters could be useful to people. I think it's just a matter of reconfiguring the lexer to treat characters coming after a backslash as a literal. But I think it should definitely be in a separate PR.
I think it would be helpful to allow non-alphanumeric characters in a regex, such that you could create a regex for an email address, @username
, etc. This enhancement would imply that you can also escape symbols to be literal characters.
How to add user input to a dfa or nfa ?
Currently, the API documentation in the README is massive and monolithic. It potentially hides the presence of certain features because there is so much to scroll through, and it can make the documentation more overwhelming for newcomers. Sure, there's the Table of Contents, but it is not as easily accessible from any one section (i.e. scroll to the top of the page, then down a bit).
I'm thinking of moving all API documentation (including the TOC) to a new docs/
directory in this repository. It would still all be Markdown, just broken up across multiple files (mostly mapped to the current TOC links).
To ease access from one page to another, I'm thinking of including a link to the TOC at the top and bottom of every documentation page/file. We could also add Next/Prev links (on DFA docs: "Next Up: NFA class"), but this could become cumbersome to manage.
A prerequisite of this reorganization would be to close out all existing PRs that touch the README in any way. I'm creating this Issue to give you guys a heads-up of my intention, and also to solicit feedback.
Automata version: 5.0.0
Presently kleene_star() function adds two new states (new initial state and new final state). However, this can be done by just adding one new initial state. The following image explains the method: It is not necessary for us to have only one accept state.
I'm working on the conversion of regular expressions to NFA, it has to be done piecewise, and I am using the functions concatenate, kleene_star (wrote union myself). If kleene_star function adds only one new state instead of two, it would generate NFA with lesser states in this respect.
Also there is a bug:
from automata.fa.nfa import NFA
nfa = NFA(
states={'q0', 'q1'},
input_symbols={'a'},
transitions={
'q0': {'a': {'q1'}}
},
initial_state='q0',
final_states={'q1'}
)
nfa2 = nfa.kleene_star()
Traceback (most recent call last):
File "/media/abhinav/store/GitHub/automata/test.py", line 12, in <module>
nfa2 = nfa.kleene_star()
File "/media/abhinav/store/GitHub/automata/automata/fa/nfa.py", line 213, in kleene_star
if '' not in new_transitions[state]:
KeyError: 'q1'
It assumes outgoing transitions from every final state which is not necessarily true.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.