/-
Copyright (c) 2021 Yaël Dillies, Bhavik Mehta. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yaël Dillies, Bhavik Mehta
-/
import combinatorics.simplicial_complex.closure
import combinatorics.simplicial_complex.star

namespace affine
open set
variables {m n k : ℕ} {E : Type*} [normed_group E] [normed_space ℝ E]
  {S : simplicial_complex E} {X Y : finset E} {A : set (finset E)}
  [semilattice_inf_bot (finset E)] [decidable_eq E]

def simplicial_complex.link (S : simplicial_complex E) (A : set (finset E)) :
  simplicial_complex E :=
{ faces := {X | (∀ {W}, W ∈ A → disjoint W X) ∧ ∃ {Y Z}, Y ∈ A ∧ Z ∈ S.faces ∧ X ⊆ Z ∧ Y ⊆ Z},
  indep := λ X ⟨hXdisj, Y, Z, hY, hZ, hXZ, hYZ⟩, S.indep (S.down_closed hZ hXZ),
  down_closed := begin
    rintro X W ⟨hXdisj, Y, Z, hY, hZ, hXZ, hYZ⟩ hWX,
    split,
    { rintro V hV,
     -- exact finset.disjoint_of_subset_right hWX (hXdisj hV),
     sorry
    },
    { exact ⟨Y, Z, hY, hZ, subset.trans hWX hXZ, hYZ⟩ }
  end,
  disjoint := λ X X' ⟨hXdisj, Y, Z, hY, hZ, hXZ, hYZ⟩ ⟨hXdisj', Y', Z', hY', hZ', hXZ', hYZ'⟩,
    S.disjoint (S.down_closed hZ hXZ) (S.down_closed hZ' hXZ') }

lemma link_empty :
  (S.link ∅).faces = ∅ :=
begin
  unfold simplicial_complex.link,
  simp,
end

lemma link_singleton_empty :
  S.link {∅} = S :=
begin
  /-
  ext X,
  split,
  {
    rintro ⟨_, _, Z, _, hZ, hXZ, _⟩,
    exact S.down_closed hZ hXZ,
  },
  {
    rintro hX,
    split,
    { rintro W (h : W = ∅),
      rw h,
      exact finset.disjoint_empty_left X, },
    exact ⟨∅, X, rfl, hX, subset.refl X, empty_subset X⟩,
  }
  -/
  sorry
end

lemma mem_link_singleton_iff :
  Y ∈ (S.link {X}).faces ↔ disjoint X Y ∧ ∃ {Z}, Z ∈ S.faces ∧ Y ⊆ Z ∧ X ⊆ Z :=
begin
  unfold simplicial_complex.link,
  simp,
end

lemma link_singleton_subset (hX : X ≠ ∅) :
  (S.link {X}).faces ⊆ (S.Star {X}).faces \ S.star {X} :=
begin
  rintro Y ⟨hY, W, Z, (hWX : W = X), hZ, hYZ, hWZ⟩,
  simp at hY,
  subst hWX,
  split,
  { exact ⟨W, Z, mem_singleton W, hZ, hYZ, hWZ⟩, },
  { rintro h,
    rw mem_star_singleton_iff at h,
    --exact hX (disjoint_self.1 (finset.disjoint_of_subset_right h.2 hY)), }
    sorry
  }
end

lemma link_singleton_eq_Star_minus_star_iff_singleton (hX : X ≠ ∅) :
  (S.link {X}).faces = (S.Star {X}).faces \ S.star {X} ↔ X.card = 1 :=
begin
  split,
  {
    sorry --true? The PDF claims so but I'm not sure
  },
  {
    sorry
    /-
    rintro hXcard,
    apply subset.antisymm (link_singleton_subset hX),
    rintro Y ⟨h, hYstar⟩,
    obtain ⟨Z, hZ, hYZ, hXZ⟩ := mem_Star_singleton_iff.1 h,
    split,
    {
      obtain ⟨x, hxX⟩ := finset.card_eq_one.1 hXcard,
      rintro W (hW : W = X),
      subst hW,
      subst hxX,
      rw finset.singleton_disjoint,
      rintro hx,
      apply hYstar,
      rw [mem_star_singleton_iff, finset.singleton_subset_iff],
      exact ⟨S.down_closed hZ hYZ, hx⟩,
    },
    exact ⟨X, Z, rfl, hZ, hYZ, hXZ⟩,
    -/
  }
end

lemma link_subset :
  (S.link A).faces ⊆ S.faces :=
λ X ⟨hXdisj, Y, Z, hY, hZ, hXZ, hYZ⟩, S.down_closed hZ hXZ

lemma link_eq_Star_sub_star_closure {S : simplicial_complex E} {A : set (finset E)} :
  (S.link A).faces = (S.Star A).faces \ S.star ((S.closure A).faces \ {∅}) :=
begin
  /-
  ext X,
  split,
  {

    rintro ⟨hXdisj, hXStar⟩,
    use hXStar,
    rintro ⟨hX, Y, ⟨⟨hY, Z, hZ, hYZ⟩, (hYnonempty : Y ≠ ∅)⟩, hYX⟩,
    have hYZX : Y ⊆ Z ∩ X := finset.subset_inter hYZ hYX,
    rw finset.disjoint_iff_inter_eq_empty.mp (hXdisj hZ) at hYZX,
    exact hYnonempty (finset.subset_empty.mp hYZX),
  },
  {
    rintro ⟨hXStar, hX'⟩,
    split,
    {
      rintro W hW,
      rw finset.disjoint_iff_inter_eq_empty,
      apply finset.eq_empty_of_forall_not_mem,
      rintro x hx,
      apply hX',
      use Star_subset hXStar,
      use {x},
      split,
      split,
      {
        unfold simplicial_complex.closure simplicial_complex.of_surcomplex,
        simp,
        exact ⟨S.down_closed (Star_subset hXStar) (subset.trans (finset.singleton_subset_iff.2 hx)
          (finset.inter_subset_right _ _)), W, hW, finset.inter_subset_left _ _ hx⟩,
      },
      rintro (h : {x} = ∅),
      exact (finset.singleton_ne_empty x) h,
      exact finset.singleton_subset_iff.2 (finset.inter_subset_right W X hx),
    },
    { exact hXStar }
  }
  -/
  sorry
end
/-

lemma link_facet_iff {S : simplicial_complex E} {A : set (finset E)} {n k : ℕ}
  (hS : S.pure_of n) {X : finset E} (hA : ∀ {W}, W ∈ A → (W : finset _).card = k) :
  X ∈ (S.link A).facets ↔ ∃ {W Y}, W ∈ A ∧ Y ∈ S.facets ∧ W ⊆ Y ∧ X = Y \ W :=-/

-- X ∈ (S.link A).facets ↔ X ∉ S.facets ∧ (∀ {W}, W ∈ A → disjoint W X) ∧ ∃ {Y W Z}, Y ∈ S.facets ∧
--   W ∈ A ∧ Z ∈ S.facets ∧ X ∪ W ⊆ Z ∧ ∀ {y}, y ∈ Y → y ∈ X ∨ ∃ {V}, V ∈ A ∧ y ∈ V
lemma link_facet_iff :
  X ∈ (S.link A).facets ↔ X ∉ S.facets ∧ (∀ {W}, W ∈ A → disjoint W X) ∧ ∃ {W Y Z},
   W ∈ A ∧ Y ∈ S.facets ∧ Z ∈ S.faces ∧ X ∪ W ⊆ Z ∧ ∀ {y}, y ∈ Y → y ∈ X ∨ ∃ {V}, V ∈ A ∧ y ∈ V :=
begin
  split,
  {
    rintro ⟨⟨hXdisj, W, Z, hW, hZ, hXZ, hWZ⟩, hXmax⟩,
    sorry
    /-obtain ⟨Y, hY, hZY⟩ := subfacet hZ,
    split,
    {
      sorry
    },
    {
      use [(λ W, hXdisj), W, Y, Z, hW, hY, hZ, finset.union_subset hXZ hWZ],
      rintro y hy,
      sorry
    }-/
  },
  {
    rintro ⟨stuff, hXdisj, W, Y, Z, hW, hY, hZ, hXYW, hunion⟩,
    split,
    {
      have hXZ : X ⊆ Z := sorry, -- finset.union_subset_iff.1 hXYW
      have hWZ : W ⊆ Z := sorry, -- finset.union_subset_iff.1 hXYW
      exact ⟨(λ V, hXdisj), W, Z, hW, hZ, hXZ, hWZ⟩,
    },
    {
      rintro V ⟨hVdisj, U, R, hU, hR, hVR, hUR⟩ hXV,
      apply finset.subset.antisymm hXV,
      rintro v hv,
      /-have := hA hU hW (facets_subset hY) hWY,
      rw finset.mem_sdiff,-/
      --have := hA hV hW (facets_subset hY) hWY ⟨x, finset.mem_inter.2 ⟨hx.1, hx.2.1⟩⟩,
      sorry
      /-apply finset.eq_of_subset_of_card_le hYWX,
      rw finset.card_sdiff hWY,
      have := finset.card_le_of_subset (finset.union_subset hUV hXV),
      rw [finset.card_disjoint_union (hXdisj hU), hA hU] at this,
      rw [hA hW, hS hY],
      exact nat.le_sub_left_of_add_le (le_trans this (face_card_le_pureness hS hV)),-/
    }
  }
end

lemma pure_link_of_pure (hS : S.pure_of n) (hA : ∀ {X}, X ∈ A → (X : finset _).card = k) :
  (S.link A).pure_of (n - k) :=
begin
  rintro X ⟨⟨hXdisj, W, Z, hW, hZ, hXZ, hWZ⟩, hXmax⟩, --easy once we have `link_facet_iff`
  sorry
end

end affine


/-
Copyright (c) 2019 Scott Morrison. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Reid Barton, Patrick Massot, Scott Morrison

! This file was ported from Lean 3 source module topology.category.UniformSpace
! leanprover-community/mathlib commit 70fd9563a21e7b963887c9360bd29b2393e6225a
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.CategoryTheory.Adjunction.Reflective
import Mathbin.CategoryTheory.ConcreteCategory.UnbundledHom
import Mathbin.CategoryTheory.Monad.Limits
import Mathbin.Topology.Category.Top.Basic
import Mathbin.Topology.UniformSpace.Completion

/-!
# The category of uniform spaces

We construct the category of uniform spaces, show that the complete separated uniform spaces
form a reflective subcategory, and hence possess all limits that uniform spaces do.

TODO: show that uniform spaces actually have all limits!
-/

universe u

open CategoryTheory

/-- A (bundled) uniform space. -/
def UniformSpaceCat : Type (u + 1) :=
  Bundled UniformSpace
#align UniformSpace UniformSpaceCat

namespace UniformSpaceCat

/-- The information required to build morphisms for `UniformSpace`. -/
instance : UnbundledHom @UniformContinuous :=
  ⟨@uniformContinuous_id, @UniformContinuous.comp⟩

deriving instance LargeCategory, ConcreteCategory for UniformSpaceCat

instance : CoeSort UniformSpaceCat (Type _) :=
  Bundled.hasCoeToSort

instance (x : UniformSpaceCat) : UniformSpace x :=
  x.str

/-- Construct a bundled `UniformSpace` from the underlying type and the typeclass. -/
def of (α : Type u) [UniformSpace α] : UniformSpaceCat :=
  ⟨α⟩
#align UniformSpace.of UniformSpaceCat.of

instance : Inhabited UniformSpaceCat :=
  ⟨UniformSpaceCat.of Empty⟩

@[simp]
theorem coe_of (X : Type u) [UniformSpace X] : (of X : Type u) = X :=
  rfl
#align UniformSpace.coe_of UniformSpaceCat.coe_of

instance (X Y : UniformSpaceCat) : CoeFun (X ⟶ Y) fun _ => X → Y :=
  ⟨CategoryTheory.Functor.map (forget UniformSpaceCat)⟩

@[simp]
theorem coe_comp {X Y Z : UniformSpaceCat} (f : X ⟶ Y) (g : Y ⟶ Z) : (f ≫ g : X → Z) = g ∘ f :=
  rfl
#align UniformSpace.coe_comp UniformSpaceCat.coe_comp

@[simp]
theorem coe_id (X : UniformSpaceCat) : (𝟙 X : X → X) = id :=
  rfl
#align UniformSpace.coe_id UniformSpaceCat.coe_id

@[simp]
theorem coe_mk {X Y : UniformSpaceCat} (f : X → Y) (hf : UniformContinuous f) :
    ((⟨f, hf⟩ : X ⟶ Y) : X → Y) = f :=
  rfl
#align UniformSpace.coe_mk UniformSpaceCat.coe_mk

theorem hom_ext {X Y : UniformSpaceCat} {f g : X ⟶ Y} : (f : X → Y) = g → f = g :=
  Subtype.eq
#align UniformSpace.hom_ext UniformSpaceCat.hom_ext

/-- The forgetful functor from uniform spaces to topological spaces. -/
instance hasForgetToTop : HasForget₂ UniformSpaceCat.{u} TopCat.{u}
    where forget₂ :=
    { obj := fun X => TopCat.of X
      map := fun X Y f =>
        { toFun := f
          continuous_toFun := UniformContinuous.continuous f.property } }
#align UniformSpace.has_forget_to_Top UniformSpaceCat.hasForgetToTop

end UniformSpaceCat

/-- A (bundled) complete separated uniform space. -/
structure CpltSepUniformSpace where
  α : Type u
  [isUniformSpace : UniformSpace α]
  [is_completeSpace : CompleteSpace α]
  [is_separated : SeparatedSpace α]
#align CpltSepUniformSpace CpltSepUniformSpace

namespace CpltSepUniformSpace

instance : CoeSort CpltSepUniformSpace (Type u) :=
  ⟨CpltSepUniformSpace.α⟩

attribute [instance] is_uniform_space is_complete_space is_separated

