/-
Copyright (c) 2018 Johannes Hölzl. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl, Callum Sutton, Yury Kudryashov

! This file was ported from Lean 3 source module algebra.ring.aut
! leanprover-community/mathlib commit c3291da49cfa65f0d43b094750541c0731edc932
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Algebra.GroupRingAction.Basic
import Mathbin.Algebra.Hom.Aut
import Mathbin.Algebra.Ring.Equiv

/-!
# Ring automorphisms

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

This file defines the automorphism group structure on `ring_aut R := ring_equiv R R`.

## Implementation notes

The definition of multiplication in the automorphism group agrees with function composition,
multiplication in `equiv.perm`, and multiplication in `category_theory.End`, but not with
`category_theory.comp`.

This file is kept separate from `data/equiv/ring` so that `group_theory.perm` is free to use
equivalences (and other files that use them) before the group structure is defined.

## Tags

ring_aut
-/

#print RingAut /-
/-- The group of ring automorphisms. -/
@[reducible]
def RingAut (R : Type _) [Mul R] [Add R] :=
  RingEquiv R R
#align ring_aut RingAut
-/

namespace RingAut

section mul_add

variable (R : Type _) [Mul R] [Add R]

/-- The group operation on automorphisms of a ring is defined by
`λ g h, ring_equiv.trans h g`.
This means that multiplication agrees with composition, `(g*h)(x) = g (h x)`.
-/
instance : Group (RingAut R) := by
  refine_struct
            { mul := fun g h => RingEquiv.trans h g
              one := RingEquiv.refl R
              inv := RingEquiv.symm
              div := _
              npow := @npowRec _ ⟨RingEquiv.refl R⟩ ⟨fun g h => RingEquiv.trans h g⟩
              zpow :=
                @zpowRec _ ⟨RingEquiv.refl R⟩ ⟨fun g h => RingEquiv.trans h g⟩
                  ⟨RingEquiv.symm⟩ } <;>
          intros <;>
        ext <;>
      try rfl <;>
    apply Equiv.left_inv

instance : Inhabited (RingAut R) :=
  ⟨1⟩

/- warning: ring_aut.to_add_aut -> RingAut.toAddAut is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) [_inst_1 : Mul.{u1} R] [_inst_2 : Add.{u1} R], MonoidHom.{u1, u1} (RingAut.{u1} R _inst_1 _inst_2) (AddAut.{u1} R _inst_2) (Monoid.toMulOneClass.{u1} (RingAut.{u1} R _inst_1 _inst_2) (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (RingAut.group.{u1} R _inst_1 _inst_2)))) (Monoid.toMulOneClass.{u1} (AddAut.{u1} R _inst_2) (DivInvMonoid.toMonoid.{u1} (AddAut.{u1} R _inst_2) (Group.toDivInvMonoid.{u1} (AddAut.{u1} R _inst_2) (AddAut.group.{u1} R _inst_2))))
but is expected to have type
  forall (R : Type.{u1}) [_inst_1 : Mul.{u1} R] [_inst_2 : Add.{u1} R], MonoidHom.{u1, u1} (RingAut.{u1} R _inst_1 _inst_2) (AddAut.{u1} R _inst_2) (Monoid.toMulOneClass.{u1} (RingAut.{u1} R _inst_1 _inst_2) (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (RingAut.instGroupRingAut.{u1} R _inst_1 _inst_2)))) (Monoid.toMulOneClass.{u1} (AddAut.{u1} R _inst_2) (DivInvMonoid.toMonoid.{u1} (AddAut.{u1} R _inst_2) (Group.toDivInvMonoid.{u1} (AddAut.{u1} R _inst_2) (AddAut.group.{u1} R _inst_2))))
Case conversion may be inaccurate. Consider using '#align ring_aut.to_add_aut RingAut.toAddAutₓ'. -/
/-- Monoid homomorphism from ring automorphisms to additive automorphisms. -/
def toAddAut : RingAut R →* AddAut R := by
  refine_struct { toFun := RingEquiv.toAddEquiv } <;> intros <;> rfl
#align ring_aut.to_add_aut RingAut.toAddAut

