(* define two strings to be equivalent if one can be reached from
   the other by a sequence of inserting or deleting opposite pairs *)
Inductive group_str_equiv : group_str -> group_str -> Prop :=
  | insert_opposite_pair: forall (S T:group_str) (a:alphabet),
    group_str_equiv (S ++ T) (S ++ opposite a :: a :: T)
  | group_str_equiv_refl: forall S:group_str, group_str_equiv S S
  | group_str_equiv_sym: forall S T:group_str,
    group_str_equiv S T -> group_str_equiv T S
  | group_str_equiv_trans: forall S T U:group_str,
    group_str_equiv S T -> group_str_equiv T U ->
    group_str_equiv S U.(* define two strings to be equivalent if one can be reached from
   the other by a sequence of inserting or deleting opposite pairs *)
Inductive group_str_equiv : group_str -> group_str -> Prop :=
  | insert_opposite_pair: forall (S T:group_str) (a:alphabet),
    group_str_equiv (S ++ T) (S ++ opposite a :: a :: T)
  | group_str_equiv_refl: forall S:group_str, group_str_equiv S S
  | group_str_equiv_sym: forall S T:group_str,
    group_str_equiv S T -> group_str_equiv T S
  | group_str_equiv_trans: forall S T U:group_str,
    group_str_equiv S T -> group_str_equiv T U ->
    group_str_equiv S U.(* define two strings to be equivalent if one can be reached from
   the other by a sequence of inserting or deleting opposite pairs *)
Inductive group_str_equiv : group_str -> group_str -> Prop :=
  | insert_opposite_pair: forall (S T:group_str) (a:alphabet),
    group_str_equiv (S ++ T) (S ++ opposite a :: a :: T)
  | group_str_equiv_refl: forall S:group_str, group_str_equiv S S
  | group_str_equiv_sym: forall S T:group_str,
    group_str_equiv S T -> group_str_equiv T S
  | group_str_equiv_trans: forall S T U:group_str,
    group_str_equiv S T -> group_str_equiv T U ->
    group_str_equiv S U.(* define two strings to be equivalent if one can be reached from
   the other by a sequence of inserting or deleting opposite pairs *)
Inductive group_str_equiv : group_str -> group_str -> Prop :=
  | insert_opposite_pair: forall (S T:group_str) (a:alphabet),
    group_str_equiv (S ++ T) (S ++ opposite a :: a :: T)
  | group_str_equiv_refl: forall S:group_str, group_str_equiv S S
  | group_str_equiv_sym: forall S T:group_str,
    group_str_equiv S T -> group_str_equiv T S
  | group_str_equiv_trans: forall S T U:group_str,
    group_str_equiv S T -> group_str_equiv T U ->
    group_str_equiv S U.(* define two strings to be equivalent if one can be reached from
   the other by a sequence of inserting or deleting opposite pairs *)
Inductive group_str_equiv : group_str -> group_str -> Prop :=
  | insert_opposite_pair: forall (S T:group_str) (a:alphabet),
    group_str_equiv (S ++ T) (S ++ opposite a :: a :: T)
  | group_str_equiv_refl: forall S:group_str, group_str_equiv S S
  | group_str_equiv_sym: forall S T:group_str,
    group_str_equiv S T -> group_str_equiv T S
  | group_str_equiv_trans: forall S T U:group_str,
    group_str_equiv S T -> group_str_equiv T U ->
    group_str_equiv S U.Notation "S ~~ T" := (group_str_equiv S T) (at level 80).Add Parametric Relation: group_str group_str_equiv
  reflexivity proved by group_str_equiv_refl
  symmetry proved by group_str_equiv_sym
  transitivity proved by group_str_equiv_trans
  as group_str_equiv_rel.

Lemma cons_respects_group_str_equiv: forall (S T:group_str) (a:alphabet), S ~~ T -> (a :: S) ~~ (a :: T).