/-- The function forgetting that a complete separated uniform spaces is complete and separated. -/
def toUniformSpace (X : CpltSepUniformSpace) : UniformSpaceCat :=
  UniformSpaceCat.of X
#align CpltSepUniformSpace.to_UniformSpace CpltSepUniformSpace.toUniformSpace

instance completeSpace (X : CpltSepUniformSpace) : CompleteSpace (toUniformSpace X).α :=
  CpltSepUniformSpace.is_completeSpace X
#align CpltSepUniformSpace.complete_space CpltSepUniformSpace.completeSpace

instance separatedSpace (X : CpltSepUniformSpace) : SeparatedSpace (toUniformSpace X).α :=
  CpltSepUniformSpace.is_separated X
#align CpltSepUniformSpace.separated_space CpltSepUniformSpace.separatedSpace

/-- Construct a bundled `UniformSpace` from the underlying type and the appropriate typeclasses. -/
def of (X : Type u) [UniformSpace X] [CompleteSpace X] [SeparatedSpace X] : CpltSepUniformSpace :=
  ⟨X⟩
#align CpltSepUniformSpace.of CpltSepUniformSpace.of

@[simp]
theorem coe_of (X : Type u) [UniformSpace X] [CompleteSpace X] [SeparatedSpace X] :
    (of X : Type u) = X :=
  rfl
#align CpltSepUniformSpace.coe_of CpltSepUniformSpace.coe_of

instance : Inhabited CpltSepUniformSpace :=
  haveI : SeparatedSpace Empty := separated_iff_t2.mpr (by infer_instance)
  ⟨CpltSepUniformSpace.of Empty⟩

/-- The category instance on `CpltSepUniformSpace`. -/
instance category : LargeCategory CpltSepUniformSpace :=
  InducedCategory.category toUniformSpace
#align CpltSepUniformSpace.category CpltSepUniformSpace.category

/-- The concrete category instance on `CpltSepUniformSpace`. -/
instance concreteCategory : ConcreteCategory CpltSepUniformSpace :=
  InducedCategory.concreteCategory toUniformSpace
#align CpltSepUniformSpace.concrete_category CpltSepUniformSpace.concreteCategory

instance hasForgetToUniformSpace : HasForget₂ CpltSepUniformSpace UniformSpaceCat :=
  InducedCategory.hasForget₂ toUniformSpace
#align CpltSepUniformSpace.has_forget_to_UniformSpace CpltSepUniformSpace.hasForgetToUniformSpace

end CpltSepUniformSpace

namespace UniformSpaceCat

open UniformSpace

open CpltSepUniformSpace

/-- The functor turning uniform spaces into complete separated uniform spaces. -/
noncomputable def completionFunctor : UniformSpaceCat ⥤ CpltSepUniformSpace
    where
  obj X := CpltSepUniformSpace.of (Completion X)
  map X Y f := ⟨Completion.map f.1, Completion.uniformContinuous_map⟩
  map_id' X := Subtype.eq Completion.map_id
  map_comp' X Y Z f g := Subtype.eq (Completion.map_comp g.property f.property).symm
#align UniformSpace.completion_functor UniformSpaceCat.completionFunctor

/-- The inclusion of a uniform space into its completion. -/
def completionHom (X : UniformSpaceCat) :
    X ⟶ (forget₂ CpltSepUniformSpace UniformSpaceCat).obj (completionFunctor.obj X)
    where
  val := (coe : X → Completion X)
  property := Completion.uniformContinuous_coe X
#align UniformSpace.completion_hom UniformSpaceCat.completionHom

@[simp]
theorem completionHom_val (X : UniformSpaceCat) (x) : (completionHom X) x = (x : Completion X) :=
  rfl
#align UniformSpace.completion_hom_val UniformSpaceCat.completionHom_val

/-- The mate of a morphism from a `UniformSpace` to a `CpltSepUniformSpace`. -/
noncomputable def extensionHom {X : UniformSpaceCat} {Y : CpltSepUniformSpace}
    (f : X ⟶ (forget₂ CpltSepUniformSpace UniformSpaceCat).obj Y) : completionFunctor.obj X ⟶ Y
    where
  val := Completion.extension f
  property := Completion.uniformContinuous_extension
#align UniformSpace.extension_hom UniformSpaceCat.extensionHom

@[simp]
theorem extensionHom_val {X : UniformSpaceCat} {Y : CpltSepUniformSpace}
    (f : X ⟶ (forget₂ _ _).obj Y) (x) : (extensionHom f) x = Completion.extension f x :=
  rfl
#align UniformSpace.extension_hom_val UniformSpaceCat.extensionHom_val

@[simp]
theorem extension_comp_coe {X : UniformSpaceCat} {Y : CpltSepUniformSpace}
    (f : toUniformSpace (CpltSepUniformSpace.of (Completion X)) ⟶ toUniformSpace Y) :
    extensionHom (completionHom X ≫ f) = f :=
  by
  apply Subtype.eq
  funext x
  exact congr_fun (completion.extension_comp_coe f.property) x
#align UniformSpace.extension_comp_coe UniformSpaceCat.extension_comp_coe

/-- The completion functor is left adjoint to the forgetful functor. -/
noncomputable def adj : completionFunctor ⊣ forget₂ CpltSepUniformSpace UniformSpaceCat :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => completionHom X ≫ f
          invFun := fun f => extensionHom f
          left_inv := fun f => by
            dsimp
            erw [extension_comp_coe]
          right_inv := fun f => by
            apply Subtype.eq; funext x; cases f
            exact
              @completion.extension_coe _ _ _ _ _ (CpltSepUniformSpace.separatedSpace _) f_property
                _ }
      homEquiv_naturality_left_symm := fun X X' Y f g =>
        by
        apply hom_ext; funext x; dsimp
        erw [coe_comp, ← completion.extension_map]
        rfl; exact g.property; exact f.property }
#align UniformSpace.adj UniformSpaceCat.adj

noncomputable instance : IsRightAdjoint (forget₂ CpltSepUniformSpace UniformSpaceCat) :=
  ⟨completionFunctor, adj⟩

noncomputable instance : Reflective (forget₂ CpltSepUniformSpace UniformSpaceCat) where

open CategoryTheory.Limits

-- TODO Once someone defines `has_limits UniformSpace`, turn this into an instance.
example [HasLimits.{u} UniformSpaceCat.{u}] : HasLimits.{u} CpltSepUniformSpace.{u} :=
  has_limits_of_reflective <| forget₂ CpltSepUniformSpace UniformSpaceCat.{u}

end UniformSpaceCat


/-
Copyright (c) 2019 Scott Morrison. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Scott Morrison, Johannes Hölzl
-/
import Mathlib.PrePort
import Mathlib.Lean3Lib.init.default
import Mathlib.algebra.category.CommRing.basic
import Mathlib.data.mv_polynomial.default
import Mathlib.PostPort

universes u u_1 u_2

namespace Mathlib

/-!
Multivariable polynomials on a type is the left adjoint of the
forgetful functor from commutative rings to types.
-/

namespace CommRing

/--
The free functor `Type u ⥤ CommRing` sending a type `X` to the multivariable (commutative)
polynomials with variables `x : X`.
-/
def free : Type u ⥤ CommRing :=
  category_theory.functor.mk (fun (α : Type u) => of (mv_polynomial α ℤ))
    fun (X Y : Type u) (f : X ⟶ Y) => ↑(mv_polynomial.rename f)

@[simp] theorem free_obj_coe {α : Type u} : ↥(category_theory.functor.obj free α) = mv_polynomial α ℤ :=
  rfl

@[simp] theorem free_map_coe {α : Type u} {β : Type u} {f : α → β} : ⇑(category_theory.functor.map free f) = ⇑(mv_polynomial.rename f) :=
  rfl

/--
The free-forgetful adjunction for commutative rings.
-/
def adj : free ⊣ category_theory.forget CommRing :=
  category_theory.adjunction.mk_of_hom_equiv
    (category_theory.adjunction.core_hom_equiv.mk fun (X : Type (max u_1 u_2)) (R : CommRing) => mv_polynomial.hom_equiv)


import analysis.complex.basic
import analysis.normed_space.operator_norm
import analysis.normed_space.hahn_banach
import .extend

open complex

variables {F : Type*} [normed_group F] [normed_space ℂ F]

noncomputable def restrict_scalars (p: subspace ℂ F) : subspace ℝ F := p.restrict_scalars ℝ