/- warning: ring_aut.to_mul_aut -> RingAut.toMulAut is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) [_inst_1 : Mul.{u1} R] [_inst_2 : Add.{u1} R], MonoidHom.{u1, u1} (RingAut.{u1} R _inst_1 _inst_2) (MulAut.{u1} R _inst_1) (Monoid.toMulOneClass.{u1} (RingAut.{u1} R _inst_1 _inst_2) (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (RingAut.group.{u1} R _inst_1 _inst_2)))) (Monoid.toMulOneClass.{u1} (MulAut.{u1} R _inst_1) (DivInvMonoid.toMonoid.{u1} (MulAut.{u1} R _inst_1) (Group.toDivInvMonoid.{u1} (MulAut.{u1} R _inst_1) (MulAut.group.{u1} R _inst_1))))
but is expected to have type
  forall (R : Type.{u1}) [_inst_1 : Mul.{u1} R] [_inst_2 : Add.{u1} R], MonoidHom.{u1, u1} (RingAut.{u1} R _inst_1 _inst_2) (MulAut.{u1} R _inst_1) (Monoid.toMulOneClass.{u1} (RingAut.{u1} R _inst_1 _inst_2) (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (RingAut.instGroupRingAut.{u1} R _inst_1 _inst_2)))) (Monoid.toMulOneClass.{u1} (MulAut.{u1} R _inst_1) (DivInvMonoid.toMonoid.{u1} (MulAut.{u1} R _inst_1) (Group.toDivInvMonoid.{u1} (MulAut.{u1} R _inst_1) (MulAut.instGroupMulAut.{u1} R _inst_1))))
Case conversion may be inaccurate. Consider using '#align ring_aut.to_mul_aut RingAut.toMulAutₓ'. -/
/-- Monoid homomorphism from ring automorphisms to multiplicative automorphisms. -/
def toMulAut : RingAut R →* MulAut R := by
  refine_struct { toFun := RingEquiv.toMulEquiv } <;> intros <;> rfl
#align ring_aut.to_mul_aut RingAut.toMulAut

/- warning: ring_aut.to_perm -> RingAut.toPerm is a dubious translation:
lean 3 declaration is
  forall (R : Type.{u1}) [_inst_1 : Mul.{u1} R] [_inst_2 : Add.{u1} R], MonoidHom.{u1, u1} (RingAut.{u1} R _inst_1 _inst_2) (Equiv.Perm.{succ u1} R) (Monoid.toMulOneClass.{u1} (RingAut.{u1} R _inst_1 _inst_2) (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (RingAut.group.{u1} R _inst_1 _inst_2)))) (Monoid.toMulOneClass.{u1} (Equiv.Perm.{succ u1} R) (DivInvMonoid.toMonoid.{u1} (Equiv.Perm.{succ u1} R) (Group.toDivInvMonoid.{u1} (Equiv.Perm.{succ u1} R) (Equiv.Perm.permGroup.{u1} R))))
but is expected to have type
  forall (R : Type.{u1}) [_inst_1 : Mul.{u1} R] [_inst_2 : Add.{u1} R], MonoidHom.{u1, u1} (RingAut.{u1} R _inst_1 _inst_2) (Equiv.Perm.{succ u1} R) (Monoid.toMulOneClass.{u1} (RingAut.{u1} R _inst_1 _inst_2) (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R _inst_1 _inst_2) (RingAut.instGroupRingAut.{u1} R _inst_1 _inst_2)))) (Monoid.toMulOneClass.{u1} (Equiv.Perm.{succ u1} R) (DivInvMonoid.toMonoid.{u1} (Equiv.Perm.{succ u1} R) (Group.toDivInvMonoid.{u1} (Equiv.Perm.{succ u1} R) (Equiv.Perm.permGroup.{u1} R))))
Case conversion may be inaccurate. Consider using '#align ring_aut.to_perm RingAut.toPermₓ'. -/
/-- Monoid homomorphism from ring automorphisms to permutations. -/
def toPerm : RingAut R →* Equiv.Perm R := by
  refine_struct { toFun := RingEquiv.toEquiv } <;> intros <;> rfl
#align ring_aut.to_perm RingAut.toPerm

end mul_add

section Semiring

variable {G R : Type _} [Group G] [Semiring R]

/- warning: ring_aut.apply_mul_semiring_action -> RingAut.applyMulSemiringAction is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} [_inst_2 : Semiring.{u1} R], MulSemiringAction.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.group.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) _inst_2
but is expected to have type
  forall {R : Type.{u1}} [_inst_2 : Semiring.{u1} R], MulSemiringAction.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.instGroupRingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) _inst_2
