Closed Tagl closed 2 years ago
@eliotwrobson I just realized that a matching predecessor may potentially need to return an infinite string so can't do that one.
For example DFA.universal_language({'0', '1'}).predecessor('1')
would have to return 01111...
@Tagl Yes, there's some subtlety to this, especially dealing with infinite languages. You might just want to say that this is only for DFAs over finite languages. There's some discussion of this issue in that original blog post, apparently you can always make it return a prefix of the lexicographically next thing? I think sticking with finite languages may be the least confusing way to go.
Successor works fine for infinite languages since it yields in preorder. Predecessor would follow a similar DFS process but yields postorder and therefore may never yield. If we really want to include a predecessor function along with the successor function then there are a number ways we could do it:
1.
but raise exception if language is infinite, very restrictive but still useful in some cases.1.
but raise exception if a cycle is required to produce the predecessor.I'm kindof leaning toward option 2, since this seems the least confusing for an end user.
I'm kindof leaning toward option 2, since this seems the least confusing for an end user.
I think 2 is a good start and easier to implement. Can be updated to 3 later on if deemed necessary.
We already have potentially-infinite iteration in DFA.__iter__
, don't we? So I'm not sure if Option 1 is as bad as it sounds.
I suppose a fifth option might be to add a keyword arg that controls the behavior—whether an exception is raised, or whether yielding is infinite.
We already have potentially-infinite iteration in
DFA.__iter__
, don't we? So I'm not sure if Option 1 is as bad as it sounds.I suppose a fifth option might be to add a keyword arg that controls the behavior—whether an exception is raised, or whether yielding is infinite.
I should clarify, this would be infinite iteration without any results because the search algorithm would keep adding a token. The while loop would iterate forever without yielding once because for each potential predecessor that it does find, there is gonna be one that is longer and therefore is lexicographically larger. Therefore in this case it will never be a useful function, even though it is trying to do exactly what is asked of it, that's why I believe we should raise an exception, but it would be more practical if that only happens when absolutely necessary.
The infinite iteration in __iter__
is quite different will eventually find a result and yield it. So it can generate an infinite amount of data but it will always yield the next result within a finite amount of time.
@Tagl I see. Then yeah, if we can identify the never-yielding case ahead of time, then I'd say throw an exception (probably a specialized one).
@Tagl (cc @eliotwrobson) What is the status of this PR? Does Option 2 still need to be implemented?
If possible, I would kindly ask if we could convert to drafts any PRs that are not yet ready for my review. That helps me out a lot.
My mistake, I thought I had made it a draft originally
I will change it back once I've implemented predecessor
with option 2
@caleb531 @eliotwrobson Ready for review
@Tagl Just an update: this PR is looking pretty good currently, I've just been mulling over the effort required to make ignore_rejection
a standard parameter for read_input_stepwise
on all automaton types. Most of that centers around when None
should be yielded, or if that is even necessary (e.g. in the case of nondeterminism).
But after reviewing the other automaton classes just now, that should be doable (or doesn't even seem to be an issue thanks to the nondeterminism in some of those types). So I plan to be merging this PR shortly.
Might be a bit out of scope though, maybe better to just adapt this PR to the current implementation and then we can discuss the change to the API better later
On Tue, Nov 8, 2022, 00:12 Caleb Evans @.***> wrote:
@Tagl https://github.com/Tagl Just an update: this PR is looking pretty good currently, I've just been mulling over the effort required to make ignore_rejection a standard parameter for read_input_stepwise on all automaton types. Most of that centers around when None should be yielded, or if that is even necessary (e.g. in the case of nondeterminism).
But after reviewing the other automaton classes just now, that should be doable (or doesn't even seem to be an issue thanks to the nondeterminism in some of those types). So I plan to be merging this PR shortly.
— Reply to this email directly, view it on GitHub https://github.com/caleb531/automata/pull/92#issuecomment-1306401451, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB2ZBKXC46FKCVQHXEUTXXDWHGLHHANCNFSM6AAAAAARSCH6RM . You are receiving this because you were mentioned.Message ID: @.***>
@Tagl Well, to clarify—I would not be standardizing ignore_rejection
in this PR, as I agree that it is out of scope. I would be implementing that after this PR is merged.
@caleb531 Here's a draft of the algorithm, a lot of optimizations to be made regarding precomputation.