private lemma apply_real (p : subspace ℂ F) (f' : p →L[ℝ] ℝ) :
  ∃ g : F →L[ℝ] ℝ, (∀ x : restrict_scalars p, g x = f' x) ∧ ∥g∥ = ∥f'∥ :=
  exists_extension_norm_eq (p.restrict_scalars ℝ) f'

theorem complex.exists_extension_norm_eq (p : subspace ℂ F) (f : p →L[ℂ] ℂ) :
  ∃ g : F →L[ℂ] ℂ, (∀ x : p, g x = f x) ∧ ∥g∥ = ∥f∥ :=
begin
  -- Let `fr: p →L[ℝ] ℝ` be the real part of `f`.
  let fr := continuous_linear_map.re.comp (f.restrict_scalars ℝ),
  have fr_apply : ∀ x, fr x = (f x).re := λ x, rfl,

  -- Use the real version to get a norm-preserving extension of `fr`, which we'll call `g: F →L[ℝ] ℝ`.
  rcases apply_real p fr with ⟨g, ⟨hextends, hnormeq⟩⟩,

  -- Now `g` can be extended to the `F →L[ℂ] ℂ` we need.
  use g.extend_to_C,

  -- It is an extension of `f`.
  have : ∀ x : p, g.extend_to_C x = f x,
  {
    intros,
    change (g x : ℂ) - I * g ((I • x) : p) = f x,
    rw [sub_eq_add_neg, neg_mul_eq_mul_neg, ←of_real_neg, mul_comm, ←mk_eq_add_mul_I],
    ext,
    { rw [hextends, fr_apply] },
    rw [hextends (I • x : p), fr_apply, continuous_linear_map.map_smul,
      algebra.id.smul_eq_mul, mul_re, I_re, zero_mul, zero_sub, neg_neg, I_im, one_mul],
  },

  split,
  assumption,

  -- And we derive the equality of the norms by bounding on both sides.
  refine le_antisymm _ _,
  {
    calc ∥g.extend_to_C∥
        ≤ ∥g∥ : g.extend_to_C.op_norm_le_bound g.op_norm_nonneg (norm_bound _)
    ... = ∥fr∥ : hnormeq
    ... ≤ ∥continuous_linear_map.re∥ * ∥f∥ : continuous_linear_map.op_norm_comp_le _ _
    ... = ∥f∥ : by rw [complex.continuous_linear_map.re_norm, one_mul],
  },

  exact f.op_norm_le_bound g.extend_to_C.op_norm_nonneg (λ x, this x ▸ g.extend_to_C.le_op_norm x),
end


import for_mathlib.homological_complex_op
import for_mathlib.has_homology

noncomputable theory

open category_theory opposite

variables {𝓐 : Type*} [category 𝓐] [abelian 𝓐]
variables {ι : Type*} {c : complex_shape ι}

lemma is_iso_of_square {A B C D : 𝓐} (a : A ⟶ B) (b : B ⟶ D) (a' : A ⟶ C) (c : C ⟶ D) (w : a ≫ b = a' ≫ c)
  (ha : is_iso a) (hb : is_iso b) (ha' : is_iso a') :
  is_iso c :=
begin
  have hc : c = inv a' ≫ a ≫ b, { rw [is_iso.eq_inv_comp, w], },
  rw [hc], apply_instance,
end

def homology.map' {A₁ B₁ C₁ A₂ B₂ C₂ : 𝓐}
  {f₁ : A₁ ⟶ B₁} {g₁ : B₁ ⟶ C₁} (w₁ : f₁ ≫ g₁ = 0)
  {f₂ : A₂ ⟶ B₂} {g₂ : B₂ ⟶ C₂} (w₂ : f₂ ≫ g₂ = 0)
  {a : A₁ ⟶ A₂} {b : B₁ ⟶ B₂} {c : C₁ ⟶ C₂}
  (sq1 : commsq f₁ a b f₂) (sq2 : commsq g₁ b c g₂) :
  homology f₁ g₁ w₁ ⟶ homology f₂ g₂ w₂ :=
(homology.has f₁ g₁ w₁).map (homology.has f₂ g₂ w₂) sq1 sq2

lemma homology.map_eq {A₁ B₁ C₁ A₂ B₂ C₂ : 𝓐}
  {f₁ : A₁ ⟶ B₁} {g₁ : B₁ ⟶ C₁} (w₁ : f₁ ≫ g₁ = 0)
  {f₂ : A₂ ⟶ B₂} {g₂ : B₂ ⟶ C₂} (w₂ : f₂ ≫ g₂ = 0)
  (sq1 : arrow.mk f₁ ⟶ arrow.mk f₂) (sq2 : arrow.mk g₁ ⟶ arrow.mk g₂) (H) :
  homology.map w₁ w₂ sq1 sq2 H =
    @homology.map' _ _ _ _ _ _ _ _ _ _ _ w₁ _ _ w₂ sq1.left sq1.right sq2.right
      (commsq.of_eq sq1.w.symm) (commsq.of_eq $ by { rw H, exact sq2.w.symm }) :=
begin
  apply (homology.has f₂ g₂ w₂).ext_ι,
  erw [has_homology.map_ι],
  apply (homology.has f₁ g₁ w₁).ext_π,
  erw [← category.assoc, homology.π'_map, category.assoc, homology.π'_ι, has_homology.π_comp_desc,
    limits.kernel.lift_ι_assoc, category.assoc],
end


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

! This file was ported from Lean 3 source module topology.algebra.uniform_mul_action
! leanprover-community/mathlib commit 70fd9563a21e7b963887c9360bd29b2393e6225a
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Topology.Algebra.UniformGroup
import Mathlib.Topology.UniformSpace.Completion

/-!
# Multiplicative action on the completion of a uniform space

In this file we define typeclasses `UniformContinuousConstVAdd` and
`UniformContinuousConstSMul` and prove that a multiplicative action on `X` with uniformly
continuous `(•) c` can be extended to a multiplicative action on `UniformSpace.Completion X`.

In later files once the additive group structure is set up, we provide
* `UniformSpace.Completion.DistribMulAction`
* `UniformSpace.Completion.MulActionWithZero`
* `UniformSpace.Completion.Module`

TODO: Generalise the results here from the concrete `Completion` to any `AbstractCompletion`.
-/

universe u v w x y z

noncomputable section

variable (R : Type u) (M : Type v) (N : Type w) (X : Type x) (Y : Type y) [UniformSpace X]
  [UniformSpace Y]

/-- An additive action such that for all `c`, the map `λ x, c +ᵥ x` is uniformly continuous. -/
class UniformContinuousConstVAdd [VAdd M X] : Prop where
  uniformContinuous_const_vadd : ∀ c : M, UniformContinuous ((· +ᵥ ·) c : X → X)
#align has_uniform_continuous_const_vadd UniformContinuousConstVAdd

/-- A multiplicative action such that for all `c`, the map `λ x, c • x` is uniformly continuous. -/
@[to_additive]
class UniformContinuousConstSMul [SMul M X] : Prop where
  uniformContinuous_const_smul : ∀ c : M, UniformContinuous ((· • ·) c : X → X)
#align has_uniform_continuous_const_smul UniformContinuousConstSMul

export UniformContinuousConstVAdd (uniformContinuous_const_vadd)

export UniformContinuousConstSMul (uniformContinuous_const_smul)

instance AddMonoid.uniformContinuousConstSMul_nat [AddGroup X] [UniformAddGroup X] :
    UniformContinuousConstSMul ℕ X :=
  ⟨uniformContinuous_const_nsmul⟩
#align add_monoid.has_uniform_continuous_const_smul_nat AddMonoid.uniformContinuousConstSMul_nat

instance AddGroup.uniformContinuousConstSMul_int [AddGroup X] [UniformAddGroup X] :
    UniformContinuousConstSMul ℤ X :=
  ⟨uniformContinuous_const_zsmul⟩
#align add_group.has_uniform_continuous_const_smul_int AddGroup.uniformContinuousConstSMul_int

/-- A `DistribMulAction` that is continuous on a uniform group is uniformly continuous.
This can't be an instance due to it forming a loop with
`UniformContinuousConstSMul.to_continuousConstSMul` -/
theorem uniformContinuousConstSMul_of_continuousConstSMul [Monoid R] [AddCommGroup M]
    [DistribMulAction R M] [UniformSpace M] [UniformAddGroup M] [ContinuousConstSMul R M] :
    UniformContinuousConstSMul R M :=
  ⟨fun r =>
    uniformContinuous_of_continuousAt_zero (DistribMulAction.toAddMonoidHom M r)
      (Continuous.continuousAt (continuous_const_smul r))⟩
#align has_uniform_continuous_const_smul_of_continuous_const_smul uniformContinuousConstSMul_of_continuousConstSMul

section instances

variable [Ring R]

-- Porting note: needs Lean4#2074
instance : Module R R := Semiring.toModule
/-- The action of `Semiring.toModule` is uniformly continuous. -/
instance Ring.uniformContinuousConstSMul [Ring R] [UniformSpace R] [UniformAddGroup R]
    [ContinuousMul R] : UniformContinuousConstSMul R R :=
  uniformContinuousConstSMul_of_continuousConstSMul _ _
#align ring.has_uniform_continuous_const_smul Ring.uniformContinuousConstSMul

-- Porting note: needs Lean4#2074
instance : Module Rᵐᵒᵖ R := Semiring.toOppositeModule
/-- The action of `Semiring.toOppositeModule` is uniformly continuous. -/
instance Ring.uniformContinuousConstSMul_op [Ring R] [UniformSpace R] [UniformAddGroup R]
    [ContinuousMul R] : UniformContinuousConstSMul Rᵐᵒᵖ R :=
  uniformContinuousConstSMul_of_continuousConstSMul _ _
#align ring.has_uniform_continuous_const_op_smul Ring.uniformContinuousConstSMul_op

end instances

section SMul

variable [SMul M X]

@[to_additive]
instance (priority := 100) UniformContinuousConstSMul.to_continuousConstSMul
    [UniformContinuousConstSMul M X] : ContinuousConstSMul M X :=
  ⟨fun c => (uniformContinuous_const_smul c).continuous⟩
#align has_uniform_continuous_const_smul.to_has_continuous_const_smul UniformContinuousConstSMul.to_continuousConstSMul
#align has_uniform_continuous_const_vadd.to_has_continuous_const_vadd UniformContinuousConstVAdd.to_continuousConstVAdd

variable {M X Y}

@[to_additive]
theorem UniformContinuous.const_smul [UniformContinuousConstSMul M X] {f : Y → X}
    (hf : UniformContinuous f) (c : M) : UniformContinuous (c • f) :=
  (uniformContinuous_const_smul c).comp hf
#align uniform_continuous.const_smul UniformContinuous.const_smul
#align uniform_continuous.const_vadd UniformContinuous.const_vadd

/-- If a scalar action is central, then its right action is uniform continuous when its left action
is. -/
@[to_additive "If an additive action is central, then its right action is uniform
continuous when its left action is."]
instance (priority := 100) UniformContinuousConstSMul.op [SMul Mᵐᵒᵖ X] [IsCentralScalar M X]
    [UniformContinuousConstSMul M X] : UniformContinuousConstSMul Mᵐᵒᵖ X :=
  ⟨MulOpposite.rec' fun c =>
      by
      change UniformContinuous fun m => MulOpposite.op c • m
      simp_rw [op_smul_eq_smul]
      exact uniformContinuous_const_smul c⟩
#align has_uniform_continuous_const_smul.op UniformContinuousConstSMul.op
#align has_uniform_continuous_const_vadd.op UniformContinuousConstVAdd.op

@[to_additive]
instance MulOpposite.uniformContinuousConstSMul [UniformContinuousConstSMul M X] :
    UniformContinuousConstSMul M Xᵐᵒᵖ :=
  ⟨fun c =>
    MulOpposite.uniformContinuous_op.comp <| MulOpposite.uniformContinuous_unop.const_smul c⟩
#align mul_opposite.has_uniform_continuous_const_smul MulOpposite.uniformContinuousConstSMul
#align add_opposite.has_uniform_continuous_const_vadd AddOpposite.uniformContinuousConstVAdd

end SMul

@[to_additive]
instance UniformGroup.to_uniformContinuousConstSMul {G : Type u} [Group G] [UniformSpace G]
    [UniformGroup G] : UniformContinuousConstSMul G G :=
  ⟨fun _ => uniformContinuous_const.mul uniformContinuous_id⟩
#align uniform_group.to_has_uniform_continuous_const_smul UniformGroup.to_uniformContinuousConstSMul
#align uniform_add_group.to_has_uniform_continuous_const_vadd UniformAddGroup.to_uniformContinuousConstVAdd

namespace UniformSpace

namespace Completion

section SMul

variable [SMul M X]

@[to_additive]
noncomputable instance : SMul M (Completion X) :=
  ⟨fun c => Completion.map ((· • ·) c)⟩

@[to_additive]
theorem smul_def (c : M) (x : Completion X) : c • x = Completion.map (c • ·) x :=
  rfl
#align uniform_space.completion.smul_def UniformSpace.Completion.smul_def
#align uniform_space.completion.vadd_def UniformSpace.Completion.vadd_def

@[to_additive]
instance : UniformContinuousConstSMul M (Completion X) :=
  ⟨fun _ => uniformContinuous_map⟩

@[to_additive]
instance [SMul N X] [SMul M N] [UniformContinuousConstSMul M X]
    [UniformContinuousConstSMul N X] [IsScalarTower M N X] : IsScalarTower M N (Completion X) :=
  ⟨fun m n x =>
    by
    have : _ = (_ : Completion X → Completion X) :=
      map_comp (uniformContinuous_const_smul m) (uniformContinuous_const_smul n)
    refine' Eq.trans _ (congr_fun this.symm x)
    exact congr_arg (fun f => Completion.map f x) (funext (smul_assoc _ _))⟩

@[to_additive]
instance [SMul N X] [SMulCommClass M N X] [UniformContinuousConstSMul M X]
    [UniformContinuousConstSMul N X] : SMulCommClass M N (Completion X) :=
  ⟨fun m n x =>
    by
    have hmn : m • n • x = (Completion.map (SMul.smul m) ∘ Completion.map (SMul.smul n)) x := rfl
    have hnm : n • m • x = (Completion.map (SMul.smul n) ∘ Completion.map (SMul.smul m)) x := rfl
    rw [hmn, hnm, map_comp, map_comp]
    exact congr_arg (fun f => Completion.map f x) (funext (smul_comm _ _))
    repeat' exact uniformContinuous_const_smul _⟩

@[to_additive]
instance [SMul Mᵐᵒᵖ X] [IsCentralScalar M X] : IsCentralScalar M (Completion X) :=
  ⟨fun c a => (congr_arg fun f => Completion.map f a) <| funext (op_smul_eq_smul c)⟩

variable {M X}
variable [UniformContinuousConstSMul M X]

@[to_additive (attr := simp, nolint simpNF)]
-- Porting note: `simpNF` complains that this lemma can be reduced using `Function.comp`
-- Porting note: `norm_cast` claims this is a badly shaped lemma
theorem coe_smul (c : M) (x : X) : (↑(c • x) : Completion X) = c • (x : Completion X) :=
  (map_coe (uniformContinuous_const_smul c) x).symm
#align uniform_space.completion.coe_smul UniformSpace.Completion.coe_smul
#align uniform_space.completion.coe_vadd UniformSpace.Completion.coe_vadd

end SMul

@[to_additive]
instance [Monoid M] [MulAction M X] [UniformContinuousConstSMul M X] : MulAction M (Completion X)
    where
  smul := (· • ·)
  one_smul := ext' (continuous_const_smul _) continuous_id fun a => by rw [← coe_smul, one_smul]
  mul_smul x y :=
    ext' (continuous_const_smul _) ((continuous_const_smul _).const_smul _) fun a => by
      simp only [← coe_smul, mul_smul]

end Completion

end UniformSpace


import data.set.basic

-- project logical verification 2018 - marcus klaas de vries

-- this file defines some elementary structures and results used in the semantics of
-- basic unimodal logic.
-- we first show that reflexivity of frames is modally definable
-- then, we prove that bisimulations preserves formula satisfaction
-- as a corollary, bounded morphic images of frames preserve formula validity
-- finally, we use this result to prove that irreflexivity of frames is *not*
-- modally definable

-- basic formula for unimodal logic
inductive formula : Type
| bottom        : formula
| propositional : string → formula
| negation      : formula → formula
| diamond       : formula → formula
| disjunction   : formula → formula → formula

-- define box, conjunction and implication in terms of other operators
-- to reduce the number of induction steps!
def box : formula → formula
:= formula.negation ∘ formula.diamond ∘ formula.negation

def conjunction : formula → formula → formula
| f g := formula.negation $ formula.disjunction (formula.negation f) (formula.negation g)

def implication : formula → formula → formula
| φ ψ := formula.disjunction ψ (formula.negation φ)

-- we could fix formatting of more complex formulas using parens,
-- but that is not so interesting from a verification point of view.
-- also, we disobey Jasmin's suggestion to match only on disjoint
-- cases. it's more convenient to do it this way. also, we're rebels
def formula.repr : formula → string
| (formula.negation (formula.diamond (formula.negation ψ))) := "□" ++ formula.repr ψ
| (formula.negation (formula.disjunction (formula.negation ψ) (formula.negation χ))) := formula.repr ψ ++ " ∧ " ++ formula.repr χ
| (formula.disjunction χ (formula.negation ψ)) := formula.repr ψ ++ " → " ++ formula.repr χ
| (formula.disjunction (formula.negation ψ) χ) := formula.repr ψ ++ " → " ++ formula.repr χ
| formula.bottom := "⊥"
| (formula.propositional s) := s
| (formula.negation ψ) := "¬" ++ formula.repr ψ
| (formula.diamond ψ) := "⋄" ++ formula.repr ψ
| (formula.disjunction ψ χ) := formula.repr ψ ++ " ∨ " ++ formula.repr χ

instance : has_repr formula := ⟨formula.repr⟩

-- let the worlds be all values in set α. this is general enough in principle (we can always take subtypes)
def Valuation (α : Type) := string → set α

-- instead of defining relations as sets of pairs, we can also see them as
-- predicates α → α → Prop, as is more commonly done in Lean. i would have chosen
-- this if i were to do it again, as working with sets can be a bit painful
structure Model (α : Type) :=
    (frame : set (α × α))
    (valuation : Valuation α)

def satisfies {α : Type} (m : Model α) : α → formula → Prop
| _ formula.bottom            := false
| w (formula.negation f)      := ¬ (satisfies w f)
| w (formula.disjunction f g) := (satisfies w f) ∨ (satisfies w g)
| w (formula.propositional p) := w ∈ m.valuation p
| w (formula.diamond f)       := ∃ v : α, ((w, v) ∈ m.frame ∧ satisfies v f)

-- a frame validates a formula when all models based on the frame satisfy the formula everywhere
def validates {α : Type} : set (α × α) → formula → Prop
| 𝔽 φ := ∀ (V : Valuation α) (w : α), satisfies {frame := 𝔽, valuation := V} w φ

-- shorthands
notation `□`       := box
notation `⋄`       := formula.diamond
notation `!`       := formula.negation -- ¬ would be nicer, but overloading is not allowed
notation `⟦` p `⟧` := formula.propositional p
notation `⊥`       := formula.bottom
infixr ` => ` : 90 := implication
infixl ` | ` : 40  := formula.disjunction
infixl ` & ` : 50  := conjunction
infixl `⊢` : 50    := function.uncurry satisfies
infixl `⊨` : 50    := validates

def Id (α : Type) : set (α × α) := { x | x.2 = x.1 }
def refl_rel {α} (𝔽 : set (α × α)) := Id α ⊆ 𝔽
def irrefl_rel {α} (𝔽 : set (α × α)) := Id α ∩ 𝔽 = ∅

-- successors of a given world, useful in the pf of the reflexivity lemma
def custom_val {α : Type} (𝔽 : set (α × α)) (w : α) (s : string) : set α :=
    { x | (w, x) ∈ 𝔽 }

lemma contrapositive {A B : Prop} (h : A → B) : ¬ B → ¬ A :=
begin
    intros h2 ha,
    have uh_oh := h ha,
    contradiction
end

lemma reflexivity_modally_definable {α : Type} {𝔽 : set (α × α)} {p : string} :
    refl_rel 𝔽 ↔ 𝔽 ⊨ □⟦p⟧ => ⟦p⟧ :=
begin
    apply iff.intro,
    {
        intros h V w,
        cases classical.em (w ∈ V p),
        {
            exact or.inl h_1
        },
        {
            apply or.inr,
            intro h2,
            exact h2 ⟨w, by { apply h, exact rfl }, h_1⟩
        }
    },
    {
        intros val r h2,
        cases r,
        cases h2,
        apply classical.by_contradiction,
        have neighbour_iff_in_val : ∀ x : α, (r_fst, x) ∈ 𝔽 ↔ x ∈ custom_val 𝔽 r_fst p := (λ x, by refl),
        specialize val (custom_val 𝔽 r_fst) r_fst,
        cases val,
        {
            have oh_no := iff.elim_right (neighbour_iff_in_val r_fst) val,
            contradiction
        },
        {
            cases classical.by_contradiction val,
            cases h,
            have oh_no := contrapositive (iff.elim_left (neighbour_iff_in_val w)) h_right,
            contradiction
        }
    }
end

def bisimulation {α β : Type} (Z : set (α × β)) (m : Model α) (k : Model β) :=
    (∀ prop (z : α × β), z ∈ Z → (z.1 ∈ (m.valuation prop) ↔ z.2 ∈ (k.valuation prop))) -- valuation invariance
  ∧ (∀ (z : α × β), z ∈ Z → (∀ a', (z.1, a') ∈ m.frame → ∃ b', (z.2, b') ∈ k.frame ∧ (a', b') ∈ Z)) -- ZIG
  ∧ (∀ (z : α × β), z ∈ Z → (∀ b', (z.2, b') ∈ k.frame → ∃ a', (z.1, a') ∈ m.frame ∧ (a', b') ∈ Z)) -- ZAG