Case conversion may be inaccurate. Consider using '#align ring_aut.apply_mul_semiring_action RingAut.applyMulSemiringActionₓ'. -/
/-- The tautological action by the group of automorphism of a ring `R` on `R`.-/
instance applyMulSemiringAction : MulSemiringAction (RingAut R) R
    where
  smul := (· <| ·)
  smul_zero := RingEquiv.map_zero
  smul_add := RingEquiv.map_add
  smul_one := RingEquiv.map_one
  smul_mul := RingEquiv.map_mul
  one_smul _ := rfl
  mul_smul _ _ _ := rfl
#align ring_aut.apply_mul_semiring_action RingAut.applyMulSemiringAction

/- warning: ring_aut.smul_def -> RingAut.smul_def is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} [_inst_2 : Semiring.{u1} R] (f : RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (r : R), Eq.{succ u1} R (SMul.smul.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (SMulZeroClass.toHasSmul.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (AddZeroClass.toHasZero.{u1} R (AddMonoid.toAddZeroClass.{u1} R (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))))) (DistribSMul.toSmulZeroClass.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (AddMonoid.toAddZeroClass.{u1} R (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (DistribMulAction.toDistribSMul.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.group.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (MulSemiringAction.toDistribMulAction.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.group.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) _inst_2 (RingAut.applyMulSemiringAction.{u1} R _inst_2))))) f r) (coeFn.{succ u1, succ u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (fun (_x : RingEquiv.{u1, u1} R R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) => R -> R) (RingEquiv.hasCoeToFun.{u1, u1} R R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) f r)
but is expected to have type
  forall {R : Type.{u1}} [_inst_2 : Semiring.{u1} R] (f : RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (r : R), Eq.{succ u1} R (HSMul.hSMul.{u1, u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R R (instHSMul.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (SMulZeroClass.toSMul.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (MonoidWithZero.toZero.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_2)) (DistribSMul.toSMulZeroClass.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (AddMonoid.toAddZeroClass.{u1} R (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (DistribMulAction.toDistribSMul.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.instGroupRingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (MulSemiringAction.toDistribMulAction.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.instGroupRingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) _inst_2 (RingAut.applyMulSemiringAction.{u1} R _inst_2)))))) f r) (FunLike.coe.{succ u1, succ u1, succ u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (fun (_x : R) => (fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : R) => R) _x) (EmbeddingLike.toFunLike.{succ u1, succ u1, succ u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R R (EquivLike.toEmbeddingLike.{succ u1, succ u1, succ u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R R (MulEquivClass.toEquivLike.{u1, u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (RingEquivClass.toMulEquivClass.{u1, u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (RingEquiv.instRingEquivClassRingEquiv.{u1, u1} R R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))))) f r)
Case conversion may be inaccurate. Consider using '#align ring_aut.smul_def RingAut.smul_defₓ'. -/
@[simp]
protected theorem smul_def (f : RingAut R) (r : R) : f • r = f r :=
  rfl
#align ring_aut.smul_def RingAut.smul_def

/- warning: ring_aut.apply_has_faithful_smul -> RingAut.apply_faithfulSMul is a dubious translation:
lean 3 declaration is
  forall {R : Type.{u1}} [_inst_2 : Semiring.{u1} R], FaithfulSMul.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (SMulZeroClass.toHasSmul.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (AddZeroClass.toHasZero.{u1} R (AddMonoid.toAddZeroClass.{u1} R (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))))) (DistribSMul.toSmulZeroClass.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (AddMonoid.toAddZeroClass.{u1} R (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (DistribMulAction.toDistribSMul.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.group.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (MulSemiringAction.toDistribMulAction.{u1, u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.group.{u1} R (Distrib.toHasMul.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (Distrib.toHasAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) _inst_2 (RingAut.applyMulSemiringAction.{u1} R _inst_2)))))
but is expected to have type
  forall {R : Type.{u1}} [_inst_2 : Semiring.{u1} R], FaithfulSMul.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (SMulZeroClass.toSMul.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (MonoidWithZero.toZero.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_2)) (DistribSMul.toSMulZeroClass.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (AddMonoid.toAddZeroClass.{u1} R (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (DistribMulAction.toDistribSMul.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.instGroupRingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) (AddMonoidWithOne.toAddMonoid.{u1} R (AddCommMonoidWithOne.toAddMonoidWithOne.{u1} R (NonAssocSemiring.toAddCommMonoidWithOne.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2)))) (MulSemiringAction.toDistribMulAction.{u1, u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) R (DivInvMonoid.toMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (Group.toDivInvMonoid.{u1} (RingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))) (RingAut.instGroupRingAut.{u1} R (NonUnitalNonAssocSemiring.toMul.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))) (Distrib.toAdd.{u1} R (NonUnitalNonAssocSemiring.toDistrib.{u1} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u1} R (Semiring.toNonAssocSemiring.{u1} R _inst_2))))))) _inst_2 (RingAut.applyMulSemiringAction.{u1} R _inst_2)))))
Case conversion may be inaccurate. Consider using '#align ring_aut.apply_has_faithful_smul RingAut.apply_faithfulSMulₓ'. -/
instance apply_faithfulSMul : FaithfulSMul (RingAut R) R :=
  ⟨fun _ _ => RingEquiv.ext⟩
#align ring_aut.apply_has_faithful_smul RingAut.apply_faithfulSMul

variable (G R)

/- warning: mul_semiring_action.to_ring_aut -> MulSemiringAction.toRingAut is a dubious translation:
lean 3 declaration is
  forall (G : Type.{u1}) (R : Type.{u2}) [_inst_1 : Group.{u1} G] [_inst_2 : Semiring.{u2} R] [_inst_3 : MulSemiringAction.{u1, u2} G R (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)) _inst_2], MonoidHom.{u1, u2} G (RingAut.{u2} R (Distrib.toHasMul.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2)))) (Distrib.toHasAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (Monoid.toMulOneClass.{u2} (RingAut.{u2} R (Distrib.toHasMul.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2)))) (Distrib.toHasAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))) (DivInvMonoid.toMonoid.{u2} (RingAut.{u2} R (Distrib.toHasMul.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2)))) (Distrib.toHasAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))) (Group.toDivInvMonoid.{u2} (RingAut.{u2} R (Distrib.toHasMul.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2)))) (Distrib.toHasAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))) (RingAut.group.{u2} R (Distrib.toHasMul.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2)))) (Distrib.toHasAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))))))
