Library Swaps

Require Import List.
Require Import Setoid.
Require Import Axioms.
Require Export Atoms.

Section Swap.

   Variable A : AtomT.
   Variable X : Set.

  Record SwapT : Set := mkSwap {
    swap : (A * A) -> X -> X;

    swap_same : forall a x, swap (a, a) x = x;

    swap_invol : forall ab x, swap ab (swap ab x) = x;

    swap_distrib :
      forall ab c d x,
        swap ab (swap (c, d) x) =
        swap (swapa A ab c, swapa A ab d) (swap ab x)
  }.

   Variable S : SwapT.

  Lemma swap_same' :
    forall a b x, a = b -> swap S (a, b) x = x.

  Lemma swap_invol' :
    forall a b c d x, a = c -> b = d -> swap S (a, b) (swap S (c, d) x) = x.

  Lemma swap_injective : forall ab x y, swap S ab x = swap S ab y -> x = y.

  Lemma swap_move_left : forall ab x y, swap S ab x = y -> x = swap S ab y.

  Lemma swap_move_right : forall ab x y, x = swap S ab y -> swap S ab x = y.

  Lemma swap_switch : forall a b x, swap S (a, b) x = swap S (b, a) x.

  Lemma swap_switch_invol : forall a b x, swap S (a, b) (swap S (b, a) x) = x.

  Lemma swap_switch_invol' :
    forall a b c d x, a = d -> b = c -> swap S (a, b) (swap S (c, d) x) = x.

  Lemma swap_undistrib :
    forall a b cd x,
      swap S (a, b) (swap S cd x) =
      swap S cd (swap S (swapa A cd a, swapa A cd b) x).

End Swap.

Implicit Arguments mkSwap [A X].
Implicit Arguments swap [A X].
Implicit Arguments swap_same [A X].
Implicit Arguments swap_invol [A X].
Implicit Arguments swap_distrib [A X].
Implicit Arguments swap_same' [A X a b].
Implicit Arguments swap_invol' [A X a b c d].
Implicit Arguments swap_injective [A X S ab x y].
Implicit Arguments swap_move_left [A X].
Implicit Arguments swap_move_right [A X].
Implicit Arguments swap_switch [A X].
Implicit Arguments swap_switch_invol [A X].
Implicit Arguments swap_switch_invol' [A X a b c d].
Implicit Arguments swap_undistrib [A X].
Hint Resolve swap_same swap_invol swap_distrib : nominal.
Hint Immediate swap_injective swap_move_left swap_move_right : nominal.
Hint Resolve swap_switch swap_switch_invol swap_undistrib : nominal.

Hint Rewrite swap_same : nominal.
Hint Rewrite swap_invol : nominal.
Hint Rewrite swap_same' using congruence : nominal.
Hint Rewrite swap_invol' using congruence : nominal.
Hint Rewrite swap_switch_invol : nominal.
Hint Rewrite swap_switch_invol' using congruence : nominal.

