Skip to content

Commit

Permalink
Merge branch 'develop' into feature/e2e_sequencing_channel_parameter_…
Browse files Browse the repository at this point in the history
…support
  • Loading branch information
goetzrrGit authored Aug 6, 2024
2 parents 5d58a39 + a505cf9 commit ccd4e4f
Show file tree
Hide file tree
Showing 173 changed files with 4,046 additions and 2,985 deletions.
Original file line number Diff line number Diff line change
@@ -1,42 +1,41 @@
package gov.nasa.jpl.aerie.constraints.model;

import gov.nasa.jpl.aerie.constraints.time.Interval;
import gov.nasa.jpl.aerie.merlin.driver.ActivityDirectiveId;
import gov.nasa.jpl.aerie.merlin.driver.ActivityInstanceId;
import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;

public final class ActivityInstance {
public final long id;
public final String type;
public final Map<String, SerializedValue> parameters;
public final Interval interval;

public record ActivityInstance(
ActivityInstanceId instanceId,
String type,
Map<String, SerializedValue> parameters,
Interval interval,
Optional<ActivityDirectiveId> directiveId
) {
public ActivityInstance(
final long id,
final String type,
final Map<String, SerializedValue> parameters,
final Interval interval
long id,
String type,
Map<String, SerializedValue> parameters,
Interval interval
) {
this.type = type;
this.id = id;
this.parameters = parameters;
this.interval = interval;
this(id, type, parameters, interval, Optional.empty());
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof ActivityInstance)) return false;
final var o = (ActivityInstance)obj;

return Objects.equals(this.id, o.id) &&
Objects.equals(this.type, o.type) &&
Objects.equals(this.parameters, o.parameters) &&
Objects.equals(this.interval, o.interval);
public ActivityInstance(
long id,
String type,
Map<String, SerializedValue> parameters,
Interval interval,
Optional<ActivityDirectiveId> directiveId
) {
this(new ActivityInstanceId(id), type, parameters, interval, directiveId);
}

@Override
public int hashCode() {
return Objects.hash(this.id, this.type, this.parameters, this.interval);
public long id() {
return this.instanceId().id();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public ActivitySpan(final String activityAlias) {
@Override
public Spans evaluate(final SimulationResults results, final Interval bounds, final EvaluationEnvironment environment) {
final var activity = environment.activityInstances().get(this.activityAlias);
return new Spans(Segment.of(activity.interval, Optional.of(new Spans.Metadata(activity))));
return new Spans(Segment.of(activity.interval(), Optional.of(new Spans.Metadata(activity))));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public Windows evaluate(final SimulationResults results, final Interval bounds,
final var activity = environment.activityInstances().get(this.activityAlias);
return new Windows(
Segment.of(bounds, false),
Segment.of(activity.interval, true)
Segment.of(activity.interval(), true)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public DiscreteParameter(final String activityAlias, final String parameterName)
public DiscreteProfile evaluate(final SimulationResults results, final Interval bounds, final EvaluationEnvironment environment) {
final var activity = environment.activityInstances().get(this.activityAlias);
return new DiscreteProfile(
Segment.of(bounds, activity.parameters.get(this.parameterName))
Segment.of(bounds, activity.parameters().get(this.parameterName))
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public Windows evaluate(final SimulationResults results, final Interval bounds,
final var activity = environment.activityInstances().get(this.activityAlias);
return new Windows(
Segment.of(bounds, false),
Segment.of(Interval.at(activity.interval.end), true)
Segment.of(Interval.at(activity.interval().end), true)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public String prettyPrint(final String prefix) {
public record MatchType(String type) implements TriFunction<ActivityInstance, SimulationResults, EvaluationEnvironment, Boolean> {
@Override
public Boolean apply(ActivityInstance act, SimulationResults results, EvaluationEnvironment env) {
return Objects.equals(act.type, type);
return Objects.equals(act.type(), type);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public record ForEachActivityViolations(
public ConstraintResult evaluate(final SimulationResults results, final Interval bounds, final EvaluationEnvironment environment) {
var violations = new ConstraintResult();
for (final var activity : results.activities) {
if (activity.type.equals(this.activityType)) {
if (activity.type().equals(this.activityType)) {
final var newEnvironment = new EvaluationEnvironment(
new HashMap<>(environment.activityInstances()),
environment.spansInstances(),
Expand All @@ -28,7 +28,7 @@ public ConstraintResult evaluate(final SimulationResults results, final Interval

final var newViolations = this.expression.evaluate(results, bounds, newEnvironment);
for (final var violation: newViolations.violations) {
violation.addActivityId(activity.id);
violation.addActivityId(activity.id());
}
violations = ConstraintResult.merge(violations, newViolations);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public RealParameter(final String activityAlias, final String parameterName) {
@Override
public LinearProfile evaluate(final SimulationResults results, final Interval bounds, final EvaluationEnvironment environment) {
final var activity = environment.activityInstances().get(this.activityAlias);
final var parameter = activity.parameters.get(this.parameterName);
final var parameter = activity.parameters().get(this.parameterName);
final var value = parameter.asReal().orElseThrow(
() -> new InputMismatchException(
String.format("Activity parameter \"%s\" with value %s cannot be interpreted as real",
this.parameterName,
activity.parameters.get(parameterName).toString())));
activity.parameters().get(parameterName).toString())));

return new LinearProfile(
Segment.of(Interval.FOREVER, new LinearEquation(Duration.ZERO, value, 0.0))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public ConstraintResult evaluate(SimulationResults results, final Interval bound
for (final var span : reportedSpans) {
if (!Interval.intersect(span.interval(), expandedInterval).isEmpty()) {
violationIntervals.add(span.interval());
span.value().ifPresent(m -> violationActivityIds.add(m.activityInstance().id));
span.value().ifPresent(m -> violationActivityIds.add(m.activityInstance().id()));
}
}
if (this.algorithm == RollingThresholdAlgorithm.ExcessHull || this.algorithm == RollingThresholdAlgorithm.DeficitHull) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public Windows evaluate(final SimulationResults results, final Interval bounds,
final var activity = environment.activityInstances().get(this.activityAlias);
return new Windows(
Segment.of(bounds, false),
Segment.of(Interval.at(activity.interval.start), true)
Segment.of(Interval.at(activity.interval().start), true)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public DiscreteProfile evaluate(
final Interval bounds,
final EvaluationEnvironment environment)
{
final var res = this.profile.evaluate(results, bounds, environment);
final var time = timepoint.evaluate(results, bounds, environment);
final var time = timepoint.evaluate(results, Interval.FOREVER, environment);
final var timepoint = time.iterator().next().interval().start;
final var res = this.profile.evaluate(results, Interval.at(timepoint), environment);
//REVIEW: SHOULD ASSERT A BUNCH OF THINGS HERE SO IT IS NOT WRONGLY USED
final var value = res.valueAt(timepoint);
if(value.isEmpty()){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public Cell<D> duplicate(Cell<D> cell) {
public void apply(Cell<D> cell, E effect) {
cell.initialDynamics = effect.apply(cell.dynamics).match(
ErrorCatching::success,
error -> failure(new RuntimeException(
"Applying '%s' failed.".formatted(getEffectName(effect)), error)));
error -> failure(new RuntimeException(
"Applying effect '%s' failed.".formatted(getName(effect, null)), error)));
cell.dynamics = cell.initialDynamics;
cell.elapsedTime = ZERO;
}
Expand Down Expand Up @@ -120,7 +120,7 @@ public DynamicsEffect<D> empty() {
@Override
public DynamicsEffect<D> sequentially(final DynamicsEffect<D> prefix, final DynamicsEffect<D> suffix) {
final DynamicsEffect<D> result = x -> suffix.apply(prefix.apply(x));
name(result, "(%s) then (%s)".formatted(getEffectName(prefix), getEffectName(suffix)));
name(result, "(%s) then (%s)", prefix, suffix);
return result;
}

Expand All @@ -135,22 +135,17 @@ public DynamicsEffect<D> concurrently(final DynamicsEffect<D> left, final Dynami
return failure(e);
}
};
name(result, "(%s) and (%s)".formatted(getEffectName(left), getEffectName(right)));
name(result, "(%s) and (%s)", left, right);
return result;
} catch (Throwable e) {
final DynamicsEffect<D> result = $ -> failure(e);
name(result, "Failed to combine concurrent effects: (%s) and (%s)".formatted(
getEffectName(left), getEffectName(right)));
name(result, "Failed to combine concurrent effects: (%s) and (%s)", left, right);
return result;
}
}
};
}

private static <D extends Dynamics<?, D>, E extends DynamicsEffect<D>> String getEffectName(E effect) {
return getName(effect).orElse("anonymous effect");
}

public static class Cell<D> {
public ErrorCatching<Expiring<D>> initialDynamics;
public ErrorCatching<Expiring<D>> dynamics;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ public static Expiry expiry(Optional<Duration> value) {
}

public Expiry or(Expiry other) {
return expiry(
Stream.concat(value().stream(), other.value().stream()).reduce(Duration::min));
// If this has a value...
// If other has a value, compare and return the minimum
// Else other is NEVER, so return this
// Else (this is NEVER), so return other
return this.value.map(thisValue ->
other.value.map(otherValue -> Expiry.at(Duration.min(thisValue, otherValue)))
.orElse(this))
.orElse(other);
}

public Expiry minus(Duration t) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
public interface MutableResource<D extends Dynamics<?, D>> extends Resource<D> {
void emit(DynamicsEffect<D> effect);
default void emit(String effectName, DynamicsEffect<D> effect) {
name(effect, effectName);
emit(effect);
emit(name(effect, effectName));
}

static <D extends Dynamics<?, D>> MutableResource<D> resource(D initial) {
Expand All @@ -47,21 +46,18 @@ static <D extends Dynamics<?, D>> MutableResource<D> resource(ErrorCatching<Expi

@Override
public void emit(final DynamicsEffect<D> effect) {
augmentEffectName(effect);
cell.emit(effect);
// NOTE: The strange pattern of naming effect::apply is to create a new object, identical in behavior to effect,
// which we can assign a more informative name without actually getting the name of effect.
// Replacing effect::apply with effect would create a self-loop in the naming graph on effect, which isn't allowed.
// Using Naming.getName to get effect's current name and use that when elaborating is correct but potentially slow,
// depending on how deep the naming graph is.
cell.emit(name(effect::apply, "%s on %s" + Context.get().stream().map(c -> " during " + c).collect(joining()), effect, this));
}

@Override
public ErrorCatching<Expiring<D>> getDynamics() {
return cell.get().dynamics;
}

private void augmentEffectName(DynamicsEffect<D> effect) {
String effectName = getName(effect).orElse("anonymous effect");
String resourceName = getName(this).orElse("anonymous resource");
String augmentedName = effectName + " on " + resourceName + Context.get().stream().map(c -> " during " + c).collect(joining());
name(effect, augmentedName);
}
};
if (MutableResourceFlags.DETECT_BUSY_CELLS) {
result = profileEffects(result);
Expand All @@ -73,11 +69,11 @@ private void augmentEffectName(DynamicsEffect<D> effect) {
}

static <D extends Dynamics<?, D>> void set(MutableResource<D> resource, D newDynamics) {
resource.emit("Set " + newDynamics, DynamicsMonad.effect(x -> newDynamics));
resource.emit(name(DynamicsMonad.effect(x -> newDynamics), "Set %s", newDynamics));
}

static <D extends Dynamics<?, D>> void set(MutableResource<D> resource, Expiring<D> newDynamics) {
resource.emit("Set " + newDynamics, ErrorCatchingMonad.<Expiring<D>, Expiring<D>>map($ -> newDynamics)::apply);
resource.emit(name(ErrorCatchingMonad.<Expiring<D>, Expiring<D>>map($ -> newDynamics)::apply, "Set %s", newDynamics));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,7 @@ public static Condition expires(Resource<?> resource) {
*/
public static <D extends Dynamics<?, D>> void forward(Resource<D> source, MutableResource<D> destination) {
wheneverDynamicsChange(source, s -> destination.emit(
"Forward %s dynamics: %s".formatted(getName(source).orElse("anonymous"), s),
$ -> s));
name($ -> s, "Forward %s dynamics to %s", source, destination)));
addDependency(destination, source);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import gov.nasa.jpl.aerie.merlin.protocol.types.Unit;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

Expand All @@ -15,7 +14,7 @@
public final class Context {
private Context() {}

private static final ThreadLocal<Deque<String>> contexts = ThreadLocal.withInitial(ArrayDeque::new);
private static final ThreadLocal<List<String>> contexts = ThreadLocal.withInitial(List::of);

/**
* @see Context#inContext(String, Supplier)
Expand All @@ -30,13 +29,19 @@ public static void inContext(String contextName, Runnable action) {
*/
public static <R> R inContext(String contextName, Supplier<R> action) {
// Using a thread-local context stack maintains isolation for threaded tasks.
var outerContext = contexts.get();
try {
contexts.get().push(contextName);
// Since copying the context into spawned children actually dominates performance,
// use an effectively-immutable list for the stack, and copy it to push/pop a layer.
var innerContext = new ArrayList<String>(outerContext.size() + 1);
innerContext.addAll(outerContext);
innerContext.add(contextName);
contexts.set(innerContext);
return action.get();
// TODO: Should we add a catch clause here that would add context to the error?
} finally {
// Doing the tear-down in a finally block maintains isolation for replaying tasks.
contexts.get().pop();
contexts.set(outerContext);
}
}

Expand All @@ -61,12 +66,12 @@ public static void inContext(List<String> contextStack, Runnable action) {
* @see Context#contextualized
*/
public static <R> R inContext(List<String> contextStack, Supplier<R> action) {
if (contextStack.isEmpty()) {
var outerContext = contexts.get();
try {
contexts.set(contextStack);
return action.get();
} else {
int n = contextStack.size() - 1;
return inContext(contextStack.get(n), () ->
inContext(contextStack.subList(0, n), action));
} finally {
contexts.set(outerContext);
}
}

Expand Down Expand Up @@ -133,9 +138,15 @@ public static <R> Supplier<R> contextualized(String childContext, Supplier<R> ac

/**
* Returns the list of contexts, from innermost context out.
*
* <p>
* Note: For efficiency, this returns the actual context stack, not a copy.
* Do not modify the result of this method!
* Doing so may corrupt the context-tracking system.
* </p>
*/
public static List<String> get() {
return contexts.get().stream().toList();
return contexts.get();
}

private static Supplier<Unit> asSupplier(Runnable action) {
Expand Down
Loading

0 comments on commit ccd4e4f

Please sign in to comment.