namespace prop_logic

/- [25 points total, as indicated below]

This assignment has five problems. The first
is to extend our propositional logic syntax
and semantics to support the three additional
connectives, exclusive or (⊕), implies (which
we will write as ⇒), and if and only iff (↔).
We first give you the definitions developed
in class. You are to extend/modify them to
support expressions with the new connectives.
The remaining problems use this definition of
our language of expressions in propositional
logic.
-/

/--/
    **************
    *** SYNTAX ***
    **************
-/

inductive var : Type
| mkVar : ℕ → var

inductive unOp : Type
| notOp

inductive binOp : Type
| andOp
| orOp
/-HW 5 points]-/
| xorOp
| implOp
| iffOp
/-HW-/

inductive pExp : Type
| litExp : bool → pExp
| varExp : var → pExp
| unOpExp : unOp → pExp → pExp
| binOpExp : binOp → pExp → pExp → pExp

open var
open pExp
open unOp
open binOp

-- Shorthand notations
def pTrue := litExp tt
def pFalse := litExp ff
def pNot := unOpExp notOp
def pAnd := binOpExp andOp
def pOr := binOpExp orOp
/-HW- [5 points]-/
def pXor := binOpExp xorOp
def pImpl := binOpExp implOp
def pIff := binOpExp iffOp
/-HW-/

-- conventional notation

notation e1 ∧ e2 :=  pAnd e1 e2
notation e1 ∨ e2 :=  pOr e1 e2
notation ¬ e := pNot e

#print ⇒

/-HW- [5 points] -/
notation e1 ⇒ e2 := pImpl e1 e2
notation e1 ⊕ e2 := pXor e1 e2
notation e1 ↔ e2 := pIff e1 e2
/-HW-/

/-
    *****************
    *** SEMANTICS ***
    *****************
-/

def interpUnOp : unOp → (bool → bool)
| notOp := bnot

/-

-/

/-HW [5 points] -/
def bimpl : bool → bool → bool
| tt ff := ff
| _ _ := tt

def biff : bool → bool → bool
| tt tt := tt
| ff ff := tt
| _ _ := ff
/-HW-/

def interpBinOp : binOp → (bool → bool → bool)
| andOp := band
| orOp := bor
/-HW [5 points] -/
| xorOp := bxor
| implOp := bimpl
| iffOp := biff
/-HW-/

/-
Given a pExp and an interpretation
for the variables, evaluate the pExp
to determine its Boolean truth value.
-/
def pEval : pExp → (var → bool) → bool
| (litExp b) i := b
| (varExp v) i := i v
| (unOpExp op e) i :=
    (interpUnOp op) (pEval e i)
| (binOpExp op e1 e2) i :=
     (interpBinOp op)
        (pEval e1 i)
        (pEval e2 i)

/-
#2 [5 points]. Define X, Y, and Z to be
variable expressions with no "aliases". That
is each name should be bound to a distinct
variable expression term. Hint: Just look
at the prop_logic_test.lean file to
remind yourself what we did in class.
-/

def X : pExp := varExp (mkVar 0)
def Y : pExp := varExp (mkVar 1)
def Z : pExp := varExp (mkVar 2)

/- [25 points total, as indicated]

#3. Here are some English language
sentences that you are to re-express
in propositional logic. Here's one
example.
-/

/-
EXAMPLE:

Formalize the following proposition,
as a formula in propositional logic:
If it's raining then it's raining.
-/

-- Solution

def R : pExp := varExp (mkVar 4)
def p1 : pExp := R ⇒ R

/-
Explanation: We first choose to represent
the smaller proposition, "it's raining",
by the variable expression, R. We then
formalize the overall natural language
expression, if R then R, as the formula,
R ⇒ R.

Note: R ⇒ R can be pronounced as any of:
- if R is true then R is true
- if R then R
- the truth of R implies the truth of R
- R implies R

The second and fourth pronounciations
are the two that we prefer to use.
-/

/-
For the remaining problems, use the
variables expressions, X, Y, and Z,
as already defined. Use parentheses
if needed to group sub-expressions.
-/

/-
A. [5 points]

If it's raining and the streets are
wet then it's raining.
-/

def p2 : pExp := (X ∧ Y) ⇒ X

/- [5 points]

B. If it's raining and the streets
are wet, then the streets are wet
and it's raining.
-/

def p3 := (X ∧ Y) ⇒ (Y ∧ X)

/- [5 points]

C. If it's raining then if the
streets are wet then it's raining
and the streets are wet.
-/
def p4 := X ⇒ (Y ⇒ (X ∧ Y))

/- [5 points]

D. If it's raining then it's
raining or the moon is made of
green cheese.
-/
def p5 := X ⇒ (X ∨ Y)

/- [5 points]

E. If it's raining, then if it's
raining implies that the streets
are wet, then the streets are wet.
-/
#check X ⇒ (X ⇒ Y) ⇒ Y

/-
#4. For each of the propositional
logic expressions below, write a truth
table and based on your result, state
whether the expression is unsatisfiable,
satisfiable but not valid, or valid.

Here's an example solution for the
expression, (X ∧ Y) ⇒ Y.

X   Y   X ∧ Y   (X ∧ Y) ⇒ Y
-   -   -----   -----------
T   T   T       T ⇒ T = T
T   F   F       F ⇒ F = T
F   T   F       F ⇒ T = T
F   F   F       F ⇒ F = T

The proposition is thus valid.
-/

/- [5 points]
A. After the #check give your answer
for the checked proposition. Important
to know: implies is right associative.
-/

#check (X ⇒ Y) ⇒ (¬ X ⇒ ¬ Y)

/-

X   Y   X ⇒ Y   ¬ X ⇒ ¬ Y   Result
-   -   -----   ---------   ------
T   T   T       T               T
T   F   F       T               T
F   T   T       F               F
F   F   T       T               T

Formula is satisfiable but not valid.

-/

/-
B. [10 points]
-/

#check ((X ⇒ Y) ∧ (Y ⇒ X)) ⇒ (X ⇒ Z)

/-

THE ORIGINAL ANSWER KEY GAVE ANSWER FOR A DIFFERENT QUESTION.
THIS ANSWER IS CORRECT.

X   Y   Z   X ⇒ Y   Y ⇒ X   (X ⇒ Y) ∧ (Y ⇒ X)   X ⇒ Z   Result
-   -   -   -----   -----   -----------------   -----   ------
T   T   T   T       T       T                   T       T
T   T   F   T       T       T                   F       F
T   F   T   F       T       F                   T       T
T   F   F   F       T       F                   F       T
F   T   T   T       F       F                   T       T
F   T   F   T       F       F                   T       T
F   F   T   T       T       T                   T       T
F   F   F   T       T       T                   T       T

This formula is NOT valid.
-/

/-
C. [5 points]
-/
#check pFalse ⇒ (X ∧ ¬ X)

/-

Truth table answers omitted here and below. Maybe a TA will
fill in answers.

This proposition is valid.
-/

/-
D. [5 points]
-/

#check pTrue ⇒ (X ∧ ¬ X)

-- Unsatisfiable.

/-
E. [5 points]
-/

#check (X ∨ Y) ∧ X ⇒ ¬ Y

-- Satisfiable but not valid.

/- [15 points total]

#5. Find and present an interpretation
that causes the following proposition
to be satisfied (to evaluate to true).

(X ∨ Y) ∧ (¬ Y ∨ Z)

Answer [5 points]:

Next determine how many interpretations
satisfy it.

Answer [10 points]:

X Y Z   (X ∨ Y)     (¬ Y or Z)  (X ∨ Y) ∧ (¬ Y ∨ Z)

T T T   T           F           F
T T F   T           F           F
T F T   T           F           F
T F F   T           T           T   * model
F T T   T           T           T   * model
F T F   T           F           F
F F T   F           T           F
F F F   F           T           F