lemma bisimulation_preserves_satisfaction {α β : Type} {m : Model α} {m' : Model β} {w : α} {w' : β} {Z : set (α × β)}
    (h₂ : bisimulation Z m m') (h₁ : (w, w') ∈ Z):
        ∀ φ, (m, w) ⊢ φ ↔ (m', w') ⊢ φ :=
begin
    intro φ,
    cases h₂,
    cases h₂_right,
    induction φ generalizing w w',
    {
        apply iff.intro; intro sat; cases sat
    },
    {
        exact ⟨assume sat, iff.elim_left (h₂_left φ (w, w') h₁) sat,
               assume sat, iff.elim_right (h₂_left φ (w, w') h₁) sat⟩
    },
    {
        exact ⟨assume sat, contrapositive (iff.elim_right (φ_ih h₁)) sat,
               assume sat, contrapositive (iff.elim_left (φ_ih h₁)) sat⟩
    },
    {
        apply iff.intro; intro sat; cases sat; cases sat_h,
        {
            -- use forth condition
            specialize h₂_right_left (w, w') h₁ sat_w sat_h_left,
            cases h₂_right_left,
            cases h₂_right_left_h,
            -- (sat_w, h₂_right_left_w) is our new pair
            exact exists.intro h₂_right_left_w ⟨ h₂_right_left_h_left, iff.elim_left (φ_ih h₂_right_left_h_right) sat_h_right ⟩
        },
        {
            -- use back condition
            specialize h₂_right_right (w, w') h₁ sat_w sat_h_left,
            cases h₂_right_right,
            cases h₂_right_right_h,
            -- (h₂_right_right_w, sat_w) is our new pair
            exact exists.intro h₂_right_right_w ⟨ h₂_right_right_h_left, iff.elim_right (φ_ih h₂_right_right_h_right) sat_h_right ⟩
        }
    },
    {
        apply iff.intro; intro sat; cases sat,
        exact or.inl (iff.elim_left (φ_ih_a h₁) sat),
        exact or.inr (iff.elim_left (φ_ih_a_1 h₁) sat),
        exact or.inl (iff.elim_right (φ_ih_a h₁) sat),
        exact or.inr (iff.elim_right (φ_ih_a_1 h₁) sat)
    }
end

def bounded_morphism {α β} (f : α → β) (𝔽 : set (α × α)) (ℍ : set (β × β)) :=
    (∀ (r : α × α), r ∈ 𝔽 → (f(r.1), f(r.2)) ∈ ℍ) -- ZIG
  ∧ (∀ (r' : β × β), r' ∈ ℍ → ∀ a, f a = r'.1 → ∃ a', (a, a') ∈ 𝔽 ∧ f a' = r'.2) -- ZAG

-- AKA surjection
def onto {α β} (f : α → β) := ∀ b, ∃ a, f(a) = b

def func_as_set {α β} (f : α → β) : set (α × β) := { x | x.2 = f x.1 }

lemma bounded_morphic_img_preserves_validity {α β : Type} {𝔽 : set (α × α)} {ℍ : set (β × β)} {f : α → β}
    (h₁ : bounded_morphism f 𝔽 ℍ) (h₂ : onto f) :
        ∀ φ, 𝔽 ⊨ φ → ℍ ⊨ φ :=
begin
    intros φ sat V' w',
    specialize h₂ w',
    cases h₂,
    cases h₁,
    -- our relation between 𝔽 and ℍ = func_as_set f
    -- our valuation on 𝔽 := custom_rel f V' = λ prop, { x | f x ∈ V' prop }
    have related_w_w' : (h₂_w, w') ∈ func_as_set f := begin
        rw ←h₂_h,
        exact rfl
    end,
    have bisim : bisimulation (func_as_set f) ({frame := 𝔽, valuation := λ prop, { x | f x ∈ V' prop }}) ({frame := ℍ, valuation := V'}) := begin
        apply and.intro,
        {
            -- prove that our new valuation is invariant under f (both ways!)
            intros prop z z_in_rel,
            change z.snd = f z.fst at z_in_rel,
            apply iff.intro,
            {
                intro z_fst_in_V,
                change f z.fst ∈ V' prop at z_fst_in_V,
                rw ←z_in_rel at z_fst_in_V,
                assumption
            },
            {
                intro z_snd_in_V',
                change f z.fst ∈ V' prop,
                rw z_in_rel at z_snd_in_V',
                assumption
            }
        },
        {
            -- translating ZIG and ZAG properties
            apply and.intro,
            {
                intros z z_in_rel a' 𝔽_neighbour,
                change z.snd = f z.fst at z_in_rel,
                rw z_in_rel,
                exact exists.intro (f a') (and.intro (h₁_left (z.fst, a') 𝔽_neighbour) rfl)
            },
            {
                intros z z_in_rel b' ℍ_neighbour,
                specialize h₁_right (z.snd, b') ℍ_neighbour z.fst (eq.symm z_in_rel),
                cases h₁_right,
                cases h₁_right_h,
                exact exists.intro h₁_right_w ⟨h₁_right_h_left, eq.symm h₁_right_h_right⟩
            }
        }
    end,
    -- use bisimulation result
    exact iff.elim_left (bisimulation_preserves_satisfaction bisim related_w_w' φ) (sat (λ prop, { x | f x ∈ V' prop }) h₂_w)
end

-- singleton type for creating an elementary frame
inductive onevalue
| C : onevalue

-- can we move this f into the proof somehow?
def f : bool → onevalue := λ x, onevalue.C
def refl_frame := Id onevalue
def irrefl_frame : set (bool × bool) := { x | x.2 ≠ x.1 }

-- here we show that the singleton reflexive frame is a bounded morphic image
-- of the symmetric irreflexive two-point frame. from this it follows that irreflexivity
-- is not modally definable
lemma irreflexivity_not_modally_definable :
    ¬ ∃ φ, ∀ α (𝔽 : set (α × α)), irrefl_rel 𝔽 ↔ 𝔽 ⊨ φ :=
begin
    intro h,
    cases h,
    -- here we use the mathlib to reason about empty sets
    have refl_frame_refl : Id onevalue ∩ refl_frame ≠ ∅ := begin
        rw set.ne_empty_iff_exists_mem,
        apply exists.intro (onevalue.C, onevalue.C),
        rw [refl_frame, set.inter_self (Id onevalue)],
        exact rfl
    end,
    have refl_frame_invalidates_h_w : ¬ (refl_frame ⊨ h_w) := contrapositive (iff.elim_right (h_h onevalue refl_frame)) refl_frame_refl,
    have irrefl_frame_irrefl : Id bool ∩ irrefl_frame = ∅ := begin
        rw set.eq_empty_iff_forall_not_mem,
        intros x h,
        cases iff.elim_left (set.mem_inter_iff x (Id bool) irrefl_frame) h,
        contradiction
    end,
    have irrefl_frame_accepts_h_w := iff.elim_left (h_h bool irrefl_frame) irrefl_frame_irrefl,
    have f_onto : onto f := begin
        intro y,
        cases y,
        exact ⟨ tt, rfl ⟩
    end,
    have p_morphism : bounded_morphism f irrefl_frame refl_frame := begin
        apply and.intro,
        {
            intros r h12,
            exact rfl
        },
        {
            intros r h12 twoval taut,
            cases twoval,
            exact ⟨ tt, ⟨ by simp [irrefl_frame, *], by { cases r.snd, refl } ⟩ ⟩,
            exact ⟨ ff, ⟨ by simp [irrefl_frame, *], by { cases r.snd, refl } ⟩ ⟩
        }
    end,
    have refl_frame_accepts_h_w := bounded_morphic_img_preserves_validity p_morphism f_onto h_w irrefl_frame_accepts_h_w,
    contradiction
end


import defs single finite branch grow data.list

open classical

lemma branch_to_dense : ∀ l, (∀ b, height b = height_bound l → ⟨b⟩ → (l ↦ b)) → (∀ t, height_bound l <= height t → (l ↦ t)):=
begin
  intros l h1 t h2,
  cases (kernel_lemma _ _ (height_bound_ge1 _) h2),
  have ht1 : _ := h.left,
  have ht2 : _ := h.right.left,
  have ht3 : _ := h.right.right,
  have ht : (l ↦ w), apply h1, rewrite ht2, assumption,
  cases (grow_list_exists_one _ _ ht),
  apply exists_one_grow_list,
  existsi w_1, split, exact h_1.left,
  apply grow_trans,
  exact h_1.right, exact ht3
end

lemma branch_to_complete : ∀ l, (∀ b, height b = height_bound l → ⟨b⟩ → (l ↦ b)) → almost_complete l :=
begin
  intros,
  apply almost_complete.cmp_rule,
  cases (bounded_height_list (height_bound l)),
  existsi w, intros t h',
  have ht : _ := (branch_to_dense l a t),
  have ht' : ¬(height_bound l ≤ height t), tauto,
  apply h, omega
end

lemma complete_to_week_dense : ∀ l, almost_complete l → (∃ h, h ≥ 1 ∧ (∀ t, height t = h → (l ↦ t))) :=
begin
  intros l h,
  cases h, cases h_a,
  existsi (height_bound h_a_w)+1,
  split,omega,
  intros t h1,
  classical,
  by_contra,
  have ht : _ := h_a_h _ a,
  have ht' : _ := height_bound_correct h_a_w _ ht,
  rewrite h1 at ht',
  exact nat.not_succ_le_self (height_bound h_a_w) ht'
end

lemma complete_to_branch : ∀ l, almost_complete l → (∀ b, height b = height_bound l → ⟨b⟩ → (l ↦ b)) :=
begin
  intros l h1 b h2 h3,
  classical, by_contra,
  cases complete_to_week_dense l h1,
  cases le_or_gt w (height b),
  begin
    cases (kernel_lemma b w h.left h_1),
    have ht : _ := h.right w_1 (eq.symm (h_2.right.left)),
    apply a, cases grow_list_exists_one l w_1 ht,
    have ht' : _ := grow_trans _ _ _ h_3.right h_2.right.right,
    apply exists_one_grow_list, existsi w_2,
    split, repeat {tauto}
  end,
  begin
    have ht' : height b + (w - height b) = w, omega,
    cases (grow_high_bintree b h3 (w - height b)),
    cases h_2.right,
    have h_2' : height w_1 = w, omega,
    have h' : _ := h.right w_1 h_2',
    apply a, cases grow_list_exists_one l w_1 h',
    have h_height : _ := height_bound_correct l w_2 h_3.left,
    rewrite h2.symm at h_height,
    have h_almost : _ := (branch_prefix w_1 w_2 b h_2.left h_3.right left h_height),
    apply exists_one_grow_list, existsi w_2,
    tauto
  end
end

theorem complete_iff_branch : ∀ l, almost_complete l ↔ (∀ b, height b = height_bound l → ⟨b⟩ → (l ↦ b)) :=
begin
  intros, split,
  exact complete_to_branch _,
  exact branch_to_complete _
end


/-
Copyright (c) 2019 Sébastien Gouëzel. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sébastien Gouëzel
-/
import topology.homeomorph

/-!
# Maps equivariantly-homeomorphic to projection in a product

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

This file contains the definition `is_homeomorphic_trivial_fiber_bundle F p`, a Prop saying that a
map `p : Z → B` between topological spaces is a "trivial fiber bundle" in the sense that there
exists a homeomorphism `h : Z ≃ₜ B × F` such that `proj x = (h x).1`.  This is an abstraction which
is occasionally convenient in showing that a map is open, a quotient map, etc.

This material was formerly linked to the main definition of fiber bundles, but after a series of
refactors, there is no longer a direct connection.
-/

variables {B : Type*} (F : Type*) {Z : Type*} [topological_space B] [topological_space F]
  [topological_space Z]

/-- A trivial fiber bundle with fiber `F` over a base `B` is a space `Z`
projecting on `B` for which there exists a homeomorphism to `B × F` that sends `proj`
to `prod.fst`. -/
def is_homeomorphic_trivial_fiber_bundle (proj : Z → B) : Prop :=
∃ e : Z ≃ₜ (B × F), ∀ x, (e x).1 = proj x

namespace is_homeomorphic_trivial_fiber_bundle
variables {F} {proj : Z → B}

protected lemma proj_eq (h : is_homeomorphic_trivial_fiber_bundle F proj) :
  ∃ e : Z ≃ₜ (B × F), proj = prod.fst ∘ e :=
⟨h.some, (funext h.some_spec).symm⟩

/-- The projection from a trivial fiber bundle to its base is surjective. -/
protected lemma surjective_proj [nonempty F] (h : is_homeomorphic_trivial_fiber_bundle F proj) :
  function.surjective proj :=
begin
  obtain ⟨e, rfl⟩ := h.proj_eq,
  exact prod.fst_surjective.comp e.surjective,
end

/-- The projection from a trivial fiber bundle to its base is continuous. -/
protected lemma continuous_proj (h : is_homeomorphic_trivial_fiber_bundle F proj) :
  continuous proj :=
begin
  obtain ⟨e, rfl⟩ := h.proj_eq,
  exact continuous_fst.comp e.continuous,
end

/-- The projection from a trivial fiber bundle to its base is open. -/
protected lemma is_open_map_proj (h : is_homeomorphic_trivial_fiber_bundle F proj) :
  is_open_map proj :=
begin
  obtain ⟨e, rfl⟩ := h.proj_eq,
  exact is_open_map_fst.comp e.is_open_map,
end

/-- The projection from a trivial fiber bundle to its base is open. -/
protected lemma quotient_map_proj [nonempty F] (h : is_homeomorphic_trivial_fiber_bundle F proj) :
  quotient_map proj :=
h.is_open_map_proj.to_quotient_map h.continuous_proj h.surjective_proj

end is_homeomorphic_trivial_fiber_bundle

/-- The first projection in a product is a trivial fiber bundle. -/
lemma is_homeomorphic_trivial_fiber_bundle_fst :
  is_homeomorphic_trivial_fiber_bundle F (prod.fst : B × F → B) :=
⟨homeomorph.refl _, λ x, rfl⟩

/-- The second projection in a product is a trivial fiber bundle. -/
lemma is_homeomorphic_trivial_fiber_bundle_snd :
  is_homeomorphic_trivial_fiber_bundle F (prod.snd : F × B → B) :=
⟨homeomorph.prod_comm _ _, λ x, rfl⟩


/-
Copyright (c) 2021 Tianchen Zhao. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Tianchen Zhao
-/
import congruence.Elements

/-!
# Parallelism

This file defines how two lines are parallel and proves properties
of parallel lines such as alternative angles.

## Main definitions

* `is_parallel` means the two lines have no intersections
* `hilbert_plane_playfair` is a class extended `hilbert_plane` with
  Playfair axiom that deals with parallelism

## References

* See [Geometry: Euclid and Beyond]

-/

/--We can add Playfair axiom to Hilbert plane so that given a line and a point,
we can find a unique parallel line containing this point. -/
class hilbert_plane_playfair extends hilbert_plane :=
(P : ∀ (a : pts) (l ∈ lines), (a ∉ l → ∃ l' ∈ lines, a ∈ l' ∧ (l ∥ₗ l'))
∧ (∀ m n ∈ lines, a ∈ m → (l ∥ₗ m) → a ∈ n → (l ∥ₗ n) → m = n))

open incidence_geometry incidence_order_geometry hilbert_plane hilbert_plane_playfair

variables [CP : hilbert_plane_playfair]

include CP

lemma parallel_exist {l : set pts} (a : pts) (hl : l ∈ lines) (hal : a ∉ l) :
∃ l' ∈ lines, a ∈ l' ∧ (l ∥ₗ l') :=
by {rcases (P a l hl).1 hal with ⟨l', hl', hal', hll'⟩, exact ⟨l', hl', hal', hll'⟩}

lemma parallel_unique {a : pts} {l m n : set pts} (hl : l ∈ lines) :
m ∈ lines → n ∈ lines → a ∈ m → (l ∥ₗ m) → a ∈ n → (l ∥ₗ n) → m = n :=
(P a l hl).2 m n

private lemma correspond_eq_iff_parallel_prep {a b c d e : pts}
(hab : a ≠ b) (hcd : c ≠ d) (hcae : between c a e) (hbd : same_side_line (a-ₗc) b d) :
((∠ e a b) <ₐ (∠ a c d)) → ¬((a-ₗb) ∥ₗ (c-ₗd)) :=
begin
  have hac := (between_neq hcae).1.symm,
  intros h hf,
  rcases (three_pt_ang_lt.1 h) with ⟨p, hp, key⟩,
  rw [inside_three_pt_ang, line_symm] at hp,
  have hbp := same_side_line_trans (line_in_lines hac) hbd hp.1,
  have hcp := (same_side_line_neq' hbp).2.symm,
  have habcp := correspond_eq_parallel hab hcp hcae hbp (ang_congr_symm key),
  have hcdcp := parallel_unique (line_in_lines hab) (line_in_lines hcd) (line_in_lines hcp)
    (pt_left_in_line c d) hf (pt_left_in_line c p) habcp,
  have hcdp : col c d p,
    apply col_in12', rw hcdcp, exact pt_right_in_line c p,
  have hacd := (same_side_line_noncol hbd hac).2,
  have hacp := (same_side_line_noncol hbp hac).2,
  have hcdp := same_side_line_pt hcdp (a-ₗc) (line_in_lines hac) (pt_right_in_line a c)
    (noncol_in12 hacd) (noncol_in12 hacp) hp.1,
  rw ←ang_eq_same_side_pt a hcdp at key,
  have hac := (between_neq hcae).1.symm,
  have hacb := (same_side_line_noncol hbd hac).1,
  have hae := (between_neq hcae).2.2,
  have haeb := col_noncol (col12 (between_col hcae)) hacb hae,
  apply (ang_tri (ang_proper_iff_noncol.2 (noncol12 haeb))
    (ang_proper_iff_noncol.2 hacd)).2.1,
  exact ⟨h, ang_congr_symm key⟩
end

lemma correspond_eq_iff_parallel {a b c d e : pts}
(hab : a ≠ b) (hcd : c ≠ d) (hcae : between c a e) (hbd : same_side_line (a-ₗc) b d) :
((∠ e a b) ≅ₐ (∠ a c d)) ↔ ((a-ₗb) ∥ₗ (c-ₗd)) :=
begin
  split; intro h,
  exact correspond_eq_parallel hab hcd hcae hbd h,
  { have hac := (between_neq hcae).1.symm,
    have hacb := (same_side_line_noncol hbd hac).1,
    have hae := (between_neq hcae).2.2,
    have haeb := col_noncol (col12 (between_col hcae)) hacb hae,
    have hacd := (same_side_line_noncol hbd hac).2,
    rcases (ang_tri (ang_proper_iff_noncol.2 (noncol12 haeb))
      (ang_proper_iff_noncol.2 hacd)).1 with hf | h | hf,
    exfalso, exact correspond_eq_iff_parallel_prep hab hcd hcae hbd hf h,
    exact h,
    { rcases between_extend hab.symm with ⟨b', hbab'⟩,
      rcases between_extend hcd.symm with ⟨d', hdcd'⟩,
      exfalso,
      have hab' := (between_neq hbab').2.2,
      have hcd' := (between_neq hdcd').2.2,
      have hab'c := col_noncol (col12 (between_col hbab')) (noncol23 hacb) hab',
      have had'c := col_noncol (col12 (between_col hdcd')) (noncol123 hacd) hcd',
      apply correspond_eq_iff_parallel_prep hab' hcd' hcae _ _ _,
      { have hbb' := diff_side_pt_line (between_diff_side_pt.1 hbab') (line_in_lines hac)
          (pt_left_in_line a c) (noncol_in12 hacb) (noncol_in13 hab'c),
        have hdd' := diff_side_pt_line (between_diff_side_pt.1 hdcd') (line_in_lines hac)
          (pt_right_in_line a c) (noncol_in12 hacd) (noncol_in31 had'c),
        apply diff_side_line_cancel (line_in_lines hac) (diff_side_line_symm hbb'),
        exact same_diff_side_line (line_in_lines hac) hbd hdd', },
      { apply ang_lt_supplementary hf; rw three_pt_ang_supplementary,
        exact ⟨hdcd', hacd, noncol132 had'c⟩,
        exact ⟨hbab', noncol12 haeb, noncol132
          (col_noncol (col12 (between_col hbab')) (noncol23 haeb) hab')⟩ },
      { rw two_pt_one_line (line_in_lines hab') (line_in_lines hab) hab (pt_left_in_line a b')
          (col_in23 (between_col hbab') hab') (pt_left_in_line a b) (pt_right_in_line a b),
        rw two_pt_one_line (line_in_lines hcd') (line_in_lines hcd) hcd (pt_left_in_line c d')
          (col_in23 (between_col hdcd') hcd') (pt_left_in_line c d) (pt_right_in_line c d),
        exact h  } } }
end

lemma alternative_eq_iff_parallel {a b c d : pts}
(hab : a ≠ b) (hcd : c ≠ d) (hac : a ≠ c) (hbd : diff_side_line (a-ₗc) b d) :
((∠ b a c) ≅ₐ (∠ d c a)) ↔ ((a-ₗb) ∥ₗ (c-ₗd)) :=
begin
  cases between_extend hab.symm with b' hbab',
  cases between_extend hac.symm with c' hcac',
  have hab' := (between_neq hbab').2.2,
  have hbac := noncol_in23' hac hbd.2.1,
  have hab'c := col_noncol (col12 (between_col hbab')) (noncol12 hbac) hab',
  have hbd' : same_side_line (a-ₗc) b' d,
    apply diff_side_line_cancel (line_in_lines hac) _ hbd,
    apply diff_side_line_symm,
    apply diff_side_pt_line (between_diff_side_pt.1 hbab') (line_in_lines hac)
      (pt_left_in_line a c) hbd.2.1 (noncol_in13 hab'c),
  have := correspond_eq_iff_parallel hab' hcd hcac' hbd',
  rw two_pt_one_line (line_in_lines hab') (line_in_lines hab) hab (pt_left_in_line a b')
    (col_in23 (between_col hbab') hab') (pt_left_in_line a b) (pt_right_in_line a b) at this,
  rw ←this,
  have := vertical_ang_congr hbac hbab' hcac',
  split; intro h,
  rw [ang_symm, ang_symm a c d], exact ang_congr_trans (ang_congr_symm this) h,
  rw ang_symm d c a, rw ang_symm at h, exact ang_congr_trans this h
end

/--Some hints for Tchsurvives:
  1. extend_congr_seg'
  2. SAS
  3. alternative_eq_iff_parallel
  4. ASA -/
lemma midpoint {a b c d e : pts} (habc : noncol a b c) (hadb : between a d b)
(haec : between a e c) (hd : midpt d (a-ₛb)) : (midpt e (a-ₛc)) ↔ ((d-ₗe) ∥ₗ (b-ₗc)) :=
begin
  sorry
end


/-
Copyright (c) 2021 Yury Kudryashov. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yury Kudryashov, Yaël Dillies

! This file was ported from Lean 3 source module algebra.group.order_synonym
! leanprover-community/mathlib commit 448144f7ae193a8990cb7473c9e9a01990f64ac7
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Algebra.Group.Defs
import Mathbin.Order.Synonym

/-!
# Group structure on the order type synonyms

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

Transfer algebraic instances from `α` to `αᵒᵈ` and `lex α`.
-/

open OrderDual

variable {α β : Type _}

/-! ### `order_dual` -/

@[to_additive]
instance [h : One α] : One αᵒᵈ :=
  h

@[to_additive]
instance [h : Mul α] : Mul αᵒᵈ :=
  h

@[to_additive]
instance [h : Inv α] : Inv αᵒᵈ :=
  h

@[to_additive]
instance [h : Div α] : Div αᵒᵈ :=
  h

@[to_additive]
instance [h : SMul α β] : SMul α βᵒᵈ :=
  h

#print instSMulOrderDual' /-
@[to_additive]
instance instSMulOrderDual' [h : SMul α β] : SMul αᵒᵈ β :=
  h
#align order_dual.has_smul' instSMulOrderDual'
-/

#print instPowOrderDual /-
@[to_additive instSMulOrderDual]
instance instPowOrderDual [h : Pow α β] : Pow αᵒᵈ β :=
  h
#align order_dual.has_pow instPowOrderDual
#align order_dual.has_smul instSMulOrderDual
-/

#print instPowOrderDual' /-
@[to_additive instSMulOrderDual']
instance instPowOrderDual' [h : Pow α β] : Pow α βᵒᵈ :=
  h
#align order_dual.has_pow' instPowOrderDual'
#align order_dual.has_smul' instSMulOrderDual'
-/

@[to_additive]
instance [h : Semigroup α] : Semigroup αᵒᵈ :=
  h

@[to_additive]
instance [h : CommSemigroup α] : CommSemigroup αᵒᵈ :=
  h

@[to_additive]
instance [h : LeftCancelSemigroup α] : LeftCancelSemigroup αᵒᵈ :=
  h

@[to_additive]
instance [h : RightCancelSemigroup α] : RightCancelSemigroup αᵒᵈ :=
  h

@[to_additive]
instance [h : MulOneClass α] : MulOneClass αᵒᵈ :=
  h

@[to_additive]
instance [h : Monoid α] : Monoid αᵒᵈ :=
  h

@[to_additive]
instance [h : CommMonoid α] : CommMonoid αᵒᵈ :=
  h

@[to_additive]
instance [h : LeftCancelMonoid α] : LeftCancelMonoid αᵒᵈ :=
  h

@[to_additive]
instance [h : RightCancelMonoid α] : RightCancelMonoid αᵒᵈ :=
  h

@[to_additive]
instance [h : CancelMonoid α] : CancelMonoid αᵒᵈ :=
  h

@[to_additive]
instance [h : CancelCommMonoid α] : CancelCommMonoid αᵒᵈ :=
  h

@[to_additive]
instance [h : InvolutiveInv α] : InvolutiveInv αᵒᵈ :=
  h

@[to_additive]
instance [h : DivInvMonoid α] : DivInvMonoid αᵒᵈ :=
  h

@[to_additive OrderDual.subtractionMonoid]
instance [h : DivisionMonoid α] : DivisionMonoid αᵒᵈ :=
  h

@[to_additive OrderDual.subtractionCommMonoid]
instance [h : DivisionCommMonoid α] : DivisionCommMonoid αᵒᵈ :=
  h

@[to_additive]
instance [h : Group α] : Group αᵒᵈ :=
  h

@[to_additive]
instance [h : CommGroup α] : CommGroup αᵒᵈ :=
  h

#print toDual_one /-
@[simp, to_additive]
theorem toDual_one [One α] : toDual (1 : α) = 1 :=
  rfl
#align to_dual_one toDual_one
#align to_dual_zero toDual_zero
-/

#print ofDual_one /-
@[simp, to_additive]
theorem ofDual_one [One α] : (ofDual 1 : α) = 1 :=
  rfl
#align of_dual_one ofDual_one
#align of_dual_zero ofDual_zero
-/

#print toDual_mul /-
@[simp, to_additive]
theorem toDual_mul [Mul α] (a b : α) : toDual (a * b) = toDual a * toDual b :=
  rfl
#align to_dual_mul toDual_mul
#align to_dual_add toDual_add
-/

#print ofDual_mul /-
@[simp, to_additive]
theorem ofDual_mul [Mul α] (a b : αᵒᵈ) : ofDual (a * b) = ofDual a * ofDual b :=
  rfl
#align of_dual_mul ofDual_mul
#align of_dual_add ofDual_add
-/

#print toDual_inv /-
@[simp, to_additive]
theorem toDual_inv [Inv α] (a : α) : toDual a⁻¹ = (toDual a)⁻¹ :=
  rfl
#align to_dual_inv toDual_inv
#align to_dual_neg toDual_neg
-/

#print ofDual_inv /-
@[simp, to_additive]
theorem ofDual_inv [Inv α] (a : αᵒᵈ) : ofDual a⁻¹ = (ofDual a)⁻¹ :=
  rfl
#align of_dual_inv ofDual_inv
#align of_dual_neg ofDual_neg
-/

#print toDual_div /-
@[simp, to_additive]
theorem toDual_div [Div α] (a b : α) : toDual (a / b) = toDual a / toDual b :=
  rfl
#align to_dual_div toDual_div
#align to_dual_sub toDual_sub
-/

#print ofDual_div /-
@[simp, to_additive]
theorem ofDual_div [Div α] (a b : αᵒᵈ) : ofDual (a / b) = ofDual a / ofDual b :=
  rfl
#align of_dual_div ofDual_div
#align of_dual_sub ofDual_sub
-/

/- warning: to_dual_smul -> toDual_smul is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : SMul.{u1, u2} α β] (a : α) (b : β), Eq.{succ u2} (OrderDual.{u2} β) (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} β (OrderDual.{u2} β)) (fun (_x : Equiv.{succ u2, succ u2} β (OrderDual.{u2} β)) => β -> (OrderDual.{u2} β)) (Equiv.hasCoeToFun.{succ u2, succ u2} β (OrderDual.{u2} β)) (OrderDual.toDual.{u2} β) (SMul.smul.{u1, u2} α β _inst_1 a b)) (SMul.smul.{u1, u2} α (OrderDual.{u2} β) (instSMulOrderDual.{u1, u2} α β _inst_1) a (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} β (OrderDual.{u2} β)) (fun (_x : Equiv.{succ u2, succ u2} β (OrderDual.{u2} β)) => β -> (OrderDual.{u2} β)) (Equiv.hasCoeToFun.{succ u2, succ u2} β (OrderDual.{u2} β)) (OrderDual.toDual.{u2} β) b))
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : SMul.{u2, u1} α β] (a : α) (b : β), Eq.{succ u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) (HSMul.hSMul.{u2, u1, u1} α β β (instHSMul.{u2, u1} α β _inst_1) a b)) (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} β (OrderDual.{u1} β)) β (fun (_x : β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} β (OrderDual.{u1} β)) (OrderDual.toDual.{u1} β) (HSMul.hSMul.{u2, u1, u1} α β β (instHSMul.{u2, u1} α β _inst_1) a b)) (HSMul.hSMul.{u2, u1, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) b) ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) b) (instHSMul.{u2, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) b) (instSMulOrderDual.{u2, u1} α β _inst_1)) a (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} β (OrderDual.{u1} β)) β (fun (_x : β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} β (OrderDual.{u1} β)) (OrderDual.toDual.{u1} β) b))
Case conversion may be inaccurate. Consider using '#align to_dual_smul toDual_smulₓ'. -/
@[simp, to_additive]
theorem toDual_smul [SMul α β] (a : α) (b : β) : toDual (a • b) = a • toDual b :=
  rfl
