Skip to content
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

[AERIE-1953] Interval split operation for Windows and Spans #260

Merged
merged 5 commits into from
Sep 21, 2022

Conversation

JoelCourtney
Copy link
Contributor

  • Tickets addressed: AERIE-1953
  • Review: By commit
  • Merge strategy: Merge (no squash)

Description

Implements the split(N) operation, which splits each window into N equally sized sub-windows by removing N-1 points in the middle. Instantaneous point windows are left unchanged.

In practice since windows are defined in microseconds, the sub-windows might not be exactly equal, because the last sub-window might be up to N-1 microns longer than the others if the original duration is not a multiple of N. Also, if the original window is M microns long where M < N (however unlikely that might be), only M sub-windows will be produced.

Commits:

  1. I added a basic parser for a nullable value. It is essentially chooseP(your parser, nullP) with some extra processing that turns it into Optional<your parser's output>.
  2. Converts the CodeLocation record in ConstraintsCompilationError to have nullable fields, because runtime errors don't report code location
    • The TS API throws a runtime error if N < 1
  3. Implements split
  4. Tests split

Verification

Plenty of tests, see last commit.

Documentation

The API method is doc-commented. I'll update wiki after approval but before merge.

@JoelCourtney JoelCourtney changed the title Feat/aerie 1953 split operation [AERIE-1953] Windows.split operation Jul 21, 2022
@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch 3 times, most recently from 733e55c to 94be979 Compare July 21, 2022 20:57
@JoelCourtney JoelCourtney marked this pull request as draft July 22, 2022 19:12
@JoelCourtney
Copy link
Contributor Author

Marking as draft because I'm about to open a PR for basic Spans. Will implement Spans.split as well.

@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch 4 times, most recently from a3276e9 to 1c042eb Compare August 4, 2022 17:41
@JoelCourtney JoelCourtney marked this pull request as ready for review August 4, 2022 17:41
@JoelCourtney JoelCourtney changed the title [AERIE-1953] Windows.split operation [AERIE-1953] Interval split operation for Windows and Spans Aug 4, 2022
@JoelCourtney
Copy link
Contributor Author

I've marked ready for review now that this PR includes Spans! This change introduces the IntervalContainer interface, which will be the unifying interface between Windows and Spans. Any operations that will exist on both container types (such as Split and many others) should be added to this interface. This way the Split node doesn't have to be duplicated for WindowsSplit and SpansSplit, and can just use the interface.

@JoelCourtney JoelCourtney removed the draft label Aug 4, 2022
@JoelCourtney JoelCourtney requested a review from dyst5422 August 4, 2022 17:44
@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch 2 times, most recently from 76013d4 to a250971 Compare August 8, 2022 16:37
@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch 3 times, most recently from 361d2a9 to 6fb824c Compare August 10, 2022 16:53
@JoelCourtney JoelCourtney temporarily deployed to e2e-test August 10, 2022 16:53 Inactive
@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch from 6fb824c to 2830bae Compare August 11, 2022 23:11
@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch from 2830bae to 3f98ca6 Compare August 15, 2022 23:44
@JoelCourtney JoelCourtney temporarily deployed to e2e-test August 15, 2022 23:44 Inactive
Copy link
Contributor

@dyst5422 dyst5422 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Thanks again for finding the user code runner bug!

@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch from 3f98ca6 to 57f6d40 Compare August 17, 2022 18:09
@JoelCourtney JoelCourtney temporarily deployed to e2e-test August 17, 2022 18:09 Inactive
Copy link
Contributor

@adrienmaillard adrienmaillard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only have one (quite fundamental) question but otherwise all of this looks good to me.

@JoelCourtney
Copy link
Contributor Author

JoelCourtney commented Sep 16, 2022

Ok! Now that nullable windows is merged, the situation for split is a little different.

