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

Performance/intervalmap #1371

Merged
merged 6 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,14 @@ public Windows notEqualTo(final DiscreteProfile other) {
@Override
public Windows changePoints() {
final var result = IntervalMap.<Boolean>builder().set(this.profilePieces.map($ -> false));
for (int i = 0; i < this.profilePieces.size(); i++) {
final var segment = this.profilePieces.get(i);
if (i == 0) {
for (final var segment : profilePieces) {
if (segment == profilePieces.first()) {
if (!segment.interval().contains(Duration.MIN_VALUE)) {
result.unset(Interval.at(segment.interval().start));
}
} else {
final var previousSegment = this.profilePieces.get(i-1);
if (Interval.meets(previousSegment.interval(), segment.interval())) {
final var previousSegment = this.profilePieces.segments().lower(segment);
if (previousSegment != null && Interval.meets(previousSegment.interval(), segment.interval())) {
if (!previousSegment.value().equals(segment.value())) {
result.set(Interval.at(segment.interval().start), true);
}
Expand All @@ -83,15 +82,16 @@ public Windows changePoints() {

public Windows transitions(final SerializedValue oldState, final SerializedValue newState) {
final var result = IntervalMap.<Boolean>builder().set(this.profilePieces.map($ -> false));
for (int i = 0; i < this.profilePieces.size(); i++) {
final var segment = this.profilePieces.get(i);
if (i == 0) {
for (final var segment : profilePieces) {
//for (int i = 0; i < this.profilePieces.size(); i++) {
//final var segment = this.profilePieces.get(i);
if (segment == profilePieces.first()) {
if (segment.value().equals(newState) && !segment.interval().contains(Duration.MIN_VALUE)) {
result.unset(Interval.at(segment.interval().start));
}
} else {
final var previousSegment = this.profilePieces.get(i-1);
if (Interval.meets(previousSegment.interval(), segment.interval())) {
final var previousSegment = this.profilePieces.segments().lower(segment);
if (previousSegment != null && Interval.meets(previousSegment.interval(), segment.interval())) {
if (previousSegment.value().equals(oldState) && segment.value().equals(newState)) {
result.set(Interval.at(segment.interval().start), true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/**
* A linear equation in point-slope form.
*/
public final class LinearEquation {
public final class LinearEquation implements Comparable<LinearEquation> {
public final Duration initialTime;
public final double initialValue;
public final double rate;
Expand Down Expand Up @@ -185,4 +185,12 @@ public boolean equals(final Object obj) {
public int hashCode() {
return Objects.hash(this.initialValue, this.initialTime, this.rate);
}

@Override
public int compareTo(final LinearEquation o) {
int c = Double.compare(this.valueAt(Duration.ZERO), o.valueAt(Duration.ZERO));
if (c != 0) return c;
c = Double.compare(this.valueAt(Duration.MINUTE), o.valueAt(Duration.MINUTE));
return c;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,16 @@ private Windows getWindowsSatisfying(final LinearProfile other, final BiFunction
@Override
public Windows changePoints() {
final var result = IntervalMap.<Boolean>builder().set(this.profilePieces.map(LinearEquation::changing));
for (int i = 0; i < this.profilePieces.size(); i++) {
final var segment = this.profilePieces.get(i);
for (final var segment : profilePieces) {
final var startTime = segment.interval().start;
if (i == 0) {
if (segment == profilePieces.first()) {
if (!segment.interval().contains(Duration.MIN_VALUE)) {
result.unset(Interval.at(startTime));
}
} else {
final var previousSegment = this.profilePieces.get(i-1);
final var previousSegment = this.profilePieces.segments().lower(segment);

if (Interval.meets(previousSegment.interval(), segment.interval())) {
if (previousSegment != null && Interval.meets(previousSegment.interval(), segment.interval())) {
if (previousSegment.value().valueAt(startTime) != segment.value().valueAt(startTime)) {
result.set(Interval.at(startTime), true);
}
Expand All @@ -133,7 +132,7 @@ public Windows changePoints() {
@Override
public boolean isConstant() {
return profilePieces.isEmpty() ||
(profilePieces.size() == 1 && !profilePieces.get(0).value().changing());
(profilePieces.size() == 1 && !profilePieces.first().value().changing());
}

/** Assigns a default value to all gaps in the profile. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import gov.nasa.jpl.aerie.merlin.protocol.types.Duration;
import org.apache.commons.lang3.tuple.Pair;

import java.util.Comparator;
import java.util.Objects;

import static gov.nasa.jpl.aerie.constraints.time.Interval.Inclusivity.Exclusive;
Expand Down Expand Up @@ -277,7 +278,10 @@ public boolean adjacent(Interval x){

@Override
public int compareTo(final Interval o) {
return start.compareTo(o.start);
int c = compareStarts(o);
if (c != 0) return c;
c = compareEnds(o);
return c;
}

public static int compareStartToStart(final Interval x, final Interval y) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,54 @@ public static Interval strictUpperBoundsOf(final Interval x) {
);
}

/**
* Whether the start of one interval is before the start of another. This assumes that the intervals are both
* non-empty but does not check.
* @param x the first interval
* @param y the second interval
* @return whether the start of x is before the start of y
*/
public static boolean startBeforeStart(Interval x, Interval y) {
return x.start.shorterThan(y.start) ||
(x.start.isEqualTo(y.start) && (x.includesStart() && !y.includesStart()));
}

/**
* Whether the end of one interval is before the start of another. This assumes that the intervals are both
* non-empty but does not check.
* @param x the first interval
* @param y the second interval
* @return whether the end of x is before the start of y
*/
public static boolean endBeforeStart(Interval x, Interval y) {
return x.end.shorterThan(y.start) ||
(x.end.isEqualTo(y.start) && (!x.includesEnd() || !y.includesStart()));
}

/**
* Whether the end of one interval is before the end of another. This assumes that the intervals are both
* non-empty but does not check.
* @param x the first interval
* @param y the second interval
* @return whether the end of x is before the end of y
*/
public static boolean endBeforeEnd(Interval x, Interval y) {
return x.end.shorterThan(y.end) ||
(x.end.isEqualTo(y.end) && (!x.includesEnd() && y.includesEnd()));
}

/**
* Whether the start of one interval is before the end of another. This assumes that the intervals are both
* non-empty but does not check.
* @param x the first interval
* @param y the second interval
* @return whether the start of x is before the end of y
*/
public static boolean startBeforeEnd(Interval x, Interval y) {
return x.start.shorterThan(y.end);
}


/**
* Whether any point is contained in both operands.
*
Expand All @@ -110,7 +158,8 @@ public static Interval strictUpperBoundsOf(final Interval x) {
* @return whether the operands overlap
*/
static boolean overlaps(Interval x, Interval y) {
return !isEmpty(intersect(x, y));
if (x.isEmpty() || y.isEmpty()) return false;
return !endBeforeStart(x, y) && !endBeforeStart(y, x);
}

/**
Expand All @@ -121,9 +170,8 @@ static boolean overlaps(Interval x, Interval y) {
* @return whether `outer` contains every point in `inner`
*/
static boolean contains(Interval outer, Interval inner) {
// If `inner` doesn't overlap with the complement of `outer`,
// then `inner` must exist entirely within `outer`.
return !(overlaps(inner, strictUpperBoundsOf(outer)) || overlaps(inner, strictLowerBoundsOf(outer)));
if (outer.isEmpty() || inner.isEmpty()) return false;
return !startBeforeStart(inner, outer) && !endBeforeEnd(outer, inner);
}

/**
Expand Down Expand Up @@ -158,7 +206,8 @@ static boolean equals(Interval x, Interval y) {
* @return whether the start point of x is before all points in y
*/
static boolean startsBefore(Interval x, Interval y) {
return strictlyContains(strictLowerBoundsOf(y), strictLowerBoundsOf(x));
if (x.isEmpty() || y.isEmpty()) return false;
return startBeforeStart(x, y);
}

/**
Expand All @@ -169,7 +218,8 @@ static boolean startsBefore(Interval x, Interval y) {
* @return whether the end point of x is after all points in y
*/
static boolean endsAfter(Interval x, Interval y) {
return strictlyContains(strictUpperBoundsOf(y), strictUpperBoundsOf(x));
if (x.isEmpty() || y.isEmpty()) return false;
return endBeforeEnd(y, x);
}

/**
Expand Down Expand Up @@ -213,7 +263,9 @@ static boolean startsStrictlyAfter(Interval x, Interval y) {
* @return whether the end point of x is strictly before all points in y
*/
static boolean endsStrictlyBefore(Interval x, Interval y) {
return !isEmpty(intersect(strictUpperBoundsOf(x), strictLowerBoundsOf(y)));
if (x.isEmpty() || y.isEmpty()) return false;
return x.end.shorterThan(y.start) ||
(x.end.isEqualTo(y.start) && (!x.includesEnd() && !y.includesStart()));
}

/**
Expand All @@ -224,7 +276,8 @@ static boolean endsStrictlyBefore(Interval x, Interval y) {
* @return whether x ends when y begins, with no overlap and no gap
*/
static boolean meets(Interval x, Interval y) {
return equals(strictUpperBoundsOf(x), strictUpperBoundsOf(strictLowerBoundsOf(y)));
if (x.isEmpty() || y.isEmpty()) return false;
return x.end.isEqualTo(y.start) && (x.endInclusivity != y.startInclusivity);
}

/**
Expand Down
Loading