but is expected to have type
  forall (G : Type.{u1}) (R : Type.{u2}) [_inst_1 : Group.{u1} G] [_inst_2 : Semiring.{u2} R] [_inst_3 : MulSemiringAction.{u1, u2} G R (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)) _inst_2], MonoidHom.{u1, u2} G (RingAut.{u2} R (NonUnitalNonAssocSemiring.toMul.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))) (Distrib.toAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (Monoid.toMulOneClass.{u2} (RingAut.{u2} R (NonUnitalNonAssocSemiring.toMul.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))) (Distrib.toAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))) (DivInvMonoid.toMonoid.{u2} (RingAut.{u2} R (NonUnitalNonAssocSemiring.toMul.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))) (Distrib.toAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))) (Group.toDivInvMonoid.{u2} (RingAut.{u2} R (NonUnitalNonAssocSemiring.toMul.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))) (Distrib.toAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))) (RingAut.instGroupRingAut.{u2} R (NonUnitalNonAssocSemiring.toMul.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))) (Distrib.toAdd.{u2} R (NonUnitalNonAssocSemiring.toDistrib.{u2} R (NonAssocSemiring.toNonUnitalNonAssocSemiring.{u2} R (Semiring.toNonAssocSemiring.{u2} R _inst_2))))))))
Case conversion may be inaccurate. Consider using '#align mul_semiring_action.to_ring_aut MulSemiringAction.toRingAutₓ'. -/
/-- Each element of the group defines a ring automorphism.

This is a stronger version of `distrib_mul_action.to_add_aut` and
`mul_distrib_mul_action.to_mul_aut`. -/
@[simps]
def MulSemiringAction.toRingAut [MulSemiringAction G R] : G →* RingAut R
    where
  toFun := MulSemiringAction.toRingEquiv G R
  map_mul' g h := RingEquiv.ext <| mul_smul g h
  map_one' := RingEquiv.ext <| one_smul _
#align mul_semiring_action.to_ring_aut MulSemiringAction.toRingAut