ANSWER: Two interpretations satisfy the formula,
as per the truth table above, which gives the two
satisfying assignments of values to the variables
(models).
-/

end prop_logic


import Mathlib.Data.Nat.GCD.Basic
import Mathlib.Tactic.Ring
import Std
import Demo.Util

def fib : Nat → Nat
  | 0 => 0
  | 1 => 1
  | n + 2 => fib (n + 1) + fib n

#eval fib 15
#eval List.map fib (List.range 20)

--set_option trace.Meta.Tactic.simp.rewrite true in
theorem fib_add_two {n : ℕ} : fib (n + 2) = fib n + fib (n + 1) := by
  simp [fib, add_comm]

lemma fib_add (m n : ℕ) :
    fib (m + n + 1) = fib m * fib n + fib (m + 1) * fib (n + 1) := by
  induction n generalizing m
  case zero =>
    simp [fib]
  case succ n ih =>
    specialize ih (m + 1)
    rw [add_assoc m 1 n, add_comm 1 n] at ih
    simp only [fib_add_two, ih]
    ring

def fib₀ : Nat → Nat
  | 0 => 0
  | n + 1 => (aux n).2
where
  aux : Nat → Nat × Nat
    | 0 => (0, 1)
    | n + 1 =>
      let (a, b) := aux n
      (b, a + b)

#eval fib₀ 1000

lemma fib₀_aux_eq (n : Nat) : fib₀.aux n = (fib n, fib (n + 1)) := by
  induction n
  . simp [fib]
  . next _ ih => simp [fib₀.aux, fib, ih, add_comm]

@[csimp] theorem fib_eq : fib = fib₀ := by
  ext n
  cases n <;> simp [fib, fib₀, fib₀_aux_eq, add_comm]

#eval fib 1000

def fib₁ (n : Nat) :=
  aux n 0 1
where aux : Nat → Nat → Nat → Nat
  | 0, _, b => b
  | n+1, a, b => aux n b (a + b)

#eval fib₁ 400000
-- #eval fib₁ 400000

def fib₂ (n : Nat) : Nat := Id.run do
  let mut p := (0, 1)
  for _ in [:n] do
    let (a, b) := p
    p := (b, a + b)
  return p.1

#eval fib₂ 100

def fib₃ (n : Nat) : Nat := Id.run do
  let mut a := 0
  let mut b := 1
  for _ in [:n] do
    let temp := a
    a := b
    b := temp + b
  return b

def fib₄ (n : Nat) : { m // m = fib n } :=
  let ⟨pair, property⟩ :=
  loop_with_invariant
    (invariant := fun i p => p = (fib i, fib (i + 1)))
    (start_state := (0, 1))
    (init := by simp [fib])
    (next_state := fun i p =>
      let (a, b) := p
      (b, a + b))
    (step := by intro i; simp [fib, add_comm])
    n
  ⟨pair.1, by simp [property]⟩

#eval fib₄ 10000

def fib₅ (n : Nat) : { m // m = fib n } :=
  for i upto n
    state: p := (0, 1)
    invariant: inv := p = (fib i, fib (i + 1))
    init:= by simp
    next:
      let (a, b) := p
      (b, a + b)
    step:= by intro i; simp [fib, add_comm]
  ⟨p.1, by simp [inv]⟩

/-
Notes.

Conventional wisdom:
- Functional programming is easier to reason about.
- Functional proramming is better for concurrency.
- Imperative programming is more efficient.

Lean somewhat simulates an imperative style.
It uses dynamic arrays with destructive updates when they are not shared.
The standard library has arrays and hashmaps.

Two questions:
- Are the imperative features good enough for real applications? Which ones?
- Can we reason about them?

Two big Lean programming projects:
- https://github.com/leanprover/lean4
- https://github.com/leanprover-community/duper

Thesis: we should be able to simulate the functionality of e.g. Dafny.
- SMT proofs can be trusted, reconstructed, or checked.
- We can use varying degrees of interaction.
- Lean can call external functions and link them to reference implementations

-/

-- set_option trace.Meta.Tactic.simp true in
set_option trace.Meta.synthInstance true in
example : (x + 2) + 2 = x + 4 := by simp [add_assoc]

#check add_assoc


/-
Copyright (c) 2018 Chris Hughes. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes, Scott Morrison, Johan Commelin
-/
import data.finset.card

/-!
# Finsets in `fin n`

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

A few constructions for finsets in `fin n`.

## Main declarations

* `finset.attach_fin`: Turns a finset of naturals strictly less than `n` into a `finset (fin n)`.
-/

variables {n : ℕ}

namespace finset

/-- Given a finset `s` of `ℕ` contained in `{0,..., n-1}`, the corresponding finset in `fin n`
is `s.attach_fin h` where `h` is a proof that all elements of `s` are less than `n`. -/
def attach_fin (s : finset ℕ) {n : ℕ} (h : ∀ m ∈ s, m < n) : finset (fin n) :=
⟨s.1.pmap (λ a ha, ⟨a, ha⟩) h, s.nodup.pmap $ λ _ _ _ _, fin.veq_of_eq⟩

@[simp] lemma mem_attach_fin {n : ℕ} {s : finset ℕ} (h : ∀ m ∈ s, m < n) {a : fin n} :
  a ∈ s.attach_fin h ↔ (a : ℕ) ∈ s :=
⟨λ h, let ⟨b, hb₁, hb₂⟩ := multiset.mem_pmap.1 h in hb₂ ▸ hb₁,
λ h, multiset.mem_pmap.2 ⟨a, h, fin.eta _ _⟩⟩

@[simp] lemma card_attach_fin {n : ℕ} (s : finset ℕ) (h : ∀ m ∈ s, m < n) :
  (s.attach_fin h).card = s.card :=
multiset.card_pmap _ _ _

end finset


/-
Copyright © 2021 Nicolò Cavalleri. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Nicolò Cavalleri

! This file was ported from Lean 3 source module data.bundle
! leanprover-community/mathlib commit baba818b9acea366489e8ba32d2cc0fcaf50a1f7
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Algebra.Module.Basic

/-!
# Bundle

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.
Basic data structure to implement fiber bundles, vector bundles (maybe fibrations?), etc. This file
should contain all possible results that do not involve any topology.

We represent a bundle `E` over a base space `B` as a dependent type `E : B → Type*`.

We provide a type synonym of `Σ x, E x` as `bundle.total_space E`, to be able to endow it with
a topology which is not the disjoint union topology `sigma.topological_space`. In general, the
constructions of fiber bundles we will make will be of this form.

## Main Definitions

* `bundle.total_space` the total space of a bundle.
* `bundle.total_space.proj` the projection from the total space to the base space.
* `bundle.total_space_mk` the constructor for the total space.

## References
- https://en.wikipedia.org/wiki/Bundle_(mathematics)
-/

namespace Bundle

variable {B : Type _} (E : B → Type _)

#print Bundle.TotalSpace /-
/-- `bundle.total_space E` is the total space of the bundle `Σ x, E x`.
This type synonym is used to avoid conflicts with general sigma types.
-/
def TotalSpace :=
  Σx, E x
#align bundle.total_space Bundle.TotalSpace
-/

instance [Inhabited B] [Inhabited (E default)] : Inhabited (TotalSpace E) :=
  ⟨⟨default, default⟩⟩

variable {E}

#print Bundle.TotalSpace.proj /-
/-- `bundle.total_space.proj` is the canonical projection `bundle.total_space E → B` from the
total space to the base space. -/
@[simp, reducible]
def TotalSpace.proj : TotalSpace E → B :=
  Sigma.fst
#align bundle.total_space.proj Bundle.TotalSpace.proj
-/

-- mathport name: exprπ
-- this notation won't be used in the pretty-printer
scoped notation "π" => @Bundle.TotalSpace.proj _

#print Bundle.totalSpaceMk /-
/-- Constructor for the total space of a bundle. -/
@[simp, reducible]
def totalSpaceMk (b : B) (a : E b) : Bundle.TotalSpace E :=
  ⟨b, a⟩
#align bundle.total_space_mk Bundle.totalSpaceMk
-/

/- warning: bundle.total_space.proj_mk -> Bundle.TotalSpace.proj_mk is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} {x : B} {y : E x}, Eq.{succ u1} B (Bundle.TotalSpace.proj.{u1, u2} B (fun {x : B} => E x) (Bundle.totalSpaceMk.{u1, u2} B (fun {x : B} => E x) x y)) x
but is expected to have type
  forall {B : Type.{u2}} {E : B -> Type.{u1}} {x : B} {y : E x}, Eq.{succ u2} B (Bundle.TotalSpace.proj.{u2, u1} B E (Bundle.totalSpaceMk.{u2, u1} B E x y)) x
Case conversion may be inaccurate. Consider using '#align bundle.total_space.proj_mk Bundle.TotalSpace.proj_mkₓ'. -/
theorem TotalSpace.proj_mk {x : B} {y : E x} : (totalSpaceMk x y).proj = x :=
  rfl
#align bundle.total_space.proj_mk Bundle.TotalSpace.proj_mk

/- warning: bundle.sigma_mk_eq_total_space_mk -> Bundle.sigma_mk_eq_totalSpaceMk is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} {x : B} {y : E x}, Eq.{max (succ u1) (succ u2)} (Sigma.{u1, u2} B (fun {x : B} => E x)) (Sigma.mk.{u1, u2} B (fun {x : B} => E x) x y) (Bundle.totalSpaceMk.{u1, u2} B (fun (x : B) => E x) x y)
but is expected to have type
  forall {B : Type.{u2}} {E : B -> Type.{u1}} {x : B} {y : E x}, Eq.{max (succ u2) (succ u1)} (Sigma.{u2, u1} B E) (Sigma.mk.{u2, u1} B E x y) (Bundle.totalSpaceMk.{u2, u1} B E x y)