#align to_dual_smul toDual_smul
#align to_dual_vadd toDual_vadd

/- warning: of_dual_smul -> ofDual_smul is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : SMul.{u1, u2} α β] (a : α) (b : OrderDual.{u2} β), Eq.{succ u2} β (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} (OrderDual.{u2} β) β) (fun (_x : Equiv.{succ u2, succ u2} (OrderDual.{u2} β) β) => (OrderDual.{u2} β) -> β) (Equiv.hasCoeToFun.{succ u2, succ u2} (OrderDual.{u2} β) β) (OrderDual.ofDual.{u2} β) (SMul.smul.{u1, u2} α (OrderDual.{u2} β) (instSMulOrderDual.{u1, u2} α β _inst_1) a b)) (SMul.smul.{u1, u2} α β _inst_1 a (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} (OrderDual.{u2} β) β) (fun (_x : Equiv.{succ u2, succ u2} (OrderDual.{u2} β) β) => (OrderDual.{u2} β) -> β) (Equiv.hasCoeToFun.{succ u2, succ u2} (OrderDual.{u2} β) β) (OrderDual.ofDual.{u2} β) b))
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : SMul.{u2, u1} α β] (a : α) (b : OrderDual.{u1} β), Eq.{succ u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) (HSMul.hSMul.{u2, u1, u1} α (OrderDual.{u1} β) (OrderDual.{u1} β) (instHSMul.{u2, u1} α (OrderDual.{u1} β) (instSMulOrderDual.{u2, u1} α β _inst_1)) a b)) (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} (OrderDual.{u1} β) β) (OrderDual.{u1} β) (fun (_x : OrderDual.{u1} β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} (OrderDual.{u1} β) β) (OrderDual.ofDual.{u1} β) (HSMul.hSMul.{u2, u1, u1} α (OrderDual.{u1} β) (OrderDual.{u1} β) (instHSMul.{u2, u1} α (OrderDual.{u1} β) (instSMulOrderDual.{u2, u1} α β _inst_1)) a b)) (HSMul.hSMul.{u2, u1, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) b) ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) b) (instHSMul.{u2, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) b) _inst_1) a (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} (OrderDual.{u1} β) β) (OrderDual.{u1} β) (fun (_x : OrderDual.{u1} β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} (OrderDual.{u1} β) β) (OrderDual.ofDual.{u1} β) b))
Case conversion may be inaccurate. Consider using '#align of_dual_smul ofDual_smulₓ'. -/
@[simp, to_additive]
theorem ofDual_smul [SMul α β] (a : α) (b : βᵒᵈ) : ofDual (a • b) = a • ofDual b :=
  rfl