end Semiring

end RingAut


/-
Copyright (c) 2022 Tian Chen. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Tian Chen
-/

import matrix.support

open_locale big_operators matrix

namespace matrix

section

variables {m n α : Type*} [fintype m] [fintype n] [ordered_add_comm_monoid α] [has_one α]

structure doubly_stochastic (M : matrix m n α) : Prop :=
  (nonneg : ∀ i j, 0 ≤ M i j)
  (row : ∀ i, ∑ j, M i j = 1)
  (col : ∀ j, ∑ i, M i j = 1)

lemma doubly_stochastic_iff (M : matrix m n α) :
  M.doubly_stochastic ↔
    (∀ i j, 0 ≤ M i j) ∧ (∀ i, ∑ j, M i j = 1) ∧ (∀ j, ∑ i, M i j = 1) :=
⟨λ h, ⟨h.nonneg, h.row, h.col⟩, λ ⟨h₁, h₂, h₃⟩, ⟨h₁, h₂, h₃⟩⟩

lemma _root_.equiv.doubly_stochastic [decidable_eq m] [decidable_eq n] (σ : m ≃ n) (β : Type*)
  [ordered_add_comm_monoid β] [has_one β] [zero_le_one_class β] :
  (σ.to_pequiv.to_matrix : matrix m n β).doubly_stochastic :=
⟨λ i j, begin
  rw pequiv.to_matrix,
  split_ifs,
  exact zero_le_one,
  exact le_rfl
end,
λ i, by simp_rw [pequiv.to_matrix, equiv.to_pequiv_apply, option.mem_some_iff];
  rw [finset.sum_ite_eq, if_pos]; exact finset.mem_univ _,