Case conversion may be inaccurate. Consider using '#align bundle.sigma_mk_eq_total_space_mk Bundle.sigma_mk_eq_totalSpaceMkₓ'. -/
theorem sigma_mk_eq_totalSpaceMk {x : B} {y : E x} : Sigma.mk x y = totalSpaceMk x y :=
  rfl
#align bundle.sigma_mk_eq_total_space_mk Bundle.sigma_mk_eq_totalSpaceMk

/- warning: bundle.total_space.mk_cast -> Bundle.TotalSpace.mk_cast is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} {x : B} {x' : B} (h : Eq.{succ u1} B x x') (b : E x), Eq.{max (succ u1) (succ u2)} (Bundle.TotalSpace.{u1, u2} B E) (Bundle.totalSpaceMk.{u1, u2} B E x' (cast.{succ u2} (E x) (E x') (congr_arg.{succ u1, succ (succ u2)} B Type.{u2} x x' E h) b)) (Bundle.totalSpaceMk.{u1, u2} B E x b)
but is expected to have type
  forall {B : Type.{u2}} {E : B -> Type.{u1}} {x : B} {x' : B} (h : Eq.{succ u2} B x x') (b : E x), Eq.{max (succ u2) (succ u1)} (Bundle.TotalSpace.{u2, u1} B E) (Bundle.totalSpaceMk.{u2, u1} B E x' (cast.{succ u1} (E x) (E x') (congr_arg.{succ u2, succ (succ u1)} B Type.{u1} x x' E h) b)) (Bundle.totalSpaceMk.{u2, u1} B E x b)
Case conversion may be inaccurate. Consider using '#align bundle.total_space.mk_cast Bundle.TotalSpace.mk_castₓ'. -/
theorem TotalSpace.mk_cast {x x' : B} (h : x = x') (b : E x) :
    totalSpaceMk x' (cast (congr_arg E h) b) = totalSpaceMk x b :=
  by
  subst h
  rfl
#align bundle.total_space.mk_cast Bundle.TotalSpace.mk_cast

/- warning: bundle.total_space.eta -> Bundle.TotalSpace.eta is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} (z : Bundle.TotalSpace.{u1, u2} B E), Eq.{max (succ u1) (succ u2)} (Bundle.TotalSpace.{u1, u2} B E) (Bundle.totalSpaceMk.{u1, u2} B E (Bundle.TotalSpace.proj.{u1, u2} B E z) (Sigma.snd.{u1, u2} B (fun (x : B) => E x) z)) z
but is expected to have type
  forall {B : Type.{u2}} {E : B -> Type.{u1}} (z : Bundle.TotalSpace.{u2, u1} B E), Eq.{max (succ u2) (succ u1)} (Bundle.TotalSpace.{u2, u1} B E) (Bundle.totalSpaceMk.{u2, u1} B E (Bundle.TotalSpace.proj.{u2, u1} B E z) (Sigma.snd.{u2, u1} B (fun (x : B) => E x) z)) z
Case conversion may be inaccurate. Consider using '#align bundle.total_space.eta Bundle.TotalSpace.etaₓ'. -/
theorem TotalSpace.eta (z : TotalSpace E) : totalSpaceMk z.proj z.2 = z :=
  Sigma.eta z
#align bundle.total_space.eta Bundle.TotalSpace.eta

instance {x : B} : CoeTC (E x) (TotalSpace E) :=
  ⟨totalSpaceMk x⟩

/- warning: bundle.coe_fst -> Bundle.coe_fst is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} (x : B) (v : E x), Eq.{succ u1} B (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) v)) x
but is expected to have type
  forall {B : Type.{u2}} {E : B -> Type.{u1}} (x : B) (v : E x), Eq.{succ u2} B (Sigma.fst.{u2, u1} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u1} B E x v)) x
Case conversion may be inaccurate. Consider using '#align bundle.coe_fst Bundle.coe_fstₓ'. -/
@[simp]
theorem coe_fst (x : B) (v : E x) : (v : TotalSpace E).fst = x :=
  rfl
#align bundle.coe_fst Bundle.coe_fst

#print Bundle.coe_snd /-
@[simp]
theorem coe_snd {x : B} {y : E x} : (y : TotalSpace E).snd = y :=
  rfl
#align bundle.coe_snd Bundle.coe_snd
-/

/- warning: bundle.to_total_space_coe clashes with [anonymous] -> [anonymous]
warning: bundle.to_total_space_coe -> [anonymous] is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} {x : B} (v : E x), Eq.{max (succ u1) (succ u2)} (Bundle.TotalSpace.{u1, u2} B E) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) v) (Bundle.totalSpaceMk.{u1, u2} B E x v)
but is expected to have type
  forall {B : Type.{u1}} {E : Type.{u2}}, (Nat -> B -> E) -> Nat -> (List.{u1} B) -> (List.{u2} E)
Case conversion may be inaccurate. Consider using '#align bundle.to_total_space_coe [anonymous]ₓ'. -/
theorem [anonymous] {x : B} (v : E x) : (v : TotalSpace E) = totalSpaceMk x v :=
  rfl
#align bundle.to_total_space_coe [anonymous]

-- mathport name: «expr ×ᵇ »
notation:100 -- notation for the direct sum of two bundles over the same base
E₁ " ×ᵇ " E₂ => fun x => E₁ x × E₂ x

#print Bundle.Trivial /-
/-- `bundle.trivial B F` is the trivial bundle over `B` of fiber `F`. -/
def Trivial (B : Type _) (F : Type _) : B → Type _ :=
  Function.const B F
