diff --git a/restructuring/analysis/transform/facts/replace_at.v b/restructuring/analysis/transform/facts/replace_at.v
new file mode 100644
index 0000000000000000000000000000000000000000..4c16fe2fa8f6f85c4665a5e2e4a9085f9c906e59
--- /dev/null
+++ b/restructuring/analysis/transform/facts/replace_at.v
@@ -0,0 +1,117 @@
+From rt.restructuring.analysis.transform Require Export swap.
+From rt.restructuring.behavior.facts Require Import all.
+From rt.util Require Import nat.
+
+(** In this file, we make a few simple observations about schedules with
+    replacements. *)
+Section ReplaceAtFacts.
+
+  (* For any given type of jobs... *)
+  Context {Job : JobType}.
+
+  (* ... and any given type of processor states, ... *)
+  Context {PState: eqType}.
+  Context `{ProcessorState Job PState}.
+
+  (* ...consider any given reference schedule. *)
+  Variable sched: schedule PState.
+
+  (* Suppose we are given a specific time [t'] ... *)
+  Variable t': instant.
+
+  (* ...and a replacement state [state]. *)
+  Variable nstate: PState.
+
+  (* In the following, let sched' denote the schedule with replacement at time
+     t'. *)
+  Let sched' := replace_at sched t' nstate.
+
+  (* We begin with the trivial observation that the schedule doesn't change at
+     other times. *)
+  Lemma rest_of_schedule_invariant:
+    forall t, t <> t' -> sched' t = sched t.
+  Proof.
+    move => t DIFF.
+    rewrite /sched' /replace_at.
+    case (t' == t) eqn:TT; last by done.
+    by move/eqP in TT; rewrite TT in DIFF; contradiction.
+  Qed.
+
+  (* As a result, the service in intervals that do not intersect with t' is
+     invariant, too. *)
+  Lemma service_at_other_times_invariant:
+    forall t1 t2,
+      t2 <= t' \/ t' < t1 ->
+      forall j,
+        service_during sched  j t1 t2
+        =
+        service_during sched' j t1 t2.
+  Proof.
+    move => t1 t2 SWAP_EXCLUDED j.
+    rewrite /service_during /service_at.
+    apply eq_big_nat => t /andP [le_t1t lt_tt2].
+    rewrite rest_of_schedule_invariant//.
+    eapply point_not_in_interval; eauto.
+  Qed.
+
+  (* Next, we consider the amount of service received in intervals that do span
+     across the replacement point.  We can relate the service received in the
+     original and the new schedules by adding the service in the respective
+     "missing" state... *)
+  Lemma service_delta:
+    forall t1 t2,
+      t1 <= t' < t2 ->
+      forall j,
+        service_during sched  j t1 t2 + service_at sched' j t'
+        =
+        service_during sched' j t1 t2 + service_at sched  j t'.
+  Proof.
+    move => t1 t2 TIMES j.
+    rewrite -(service_split_at_point sched  _ _ t' _) //
+            -(service_split_at_point sched' _ _ t' _) //.
+    by rewrite !service_at_other_times_invariant -/sched'; [ring | right | left].
+  Qed.
+
+  (* ...which we can also rewrite as follows. *)
+  Corollary service_in_replaced:
+    forall t1 t2,
+      t1 <= t' < t2 ->
+      forall j,
+        service_during sched' j t1 t2
+        =
+        service_during sched  j t1 t2 + service_at sched' j t' - service_at sched j t'.
+  Proof. move => t1 t2 ORDER j. by rewrite service_delta// addnK. Qed.
+
+  (* As another simple invariant (useful for case analysis), we observe that if
+     a job is scheduled neither in the replaced nor in the new state, then at
+     any time it receives exactly the same amount of service in the new
+     schedule with replacements as in the original schedule. *)
+  Lemma service_at_of_others_invariant (j: Job):
+    ~~ scheduled_in j (sched' t') ->
+    ~~ scheduled_in j (sched t') ->
+    forall t,
+      service_at sched j t = service_at sched' j t.
+  Proof.
+    move=> NOT_IN_NEW NOT_IN_OLD t.
+    rewrite /service_at.
+    case: (boolP (t == t')) => /eqP TT.
+    - rewrite !TT !service_implies_scheduled //; by apply negbTE.
+    - rewrite rest_of_schedule_invariant//.
+  Qed.
+
+  (* Based on the previous observation, we can trivially lift the invariant
+     that jobs not involved in the replacement receive equal service to the
+     cumulative service received in any interval. *)
+  Corollary service_during_of_others_invariant (j: Job):
+    ~~ scheduled_in j (sched' t') ->
+    ~~ scheduled_in j (sched t') ->
+    forall t1 t2,
+      service_during sched j t1 t2 = service_during sched' j t1 t2.
+  Proof.
+    move=> NOT_IN_NEW NOT_IN_OLD t1 t2.
+    rewrite /service_during.
+    apply eq_big_nat => t /andP [le_t1t lt_tt2].
+    rewrite service_at_of_others_invariant //.
+  Qed.
+
+End ReplaceAtFacts.
diff --git a/restructuring/analysis/transform/facts/swaps.v b/restructuring/analysis/transform/facts/swaps.v
new file mode 100644
index 0000000000000000000000000000000000000000..29d62e843a597763963c37dbada053300e2cf916
--- /dev/null
+++ b/restructuring/analysis/transform/facts/swaps.v
@@ -0,0 +1,456 @@
+From rt.restructuring.analysis.transform Require Export swap facts.replace_at.
+From rt.restructuring.behavior.facts Require Import all.
+From rt.util Require Import nat.
+
+(** In this file, we establish invariants about schedules in which two
+    allocations have been swapped, as for instance it is done in the
+    classic EDF optimality proof. *)
+
+Section SwappedFacts.
+  (* For any given type of jobs... *)
+  Context {Job : JobType}.
+  (* ... any given type of processor states: *)
+  Context {PState: eqType}.
+  Context `{ProcessorState Job PState}.
+
+  (* ...consider any given reference schedule. *)
+  Variable sched: schedule PState.
+
+  (* Suppose we are given two specific times [t1] and [t2]. *)
+  Variable t1 t2: instant.
+
+  (* In the following, let [sched'] denote the schedule in which the
+     allocations at [t1] and [t2] have been swapped. *)
+  Let sched' := swapped sched t1 t2.
+  
+  (* First, we note that the trivial case where t1 == t2 is not interesting
+     because then the two schedules are identical. *)
+  Lemma trivial_swap:
+    t1 = t2 ->
+    forall t,
+      sched t = sched' t.
+  Proof.
+    rewrite /sched' => <- t.
+    rewrite /swapped /replace_at.
+    case: (boolP (t1 == t)); last by done.
+    by move /eqP ->.
+  Qed.
+
+  (* In this trivial case, the amount of service received hence
+     is obviously always identical. *)
+  Lemma trivial_swap_service_invariant:
+    t1 = t2 ->
+    forall t j,
+      service sched j t = service sched' j t.
+  Proof.
+    move=> SAME t j.
+    rewrite /service /service_during /service_at.
+    apply eq_big_nat => t' RANGE.
+    by rewrite trivial_swap.
+  Qed.
+
+  (* In any case, the two schedules do not differ at non-swapped times. *)
+  Lemma swap_other_times_invariant:
+    forall t,
+      t <> t1 ->
+      t <> t2 ->
+      sched t = sched' t.
+  Proof.
+    move=> t NOT_t1 NOT_t2.
+    by rewrite /sched' /swapped !rest_of_schedule_invariant //.
+  Qed.
+
+  (* By definition, if a job is scheduled at t2 in the original
+     schedule, then it is found at t1 in the new schedule. *)
+  Lemma swap_job_scheduled_t1:
+    forall j,
+      scheduled_at sched' j t1 =
+      scheduled_at sched j t2.
+  Proof.
+    move=> j.
+    rewrite /scheduled_at /sched' /swapped /replace_at.
+    case: (boolP(t2 == t1)) => [/eqP EQ|NE].
+    - by rewrite EQ.
+    - by rewrite ifT.
+  Qed.
+
+  (* Similarly, a job scheduled at t1 in the original schedule is
+     scheduled at t2 after the swap. *)
+  Lemma swap_job_scheduled_t2:
+    forall j,
+      scheduled_at sched' j t2 =
+      scheduled_at sched j t1.
+  Proof.
+    move=> j.
+    rewrite /sched' /scheduled_at /swapped /replace_at.
+    case: (boolP(t2 == t1)) => [/eqP EQ|NE].
+    - by rewrite ifT.
+    - by rewrite ifT.
+  Qed.
+
+  (* If a job is scheduled at any time not involved in the swap, then
+     it remains scheduled at that time in the new schedule. *)
+  Lemma swap_job_scheduled_other_times:
+    forall j t,
+      t1 != t ->
+      t2 != t ->
+      scheduled_at sched' j t =
+      scheduled_at sched j t.
+  Proof.
+    move=> j t /eqP NOT_t1 /eqP NOT_t2.
+    rewrite /scheduled_at.
+    by rewrite swap_other_times_invariant //; apply: not_eq_sym.
+  Qed.
+
+  (* To make case analysis more convenient, we summarize the preceding
+     three lemmas as a disjunction. *)
+  Corollary swap_job_scheduled_cases:
+    forall j t,
+      scheduled_at sched' j t ->
+      scheduled_at sched' j t = scheduled_at sched j t
+      \/
+      t = t1 /\ scheduled_at sched' j t = scheduled_at sched j t2
+      \/
+      t = t2 /\ scheduled_at sched' j t = scheduled_at sched j t1.
+  Proof.
+    move=> j t SCHED.
+    destruct (t1 == t) eqn:T1.
+    - right. left. move: T1 => /eqP T1.
+      split => //.
+      by rewrite -swap_job_scheduled_t1 T1.
+    - destruct (t2 == t) eqn:T2.
+      + right. right. move: T2 => /eqP T2.
+        split => //.
+        by rewrite -swap_job_scheduled_t2 T2.
+      + left. move: T1 T2 => /eqP/eqP T1 /eqP/eqP T2.
+        by rewrite -swap_job_scheduled_other_times.
+  Qed.
+
+  (* From this, we can easily conclude that no jobs have appeared out
+     of thin air: if a job scheduled at some time in the new schedule,
+     then it was also scheduled at some time in the original
+     schedule. *)
+  Corollary swap_job_scheduled:
+    forall j t,
+      scheduled_at sched' j t ->
+      exists t',
+        scheduled_at sched j t'.
+  Proof.
+    move=> j t SCHED.
+    move: (SCHED).
+    move: (swap_job_scheduled_cases j t SCHED) => [->|[[_ ->] | [_ ->]]].
+    - by exists t.
+    - by exists t2.
+    - by exists t1.
+  Qed.
+
+  (* Mirroring swap_job_scheduled_cases above, we also state a
+     disjunction for case analysis under the premise that a job is
+     scheduled in the original schedule. *)
+  Lemma swap_job_scheduled_original_cases:
+    forall j t,
+      scheduled_at sched j t ->
+      scheduled_at sched' j t = scheduled_at sched j t
+      \/
+      t = t1 /\ scheduled_at sched' j t2 = scheduled_at sched j t
+      \/
+      t = t2 /\ scheduled_at sched' j t1 = scheduled_at sched j t.
+  Proof.
+    move=> j t SCHED.
+    destruct (t1 == t) eqn:T1.
+    - right; left. move: T1 => /eqP T1.
+      split => //.
+      by rewrite swap_job_scheduled_t2 T1.
+    - destruct (t2 == t) eqn:T2.
+      + right; right. move: T2 => /eqP T2.
+        split => //.
+        by rewrite swap_job_scheduled_t1 T2.
+      + left. move: T1 T2 => /eqP/eqP T1 /eqP/eqP T2.
+        by rewrite swap_job_scheduled_other_times.
+  Qed.
+
+  (* Thus, we can conclude that no jobs are lost: if a job is
+     scheduled at some point in the original schedule, then it is also
+     scheduled at some point in the new schedule. *)
+  Corollary swap_job_scheduled_original:
+    forall j t,
+      scheduled_at sched j t ->
+      exists t',
+        scheduled_at sched' j t'.
+  Proof.
+    move=> j t SCHED.
+    move: (SCHED).
+    move: (swap_job_scheduled_original_cases j t SCHED) => [<-|[[_ <-] | [_ <-]]].
+    - by exists t.
+    - by exists t2.
+    - by exists t1.
+  Qed.
+
+  (** In the following, we lift the above basic invariants to
+      statements about invariants about the cumulative amount of
+      service received. *)
+  
+  (* To avoid dealing with symmetric cases, assume in the following
+     that t1 and t2 are ordered. *)
+  Hypothesis H_well_ordered: t1 <= t2.
+
+  (* As another trivial invariant, we observe that nothing has changed
+     before time t1. *)
+  Lemma swap_before_invariant:
+    forall t,
+      t < t1 ->
+      sched t = sched' t.
+  Proof.
+    move=> t t_lt_t1.
+    move: (ltn_leq_trans t_lt_t1 H_well_ordered) => t_lt_t2.
+    by apply swap_other_times_invariant => /eqP /eqP EQ; subst;
+       [move: t_lt_t1|move: t_lt_t2]; rewrite ltnn.
+  Qed.
+
+  (* Similarly, nothing has changed after time t2. *)
+  Lemma swap_after_invariant:
+    forall t,
+      t2 < t ->
+      sched t = sched' t.
+  Proof.
+    move=> t t2_lt_t.
+    move: (leq_ltn_trans H_well_ordered t2_lt_t) => t1_lt_t.
+    by apply swap_other_times_invariant => /eqP /eqP EQ; subst;
+       [move: t1_lt_t|move: t2_lt_t]; rewrite ltnn.
+  Qed.
+
+  (* Thus, we observe that, before t1, the two schedules are identical with
+     regard to the service received by any job because they are identical. *)
+  Corollary service_before_swap_invariant:
+    forall t,
+      t <= t1 ->
+      forall (j : Job),
+        service sched j t = service sched' j t.
+  Proof.
+    move => t le_tt1 j.
+    rewrite /service.
+    rewrite -!service_at_other_times_invariant //; left; first by done.
+    apply leq_trans with (n := t1) => //;
+      by apply ltnW.
+  Qed.
+
+  (* We further observe that, *after* t2, the swapped schedule again does not
+     differ with regard to the service received by any job. *)
+  Lemma service_after_swap_invariant:
+    forall t,
+      t2 < t ->
+      forall (j : Job),
+        service sched j t = service sched' j t.
+  Proof.
+    move => t t2t j.
+    move: H_well_ordered. rewrite leq_eqVlt => /orP [/eqP EQ|t1_lt_t2];
+      first by apply trivial_swap_service_invariant.
+    have TIME: 0 <= t1 < t
+      by apply /andP; split; try apply ltn_trans with (n := t2); done.
+    rewrite /service !service_in_replaced// /service_at// /replace_at //.
+    rewrite ifT// ifT// ifF;
+      last by apply ltn_eqF; exact.
+    rewrite subn_abba //.
+    rewrite -(service_split_at_point _ _ _ t1 _) /service_at //.
+    apply leq_trans with (n := service_during sched j 0 t1 + service_in j (sched t1));
+      [rewrite addnC|]; by apply leq_addr.
+  Qed.
+
+  (* Finally, we note that, trivially, jobs that are not involved in
+     the swap receive invariant service. *)
+  Lemma service_of_others_invariant:
+    forall t j,
+      ~~ scheduled_in j (sched t1) ->
+      ~~ scheduled_in j (sched t2) ->
+      service sched j t = service sched' j t.
+  Proof.
+    move=> t j NOT1 NOT2.
+    move: H_well_ordered. rewrite leq_eqVlt => /orP [/eqP EQ|t1_lt_t2];
+      first by apply trivial_swap_service_invariant.
+    rewrite /service.
+    rewrite -!service_during_of_others_invariant // !/replace_at //;
+            [rewrite ifT// | rewrite ifT// | rewrite ifF// ].
+      by apply ltn_eqF.
+  Qed.
+
+End SwappedFacts.
+
+(** In the following section, we observe that, if the original
+    schedule satisfies certain properties, then so does the new
+    scheduled obtained by swapping the allocations at times [t1] and
+    [t2]. *)
+Section SwappedScheduleProperties.
+  (* For any given type of jobs... *)
+  Context {Job : JobType} `{JobCost Job} `{JobDeadline Job} `{JobArrival Job}.
+  (* ... any given type of processor states: *)
+  Context {PState: eqType}.
+  Context `{ProcessorState Job PState}.
+
+  (* ...consider any given reference schedule. *)
+  Variable sched: schedule PState.
+
+  (* Suppose we are given two specific times [t1] and [t2]... *)
+  Variable t1 t2: instant.
+
+  (* ...such that [t1] is no later than [t2]. *)
+  Hypothesis H_order: t1 <= t2.
+
+  (* We let [sched'] denote the schedule in which the allocations at
+     [t1] and [t2] have been swapped. *)
+  Let sched' := swapped sched t1 t2.
+
+  (* First, we observe that if completed jobs don't execute in the
+     original schedule, then that's still the case after the swap. *)
+  Lemma swapped_completed_jobs_dont_execute:
+    completed_jobs_dont_execute sched ->
+    completed_jobs_dont_execute sched'.
+  Proof.
+    move=> COMP.
+    rewrite /completed_jobs_dont_execute => j  t.
+    wlog: t /  (t2 < t); last first.
+    {
+      move=> LATE.
+      move: H_order. rewrite leq_eqVlt => /orP [/eqP EQ| LT].
+      - by rewrite -(trivial_swap_service_invariant sched t1 t2) //.
+      - by rewrite -(service_after_swap_invariant sched t1 t2) //.
+    }
+    {
+      move=> ARGUMENT.
+      case: (boolP (t2 < t)); first by apply (ARGUMENT t).
+      rewrite -leqNgt => EARLY.
+      apply leq_trans with (n := service sched' j t2.+1).
+      - apply service_monotonic.
+        by apply leq_trans with (n := t2) => //.
+      - by apply (ARGUMENT t2.+1).
+    }
+  Qed.
+
+  (* Suppose all jobs in the original schedule come from some arrival sequence... *)
+  Variable arr_seq: arrival_sequence Job.
+  Hypothesis H_from_arr_seq: jobs_come_from_arrival_sequence sched arr_seq.
+
+  (* ...then that's still the case in the new schedule. *)
+  Lemma swapped_jobs_come_from_arrival_sequence:
+    jobs_come_from_arrival_sequence sched' arr_seq.
+  Proof.
+    move: H_from_arr_seq. rewrite /jobs_come_from_arrival_sequence => ARR_sched j t SCHED.
+    move: (swap_job_scheduled sched _ _ j t SCHED) => [t' SCHED'].
+    by apply (ARR_sched j t' SCHED').
+  Qed.
+
+End SwappedScheduleProperties.
+
+(** In the next section, we consider a special case of swaps: namely,
+    when the job moved earlier has an earlier deadline than the job
+    being moved to a later allocation, assuming that the former has
+    not yet missed its deadline, which is the core transformation of
+    the classic EDF optimality proof. *) 
+Section EDFSwap.
+  (* For any given type of jobs with costs and deadlines... *)
+  Context {Job : JobType} `{JobCost Job} `{JobDeadline Job}.
+  (* ... any given type of processor states... *)
+  Context {PState: eqType}.
+  Context `{ProcessorState Job PState}.
+
+  (* ...consider a given reference schedule... *)
+  Variable sched: schedule PState.
+
+  (* ...in which complete jobs don't execute... *)
+  Hypothesis H_completed_jobs:
+    completed_jobs_dont_execute sched.
+
+  (* ...and scheduled jobs always receive service. *)
+  Hypothesis H_scheduled_implies_serviced: ideal_progress_proc_model.
+
+  (* Suppose we are given two specific times [t1] and [t2]... *)
+  Variable t1 t2: instant.
+
+  (* ...that are ordered. *)
+  Hypothesis H_well_ordered: t1 <= t2.
+
+  (* Further, assume that, if there are jobs scheduled at times t1 and t2, then
+     they either have the same deadline or violate EDF, ... *)
+  Hypothesis H_not_EDF:
+    forall j1 j2,
+      scheduled_at sched j1 t1 ->
+      scheduled_at sched j2 t2 ->
+      job_deadline j1 >=  job_deadline j2.
+
+  (* ...and that we don't move idle times or deadline misses earlier,
+     i.e., if t1 is not an idle time, then neither is t2 and whatever
+     job is scheduled at time t2 has not yet missed its deadline. *)
+  Hypothesis H_no_idle_time_at_t2:
+    forall j1,
+      scheduled_at sched j1 t1 ->
+      exists j2, scheduled_at sched j2 t2 /\ job_deadline j2 > t2.
+
+  (* Consider the schedule obtained from swapping the allocations at times t1 and t2. *)
+  Let sched' := swapped sched t1 t2.
+
+  (* The key property of this transformation is that, for any job that
+     meets its deadline in the original schedule, we have not
+     introduced any deadline misses, which we establish by considering
+     a number of different cases. *)
+  Section NoNewDeadlineMissesCases.
+
+    (* Consider any job... *)
+    Variable j: Job.
+
+    (* ... that meets its deadline in the original schedule. *)
+    Hypothesis H_deadline_met: job_meets_deadline sched j.
+
+    (* First we observe that jobs that are not involved in the swap
+       still meet their deadlines. *)
+    Lemma uninvolved_implies_deadline_met:
+      ~~ scheduled_at sched j t1 ->
+      ~~ scheduled_at sched j t2 ->
+      job_meets_deadline sched' j.
+    Proof.
+      rewrite /scheduled_at => NOT_t1 NOT_t2.
+      rewrite -service_invariant_implies_deadline_met; first by exact H_deadline_met.
+      by apply: service_of_others_invariant.
+    Qed.
+
+    (* Next, we observe that a swap is unproblematic for the job scheduled at
+       time t2. *)
+    Lemma moved_earlier_implies_deadline_met:
+      scheduled_at sched j t2 ->
+      job_meets_deadline sched' j.
+    Proof.
+      move=> AT_t2.
+      rewrite -service_invariant_implies_deadline_met; first by exact H_deadline_met.
+      apply service_after_swap_invariant => //.
+      by apply scheduled_at_implies_later_deadline with (sched0 := sched) => //.
+    Qed.
+
+    (* Finally, we observe is also unproblematic for the job that is
+       moved to a later allocation. *)
+    Lemma moved_later_implies_deadline_met:
+      scheduled_at sched j t1 ->
+      job_meets_deadline sched' j.
+    Proof.
+      move=> AT_t1.
+      move: (H_no_idle_time_at_t2 j AT_t1) => [j2 [AT_t2 DL2]].
+      move: (H_not_EDF j j2 AT_t1 AT_t2) => DL2_le_DL1.
+      rewrite -service_invariant_implies_deadline_met; first by exact H_deadline_met.
+      apply service_after_swap_invariant => //.
+      apply ltn_leq_trans with (n := job_deadline j2) => //.
+    Qed.
+
+  End NoNewDeadlineMissesCases.
+
+  (* From the above case analysis, we conclude that no deadline misses
+     are introduced in the schedule obtained from swapping the
+     allocations at times t1 and t2. *)
+  Theorem edf_swap_no_deadline_misses_introduced:
+    forall j, job_meets_deadline sched j -> job_meets_deadline sched' j.
+  Proof.
+    move=> j DL_MET.
+    case: (boolP (scheduled_at sched j t1)) => AT_t1.
+    - by apply moved_later_implies_deadline_met.
+    - case (boolP (scheduled_at sched j t2)) => AT_t2.
+      + by apply moved_earlier_implies_deadline_met.
+      + by apply uninvolved_implies_deadline_met.
+  Qed.
+
+ End EDFSwap.
diff --git a/restructuring/analysis/transform/swap.v b/restructuring/analysis/transform/swap.v
new file mode 100644
index 0000000000000000000000000000000000000000..1cd62f9e1290463d69dad713c793d525df3ff00c
--- /dev/null
+++ b/restructuring/analysis/transform/swap.v
@@ -0,0 +1,56 @@
+From rt.restructuring.behavior Require Export schedule job.
+From rt.restructuring.behavior.facts Require Import all.
+
+(** This file defines simple allocation substitutions and a swapping operation
+    as used for instance in the classic EDF optimality proof. *)
+
+(** We begin by defining the notion of a schedule with a "tweaked" (i.e.,
+    overridden) allocation. *)
+Section ReplaceAt.
+  (* For any given type of jobs... *)
+  Context {Job : JobType}.
+  (* ... any given type of processor states, ... *)
+  Context {PState: eqType}.
+  Context `{ProcessorState Job PState}.
+
+  (* ...consider any given reference schedule. *)
+  Variable original_sched: schedule PState.
+
+  (* Suppose we are given a specific time [t'] ... *)
+  Variable t': instant.
+
+  (* ...and a replacement state [new_state]. *)
+  Variable new_state: PState.
+
+  (* Then the schedule with replacement is simply one that returns the given
+     [new_state] at [t'], and the original allocation at all other times. *)
+  Definition replace_at (t : instant) :=
+    if t' == t then new_state else (original_sched t).
+
+End ReplaceAt.
+
+
+(** Based on [replace_at], we define the notion of a schedule with swapped
+    allocations. *)
+Section Swapped.
+  (* For any given type of jobs... *)
+  Context {Job : JobType}.
+  (* ... any given type of processor states, ... *)
+  Context {PState: eqType}.
+  Context `{ProcessorState Job PState}.
+
+  (* ...consider any given reference schedule. *)
+  Variable original_sched: schedule PState.
+
+  (* Given two specific times [t1] and [t2]... *)
+  Variable t1 t2: instant.
+
+  (* ...we define the notion of a schedule in which the two allocations at [t1]
+     and [t2] have been swapped. *)
+  Definition swapped : schedule PState :=
+    let s1 := original_sched t1 in
+    let s2 := original_sched t2 in
+    let replaced_s1 := replace_at original_sched t1 s2 in
+    replace_at replaced_s1 t2 s1.
+
+End Swapped.