#align of_dual_smul ofDual_smul
#align of_dual_vadd ofDual_vadd

/- warning: to_dual_smul' -> toDual_smul' is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : SMul.{u1, u2} α β] (a : α) (b : β), Eq.{succ u2} β (SMul.smul.{u1, u2} (OrderDual.{u1} α) β (instSMulOrderDual'.{u1, u2} α β _inst_1) (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} α (OrderDual.{u1} α)) (fun (_x : Equiv.{succ u1, succ u1} α (OrderDual.{u1} α)) => α -> (OrderDual.{u1} α)) (Equiv.hasCoeToFun.{succ u1, succ u1} α (OrderDual.{u1} α)) (OrderDual.toDual.{u1} α) a) b) (SMul.smul.{u1, u2} α β _inst_1 a b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : SMul.{u2, u1} α β] (a : α) (b : β), Eq.{succ u1} β (HSMul.hSMul.{u2, u1, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) a) β β (instHSMul.{u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) a) β (instSMulOrderDual'.{u2, u1} α β _inst_1)) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} α (OrderDual.{u2} α)) α (fun (_x : α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} α (OrderDual.{u2} α)) (OrderDual.toDual.{u2} α) a) b) (HSMul.hSMul.{u2, u1, u1} α β β (instHSMul.{u2, u1} α β _inst_1) a b)
Case conversion may be inaccurate. Consider using '#align to_dual_smul' toDual_smul'ₓ'. -/
@[simp, to_additive]
theorem toDual_smul' [SMul α β] (a : α) (b : β) : toDual a • b = a • b :=
  rfl
#align to_dual_smul' toDual_smul'
#align to_dual_vadd' toDual_vadd'

/- warning: of_dual_smul' -> ofDual_smul' is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : SMul.{u1, u2} α β] (a : OrderDual.{u1} α) (b : β), Eq.{succ u2} β (SMul.smul.{u1, u2} α β _inst_1 (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} (OrderDual.{u1} α) α) (fun (_x : Equiv.{succ u1, succ u1} (OrderDual.{u1} α) α) => (OrderDual.{u1} α) -> α) (Equiv.hasCoeToFun.{succ u1, succ u1} (OrderDual.{u1} α) α) (OrderDual.ofDual.{u1} α) a) b) (SMul.smul.{u1, u2} (OrderDual.{u1} α) β (instSMulOrderDual'.{u1, u2} α β _inst_1) a b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : SMul.{u2, u1} α β] (a : OrderDual.{u2} α) (b : β), Eq.{succ u1} β (HSMul.hSMul.{u2, u1, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) a) β β (instHSMul.{u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) a) β _inst_1) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} (OrderDual.{u2} α) α) (OrderDual.{u2} α) (fun (_x : OrderDual.{u2} α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} (OrderDual.{u2} α) α) (OrderDual.ofDual.{u2} α) a) b) (HSMul.hSMul.{u2, u1, u1} (OrderDual.{u2} α) β β (instHSMul.{u2, u1} (OrderDual.{u2} α) β (instSMulOrderDual'.{u2, u1} α β _inst_1)) a b)
Case conversion may be inaccurate. Consider using '#align of_dual_smul' ofDual_smul'ₓ'. -/
@[simp, to_additive]
theorem ofDual_smul' [SMul α β] (a : αᵒᵈ) (b : β) : ofDual a • b = a • b :=
  rfl
#align of_dual_smul' ofDual_smul'
#align of_dual_vadd' ofDual_vadd'

/- warning: to_dual_pow -> toDual_pow is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : Pow.{u1, u2} α β] (a : α) (b : β), Eq.{succ u1} (OrderDual.{u1} α) (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} α (OrderDual.{u1} α)) (fun (_x : Equiv.{succ u1, succ u1} α (OrderDual.{u1} α)) => α -> (OrderDual.{u1} α)) (Equiv.hasCoeToFun.{succ u1, succ u1} α (OrderDual.{u1} α)) (OrderDual.toDual.{u1} α) (HPow.hPow.{u1, u2, u1} α β α (instHPow.{u1, u2} α β _inst_1) a b)) (HPow.hPow.{u1, u2, u1} (OrderDual.{u1} α) β (OrderDual.{u1} α) (instHPow.{u1, u2} (OrderDual.{u1} α) β (instPowOrderDual.{u1, u2} α β _inst_1)) (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} α (OrderDual.{u1} α)) (fun (_x : Equiv.{succ u1, succ u1} α (OrderDual.{u1} α)) => α -> (OrderDual.{u1} α)) (Equiv.hasCoeToFun.{succ u1, succ u1} α (OrderDual.{u1} α)) (OrderDual.toDual.{u1} α) a) b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : Pow.{u2, u1} α β] (a : α) (b : β), Eq.{succ u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) (HPow.hPow.{u2, u1, u2} α β α (instHPow.{u2, u1} α β _inst_1) a b)) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} α (OrderDual.{u2} α)) α (fun (_x : α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} α (OrderDual.{u2} α)) (OrderDual.toDual.{u2} α) (HPow.hPow.{u2, u1, u2} α β α (instHPow.{u2, u1} α β _inst_1) a b)) (HPow.hPow.{u2, u1, u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) a) β ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) a) (instHPow.{u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) a) β (instPowOrderDual.{u2, u1} α β _inst_1)) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} α (OrderDual.{u2} α)) α (fun (_x : α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => OrderDual.{u2} α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} α (OrderDual.{u2} α)) (OrderDual.toDual.{u2} α) a) b)
Case conversion may be inaccurate. Consider using '#align to_dual_pow toDual_powₓ'. -/
@[simp, to_additive toDual_smul, to_additive_reorder 1 4]
theorem toDual_pow [Pow α β] (a : α) (b : β) : toDual (a ^ b) = toDual a ^ b :=
  rfl