#align bundle.trivial Bundle.Trivial
-/

instance {F : Type _} [Inhabited F] {b : B} : Inhabited (Bundle.Trivial B F b) :=
  ⟨(default : F)⟩

#print Bundle.Trivial.projSnd /-
/-- The trivial bundle, unlike other bundles, has a canonical projection on the fiber. -/
def Trivial.projSnd (B : Type _) (F : Type _) : TotalSpace (Bundle.Trivial B F) → F :=
  Sigma.snd
#align bundle.trivial.proj_snd Bundle.Trivial.projSnd
-/

section Pullback

variable {B' : Type _}

#print Bundle.Pullback /-
/-- The pullback of a bundle `E` over a base `B` under a map `f : B' → B`, denoted by `pullback f E`
or `f *ᵖ E`,  is the bundle over `B'` whose fiber over `b'` is `E (f b')`. -/
@[nolint has_nonempty_instance]
def Pullback (f : B' → B) (E : B → Type _) := fun x => E (f x)
#align bundle.pullback Bundle.Pullback
-/

-- mathport name: «expr *ᵖ »
notation f " *ᵖ " E => Pullback f E

#print Bundle.pullbackTotalSpaceEmbedding /-
/-- Natural embedding of the total space of `f *ᵖ E` into `B' × total_space E`. -/
@[simp]
def pullbackTotalSpaceEmbedding (f : B' → B) : TotalSpace (f *ᵖ E) → B' × TotalSpace E := fun z =>
  (z.proj, totalSpaceMk (f z.proj) z.2)
#align bundle.pullback_total_space_embedding Bundle.pullbackTotalSpaceEmbedding
-/

#print Bundle.Pullback.lift /-
/-- The base map `f : B' → B` lifts to a canonical map on the total spaces. -/
def Pullback.lift (f : B' → B) : TotalSpace (f *ᵖ E) → TotalSpace E := fun z =>
  totalSpaceMk (f z.proj) z.2
#align bundle.pullback.lift Bundle.Pullback.lift
-/

#print Bundle.Pullback.proj_lift /-
@[simp]
theorem Pullback.proj_lift (f : B' → B) (x : TotalSpace (f *ᵖ E)) :
    (Pullback.lift f x).proj = f x.1 :=
  rfl
#align bundle.pullback.proj_lift Bundle.Pullback.proj_lift
-/

/- warning: bundle.pullback.lift_mk -> Bundle.Pullback.lift_mk is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} {B' : Type.{u3}} (f : B' -> B) (x : B') (y : E (f x)), Eq.{max (succ u1) (succ u2)} (Bundle.TotalSpace.{u1, u2} B E) (Bundle.Pullback.lift.{u1, u2, u3} B E B' f (Bundle.totalSpaceMk.{u3, u2} B' (Bundle.Pullback.{u1, u3, u2} B B' f E) x y)) (Bundle.totalSpaceMk.{u1, u2} B E (f x) y)
but is expected to have type
  forall {B : Type.{u3}} {E : B -> Type.{u2}} {B' : Type.{u1}} (f : B' -> B) (x : B') (y : E (f x)), Eq.{max (succ u3) (succ u2)} (Bundle.TotalSpace.{u3, u2} B E) (Bundle.Pullback.lift.{u3, u2, u1} B E B' f (Bundle.totalSpaceMk.{u1, u2} B' (Bundle.Pullback.{u3, u1, u2} B B' f E) x y)) (Bundle.totalSpaceMk.{u3, u2} B E (f x) y)
Case conversion may be inaccurate. Consider using '#align bundle.pullback.lift_mk Bundle.Pullback.lift_mkₓ'. -/
@[simp]
theorem Pullback.lift_mk (f : B' → B) (x : B') (y : E (f x)) :
    Pullback.lift f (totalSpaceMk x y) = totalSpaceMk (f x) y :=
  rfl
#align bundle.pullback.lift_mk Bundle.Pullback.lift_mk

#print Bundle.pullbackTotalSpaceEmbedding_snd /-
theorem pullbackTotalSpaceEmbedding_snd (f : B' → B) (x : TotalSpace (f *ᵖ E)) :
    (pullbackTotalSpaceEmbedding f x).2 = Pullback.lift f x :=
  rfl
#align bundle.pullback_total_space_embedding_snd Bundle.pullbackTotalSpaceEmbedding_snd
-/

end Pullback

section FiberStructures

variable [∀ x, AddCommMonoid (E x)]

/- warning: bundle.coe_snd_map_apply -> Bundle.coe_snd_map_apply is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} [_inst_1 : forall (x : B), AddCommMonoid.{u2} (E x)] (x : B) (v : E x) (w : E x), Eq.{succ u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (Sigma.snd.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w))) (HAdd.hAdd.{u2, u2, u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (instHAdd.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (AddZeroClass.toHasAdd.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (AddMonoid.toAddZeroClass.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (AddCommMonoid.toAddMonoid.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (_inst_1 (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toHasAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))))))) (Sigma.snd.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) v)) (Sigma.snd.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) w)))
but is expected to have type
  forall {B : Type.{u1}} {E : B -> Type.{u2}} [_inst_1 : forall (x : B), AddCommMonoid.{u2} (E x)] (x : B) (v : E x) (w : E x), Eq.{succ u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w)))) (Sigma.snd.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x (HAdd.hAdd.{u2, u2, u2} (E x) (E x) (E x) (instHAdd.{u2} (E x) (AddZeroClass.toAdd.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x))))) v w))) (HAdd.hAdd.{u2, u2, u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x v))) (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x w))) (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x v))) (instHAdd.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x v))) (AddZeroClass.toAdd.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x v))) (AddMonoid.toAddZeroClass.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x v))) (AddCommMonoid.toAddMonoid.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x v))) (_inst_1 (Sigma.fst.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x v))))))) (Sigma.snd.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x v)) (Sigma.snd.{u1, u2} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u1, u2} B E x w)))
Case conversion may be inaccurate. Consider using '#align bundle.coe_snd_map_apply Bundle.coe_snd_map_applyₓ'. -/
@[simp]
theorem coe_snd_map_apply (x : B) (v w : E x) :
    (↑(v + w) : TotalSpace E).snd = (v : TotalSpace E).snd + (w : TotalSpace E).snd :=
  rfl
#align bundle.coe_snd_map_apply Bundle.coe_snd_map_apply

variable (R : Type _) [Semiring R] [∀ x, Module R (E x)]

