This class represents allows to represent and specify goals.

Hierarchy

  • Goal

Methods

  • The AND Goal aggregates several goals together and specifies that at least one of them must be satisfied.

    Inputs

    • goals: an ordered list of goals (here below referenced as the subgoals)

    Behavior

    The scheduler will try to satisfy each subgoal in the list. If a subgoal is only partially satisfied, the scheduler will not backtrack and will let the inserted activities in the plan. If all the subgoals are satisfied, the AND goal will appear satisfied. If one or several subgoals have not been satisfied, the AND goal will appear unsatisfied.

    Examples

    export default function myGoal() {
    return Goal.CoexistenceGoal({
    forEach: Real.Resource("/fruit").equal(4.0),
    activityTemplate: ActivityTemplates.PeelBanana({peelDirection: "fromStem"}),
    endsAt: TimingConstraint.singleton(WindowProperty.END).plus(Temporal.Duration.from({ minutes: 5 }))
    }).and(
    Goal.CardinalityGoal({
    activityTemplate: ActivityTemplates.PeelBanana({peelDirection: "fromStem"}),
    specification: { occurrence : 10 }
    }))
    }

    The AND goal above has two subgoals. The coexistence goal will place activities of type PeelBanana everytime the /fruit resource is equal to 4. The second goal will place 10 occurrences of the same kind of activities PeelBanana. The first subgoal will be evaluated first and will place a certain number of PeelBanana activities in the plan. When the second goal will be evaluated, it will count already present PeelBanana activities and insert the missing number. Imagine the first goals leads to inserting 2 activities. The second goal will then have to place 8 activities to be satisfied.

    Parameters

    • Rest ...others: Goal[]

      the list of goals

    Returns Goal

  • Restricts the windows on which a goal is applied

    By default, a goal applies on the whole planning horizon. The Aerie scheduler provides support for restricting when a goal applies with the .applyWhen() method in the Goal class. This node allows users to provide a set of windows (Windows, see documentation) which could be a time or a resource-based window.

    The .applyWhen() method, takes one argument: the windows (in the form of an expression) that the goal should apply over. What follows is an example that applies a daily recurrence goal only when a given resource is greater than 2. If the resource is less than two, then the goal is no longer applied.

    export default function myGoal() {
    return Goal.ActivityRecurrenceGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ hours: 1 })
    }),
    interval: Temporal.Duration.from({ hours: 2 })
    }).applyWhen(Real.Resource("/fruit").greaterThan(2))
    }

    Notes on boundaries:

    • If you are trying to schedule an activity, or a recurrence within a window but that window cuts off either the activity or the recurrence interval (depending on the goal type), it will not be scheduled. For example, if you had a recurrence interval of 3 seconds, scheduling a 2 second activity each recurrence, and had the following window, you'd get the following:
    Recurrence interval: [++-++-++-]
    Goal window: [+++++----]
    Result: [++-------]

    That, is, the second activity won't be scheduled as the goal window cuts off its recurrence interval.

    • Scheduling is local, not global. This means for every window that is matched (as it is possible to have disjoint windows, imagine a resource that fluctuates upward and downward but only applying that goal when the resource is over a certain value), the goal is applied individually. So, for that same recurrence interval setup as before, we could have:
    Recurrence interval: [++-++-++-++-]
    Goal window: [+++++--+++--]
    Result: [++-----++---] //(the second one is applied independently of the first!)
    • When mapping out a temporal window to apply a goal over, keep in mind that the ending boundary of the goal is exclusive, i.e. if I want to apply a goal in the window of 10-12 seconds, it will apply only on seconds 10 and 11. This is in line with the fencepost problem.

    Returns

    a new goal applying on a restricted horizon

    Parameters

    • windows: Windows

      the windows on which this goal applies

    Returns Goal

  • The OR Goal aggregates several goals together and specifies that at least one of them must be satisfied.

    Inputs

    • goals: a list of goals (here below referenced as the subgoals)

    Behavior

    The scheduler will try to satisfy each subgoal in the list until one is satisfied. If a subgoal is only partially satisfied, the scheduler will not backtrack and will let the inserted activities in the plan.

    Examples

    export default function myGoal() {
    return Goal.CardinalityGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ hours: 1 })
    }),
    specification: { occurrence : 10 }
    }).or(
    Goal.ActivityRecurrenceGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ hours: 1 })
    }),
    interval: Temporal.Duration.from({ hours: 2 })
    }))
    }

    If the plan has a 24-hour planning horizon, the OR goal above will try placing activities of the GrowBanana type. The first subgoal will try placing 10 1-hour occurrences. If it fails to do so, because the planning horizon is maybe too short, it will then try to schedule 1 activity every 2 hours for the duration of the planning horizon.

    It may fail to achieve both subgoals but as the scheduler does not backtrack for now, activities inserted by any of the subgoals are kept in the plan.

    Parameters

    • Rest ...others: Goal[]

      the list of goals

    Returns Goal

  • Specifies whether the scheduler should rollback or not if the goal is only partially satisfied. Rolling back is removing all inserted activities to satisfy the goal as well as removing associations to existing activities

    Parameters

    • shouldRollbackIfUnsatisfied: boolean

      boolean specifying the behavior of the scheduler in terms of rollback

    Returns Goal

  • Creates an ActivityRecurrenceGoal

    The Activity Recurrence Goal (sometimes referred to as a "frequency goal") specifies that a certain activity should occur repeatedly throughout the plan, at some given interval.

    Inputs

    • activityTemplate: the description of the activity whose recurrence we're interested in.
    • activityFinder: an [optional] activity expression. If present, it will be used as replacement of activityTemplate to match against existing activities in the plan.
    • separatedByAtLeast: newly created activities will be separated by at least this amount
    • separatedByAtMost: maximum separation between two consecutive activities. New activities will be inserted to satisfy this constraint.
    • previousActivityStartedAt: [optional] start time of a fictional activity from which the recurrence starts. Can be positive or negative. Default is -separatedByAtMost.
    • interval: [deprecated] maximum and minimum separation duration between 2 activities. A deprecated shorthand to set separatedByAtLeast equal to separatedAtMost.

    Behavior

    The separatedByAtMost constraint is treated as an upper bound - so if the activity occurs more frequently, that is not considered a failure.

    The scheduler will find places in the plan where the given activity has not occurred within the given interval, and it will place an instance of that activity there.

    Note: The interval is measured between the start times of two activity instances. Neither the duration, nor the end time of the activity are examined by this goal.

    Examples

    export default function myGoal() {
    return Goal.ActivityRecurrenceGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ hours: 1 })
    }),
    separatedByAtMost: Temporal.Duration.from({ hours: 2 })
    separatedByAtLeast: Temporal.Duration.from({ hours: 1 })
    previousActivityStartedAt: Temporal.Duration.from({ hours: -1 })
    })
    }

    If the plan contains intervals of more than 2 hours during which there is no activity of the desired type, this goal will insert an activity.
    It will ensure that the activities are separated by at least 1 hour. The solver will consider that there is a fictional activity at time -1.
    It follows that the first activity can be inserted in interval [-1, -1] + [1, 2] = [0, 1].

    ```typescript
    export default function myGoal() {
    return Goal.ActivityRecurrenceGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ hours: 1 })
    }),
    interval: Temporal.Duration.from({ hours: 2 })
    })
    }

    The goal above will place a GrowBanana activity every 2 hours exactly (without flexibility) if there is not already one with the exact same parameters. It is equivalent to

    export default function myGoal() {
    return Goal.ActivityRecurrenceGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ hours: 1 })
    }),
    separatedByAtMost: Temporal.Duration.from({ hours: 2 })
    separatedByAtLeast: Temporal.Duration.from({ hours: 2 })
    previousActivityStartedAt: Temporal.Duration.from({ hours: -2 })
    })
    }

    With an activityFinder

    export default function myGoal() {
    return Goal.ActivityRecurrenceGoal({
    activityFinder: ActivityExpression.build(ActivityTypes.GrowBanana, {growingDuration: Temporal.Duration.from({hours : 1})})
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ hours: 1 })
    }),
    interval: Temporal.Duration.from({ hours: 2 })
    })
    }

    Same behavior as above but in this last example, an activity finder is used to match against existing activities in the plan that would satisfy the goal. Here, any GrowBanana activity with a growingDuration parameter equal to Temporal.Duration.from({hours : 1}) would match, disregarding the value of the other parameter quantity.

    @param opts an object containing the activity template and the interval at which the activities must be placed

    Type Parameters

    Parameters

    • opts: {
          activityFinder?: ActivityExpression<B>;
          activityTemplate: ActivityTemplate<A>;
          previousActivityStartedAt?: Duration;
          separatedByAtLeast: Duration;
          separatedByAtMost: Duration;
      } | {
          activityFinder?: ActivityExpression<B>;
          activityTemplate: ActivityTemplate<A>;
          interval: Duration;
      }

    Returns Goal

  • The Cardinality Goal specifies that a certain activity should occur in the plan either a certain number of times, or for a certain total duration.

    Inputs

    • activityTemplate: the description of the activity whose recurrence we're interested in. If activityFinder is not defined, used for both matching against existing activities and creating new ones.
    • **activityFinder: an optional activity expression. If present, it will be used as replacement of activityTemplate to match against existing activities in the plan.
    • specification: an object with either an occurrence field, a duration field, or both (see examples below).

    Behavior

    The duration and occurrence are treated as lower bounds - so if the activity occurs more times, or for a longer duration, that is not considered a failure, and the scheduler will not add any more activities.

    The scheduler will identify whether it not the plan has enough occurrences or total duration of the given activity template. If not, it will add activities until satisfaction.

    Examples

    Setting a lower bound on the total duration:

    export default function myGoal() {
    return Goal.CardinalityGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ seconds: 1 }),
    }),
    specification: { duration: Temporal.Duration.from({ seconds: 10 }) }
    })
    }

    Setting a lower bound on the number of occurrences:

    export default function myGoal() {
    return Goal.CardinalityGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ seconds: 1 }),
    }),
    specification: { occurrence: 10 }
    })
    }

    Combining the two:

    export default function myGoal() {
    return Goal.CardinalityGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ seconds: 1 }),
    }),
    specification: { occurrence: 10, duration: Temporal.Duration.from({ seconds: 10 }) }
    })
    }

    With an activity finder:

    export default function myGoal() {
    return Goal.CardinalityGoal({
    activityTemplate: ActivityTemplates.GrowBanana({
    quantity: 1,
    growingDuration: Temporal.Duration.from({ seconds: 1 }),
    }),
    activityFinder: ActivityExpression.build(ActivityTypes.GrowBanana, {quantity: 1}),
    specification: { occurrence: 10, duration: Temporal.Duration.from({ seconds: 10 }) }
    })
    }

    In this last example, an activity finder is used to match against existing activities in the plan that would satisfy the goal. Here, any GrowBanana activity with a quantity parameter equal to 1 would match, disregarding the value of the other parameter growingDuration.

    NOTE: In order to avoid placing multiple activities at the same start time, the Cardinality goal introduces an assumed mutual exclusion constraint - namely that new activities will not be allowed to overlap with existing activities.

    Type Parameters

    Parameters

    Returns Goal

  • Creates a coexistence goal. The coexistence goal places one activity for each passed window. The start and end time of each activity can be parametrized relatively to its coexisting window with temporal constraints.

    The Coexistence Goal specifies that a certain activity should occur once for each occurrence of some condition.

    Inputs

    • forEach: a set of time windows (Windows, see documentation on how to produce such an expression) or a set of activities (ActivityExpression) or an Interval or a Temporal.Instant
    • activityTemplate: the description of the activity to insert after each activity identified by forEach. If activityFinder is not defined, used for both matching against existing activities and creating new ones.
    • **activityFinder: an optional activity expression. If present, it will be used as replacement of activityTemplate to match against existing activities in the plan.
    • startsAt: optionally specify a specific time when the activity should start relative to the window
    • startsWithin: optionally specify a range when the activity should start relative to the window
    • endsAt: optionally specify a specific time when the activity should end relative to the window
    • endsWithin: optionally specify a range when the activity should end relative to the window

    NOTE: Either the start or end of the activity must be constrained. This means that at least 1 of the 4 properties startsAt, startsWithin, endsAt, endsWithin must be given.

    Behavior

    The scheduler will find places in the plan where the forEach condition is true, find if an activity matching either the activity template or activity finder is present and if not, it will insert a new instance using the given activityTemplate and temporal constraints.

    Examples

    export default () => Goal.CoexistenceGoal({
    forEach: ActivityExpression.ofType(ActivityTypes.GrowBanana),
    activityTemplate: ActivityTemplates.PeelBanana({peelDirection: "fromStem"}),
    startsAt: TimingConstraint.singleton(WindowProperty.END).plus(Temporal.Duration.from({ minutes: 5 }))
    })

    Behavior: for each activity A of type GrowBanana present in the plan when the goal is evaluated, place an activity of type PeelBanana starting exactly at the end of A + 5 minutes.

    export default () => Goal.CoexistenceGoal({
    forEach: ActivityExpression.ofType(ActivityTypes.GrowBanana),
    activityTemplate: ActivityTemplates.PeelBanana({peelDirection: "fromStem"}),
    startsWithin: TimingConstraint.range(WindowProperty.END, Operator.PLUS, Temporal.Duration.from({ minutes: 5 })),
    endsWithin: TimingConstraint.range(WindowProperty.END, Operator.PLUS, Temporal.Duration.from({ minutes: 6 }))
    })

    Behavior: for each activity A of type GrowBanana present in the plan when the goal is evaluated, place an activity of type PeelBanana starting in the interval [end of A, end of A + 5 minutes] and ending in the interval [end of A, end of A + 6 minutes].

    export default () => Goal.CoexistenceGoal({
    forEach: Real.Resource("/fruit").equal(4.0),
    activityTemplate: ActivityTemplates.PeelBanana({peelDirection: "fromStem"}),
    endsAt: TimingConstraint.singleton(WindowProperty.END).plus(Temporal.Duration.from({ minutes: 5 }))
    })

    Behavior: for each continuous period of time during which the /fruit resource is equal to 4, place an activity of type PeelBanana ending exactly at the end of A + 6 minutes. Note that the scheduler will allow a default timing error of 500 milliseconds for temporal constraints. This parameter will be configurable in an upcoming release.

    KNOWN ISSUE: If the end is unconstrained while the activity has an uncontrollable duration, the scheduler may fail to place the activity. To work around this, add an endsWithin constraint that encompasses your expectation for the duration of the activity - this will help the scheduler narrow the search space.

    export default () => Goal.CoexistenceGoal({
    forEach: Real.Resource("/fruit").equal(4.0),
    activityTemplate: ActivityTemplates.PeelBanana({peelDirection: "fromStem"}),
    activityFinder: ActivityExpression.ofType(ActivityTypes.PeelBanana)
    endsAt: TimingConstraint.singleton(WindowProperty.END).plus(Temporal.Duration.from({ minutes: 5 }))
    })

    Behavior: Same as above but the activity finder is being used to match against any existing PeelBanana activity in the plan, disregarding the value of its parameters.

    Type Parameters

    Parameters

    • opts: Object

      an object containing the activity template, a set of windows, and optionally temporal constraints.

    Returns Goal

Generated using TypeDoc