#align to_dual_pow toDual_pow
#align to_dual_smul toDual_smul

/- warning: of_dual_pow -> ofDual_pow is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : Pow.{u1, u2} α β] (a : OrderDual.{u1} α) (b : β), Eq.{succ u1} α (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} (OrderDual.{u1} α) α) (fun (_x : Equiv.{succ u1, succ u1} (OrderDual.{u1} α) α) => (OrderDual.{u1} α) -> α) (Equiv.hasCoeToFun.{succ u1, succ u1} (OrderDual.{u1} α) α) (OrderDual.ofDual.{u1} α) (HPow.hPow.{u1, u2, u1} (OrderDual.{u1} α) β (OrderDual.{u1} α) (instHPow.{u1, u2} (OrderDual.{u1} α) β (instPowOrderDual.{u1, u2} α β _inst_1)) a b)) (HPow.hPow.{u1, u2, u1} α β α (instHPow.{u1, u2} α β _inst_1) (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} (OrderDual.{u1} α) α) (fun (_x : Equiv.{succ u1, succ u1} (OrderDual.{u1} α) α) => (OrderDual.{u1} α) -> α) (Equiv.hasCoeToFun.{succ u1, succ u1} (OrderDual.{u1} α) α) (OrderDual.ofDual.{u1} α) a) b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : Pow.{u2, u1} α β] (a : OrderDual.{u2} α) (b : β), Eq.{succ u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) (HPow.hPow.{u2, u1, u2} (OrderDual.{u2} α) β (OrderDual.{u2} α) (instHPow.{u2, u1} (OrderDual.{u2} α) β (instPowOrderDual.{u2, u1} α β _inst_1)) a b)) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} (OrderDual.{u2} α) α) (OrderDual.{u2} α) (fun (_x : OrderDual.{u2} α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} (OrderDual.{u2} α) α) (OrderDual.ofDual.{u2} α) (HPow.hPow.{u2, u1, u2} (OrderDual.{u2} α) β (OrderDual.{u2} α) (instHPow.{u2, u1} (OrderDual.{u2} α) β (instPowOrderDual.{u2, u1} α β _inst_1)) a b)) (HPow.hPow.{u2, u1, u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) a) β ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) a) (instHPow.{u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) a) β _inst_1) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} (OrderDual.{u2} α) α) (OrderDual.{u2} α) (fun (_x : OrderDual.{u2} α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u2} α) => α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} (OrderDual.{u2} α) α) (OrderDual.ofDual.{u2} α) a) b)
Case conversion may be inaccurate. Consider using '#align of_dual_pow ofDual_powₓ'. -/
@[simp, to_additive ofDual_smul, to_additive_reorder 1 4]
theorem ofDual_pow [Pow α β] (a : αᵒᵈ) (b : β) : ofDual (a ^ b) = ofDual a ^ b :=
  rfl
#align of_dual_pow ofDual_pow
#align of_dual_smul ofDual_smul

/- warning: pow_to_dual -> pow_toDual is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : Pow.{u1, u2} α β] (a : α) (b : β), Eq.{succ u1} α (HPow.hPow.{u1, u2, u1} α (OrderDual.{u2} β) α (instHPow.{u1, u2} α (OrderDual.{u2} β) (instPowOrderDual'.{u1, u2} α β _inst_1)) a (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} β (OrderDual.{u2} β)) (fun (_x : Equiv.{succ u2, succ u2} β (OrderDual.{u2} β)) => β -> (OrderDual.{u2} β)) (Equiv.hasCoeToFun.{succ u2, succ u2} β (OrderDual.{u2} β)) (OrderDual.toDual.{u2} β) b)) (HPow.hPow.{u1, u2, u1} α β α (instHPow.{u1, u2} α β _inst_1) a b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : Pow.{u2, u1} α β] (a : α) (b : β), Eq.{succ u2} α (HPow.hPow.{u2, u1, u2} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) b) α (instHPow.{u2, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) b) (instPowOrderDual'.{u2, u1} α β _inst_1)) a (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} β (OrderDual.{u1} β)) β (fun (_x : β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => OrderDual.{u1} β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} β (OrderDual.{u1} β)) (OrderDual.toDual.{u1} β) b)) (HPow.hPow.{u2, u1, u2} α β α (instHPow.{u2, u1} α β _inst_1) a b)
Case conversion may be inaccurate. Consider using '#align pow_to_dual pow_toDualₓ'. -/
@[simp, to_additive toDual_smul', to_additive_reorder 1 4]
theorem pow_toDual [Pow α β] (a : α) (b : β) : a ^ toDual b = a ^ b :=
  rfl
#align pow_to_dual pow_toDual
#align to_dual_smul' toDual_smul'

/- warning: pow_of_dual -> pow_ofDual is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : Pow.{u1, u2} α β] (a : α) (b : OrderDual.{u2} β), Eq.{succ u1} α (HPow.hPow.{u1, u2, u1} α β α (instHPow.{u1, u2} α β _inst_1) a (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} (OrderDual.{u2} β) β) (fun (_x : Equiv.{succ u2, succ u2} (OrderDual.{u2} β) β) => (OrderDual.{u2} β) -> β) (Equiv.hasCoeToFun.{succ u2, succ u2} (OrderDual.{u2} β) β) (OrderDual.ofDual.{u2} β) b)) (HPow.hPow.{u1, u2, u1} α (OrderDual.{u2} β) α (instHPow.{u1, u2} α (OrderDual.{u2} β) (instPowOrderDual'.{u1, u2} α β _inst_1)) a b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : Pow.{u2, u1} α β] (a : α) (b : OrderDual.{u1} β), Eq.{succ u2} α (HPow.hPow.{u2, u1, u2} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) b) α (instHPow.{u2, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) b) _inst_1) a (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} (OrderDual.{u1} β) β) (OrderDual.{u1} β) (fun (_x : OrderDual.{u1} β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : OrderDual.{u1} β) => β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} (OrderDual.{u1} β) β) (OrderDual.ofDual.{u1} β) b)) (HPow.hPow.{u2, u1, u2} α (OrderDual.{u1} β) α (instHPow.{u2, u1} α (OrderDual.{u1} β) (instPowOrderDual'.{u2, u1} α β _inst_1)) a b)
Case conversion may be inaccurate. Consider using '#align pow_of_dual pow_ofDualₓ'. -/
@[simp, to_additive ofDual_smul', to_additive_reorder 1 4]
theorem pow_ofDual [Pow α β] (a : α) (b : βᵒᵈ) : a ^ ofDual b = a ^ b :=
  rfl
#align pow_of_dual pow_ofDual
#align of_dual_smul' ofDual_smul'

/-! ### Lexicographical order -/

@[to_additive]
instance [h : One α] : One (Lex α) :=
  h

@[to_additive]
instance [h : Mul α] : Mul (Lex α) :=
  h

@[to_additive]
instance [h : Inv α] : Inv (Lex α) :=
  h

@[to_additive]
instance [h : Div α] : Div (Lex α) :=
  h

@[to_additive]
instance [h : SMul α β] : SMul α (Lex β) :=
  h

#print instSMulLex' /-
@[to_additive]
instance instSMulLex' [h : SMul α β] : SMul (Lex α) β :=
  h
#align lex.has_smul' instSMulLex'
-/

#print instPowLex /-
@[to_additive instSMulLex]
instance instPowLex [h : Pow α β] : Pow (Lex α) β :=
  h
#align lex.has_pow instPowLex
#align lex.has_smul instSMulLex
-/

#print instPowLex' /-
@[to_additive instSMulLex']
instance instPowLex' [h : Pow α β] : Pow α (Lex β) :=
  h
#align lex.has_pow' instPowLex'
#align lex.has_smul' instSMulLex'
-/

@[to_additive]
instance [h : Semigroup α] : Semigroup (Lex α) :=
  h

@[to_additive]
instance [h : CommSemigroup α] : CommSemigroup (Lex α) :=
  h

@[to_additive]
instance [h : LeftCancelSemigroup α] : LeftCancelSemigroup (Lex α) :=
  h

@[to_additive]
instance [h : RightCancelSemigroup α] : RightCancelSemigroup (Lex α) :=
  h

@[to_additive]
instance [h : MulOneClass α] : MulOneClass (Lex α) :=
  h

@[to_additive]
instance [h : Monoid α] : Monoid (Lex α) :=
  h

@[to_additive]
instance [h : CommMonoid α] : CommMonoid (Lex α) :=
  h

@[to_additive]
instance [h : LeftCancelMonoid α] : LeftCancelMonoid (Lex α) :=
  h

@[to_additive]
instance [h : RightCancelMonoid α] : RightCancelMonoid (Lex α) :=
  h

@[to_additive]
instance [h : CancelMonoid α] : CancelMonoid (Lex α) :=
  h

@[to_additive]
instance [h : CancelCommMonoid α] : CancelCommMonoid (Lex α) :=
  h

@[to_additive]
instance [h : InvolutiveInv α] : InvolutiveInv (Lex α) :=
  h

@[to_additive]
instance [h : DivInvMonoid α] : DivInvMonoid (Lex α) :=
  h

@[to_additive OrderDual.subtractionMonoid]
instance [h : DivisionMonoid α] : DivisionMonoid (Lex α) :=
  h

@[to_additive OrderDual.subtractionCommMonoid]
instance [h : DivisionCommMonoid α] : DivisionCommMonoid (Lex α) :=
  h

@[to_additive]
instance [h : Group α] : Group (Lex α) :=
  h

@[to_additive]
instance [h : CommGroup α] : CommGroup (Lex α) :=
  h

#print toLex_one /-
@[simp, to_additive]
theorem toLex_one [One α] : toLex (1 : α) = 1 :=
  rfl
#align to_lex_one toLex_one
#align to_lex_zero toLex_zero
-/

#print ofLex_one /-
@[simp, to_additive]
theorem ofLex_one [One α] : (ofLex 1 : α) = 1 :=
  rfl
#align of_lex_one ofLex_one
#align of_lex_zero ofLex_zero
-/

#print toLex_mul /-
@[simp, to_additive]
theorem toLex_mul [Mul α] (a b : α) : toLex (a * b) = toLex a * toLex b :=
  rfl
#align to_lex_mul toLex_mul
#align to_lex_add toLex_add
-/

#print ofLex_mul /-
@[simp, to_additive]
theorem ofLex_mul [Mul α] (a b : Lex α) : ofLex (a * b) = ofLex a * ofLex b :=
  rfl
#align of_lex_mul ofLex_mul
#align of_lex_add ofLex_add
-/

#print toLex_inv /-
@[simp, to_additive]
theorem toLex_inv [Inv α] (a : α) : toLex a⁻¹ = (toLex a)⁻¹ :=
  rfl
#align to_lex_inv toLex_inv
#align to_lex_neg toLex_neg
-/

#print ofLex_inv /-
@[simp, to_additive]
theorem ofLex_inv [Inv α] (a : Lex α) : ofLex a⁻¹ = (ofLex a)⁻¹ :=
  rfl
#align of_lex_inv ofLex_inv
#align of_lex_neg ofLex_neg
-/

#print toLex_div /-
@[simp, to_additive]
theorem toLex_div [Div α] (a b : α) : toLex (a / b) = toLex a / toLex b :=
  rfl
#align to_lex_div toLex_div
#align to_lex_sub toLex_sub
-/

#print ofLex_div /-
@[simp, to_additive]
theorem ofLex_div [Div α] (a b : Lex α) : ofLex (a / b) = ofLex a / ofLex b :=
  rfl
#align of_lex_div ofLex_div
#align of_lex_sub ofLex_sub
-/

/- warning: to_lex_smul -> toLex_smul is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : SMul.{u1, u2} α β] (a : α) (b : β), Eq.{succ u2} (Lex.{u2} β) (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} β (Lex.{u2} β)) (fun (_x : Equiv.{succ u2, succ u2} β (Lex.{u2} β)) => β -> (Lex.{u2} β)) (Equiv.hasCoeToFun.{succ u2, succ u2} β (Lex.{u2} β)) (toLex.{u2} β) (SMul.smul.{u1, u2} α β _inst_1 a b)) (SMul.smul.{u1, u2} α (Lex.{u2} β) (instSMulLex.{u1, u2} α β _inst_1) a (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} β (Lex.{u2} β)) (fun (_x : Equiv.{succ u2, succ u2} β (Lex.{u2} β)) => β -> (Lex.{u2} β)) (Equiv.hasCoeToFun.{succ u2, succ u2} β (Lex.{u2} β)) (toLex.{u2} β) b))
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : SMul.{u2, u1} α β] (a : α) (b : β), Eq.{succ u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) (HSMul.hSMul.{u2, u1, u1} α β β (instHSMul.{u2, u1} α β _inst_1) a b)) (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} β (Lex.{u1} β)) β (fun (_x : β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} β (Lex.{u1} β)) (toLex.{u1} β) (HSMul.hSMul.{u2, u1, u1} α β β (instHSMul.{u2, u1} α β _inst_1) a b)) (HSMul.hSMul.{u2, u1, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) b) ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) b) (instHSMul.{u2, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) b) (instSMulLex.{u2, u1} α β _inst_1)) a (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} β (Lex.{u1} β)) β (fun (_x : β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} β (Lex.{u1} β)) (toLex.{u1} β) b))
Case conversion may be inaccurate. Consider using '#align to_lex_smul toLex_smulₓ'. -/
@[simp, to_additive]
theorem toLex_smul [SMul α β] (a : α) (b : β) : toLex (a • b) = a • toLex b :=
  rfl
#align to_lex_smul toLex_smul
#align to_lex_vadd toLex_vadd