/- warning: bundle.coe_snd_map_smul -> Bundle.coe_snd_map_smul is a dubious translation:
lean 3 declaration is
  forall {B : Type.{u1}} {E : B -> Type.{u2}} [_inst_1 : forall (x : B), AddCommMonoid.{u2} (E x)] (R : Type.{u3}) [_inst_2 : Semiring.{u3} R] [_inst_3 : forall (x : B), Module.{u3, u2} R (E x) _inst_2 (_inst_1 x)] (x : B) (r : R) (v : E x), Eq.{succ u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (Sigma.snd.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v))) (SMul.smul.{u3, u2} R (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (SMulZeroClass.toHasSmul.{u3, u2} R (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (AddZeroClass.toHasZero.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (AddMonoid.toAddZeroClass.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (AddCommMonoid.toAddMonoid.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (_inst_1 (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v))))))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (AddMonoid.toAddZeroClass.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (AddCommMonoid.toAddMonoid.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (_inst_1 (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v))))))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (AddMonoid.toAddZeroClass.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (AddCommMonoid.toAddMonoid.{u2} (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (_inst_1 (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v))))))) (Module.toMulActionWithZero.{u3, u2} R (E (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) _inst_2 (_inst_1 (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))) (_inst_3 (Sigma.fst.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) (SMul.smul.{u3, u2} R (E x) (SMulZeroClass.toHasSmul.{u3, u2} R (E x) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (SMulWithZero.toSmulZeroClass.{u3, u2} R (E x) (MulZeroClass.toHasZero.{u3} R (MulZeroOneClass.toMulZeroClass.{u3} R (MonoidWithZero.toMulZeroOneClass.{u3} R (Semiring.toMonoidWithZero.{u3} R _inst_2)))) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (MulActionWithZero.toSMulWithZero.{u3, u2} R (E x) (Semiring.toMonoidWithZero.{u3} R _inst_2) (AddZeroClass.toHasZero.{u2} (E x) (AddMonoid.toAddZeroClass.{u2} (E x) (AddCommMonoid.toAddMonoid.{u2} (E x) (_inst_1 x)))) (Module.toMulActionWithZero.{u3, u2} R (E x) _inst_2 (_inst_1 x) (_inst_3 x))))) r v)))))))) r (Sigma.snd.{u1, u2} B (fun (x : B) => E x) ((fun (a : Type.{u2}) (b : Sort.{max (succ u1) (succ u2)}) [self : HasLiftT.{succ u2, max (succ u1) (succ u2)} a b] => self.0) (E x) (Bundle.TotalSpace.{u1, u2} B E) (HasLiftT.mk.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (CoeTCₓ.coe.{succ u2, max (succ u1) (succ u2)} (E x) (Bundle.TotalSpace.{u1, u2} B E) (Bundle.TotalSpace.hasCoeT.{u1, u2} B E x))) v)))
