Library Wlog

Without loss of generality tactics

Set Implicit Arguments.
Unset Strict Implicit.

Lemma wlog1_lemma Ta (a: Ta) m P :
  (forall (WLOG: forall a, m a -> P a), P a) ->
  (forall a, m a -> P a) -> P a.
Proof. eauto. Qed.
Implicit Arguments wlog1_lemma [Ta].

Lemma wlog2_lemma Ta (a: Ta) Tb (b: Tb) m P :
  (forall (WLOG: forall a b, m a b -> P a b), P a b) ->
  (forall a b, m a b -> P a b) -> P a b.
Proof. eauto. Qed.
Implicit Arguments wlog2_lemma [Ta Tb].

Tactic Notation "wlog" hyp(x1) "/" constr(m) :=
  match eval pattern x1 in m with
    ?f _ => apply (wlog1_lemma x1 f); [intro|clear x1; intros x1]
  end.

Tactic Notation "wlogC" hyp(x1) "/" constr(m) :=
  match goal with
    |- ?P =>
      let WLOG := fresh "WLOG" in
      let EQ := fresh "EQ" in
      match eval pattern x1 in m with
        ?f _ =>
           apply (wlog1_lemma x1 f); [intro WLOG;
           set (EQ := P); case_eq m; subst EQ; [exact (WLOG x1)|]
          |clear x1; intros x1]
      end
  end.

Tactic Notation "wlog" hyp(x1) hyp(x2) "/" constr(m) :=
  match goal with
    |- ?P =>
      match eval pattern x1, x2 in m with
        ?f _ _ => apply (wlog2_lemma x1 x2 f); [intro|clear x1 x2; intros x1 x2]
      end
  end.

Tactic Notation "wlogC" hyp(x1) hyp(x2) "/" constr(m) :=
  match goal with
    |- ?P =>
      let WLOG := fresh "WLOG" in
      let EQ := fresh "EQ" in
      match eval pattern x1, x2 in m with
        ?f _ _ => apply (wlog2_lemma x1 x2 f);
          [intro WLOG;
           set (EQ := P); case_eq m; subst EQ;
           [exact (WLOG x1 x2)|
            intro EQ; try rewrite EQ; intros; generalize (WLOG x2 x1)]
          |clear x1 x2; intros x1 x2]
      end
  end.