λ j, by simp_rw [pequiv.to_matrix, equiv.to_pequiv_apply,
    option.mem_some_iff, ← equiv.eq_symm_apply];
  rw [finset.sum_ite_eq', if_pos]; exact finset.mem_univ _⟩

lemma doubly_stochastic_one [decidable_eq n] [zero_le_one_class α] :
  (1 : matrix n n α).doubly_stochastic :=
⟨λ i j,
begin
  rw one_apply,
  split_ifs,
  exact zero_le_one,
  exact le_rfl
end,
λ i, show ∑ _, ite _ _ _ = _, by rw [finset.sum_ite_eq, if_pos (finset.mem_univ _)],
λ j, show ∑ _, ite _ _ _ = _, by rw [finset.sum_ite_eq', if_pos (finset.mem_univ _)]⟩

namespace doubly_stochastic

lemma of_transpose_eq_self {M : matrix n n α} (hM : Mᵀ = M)
  (h₁ : ∀ i j, 0 ≤ M i j) (h₂ : ∀ i, ∑ j, M i j = 1) :
  M.doubly_stochastic :=
begin
  refine ⟨h₁, h₂, _⟩,
  rw ← hM,
  exact h₂
end

variables {M : matrix m n α}

lemma le_one (hM : M.doubly_stochastic) (i j) : M i j ≤ 1 :=
calc M i j = ∑ j in {j}, M i j :
  finset.sum_singleton.symm
... ≤ ∑ j, M i j :
  finset.sum_le_sum_of_subset_of_nonneg (finset.subset_univ _) $ λ _ _ _, hM.nonneg _ _
... = 1 : hM.row i

lemma transpose (hM : M.doubly_stochastic) : Mᵀ.doubly_stochastic :=
  ⟨λ i j, hM.nonneg j i, hM.col, hM.row⟩

lemma reindex (hM : M.doubly_stochastic) {m' n' : Type*} [fintype m'] [fintype n']
  (e₁ : m ≃ m') (e₂ : n ≃ n') :
  (reindex e₁ e₂ M).doubly_stochastic :=
⟨λ i j, hM.nonneg _ _,
  λ i, by simp_rw [reindex_apply, submatrix_apply];
    rw [← hM.row (e₁.symm i)];
    apply fintype.sum_equiv e₂.symm;
    intro; refl,
  λ j, by simp_rw [reindex_apply, submatrix_apply];
    rw [← hM.col (e₂.symm j)];
    apply fintype.sum_equiv e₁.symm;
    intro; refl⟩

variables [ne_zero (1 : α)]

lemma apply_curry_finsupp_nonzero (hM : M.doubly_stochastic) (i : m) :
  M.finsupp.curry i ≠ 0 :=
begin
  intros h,
  apply @one_ne_zero α,
  rw ← hM.row i,
  apply finset.sum_eq_zero,
  intros j _,
  show M.finsupp (i, j) = _,
  rw [← finsupp.curry_apply, h, finsupp.zero_apply]
end

lemma card_finsupp_row_pos (hM : M.doubly_stochastic) (i : m) :
  0 < (M.finsupp.curry i).support.card :=
begin
  rw [finset.card_pos, finsupp.support_nonempty_iff],
  exact hM.apply_curry_finsupp_nonzero i
end

lemma card_univ_le_card_support (hM : M.doubly_stochastic) :
  fintype.card m ≤ M.support.card :=
calc fintype.card m = ∑ i, 1 :
  fintype.card_eq_sum_ones
... ≤ ∑ i, (M.finsupp.curry i).support.card :
  finset.sum_le_sum $ λ i _, hM.card_finsupp_row_pos _
... = M.support.card :
  support_card_eq_sum_row.symm

lemma card_support_finsupp_eq_one (hM : M.doubly_stochastic)
  (h : M.support.card = fintype.card m) (i : m) :
  (M.finsupp.curry i).support.card = 1 :=
begin
  symmetry,
  by_contra h₁,
  have h' := lt_of_le_of_ne (nat.one_le_of_lt (hM.card_finsupp_row_pos i)) h₁,
  apply h.symm.not_lt,
  calc fintype.card m
      = ∑ i, 1 :
    fintype.card_eq_sum_ones
  ... < ∑ i, (M.finsupp.curry i).support.card :
    finset.sum_lt_sum (λ i _, hM.card_finsupp_row_pos i) ⟨i, finset.mem_univ _, h'⟩
  ... = M.support.card : support_card_eq_sum_row.symm
end

lemma card_support_finsupp_col_eq_one (hM : M.doubly_stochastic)
  (h : M.support.card = fintype.card n) (j : n) :
  ((M.finsupp.equiv_map_domain (equiv.prod_comm m n)).curry j).support.card = 1 :=
by rw [finsupp.transpose', hM.transpose.card_support_finsupp_eq_one];
  rw [card_support_transpose, h]

lemma support_curry_inj (hM : M.doubly_stochastic)
  (hm : M.support.card = fintype.card m)
  (hn : M.support.card = fintype.card n) (i₁ i₂)
  (h : (M.finsupp.curry i₁).support = (M.finsupp.curry i₂).support) : i₁ = i₂ :=
begin
  obtain ⟨j₁, h₁⟩ := finsupp.card_support_eq_one.mp (hM.card_support_finsupp_eq_one hm i₁),
  obtain ⟨j₂, h₂⟩ := finsupp.card_support_eq_one.mp (hM.card_support_finsupp_eq_one hm i₂),
  rw [finsupp.support_eq_singleton.mpr h₁, finsupp.support_eq_singleton.mpr h₂,
    finset.singleton_inj] at h,
  rw h at *,
  rw [curry_finsupp_apply] at *,
  obtain ⟨i, hi⟩ := finsupp.card_support_eq_one.mp (hM.card_support_finsupp_col_eq_one hn j₂),
  have h₁':= fun_like.congr_fun hi.2 i₁,
  have h₂' := fun_like.congr_fun hi.2 i₂,
  iterate 2 {
    rw [finsupp.curry_apply, finsupp.equiv_map_domain_apply, equiv.prod_comm_symm,
      equiv.prod_comm_apply, prod.swap_prod_mk, finsupp_apply] at h₁' h₂' },
  rw h₁' at h₁,
  rw h₂' at h₂,
  rw finsupp.single_apply_ne_zero at h₁ h₂,
  rw [h₁.1.1, h₂.1.1],
end

/-- An `n` by `n` matrix is doubly stochastic and has exactly `n` non-zero entries
  iff it's a permutation matrix -/
lemma card_eq_card_support_iff [decidable_eq m] [decidable_eq n] [zero_le_one_class α] :
  M.doubly_stochastic ∧ M.support.card = fintype.card m ∧ M.support.card = fintype.card n ↔
  ∃ σ : m ≃ n, M = σ.to_pequiv.to_matrix :=
begin
  split,
  { rintro ⟨hM, hm, hn⟩,
    have h := λ i, finsupp.card_support_eq_one.mp (hM.card_support_finsupp_eq_one hm i),
    refine ⟨equiv.of_bijective (λ i, classical.some $ h i) _, _⟩,
    { suffices : function.injective _,
      { exact ⟨this, this.surjective_of_fintype (fintype.equiv_of_card_eq (hm.symm.trans hn))⟩ },
      intros i₁ i₂ hi,
      apply hM.support_curry_inj hm hn,
      have hi₁ := classical.some_spec (h i₁),
      have hi₂ := classical.some_spec (h i₂),
      rw ← finsupp.support_eq_singleton at hi₁ hi₂,
      rw [hi₁, hi₂, show classical.some _ = _, from hi] },
    { ext i j,
      have hi := classical.some_spec (h i),
      rw [pequiv.to_matrix, equiv.to_pequiv_apply],
      simp_rw [option.mem_some_iff],
      split_ifs with h' h',
      { rw [← h', ← hM.row i],
        calc  M i (classical.some (h i))
            = ∑ j, finsupp.single (classical.some (h i))
                (M.finsupp.curry i (classical.some (h i))) j :
                by rw [finsupp.sum_univ_single, curry_finsupp_apply]
        ... = ∑ j, M i j :
                finset.sum_congr rfl $ λ j' _, by rw [← hi.2, curry_finsupp_apply] },
      { by_contra hMij,
        rw ← finsupp.support_eq_singleton at hi,
        rw [← curry_finsupp_apply M i j, ← ne.def, ← finsupp.mem_support_iff,
          hi, finset.mem_singleton] at hMij,
        exact h' hMij.symm } } },
  { rintro ⟨σ, rfl⟩,
    exact ⟨σ.doubly_stochastic α, σ.card_support_to_matrix, σ.card_support_to_matrix'⟩ }
end

end doubly_stochastic

end

namespace doubly_stochastic

variables {m n α : Type*} [fintype m] [fintype n]

lemma card_eq_card [ordered_semiring α] [char_zero α]
  {M : matrix m n α} (hM : M.doubly_stochastic) :
  fintype.card m = fintype.card n :=
nat.cast_inj.1 $
calc (finset.univ.card : α)
    = ∑ i : m, 1 : by rw [finset.sum_const, nsmul_one]
... = ∑ i, (∑ j, M i j) : by simp_rw [hM.row]
... = ∑ j : n, 1 : by rw [finset.sum_comm]; simp_rw [hM.col]
... = finset.univ.card : by rw [finset.sum_const, nsmul_one]

section

variables [ordered_cancel_add_comm_monoid α] [has_one α] [decidable_eq n]
  {M : matrix m n α}

lemma row_eq_zero_of_ne (hM : M.doubly_stochastic) {i j} (h : M i j = 1) :
  ∀ j', j ≠ j' → M i j' = 0 :=
begin
  intros j' hj',
  have := hM.row i,
  rw [← finset.add_sum_erase _ _ (finset.mem_univ j), h, add_right_eq_self,
    finset.sum_eq_zero_iff_of_nonneg] at this,
  apply this,
  exact finset.mem_erase_of_ne_of_mem hj'.symm (finset.mem_univ _),
  { intros,
    apply hM.nonneg }
end

lemma col_eq_zero_of_ne [decidable_eq m] (hM : M.doubly_stochastic) {i j} (h : M i j = 1) :
  ∀ i', i ≠ i' → M i' j = 0 :=
hM.transpose.row_eq_zero_of_ne h

end

variables {l : Type*} [fintype l] [ordered_semiring α]
  {M : matrix l m α} {N : matrix m n α}

lemma mul (hM : M.doubly_stochastic) (hN : N.doubly_stochastic) :
  (M.mul N).doubly_stochastic :=
begin
  split,
  { intros i j,
    apply finset.sum_nonneg,
    intros k _,
    exact mul_nonneg (hM.nonneg _ _) (hN.nonneg _ _) },
  all_goals {
    intro,
    simp_rw [mul_apply],
    rw [finset.sum_comm] },
  { simp_rw [← finset.mul_sum, hN.row, mul_one],
    exact hM.row _ },
  { simp_rw [← finset.sum_mul, hM.col, one_mul],
    exact hN.col _ }
end

end doubly_stochastic

end matrix