but is expected to have type
  forall {B : Type.{u2}} {E : B -> Type.{u3}} [_inst_1 : forall (x : B), AddCommMonoid.{u3} (E x)] (R : Type.{u1}) [_inst_2 : Semiring.{u1} R] [_inst_3 : forall (x : B), Module.{u1, u3} R (E x) _inst_2 (_inst_1 x)] (x : B) (r : R) (v : E x), Eq.{succ u3} (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x (HSMul.hSMul.{u1, u3, u3} R (E x) (E x) (instHSMul.{u1, u3} R (E x) (SMulZeroClass.toSMul.{u1, u3} R (E x) (AddMonoid.toZero.{u3} (E x) (AddCommMonoid.toAddMonoid.{u3} (E x) (_inst_1 x))) (SMulWithZero.toSMulZeroClass.{u1, u3} R (E x) (MonoidWithZero.toZero.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_2)) (AddMonoid.toZero.{u3} (E x) (AddCommMonoid.toAddMonoid.{u3} (E x) (_inst_1 x))) (MulActionWithZero.toSMulWithZero.{u1, u3} R (E x) (Semiring.toMonoidWithZero.{u1} R _inst_2) (AddMonoid.toZero.{u3} (E x) (AddCommMonoid.toAddMonoid.{u3} (E x) (_inst_1 x))) (Module.toMulActionWithZero.{u1, u3} R (E x) _inst_2 (_inst_1 x) (_inst_3 x)))))) r v)))) (Sigma.snd.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x (HSMul.hSMul.{u1, u3, u3} R (E x) (E x) (instHSMul.{u1, u3} R (E x) (SMulZeroClass.toSMul.{u1, u3} R (E x) (AddMonoid.toZero.{u3} (E x) (AddCommMonoid.toAddMonoid.{u3} (E x) (_inst_1 x))) (SMulWithZero.toSMulZeroClass.{u1, u3} R (E x) (MonoidWithZero.toZero.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_2)) (AddMonoid.toZero.{u3} (E x) (AddCommMonoid.toAddMonoid.{u3} (E x) (_inst_1 x))) (MulActionWithZero.toSMulWithZero.{u1, u3} R (E x) (Semiring.toMonoidWithZero.{u1} R _inst_2) (AddMonoid.toZero.{u3} (E x) (AddCommMonoid.toAddMonoid.{u3} (E x) (_inst_1 x))) (Module.toMulActionWithZero.{u1, u3} R (E x) _inst_2 (_inst_1 x) (_inst_3 x)))))) r v))) (HSMul.hSMul.{u1, u3, u3} R (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (instHSMul.{u1, u3} R (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (SMulZeroClass.toSMul.{u1, u3} R (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (AddMonoid.toZero.{u3} (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (AddCommMonoid.toAddMonoid.{u3} (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (_inst_1 (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))))) (SMulWithZero.toSMulZeroClass.{u1, u3} R (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (MonoidWithZero.toZero.{u1} R (Semiring.toMonoidWithZero.{u1} R _inst_2)) (AddMonoid.toZero.{u3} (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (AddCommMonoid.toAddMonoid.{u3} (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (_inst_1 (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))))) (MulActionWithZero.toSMulWithZero.{u1, u3} R (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (Semiring.toMonoidWithZero.{u1} R _inst_2) (AddMonoid.toZero.{u3} (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (AddCommMonoid.toAddMonoid.{u3} (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (_inst_1 (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))))) (Module.toMulActionWithZero.{u1, u3} R (E (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) _inst_2 (_inst_1 (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v))) (_inst_3 (Sigma.fst.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v)))))))) r (Sigma.snd.{u2, u3} B (fun (x : B) => E x) (Bundle.totalSpaceMk.{u2, u3} B E x v)))
Case conversion may be inaccurate. Consider using '#align bundle.coe_snd_map_smul Bundle.coe_snd_map_smulₓ'. -/
@[simp]
theorem coe_snd_map_smul (x : B) (r : R) (v : E x) :
    (↑(r • v) : TotalSpace E).snd = r • (v : TotalSpace E).snd :=
  rfl
#align bundle.coe_snd_map_smul Bundle.coe_snd_map_smul

end FiberStructures

section TrivialInstances

variable {F : Type _} {R : Type _} [Semiring R] (b : B)

instance [AddCommMonoid F] : AddCommMonoid (Bundle.Trivial B F b) :=
  ‹AddCommMonoid F›

instance [AddCommGroup F] : AddCommGroup (Bundle.Trivial B F b) :=
  ‹AddCommGroup F›

instance [AddCommMonoid F] [Module R F] : Module R (Bundle.Trivial B F b) :=
  ‹Module R F›

end TrivialInstances

end Bundle


/-
Copyright (c) 2015 Jeremy Avigad. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Jeremy Avigad, Robert Y. Lewis
-/
import algebra.order.ring
import algebra.group_power.basic

/-!
# Lemmas about the interaction of power operations with order

Note that some lemmas are in `algebra/group_power/lemmas.lean` as they import files which
depend on this file.
-/

variables {A G M R : Type*}

section preorder

variables [monoid M] [preorder M] [covariant_class M M (*) (≤)]

@[to_additive nsmul_le_nsmul_of_le_right, mono]
lemma pow_le_pow_of_le_left' [covariant_class M M (function.swap (*)) (≤)]
  {a b : M} (hab : a ≤ b) : ∀ i : ℕ, a ^ i ≤ b ^ i
| 0     := by simp
| (k+1) := by { rw [pow_succ, pow_succ],
    exact mul_le_mul' hab (pow_le_pow_of_le_left' k) }

attribute [mono] nsmul_le_nsmul_of_le_right

@[to_additive nsmul_nonneg]
theorem one_le_pow_of_one_le' {a : M} (H : 1 ≤ a) : ∀ n : ℕ, 1 ≤ a ^ n
| 0       := by simp
| (k + 1) := by { rw pow_succ, exact one_le_mul H (one_le_pow_of_one_le' k) }

@[to_additive nsmul_nonpos]
lemma pow_le_one' {a : M} (H : a ≤ 1) (n : ℕ) : a ^ n ≤ 1 := @one_le_pow_of_one_le' Mᵒᵈ _ _ _ _ H n

@[to_additive nsmul_le_nsmul]
theorem pow_le_pow' {a : M} {n m : ℕ} (ha : 1 ≤ a) (h : n ≤ m) : a ^ n ≤ a ^ m :=
let ⟨k, hk⟩ := nat.le.dest h in
calc a ^ n ≤ a ^ n * a ^ k : le_mul_of_one_le_right' (one_le_pow_of_one_le' ha _)
       ... = a ^ m         : by rw [← hk, pow_add]

@[to_additive nsmul_le_nsmul_of_nonpos]
theorem pow_le_pow_of_le_one' {a : M} {n m : ℕ} (ha : a ≤ 1) (h : n ≤ m) : a ^ m ≤ a ^ n :=
@pow_le_pow' Mᵒᵈ _ _ _ _ _ _  ha h

@[to_additive nsmul_pos]
theorem one_lt_pow' {a : M} (ha : 1 < a) {k : ℕ} (hk : k ≠ 0) : 1 < a ^ k :=
begin
  rcases nat.exists_eq_succ_of_ne_zero hk with ⟨l, rfl⟩,
  clear hk,
  induction l with l IH,
  { simpa using ha },
  { rw pow_succ,
    exact one_lt_mul'' ha IH }
end

@[to_additive nsmul_neg]
lemma pow_lt_one' {a : M} (ha : a < 1) {k : ℕ} (hk : k ≠ 0) : a ^ k < 1 :=
@one_lt_pow' Mᵒᵈ _ _ _ _ ha k hk

@[to_additive nsmul_lt_nsmul]
theorem pow_lt_pow' [covariant_class M M (*) (<)] {a : M} {n m : ℕ} (ha : 1 < a) (h : n < m) :
  a ^ n < a ^ m :=
begin
  rcases nat.le.dest h with ⟨k, rfl⟩, clear h,
  rw [pow_add, pow_succ', mul_assoc, ← pow_succ],
  exact lt_mul_of_one_lt_right' _ (one_lt_pow' ha k.succ_ne_zero)
end

@[to_additive nsmul_strict_mono_right]
lemma pow_strict_mono_left [covariant_class M M (*) (<)] {a : M} (ha : 1 < a) :
  strict_mono ((^) a : ℕ → M) :=
λ m n, pow_lt_pow' ha

end preorder

section linear_order

variables [monoid M] [linear_order M] [covariant_class M M (*) (≤)]

@[to_additive nsmul_nonneg_iff]
lemma one_le_pow_iff {x : M} {n : ℕ} (hn : n ≠ 0) : 1 ≤ x ^ n ↔ 1 ≤ x :=
⟨le_imp_le_of_lt_imp_lt $ λ h, pow_lt_one' h hn, λ h, one_le_pow_of_one_le' h n⟩

@[to_additive]
lemma pow_le_one_iff {x : M} {n : ℕ} (hn : n ≠ 0) : x ^ n ≤ 1 ↔ x ≤ 1 :=
@one_le_pow_iff Mᵒᵈ _ _ _ _ _ hn

@[to_additive nsmul_pos_iff]
lemma one_lt_pow_iff {x : M} {n : ℕ} (hn : n ≠ 0) : 1 < x ^ n ↔ 1 < x :=
lt_iff_lt_of_le_iff_le (pow_le_one_iff hn)

@[to_additive]
lemma pow_lt_one_iff {x : M} {n : ℕ} (hn : n ≠ 0) : x ^ n < 1 ↔ x < 1 :=
lt_iff_lt_of_le_iff_le (one_le_pow_iff hn)

@[to_additive]
lemma pow_eq_one_iff {x : M} {n : ℕ} (hn : n ≠ 0) : x ^ n = 1 ↔ x = 1 :=
by simp only [le_antisymm_iff, pow_le_one_iff hn, one_le_pow_iff hn]

variables [covariant_class M M (*) (<)] {a : M} {m n : ℕ}

@[to_additive nsmul_le_nsmul_iff]
lemma pow_le_pow_iff' (ha : 1 < a) : a ^ m ≤ a ^ n ↔ m ≤ n := (pow_strict_mono_left ha).le_iff_le

@[to_additive nsmul_lt_nsmul_iff]
lemma pow_lt_pow_iff' (ha : 1 < a) : a ^ m < a ^ n ↔ m < n := (pow_strict_mono_left ha).lt_iff_lt

end linear_order

section div_inv_monoid

variables [div_inv_monoid G] [preorder G] [covariant_class G G (*) (≤)]

@[to_additive zsmul_nonneg]
theorem one_le_zpow {x : G} (H : 1 ≤ x) {n : ℤ} (hn : 0 ≤ n) :
  1 ≤ x ^ n :=
begin
  lift n to ℕ using hn,
  rw zpow_coe_nat,
  apply one_le_pow_of_one_le' H,
end

end div_inv_monoid

namespace canonically_ordered_comm_semiring

variables [canonically_ordered_comm_semiring R]

theorem pow_pos {a : R} (H : 0 < a) (n : ℕ) : 0 < a ^ n :=
pos_iff_ne_zero.2 $ pow_ne_zero _ H.ne'

end canonically_ordered_comm_semiring

section ordered_semiring
variables [ordered_semiring R] {a x y : R} {n m : ℕ}

theorem pow_add_pow_le (hx : 0 ≤ x) (hy : 0 ≤ y) (hn : n ≠ 0) : x ^ n + y ^ n ≤ (x + y) ^ n :=
begin
  rcases nat.exists_eq_succ_of_ne_zero hn with ⟨k, rfl⟩,
  induction k with k ih, { simp only [pow_one] },
  let n := k.succ,
  have h1 := add_nonneg (mul_nonneg hx (pow_nonneg hy n)) (mul_nonneg hy (pow_nonneg hx n)),
  have h2 := add_nonneg hx hy,
  calc x^n.succ + y^n.succ
    ≤ x*x^n + y*y^n + (x*y^n + y*x^n) :
      by { rw [pow_succ _ n, pow_succ _ n], exact le_add_of_nonneg_right h1 }
    ... = (x+y) * (x^n + y^n) :
      by rw [add_mul, mul_add, mul_add, add_comm (y*x^n), ← add_assoc,
        ← add_assoc, add_assoc (x*x^n) (x*y^n), add_comm (x*y^n) (y*y^n), ← add_assoc]
    ... ≤ (x+y)^n.succ :
      by { rw [pow_succ _ n], exact mul_le_mul_of_nonneg_left (ih (nat.succ_ne_zero k)) h2 }
end

theorem pow_lt_pow_of_lt_left (Hxy : x < y) (Hxpos : 0 ≤ x) (Hnpos : 0 < n) :
  x ^ n < y ^ n :=
begin
  cases lt_or_eq_of_le Hxpos,
  { rw ← tsub_add_cancel_of_le (nat.succ_le_of_lt Hnpos),
    induction (n - 1), { simpa only [pow_one] },
    rw [pow_add, pow_add, nat.succ_eq_add_one, pow_one, pow_one],
    apply mul_lt_mul ih (le_of_lt Hxy) h (le_of_lt (pow_pos (lt_trans h Hxy) _)) },
  { rw [←h, zero_pow Hnpos], apply pow_pos (by rwa ←h at Hxy : 0 < y),}
end

lemma pow_lt_one (h₀ : 0 ≤ a) (h₁ : a < 1) {n : ℕ} (hn : n ≠ 0) : a ^ n < 1 :=
(one_pow n).subst (pow_lt_pow_of_lt_left h₁ h₀ (nat.pos_of_ne_zero hn))

theorem strict_mono_on_pow (hn : 0 < n) : strict_mono_on (λ x : R, x ^ n) (set.Ici 0) :=
λ x hx y hy h, pow_lt_pow_of_lt_left h hx hn

theorem one_le_pow_of_one_le (H : 1 ≤ a) : ∀ (n : ℕ), 1 ≤ a ^ n
| 0     := by rw [pow_zero]
| (n+1) := by { rw pow_succ, simpa only [mul_one] using mul_le_mul H (one_le_pow_of_one_le n)
    zero_le_one (le_trans zero_le_one H) }

lemma pow_mono (h : 1 ≤ a) : monotone (λ n : ℕ, a ^ n) :=
monotone_nat_of_le_succ $ λ n,
  by { rw pow_succ, exact le_mul_of_one_le_left (pow_nonneg (zero_le_one.trans h) _) h }

theorem pow_le_pow (ha : 1 ≤ a) (h : n ≤ m) : a ^ n ≤ a ^ m :=
pow_mono ha h

theorem le_self_pow (ha : 1 ≤ a) (h : 1 ≤ m) : a ≤ a ^ m :=
eq.trans_le (pow_one a).symm (pow_le_pow ha h)

lemma strict_mono_pow (h : 1 < a) : strict_mono (λ n : ℕ, a ^ n) :=
have 0 < a := zero_le_one.trans_lt h,
strict_mono_nat_of_lt_succ $ λ n, by simpa only [one_mul, pow_succ]
  using mul_lt_mul h (le_refl (a ^ n)) (pow_pos this _) this.le

lemma pow_lt_pow (h : 1 < a) (h2 : n < m) : a ^ n < a ^ m :=
strict_mono_pow h h2

lemma pow_lt_pow_iff (h : 1 < a) : a ^ n < a ^ m ↔ n < m :=
(strict_mono_pow h).lt_iff_lt

lemma pow_le_pow_iff (h : 1 < a) : a ^ n ≤ a ^ m ↔ n ≤ m :=
(strict_mono_pow h).le_iff_le

lemma strict_anti_pow (h₀ : 0 < a) (h₁ : a < 1) : strict_anti (λ n : ℕ, a ^ n) :=
strict_anti_nat_of_succ_lt $ λ n,
  by simpa only [pow_succ, one_mul] using mul_lt_mul h₁ le_rfl (pow_pos h₀ n) zero_le_one

lemma pow_lt_pow_iff_of_lt_one (h₀ : 0 < a) (h₁ : a < 1) : a ^ m < a ^ n ↔ n < m :=
(strict_anti_pow h₀ h₁).lt_iff_lt

lemma pow_lt_pow_of_lt_one (h : 0 < a) (ha : a < 1) {i j : ℕ} (hij : i < j) : a ^ j < a ^ i :=
(pow_lt_pow_iff_of_lt_one h ha).2 hij

@[mono] lemma pow_le_pow_of_le_left {a b : R} (ha : 0 ≤ a) (hab : a ≤ b) : ∀ i : ℕ, a^i ≤ b^i
| 0     := by simp
| (k+1) := by { rw [pow_succ, pow_succ],
    exact mul_le_mul hab (pow_le_pow_of_le_left _) (pow_nonneg ha _) (le_trans ha hab) }

lemma one_lt_pow (ha : 1 < a) {n : ℕ} (hn : n ≠ 0) : 1 < a ^ n :=
pow_zero a ▸ pow_lt_pow ha (pos_iff_ne_zero.2 hn)

lemma pow_le_one : ∀ (n : ℕ) (h₀ : 0 ≤ a) (h₁ : a ≤ 1), a ^ n ≤ 1
| 0       h₀ h₁ := (pow_zero a).le
| (n + 1) h₀ h₁ := (pow_succ' a n).le.trans (mul_le_one (pow_le_one n h₀ h₁) h₀ h₁)

lemma sq_pos_of_pos (ha : 0 < a) : 0 < a ^ 2 := by { rw sq, exact mul_pos ha ha }

end ordered_semiring

section ordered_ring
variables [ordered_ring R] {a : R}

lemma sq_pos_of_neg (ha : a < 0) : 0 < a ^ 2 := by { rw sq, exact mul_pos_of_neg_of_neg ha ha }

lemma pow_bit0_pos_of_neg (ha : a < 0) (n : ℕ) : 0 < a ^ bit0 n :=
begin
  rw pow_bit0',
  exact pow_pos (mul_pos_of_neg_of_neg ha ha) _,
end

lemma pow_bit1_neg (ha : a < 0) (n : ℕ) : a ^ bit1 n < 0 :=
begin
  rw [bit1, pow_succ],
  exact mul_neg_of_neg_of_pos ha (pow_bit0_pos_of_neg ha n),
end

end ordered_ring

section linear_ordered_semiring
variable [linear_ordered_semiring R]

lemma pow_le_one_iff_of_nonneg {a : R} (ha : 0 ≤ a) {n : ℕ} (hn : n ≠ 0) : a ^ n ≤ 1 ↔ a ≤ 1 :=
begin
  refine ⟨_, pow_le_one n ha⟩,
  rw [←not_lt, ←not_lt],
  exact mt (λ h, one_lt_pow h hn),
end

lemma one_le_pow_iff_of_nonneg {a : R} (ha : 0 ≤ a) {n : ℕ} (hn : n ≠ 0) : 1 ≤ a ^ n ↔ 1 ≤ a :=
begin
  refine ⟨_, λ h, one_le_pow_of_one_le h n⟩,
  rw [←not_lt, ←not_lt],
  exact mt (λ h, pow_lt_one ha h hn),
end

lemma one_lt_pow_iff_of_nonneg {a : R} (ha : 0 ≤ a) {n : ℕ} (hn : n ≠ 0) : 1 < a ^ n ↔ 1 < a :=
lt_iff_lt_of_le_iff_le (pow_le_one_iff_of_nonneg ha hn)

lemma pow_lt_one_iff_of_nonneg {a : R} (ha : 0 ≤ a) {n : ℕ} (hn : n ≠ 0) : a ^ n < 1 ↔ a < 1 :=
lt_iff_lt_of_le_iff_le (one_le_pow_iff_of_nonneg ha hn)

lemma sq_le_one_iff {a : R} (ha : 0 ≤ a) : a^2 ≤ 1 ↔ a ≤ 1 :=
pow_le_one_iff_of_nonneg ha (nat.succ_ne_zero _)

lemma sq_lt_one_iff {a : R} (ha : 0 ≤ a) : a^2 < 1 ↔ a < 1 :=
pow_lt_one_iff_of_nonneg ha (nat.succ_ne_zero _)

lemma one_le_sq_iff {a : R} (ha : 0 ≤ a) : 1 ≤ a^2 ↔ 1 ≤ a :=
one_le_pow_iff_of_nonneg ha (nat.succ_ne_zero _)

lemma one_lt_sq_iff {a : R} (ha : 0 ≤ a) : 1 < a^2 ↔ 1 < a :=
one_lt_pow_iff_of_nonneg ha (nat.succ_ne_zero _)

@[simp] theorem pow_left_inj {x y : R} {n : ℕ} (Hxpos : 0 ≤ x) (Hypos : 0 ≤ y) (Hnpos : 0 < n) :
  x ^ n = y ^ n ↔ x = y :=
(@strict_mono_on_pow R _ _ Hnpos).inj_on.eq_iff Hxpos Hypos

lemma lt_of_pow_lt_pow {a b : R} (n : ℕ) (hb : 0 ≤ b) (h : a ^ n < b ^ n) : a < b :=
lt_of_not_ge $ λ hn, not_lt_of_ge (pow_le_pow_of_le_left hb hn _) h

lemma le_of_pow_le_pow {a b : R} (n : ℕ) (hb : 0 ≤ b) (hn : 0 < n) (h : a ^ n ≤ b ^ n) : a ≤ b :=
le_of_not_lt $ λ h1, not_le_of_lt (pow_lt_pow_of_lt_left h1 hb hn) h

@[simp] lemma sq_eq_sq {a b : R} (ha : 0 ≤ a) (hb : 0 ≤ b) : a ^ 2 = b ^ 2 ↔ a = b :=
pow_left_inj ha hb dec_trivial

end linear_ordered_semiring

section linear_ordered_ring

variable [linear_ordered_ring R]

lemma pow_abs (a : R) (n : ℕ) : |a| ^ n = |a ^ n| :=
((abs_hom.to_monoid_hom : R →* R).map_pow a n).symm

lemma abs_neg_one_pow (n : ℕ) : |(-1 : R) ^ n| = 1 :=
by rw [←pow_abs, abs_neg, abs_one, one_pow]

theorem pow_bit0_nonneg (a : R) (n : ℕ) : 0 ≤ a ^ bit0 n :=
by { rw pow_bit0, exact mul_self_nonneg _ }

theorem sq_nonneg (a : R) : 0 ≤ a ^ 2 :=
pow_bit0_nonneg a 1

alias sq_nonneg ← pow_two_nonneg

theorem pow_bit0_pos {a : R} (h : a ≠ 0) (n : ℕ) : 0 < a ^ bit0 n :=
(pow_bit0_nonneg a n).lt_of_ne (pow_ne_zero _ h).symm

theorem sq_pos_of_ne_zero (a : R) (h : a ≠ 0) : 0 < a ^ 2 :=
pow_bit0_pos h 1

alias sq_pos_of_ne_zero ← pow_two_pos_of_ne_zero

theorem pow_bit0_pos_iff (a : R) {n : ℕ} (hn : n ≠ 0) : 0 < a ^ bit0 n ↔ a ≠ 0 :=
begin
  refine ⟨λ h, _, λ h, pow_bit0_pos h n⟩,
  rintro rfl,
  rw zero_pow (nat.zero_lt_bit0 hn) at h,
  exact lt_irrefl _ h,
end

theorem sq_pos_iff (a : R) : 0 < a ^ 2 ↔ a ≠ 0 :=
pow_bit0_pos_iff a one_ne_zero

variables {x y : R}

theorem sq_abs (x : R) : |x| ^ 2 = x ^ 2 :=
by simpa only [sq] using abs_mul_abs_self x

theorem abs_sq (x : R) : |x ^ 2| = x ^ 2 :=
by simpa only [sq] using abs_mul_self x

theorem sq_lt_sq : x ^ 2 < y ^ 2 ↔ |x| < |y| :=
by simpa only [sq_abs]
  using (@strict_mono_on_pow R _ _ two_pos).lt_iff_lt (abs_nonneg x) (abs_nonneg y)

theorem sq_lt_sq' (h1 : -y < x) (h2 : x < y) : x ^ 2 < y ^ 2 :=
sq_lt_sq.2 (lt_of_lt_of_le (abs_lt.2 ⟨h1, h2⟩) (le_abs_self _))

theorem sq_le_sq : x ^ 2 ≤ y ^ 2 ↔ |x| ≤ |y| :=
by simpa only [sq_abs]
  using (@strict_mono_on_pow R _ _ two_pos).le_iff_le (abs_nonneg x) (abs_nonneg y)

theorem sq_le_sq' (h1 : -y ≤ x) (h2 : x ≤ y) : x ^ 2 ≤ y ^ 2 :=
sq_le_sq.2 (le_trans (abs_le.mpr ⟨h1, h2⟩) (le_abs_self _))

theorem abs_lt_of_sq_lt_sq (h : x^2 < y^2) (hy : 0 ≤ y) : |x| < y :=
by rwa [← abs_of_nonneg hy, ← sq_lt_sq]

theorem abs_lt_of_sq_lt_sq' (h : x^2 < y^2) (hy : 0 ≤ y) : -y < x ∧ x < y :=
abs_lt.mp $ abs_lt_of_sq_lt_sq h hy

theorem abs_le_of_sq_le_sq (h : x^2 ≤ y^2) (hy : 0 ≤ y) : |x| ≤ y :=
by rwa [← abs_of_nonneg hy, ← sq_le_sq]

theorem abs_le_of_sq_le_sq' (h : x^2 ≤ y^2) (hy : 0 ≤ y) : -y ≤ x ∧ x ≤ y :=
abs_le.mp $ abs_le_of_sq_le_sq h hy

lemma sq_eq_sq_iff_abs_eq_abs (x y : R) : x^2 = y^2 ↔ |x| = |y| :=
by simp only [le_antisymm_iff, sq_le_sq]

@[simp] lemma sq_le_one_iff_abs_le_one (x : R) : x^2 ≤ 1 ↔ |x| ≤ 1 :=
by simpa only [one_pow, abs_one] using @sq_le_sq _ _ x 1

@[simp] lemma sq_lt_one_iff_abs_lt_one (x : R) : x^2 < 1 ↔ |x| < 1 :=
by simpa only [one_pow, abs_one] using @sq_lt_sq _ _ x 1

@[simp] lemma one_le_sq_iff_one_le_abs (x : R) : 1 ≤ x^2 ↔ 1 ≤ |x| :=
by simpa only [one_pow, abs_one] using @sq_le_sq _ _ 1 x

@[simp] lemma one_lt_sq_iff_one_lt_abs (x : R) : 1 < x^2 ↔ 1 < |x| :=
by simpa only [one_pow, abs_one] using @sq_lt_sq _ _ 1 x

lemma pow_four_le_pow_two_of_pow_two_le {x y : R} (h : x^2 ≤ y) : x^4 ≤ y^2 :=
(pow_mul x 2 2).symm ▸ pow_le_pow_of_le_left (sq_nonneg x) h 2

end linear_ordered_ring

section linear_ordered_comm_ring
variables [linear_ordered_comm_ring R]

/-- Arithmetic mean-geometric mean (AM-GM) inequality for linearly ordered commutative rings. -/
lemma two_mul_le_add_sq (a b : R) : 2 * a * b ≤ a ^ 2 + b ^ 2 :=
sub_nonneg.mp ((sub_add_eq_add_sub _ _ _).subst ((sub_sq a b).subst (sq_nonneg _)))

alias two_mul_le_add_sq ← two_mul_le_add_pow_two

end linear_ordered_comm_ring


import tactic

-- In the book, Peter Smith presents a axiomatic system for FOL with two axioms
-- schemas corresponding to the `s` and `k` combinators below.

variables {p q r : Prop} (h₁ : p → q) (h₂ : q → r)

lemma s : (p → q → r) → (p → q) → p → r :=
λ x y z, x z (y z)

lemma k : p → q → p :=
λ x y, x

-- This is a proof of `p → r` in a natural-deduction system. Lambdas and
-- function application correspond respectively to conditional proofs and modus
-- ponens.
example : p → r :=
λ x, h₂ (h₁ x)

-- One can transform a lambda term into an equivalent term in SK-combinator
-- calculus, so one should be able to transform a natural-deduction proof into
-- a axiomatic proof using the combinators above.
--
-- Roughly speaking, application is equivalent to using the S-combinator. It is
-- easy to figure out the rest.
example : p → r :=
s (k h₂) h₁


import mynat.definition
import mynat.add
import world8.level4
import world8.level5

namespace mynat

theorem add_right_cancel_iff (a t b : mynat) : a + t = b + t ↔ a = b :=
begin [nat_num_game]
    split,
    {
        exact add_right_cancel a t b,
    },
    {
        induction t with n hd,
        {
            rw add_zero,
            rw add_zero,
            intro h,
            exact h,
        },
        {
            intro h,
            have res := hd h,
            rw add_succ,
            rw add_succ,
            rw eq_iff_succ_eq_succ,
            exact res,
        },
    },
end

end mynat