Ltac autorewrite_swap_in_hyp :=
  repeat (
    match goal with
    | H : context [swap ?S (?a, ?a) ?x] |- _ =>
        rewrite (@swap_same _ _ S a x) in H
    | H : context [swap ?S (?a, ?b) (swap ?S (?a, ?b) ?x)] |- _ =>
        rewrite (@swap_switch _ _ S (a, b) x) in H
    | H : context [swap ?S (?a, ?b) (swap ?S (?b, ?a) ?x)] |- _ =>
        rewrite (@swap_switch_invol _ _ S a b x) in H
    | H : context [swap ?S (?a, ?b) ?x] |- _ =>
        rewrite (@swap_same' _ _ S a b x) in H;
          [idtac | solve [congruence]]
    | H : context [swap ?S (?a, ?b) (swap ?S (?c, ?d) ?x)] |- _ =>
        (rewrite (@swap_invol _ _ S a b c d x) in H;
          [idtac | solve [congruence] | solve [congruence]]) ||
        (rewrite (@swap_switch_invol _ _ S a b c d x) in H;
          [idtac | solve [congruence] | solve [congruence]])
    end).

Swapping on atoms


Section AtomSwap.

   Variable A : AtomT.
   Variables a b c : atom A.

  Definition mkAtomSwap :=
    mkSwap
      (swapa A)
      (@swapa_same A)
      (@swapa_invol A)
      (@swapa_distrib A).

  Lemma atom_swap_left : swap mkAtomSwap (a, b) a = b.

  Lemma atom_swap_left' : a = c -> swap mkAtomSwap (a, b) c = b.

  Lemma atom_swap_right : swap mkAtomSwap (a, b) b = a.

  Lemma atom_swap_right' : b = c -> swap mkAtomSwap (a, b) c = a.

  Lemma atom_swap_neither : a <> c -> b <> c -> swap mkAtomSwap (a, b) c = c.

End AtomSwap.

atom_swap_simpl_once is just an auxilary tactic.
Ltac atom_swap_simpl_once a b c :=
  (rewrite (@atom_swap_left _ a b)) ||
  (rewrite (@atom_swap_left' _ a b c);
    [idtac | solve [congruence]]) ||
  (rewrite (@atom_swap_right _ a b)) ||
  (rewrite (@atom_swap_right' _ a b c);
    [idtac | solve [congruence]]) ||
  (rewrite (@atom_swap_neither _ a b c);
    [idtac | solve [congruence] | solve [congruence]]).

Ltac atom_swap_simpl_hyp H a b c :=
  (rewrite (@atom_swap_left _ a b) in H) ||
  (rewrite (@atom_swap_left' _ a b c) in H;
    [idtac | solve [congruence]]) ||
  (rewrite (@atom_swap_right _ a b) in H) ||
  (rewrite (@atom_swap_right' _ a b c) in H;
    [idtac | solve [congruence]]) ||
  (rewrite (@atom_swap_neither _ a b c) in H;
    [idtac | solve [congruence] | solve [congruence]]).

atom_swap_simpl performs all reductions of atom swaps (in the goal or in the hypotheses) for which the result is inferrable from the context using the congruence tactic.
Ltac atom_swap_simpl :=
  repeat (
    match goal with
    | |- context [swap (mkAtomSwap _) (?a, ?b) ?c] =>
        atom_swap_simpl_once a b c
    | H : context [swap (mkAtomSwap _) (?a, ?b) ?c] |- _ =>
        atom_swap_simpl_hyp H a b c
    end).

atom_swap_case H1 H2 a b c will reduce all expressions of the form atom_swap _ (a, b) c to either a, b, or c, splitting the goal as necessary, when the relationships between a and c and between b and c cannot be inferred from the context. H1 will be used as the name for a newly introduced assumption about the relationship between a and c, and respectively H2 for b and c. Also, any additional reductions of atom swaps that are inferrable from the context will be performed.
Ltac atom_swap_case H1 H2 a b c :=
  atom_swap_simpl;
  try match goal with
  | |- context [swap (mkAtomSwap _) (a, b) c] =>
      case (atom_eqdec _ a c); intro H1; try congruence;
      atom_swap_simpl;
      try match goal with
      | |- context [swap (mkAtomSwap _) (a, b) c] =>
          case (atom_eqdec _ b c); intro H2; try congruence;
          atom_swap_simpl
      end
  end.

The identity swap

Section IdSwap.

   Variable A : AtomT.
   Variable X : Set.

  Definition id_swap (s : A * A) (x : X) := x.

  Lemma id_swap_same : forall a x, id_swap (a, a) x = x.

  Lemma id_swap_invol : forall ab x, id_swap ab (id_swap ab x) = x.

  Lemma id_swap_distrib :
    forall ab c d x,
      id_swap ab (id_swap (c, d) x) =
      id_swap (swapa A ab c, swapa A ab d) (id_swap ab x).

  Definition mkIdSwap :=
    mkSwap
      id_swap
      id_swap_same
      id_swap_invol
      id_swap_distrib.

  Lemma id_swap_reduce :
    forall ab x,
      swap mkIdSwap ab x = x.

End IdSwap.

Implicit Arguments id_swap [A X].
Implicit Arguments id_swap_same [A X].
Implicit Arguments id_swap_invol [A X].
Implicit Arguments id_swap_distrib [A X].
Implicit Arguments id_swap_reduce [A X].

Hint Resolve id_swap_same id_swap_invol id_swap_distrib : nominal.
Hint Rewrite id_swap_same id_swap_invol id_swap_reduce : nominal.

id_swap_simpl performs all reductions of id swaps (in the goal or in the hypotheses) for which the result is inferrable from the context using the congruence tactic.
Ltac id_swap_simpl :=
  repeat (
    match goal with
    | |- context [swap (mkIdSwap _) (?a, ?b) ?x] =>
        rewrite (@id_swap_reduce _ _ (a, b) x)
    | H : context [swap (mkIdSwap _) (?a, ?b) ?x] |- _ =>
        rewrite (@id_swap_reduce _ _ (a, b) x) in H
    end).

Swapping on pairs


Section PairSwap.

   Variable A : AtomT.
   Variable X : Set.
   Variable XS : SwapT A X.
   Variable Y : Set.
   Variable YS : SwapT A Y.

  Definition pair_swap (s : atom A * atom A) (p : X * Y) :=
    let (x, y) := p in (swap XS s x, swap YS s y).

  Lemma pair_swap_same : forall a p, pair_swap (a, a) p = p.

  Lemma pair_swap_invol : forall ab p, pair_swap ab (pair_swap ab p) = p.

  Lemma pair_swap_distrib :
    forall ab c d p,
      pair_swap ab (pair_swap (c, d) p) =
      pair_swap (swapa A ab c, swapa A ab d) (pair_swap ab p).

  Definition mkPairSwap :=
    mkSwap
      pair_swap
      pair_swap_same
      pair_swap_invol
      pair_swap_distrib.

End PairSwap.

Implicit Arguments pair_swap [A X Y].
Implicit Arguments pair_swap_same [A X Y].
Implicit Arguments pair_swap_invol [A X Y].
Implicit Arguments pair_swap_distrib [A X Y].
Implicit Arguments mkPairSwap [A X Y].

Hint Resolve pair_swap_same pair_swap_invol pair_swap_distrib : nominal.
Hint Rewrite pair_swap_same pair_swap_distrib : nominal.

Notation "X ^* Y" := (mkPairSwap X Y) (at level 50, left associativity).

Swapping on lists


Section ListSwap.

   Variable A : AtomT.
   Variable X : Set.
   Variable XS : SwapT A X.

  Fixpoint list_swap (s : A * A) (ls : list X) {struct ls} : list X :=
    match ls with
      | nil => nil
      | x :: ls' => swap XS s x :: list_swap s ls'
    end.

  Lemma list_swap_same : forall a ls, list_swap (a, a) ls = ls.
    induction ls.
    simpl...
    simpl; rewrite (swap_same XS); rewrite IHls...
  Qed.

  Lemma list_swap_invol : forall ab ls, list_swap ab (list_swap ab ls) = ls.
    induction ls.
    simpl...
    simpl; rewrite (swap_invol XS); rewrite IHls...
  Qed.

  Lemma list_swap_distrib :
    forall ab c d ls,
      list_swap ab (list_swap (c, d) ls) =
      list_swap (swapa A ab c, swapa A ab d) (list_swap ab ls).
    induction ls.
    simpl...
    simpl; rewrite (swap_distrib XS); rewrite IHls...
  Qed.

  Definition mkListSwap :=
    mkSwap
      list_swap
      list_swap_same
      list_swap_invol
      list_swap_distrib.

  Lemma list_swap_In :
    forall xs x ab,
    List.In x xs <-> List.In (swap XS ab x) (list_swap ab xs).

End ListSwap.

Implicit Arguments list_swap [A X].
Implicit Arguments list_swap_same [A X].
Implicit Arguments list_swap_invol [A X].
Implicit Arguments list_swap_distrib [A X].
Implicit Arguments mkListSwap [A X].

Hint Resolve list_swap_same list_swap_invol list_swap_distrib : nominal.
Hint Rewrite list_swap_same list_swap_invol : nominal.

Swapping on functions.


Section FunctionSwap.

   Variable A : AtomT.
   Variable X : Set.
   Variable XS : SwapT A X.
   Variable Y : Set.
   Variable YS : SwapT A Y.

  Definition func_swap (s : atom A * atom A) (f : X -> Y) (x : X) :=
    swap YS s (f (swap XS s x)).

  Lemma func_swap_same : forall a f, func_swap (a, a) f = f.

  Lemma func_swap_invol : forall ab f, func_swap ab (func_swap ab f) = f.

  Lemma func_swap_distrib :
    forall ab c d f,
      func_swap ab (func_swap (c, d) f) =
      func_swap (swapa A ab c, swapa A ab d) (func_swap ab f).

  Definition mkFuncSwap :=
    mkSwap
      func_swap
      func_swap_same
      func_swap_invol
      func_swap_distrib.

  Lemma swap_app :
    forall ab f x,
    swap YS ab (f x) = (swap mkFuncSwap ab f) (swap XS ab x).

  Lemma swap_func :
    forall ab f x,
    (swap mkFuncSwap ab f) x = swap YS ab (f (swap XS ab x)).

End FunctionSwap.

Implicit Arguments func_swap [A X Y].
Implicit Arguments func_swap_same [A X Y].
Implicit Arguments func_swap_invol [A X Y].
Implicit Arguments func_swap_distrib [A X Y].
Implicit Arguments mkFuncSwap [A X Y].
Implicit Arguments swap_app [A X Y].
Implicit Arguments swap_func [A X Y].

Hint Resolve func_swap_same func_swap_invol func_swap_distrib : nominal.
Hint Rewrite func_swap_same func_swap_invol : nominal.

Hint Resolve swap_app swap_func : nomimal.

Notation "X ^-> Y" := (mkFuncSwap X Y) (at level 90, right associativity).

Index
This page has been generated by coqdoc