/- warning: of_lex_smul -> ofLex_smul is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : SMul.{u1, u2} α β] (a : α) (b : Lex.{u2} β), Eq.{succ u2} β (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} (Lex.{u2} β) β) (fun (_x : Equiv.{succ u2, succ u2} (Lex.{u2} β) β) => (Lex.{u2} β) -> β) (Equiv.hasCoeToFun.{succ u2, succ u2} (Lex.{u2} β) β) (ofLex.{u2} β) (SMul.smul.{u1, u2} α (Lex.{u2} β) (instSMulLex.{u1, u2} α β _inst_1) a b)) (SMul.smul.{u1, u2} α β _inst_1 a (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} (Lex.{u2} β) β) (fun (_x : Equiv.{succ u2, succ u2} (Lex.{u2} β) β) => (Lex.{u2} β) -> β) (Equiv.hasCoeToFun.{succ u2, succ u2} (Lex.{u2} β) β) (ofLex.{u2} β) b))
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : SMul.{u2, u1} α β] (a : α) (b : Lex.{u1} β), Eq.{succ u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) (HSMul.hSMul.{u2, u1, u1} α (Lex.{u1} β) (Lex.{u1} β) (instHSMul.{u2, u1} α (Lex.{u1} β) (instSMulLex.{u2, u1} α β _inst_1)) a b)) (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} (Lex.{u1} β) β) (Lex.{u1} β) (fun (_x : Lex.{u1} β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} (Lex.{u1} β) β) (ofLex.{u1} β) (HSMul.hSMul.{u2, u1, u1} α (Lex.{u1} β) (Lex.{u1} β) (instHSMul.{u2, u1} α (Lex.{u1} β) (instSMulLex.{u2, u1} α β _inst_1)) a b)) (HSMul.hSMul.{u2, u1, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) b) ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) b) (instHSMul.{u2, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) b) _inst_1) a (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} (Lex.{u1} β) β) (Lex.{u1} β) (fun (_x : Lex.{u1} β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} (Lex.{u1} β) β) (ofLex.{u1} β) b))
Case conversion may be inaccurate. Consider using '#align of_lex_smul ofLex_smulₓ'. -/
@[simp, to_additive]
theorem ofLex_smul [SMul α β] (a : α) (b : Lex β) : ofLex (a • b) = a • ofLex b :=
  rfl
#align of_lex_smul ofLex_smul
#align of_lex_vadd ofLex_vadd

/- warning: to_lex_smul' -> toLex_smul' is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : SMul.{u1, u2} α β] (a : α) (b : β), Eq.{succ u2} β (SMul.smul.{u1, u2} (Lex.{u1} α) β (instSMulLex'.{u1, u2} α β _inst_1) (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} α (Lex.{u1} α)) (fun (_x : Equiv.{succ u1, succ u1} α (Lex.{u1} α)) => α -> (Lex.{u1} α)) (Equiv.hasCoeToFun.{succ u1, succ u1} α (Lex.{u1} α)) (toLex.{u1} α) a) b) (SMul.smul.{u1, u2} α β _inst_1 a b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : SMul.{u2, u1} α β] (a : α) (b : β), Eq.{succ u1} β (HSMul.hSMul.{u2, u1, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) a) β β (instHSMul.{u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) a) β (instSMulLex'.{u2, u1} α β _inst_1)) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} α (Lex.{u2} α)) α (fun (_x : α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} α (Lex.{u2} α)) (toLex.{u2} α) a) b) (HSMul.hSMul.{u2, u1, u1} α β β (instHSMul.{u2, u1} α β _inst_1) a b)
Case conversion may be inaccurate. Consider using '#align to_lex_smul' toLex_smul'ₓ'. -/
@[simp, to_additive]
theorem toLex_smul' [SMul α β] (a : α) (b : β) : toLex a • b = a • b :=
  rfl
#align to_lex_smul' toLex_smul'
#align to_lex_vadd' toLex_vadd'

/- warning: of_lex_smul' -> ofLex_smul' is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : SMul.{u1, u2} α β] (a : Lex.{u1} α) (b : β), Eq.{succ u2} β (SMul.smul.{u1, u2} α β _inst_1 (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} (Lex.{u1} α) α) (fun (_x : Equiv.{succ u1, succ u1} (Lex.{u1} α) α) => (Lex.{u1} α) -> α) (Equiv.hasCoeToFun.{succ u1, succ u1} (Lex.{u1} α) α) (ofLex.{u1} α) a) b) (SMul.smul.{u1, u2} (Lex.{u1} α) β (instSMulLex'.{u1, u2} α β _inst_1) a b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : SMul.{u2, u1} α β] (a : Lex.{u2} α) (b : β), Eq.{succ u1} β (HSMul.hSMul.{u2, u1, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) a) β β (instHSMul.{u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) a) β _inst_1) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} (Lex.{u2} α) α) (Lex.{u2} α) (fun (_x : Lex.{u2} α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} (Lex.{u2} α) α) (ofLex.{u2} α) a) b) (HSMul.hSMul.{u2, u1, u1} (Lex.{u2} α) β β (instHSMul.{u2, u1} (Lex.{u2} α) β (instSMulLex'.{u2, u1} α β _inst_1)) a b)
Case conversion may be inaccurate. Consider using '#align of_lex_smul' ofLex_smul'ₓ'. -/
@[simp, to_additive]
theorem ofLex_smul' [SMul α β] (a : Lex α) (b : β) : ofLex a • b = a • b :=
  rfl
#align of_lex_smul' ofLex_smul'
#align of_lex_vadd' ofLex_vadd'

/- warning: to_lex_pow -> toLex_pow is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : Pow.{u1, u2} α β] (a : α) (b : β), Eq.{succ u1} (Lex.{u1} α) (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} α (Lex.{u1} α)) (fun (_x : Equiv.{succ u1, succ u1} α (Lex.{u1} α)) => α -> (Lex.{u1} α)) (Equiv.hasCoeToFun.{succ u1, succ u1} α (Lex.{u1} α)) (toLex.{u1} α) (HPow.hPow.{u1, u2, u1} α β α (instHPow.{u1, u2} α β _inst_1) a b)) (HPow.hPow.{u1, u2, u1} (Lex.{u1} α) β (Lex.{u1} α) (instHPow.{u1, u2} (Lex.{u1} α) β (instPowLex.{u1, u2} α β _inst_1)) (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} α (Lex.{u1} α)) (fun (_x : Equiv.{succ u1, succ u1} α (Lex.{u1} α)) => α -> (Lex.{u1} α)) (Equiv.hasCoeToFun.{succ u1, succ u1} α (Lex.{u1} α)) (toLex.{u1} α) a) b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : Pow.{u2, u1} α β] (a : α) (b : β), Eq.{succ u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) (HPow.hPow.{u2, u1, u2} α β α (instHPow.{u2, u1} α β _inst_1) a b)) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} α (Lex.{u2} α)) α (fun (_x : α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} α (Lex.{u2} α)) (toLex.{u2} α) (HPow.hPow.{u2, u1, u2} α β α (instHPow.{u2, u1} α β _inst_1) a b)) (HPow.hPow.{u2, u1, u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) a) β ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) a) (instHPow.{u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) a) β (instPowLex.{u2, u1} α β _inst_1)) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} α (Lex.{u2} α)) α (fun (_x : α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α) => Lex.{u2} α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} α (Lex.{u2} α)) (toLex.{u2} α) a) b)
Case conversion may be inaccurate. Consider using '#align to_lex_pow toLex_powₓ'. -/
@[simp, to_additive toLex_smul, to_additive_reorder 1 4]
theorem toLex_pow [Pow α β] (a : α) (b : β) : toLex (a ^ b) = toLex a ^ b :=
  rfl
#align to_lex_pow toLex_pow
#align to_lex_smul toLex_smul

/- warning: of_lex_pow -> ofLex_pow is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : Pow.{u1, u2} α β] (a : Lex.{u1} α) (b : β), Eq.{succ u1} α (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} (Lex.{u1} α) α) (fun (_x : Equiv.{succ u1, succ u1} (Lex.{u1} α) α) => (Lex.{u1} α) -> α) (Equiv.hasCoeToFun.{succ u1, succ u1} (Lex.{u1} α) α) (ofLex.{u1} α) (HPow.hPow.{u1, u2, u1} (Lex.{u1} α) β (Lex.{u1} α) (instHPow.{u1, u2} (Lex.{u1} α) β (instPowLex.{u1, u2} α β _inst_1)) a b)) (HPow.hPow.{u1, u2, u1} α β α (instHPow.{u1, u2} α β _inst_1) (coeFn.{succ u1, succ u1} (Equiv.{succ u1, succ u1} (Lex.{u1} α) α) (fun (_x : Equiv.{succ u1, succ u1} (Lex.{u1} α) α) => (Lex.{u1} α) -> α) (Equiv.hasCoeToFun.{succ u1, succ u1} (Lex.{u1} α) α) (ofLex.{u1} α) a) b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : Pow.{u2, u1} α β] (a : Lex.{u2} α) (b : β), Eq.{succ u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) (HPow.hPow.{u2, u1, u2} (Lex.{u2} α) β (Lex.{u2} α) (instHPow.{u2, u1} (Lex.{u2} α) β (instPowLex.{u2, u1} α β _inst_1)) a b)) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} (Lex.{u2} α) α) (Lex.{u2} α) (fun (_x : Lex.{u2} α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} (Lex.{u2} α) α) (ofLex.{u2} α) (HPow.hPow.{u2, u1, u2} (Lex.{u2} α) β (Lex.{u2} α) (instHPow.{u2, u1} (Lex.{u2} α) β (instPowLex.{u2, u1} α β _inst_1)) a b)) (HPow.hPow.{u2, u1, u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) a) β ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) a) (instHPow.{u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) a) β _inst_1) (FunLike.coe.{succ u2, succ u2, succ u2} (Equiv.{succ u2, succ u2} (Lex.{u2} α) α) (Lex.{u2} α) (fun (_x : Lex.{u2} α) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u2} α) => α) _x) (Equiv.instFunLikeEquiv.{succ u2, succ u2} (Lex.{u2} α) α) (ofLex.{u2} α) a) b)
Case conversion may be inaccurate. Consider using '#align of_lex_pow ofLex_powₓ'. -/
@[simp, to_additive ofLex_smul, to_additive_reorder 1 4]
theorem ofLex_pow [Pow α β] (a : Lex α) (b : β) : ofLex (a ^ b) = ofLex a ^ b :=
  rfl
#align of_lex_pow ofLex_pow
#align of_lex_smul ofLex_smul

/- warning: pow_to_lex -> pow_toLex is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : Pow.{u1, u2} α β] (a : α) (b : β), Eq.{succ u1} α (HPow.hPow.{u1, u2, u1} α (Lex.{u2} β) α (instHPow.{u1, u2} α (Lex.{u2} β) (instPowLex'.{u1, u2} α β _inst_1)) a (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} β (Lex.{u2} β)) (fun (_x : Equiv.{succ u2, succ u2} β (Lex.{u2} β)) => β -> (Lex.{u2} β)) (Equiv.hasCoeToFun.{succ u2, succ u2} β (Lex.{u2} β)) (toLex.{u2} β) b)) (HPow.hPow.{u1, u2, u1} α β α (instHPow.{u1, u2} α β _inst_1) a b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : Pow.{u2, u1} α β] (a : α) (b : β), Eq.{succ u2} α (HPow.hPow.{u2, u1, u2} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) b) α (instHPow.{u2, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) b) (instPowLex'.{u2, u1} α β _inst_1)) a (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} β (Lex.{u1} β)) β (fun (_x : β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : β) => Lex.{u1} β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} β (Lex.{u1} β)) (toLex.{u1} β) b)) (HPow.hPow.{u2, u1, u2} α β α (instHPow.{u2, u1} α β _inst_1) a b)
Case conversion may be inaccurate. Consider using '#align pow_to_lex pow_toLexₓ'. -/
@[simp, to_additive toLex_smul, to_additive_reorder 1 4]
theorem pow_toLex [Pow α β] (a : α) (b : β) : a ^ toLex b = a ^ b :=
  rfl
#align pow_to_lex pow_toLex
#align to_lex_smul' toLex_smul'

/- warning: pow_of_lex -> pow_ofLex is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : Pow.{u1, u2} α β] (a : α) (b : Lex.{u2} β), Eq.{succ u1} α (HPow.hPow.{u1, u2, u1} α β α (instHPow.{u1, u2} α β _inst_1) a (coeFn.{succ u2, succ u2} (Equiv.{succ u2, succ u2} (Lex.{u2} β) β) (fun (_x : Equiv.{succ u2, succ u2} (Lex.{u2} β) β) => (Lex.{u2} β) -> β) (Equiv.hasCoeToFun.{succ u2, succ u2} (Lex.{u2} β) β) (ofLex.{u2} β) b)) (HPow.hPow.{u1, u2, u1} α (Lex.{u2} β) α (instHPow.{u1, u2} α (Lex.{u2} β) (instPowLex'.{u1, u2} α β _inst_1)) a b)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : Pow.{u2, u1} α β] (a : α) (b : Lex.{u1} β), Eq.{succ u2} α (HPow.hPow.{u2, u1, u2} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) b) α (instHPow.{u2, u1} α ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) b) _inst_1) a (FunLike.coe.{succ u1, succ u1, succ u1} (Equiv.{succ u1, succ u1} (Lex.{u1} β) β) (Lex.{u1} β) (fun (_x : Lex.{u1} β) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Lex.{u1} β) => β) _x) (Equiv.instFunLikeEquiv.{succ u1, succ u1} (Lex.{u1} β) β) (ofLex.{u1} β) b)) (HPow.hPow.{u2, u1, u2} α (Lex.{u1} β) α (instHPow.{u2, u1} α (Lex.{u1} β) (instPowLex'.{u2, u1} α β _inst_1)) a b)
Case conversion may be inaccurate. Consider using '#align pow_of_lex pow_ofLexₓ'. -/
@[simp, to_additive ofLex_smul, to_additive_reorder 1 4]
theorem pow_ofLex [Pow α β] (a : α) (b : Lex β) : a ^ ofLex b = a ^ b :=
  rfl
#align pow_of_lex pow_ofLex
#align of_lex_smul' ofLex_smul'