I'm thinking since windows gaps mean "unknown" instead of "undefined", it would technically be unknown where to split a window if a true segment neighbors a gap. So, I'm thinking split should throw an error if called on windows that have gaps.

Additionally, I'd like to make the inclusivity of any generated internal edges be configurable, with the defaults being internalStartInclusivity = Inclusive, internalEndInclusivity = Exclusive. The general patterns would be this:

  • If calling split on Spans, just don't worry about it because its straightforward.
  • If calling split on Windows:
    1. if your windows has gaps that you want to keep, save a copy of your windows object for step 5
    2. call assignGaps(true | false) (TODO) to remove any gaps
    3. call split(N, startInclusivity?, endInclusivity?), which always produces Spans just in case the chosen inclusivities would immediately cause coalescing (which would happen by default)
    4. either use your Spans object, or call .windows() and do step 5
    5. to optionally regain gaps, call .select(oldCopy) (TODO)

example code:

export default(): Constraint {
    let unsplitWindows = /* some external profile expression with gaps */;
    let splitWindows = unsplitWindows
        .assignGaps(false)
        .split(3, Inclusivity.Exclusive, Inclusivity.Exclusive)
        .windows()
        .select(unsplitWindows);
    // do whatever with your shiny new windows object
}

At some point if performance becomes a concern it may be helpful to implement a .cache() operation to avoid reevaluating things like unsplitWindows. The ast node would hash its children and store/lookup results in the environment variable in the expression interface. But that's a separate issue.

@adrienmaillard @dyst5422 @Twisol any thoughts?

@Twisol
Copy link
Contributor

Twisol commented Sep 16, 2022

I think my first concern is what "N equally-sized windows" means if you happen to have a profile like true[-inf, 0] false[0,3] true[3, inf] (or heck, true[-inf, inf]). More generally, how should this behave on unbounded intervals?

(I know we use MIN_VALUE right now and not a proper -inf, but MIN_VALUE itself is a completely arbitrary value.)

@JoelCourtney
Copy link
Contributor Author

More generally, how should this behave on unbounded intervals?

I suppose as long as we're trying to represent infinite intervals on a finite domain, simply leaving windows that touch MIN_VALUE or MAX_VALUE unchanged is fairly accurate.

@Twisol
Copy link
Contributor

Twisol commented Sep 16, 2022

D'you think there are any valid use-cases for calling split when unbounded true intervals exist? It seems more likely to be the result of an incorrect windows expression -- maybe we'd prefer to throw when faced with such intervals, so that the author can correct their logic.

@JoelCourtney
Copy link
Contributor Author

D'you think there are any valid use-cases for calling split when unbounded true intervals exist? It seems more likely to be the result of an incorrect windows expression -- maybe we'd prefer to throw when faced with such intervals, so that the author can correct their logic.

I can't think of any, so I'll add that check and throw an error. If such a use case ever comes up, it'll be very easy and I've left a comment explaining what to do.

@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch from 57f6d40 to f453353 Compare September 21, 2022 20:56
@JoelCourtney JoelCourtney requested a review from a team as a code owner September 21, 2022 20:56
@JoelCourtney JoelCourtney temporarily deployed to e2e-test September 21, 2022 20:56 Inactive
@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch from f453353 to 4930dca Compare September 21, 2022 21:16
@JoelCourtney JoelCourtney temporarily deployed to e2e-test September 21, 2022 21:16 Inactive
@JoelCourtney JoelCourtney force-pushed the feat/AERIE-1953--split-operation branch from 4930dca to 9ce6c3c Compare September 21, 2022 21:24
@JoelCourtney JoelCourtney temporarily deployed to e2e-test September 21, 2022 21:24 Inactive
Copy link
Contributor

@adrienmaillard adrienmaillard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work.

@JoelCourtney JoelCourtney merged commit 58ce978 into develop Sep 21, 2022
@JoelCourtney JoelCourtney deleted the feat/AERIE-1953--split-operation branch September 21, 2022 23:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants