Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[amp-refactor][2/n] Create snapshot class for condition objects (#18613)
## Summary & Motivation We want to make this ConditionEvaluation class serializable, and in order to do so, we'll want to serialize snapshots of our conditions rather than the objects themselves. This brings up an interesting question: the ConditionEvaluation class has information that we want to call up from previous ticks, and it has a recursive structure. On the next tick, we need to be able to locate which part of the recursive structure we should explore next (this is the `for_child` call). However, there are three issues: 1. A given condition can have multiple identical sub-expressions, i.e. `(A & (B | C) & (B | C))` is technically valid, so we can't use a pure equality test to detect which sub-expression to go to next 2. If each node in the condition evaluation tree needs to have a snapshot class which contains all of ITS children, then the NamedTuple will end up being size O(N^2) where N is the number of nodes in the tree, as each node will need to have some limited representation of all nodes below it. 3. A condition can change between ticks, meaning that the entire structure may be different on the current tick vs. what we have a snapshot of. I solve all of these issues by not including any information about children on the snapshot itself, and instead letting that get encoded in the recursive structure of the ConditionEvaluation. Then, to retrieve a specific child, we just rely on the index of that child in the structure. Some examples of what would happen if the condition changed between ticks: Serialized: `A | B | C` Current: `A | B | D | C` Result: A and B get mapped to their previous tick's condition evaluation, D gets no data (because it's of a different type than C), C gets no data (because it's in a new index) Serialized: `A | B | C` Current: `A | B` Result: A and B get mapped to their previous tick's condition evaluation Serialized: `(A | B) & (C | D | E)` Current: `(A | B) & (C | D | E | F)` Result: All things serialized on the previous tick get mapped correctly Serialized: `(A | B) & (C | D | E)` Current: `X & (A | B) & (C | D | E)` Result: Nothing serialized on the previous tick gets mapped correctly The last case is definitely the most concerning one -- it's possible that we could create a fancier way of detecting that sort of situation in some cases (this would come in the form of fancier `for_child` logic), but it seems hard to do in a fully-general way. ## How I Tested These Changes
- Loading branch information