diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index b8a1461fbc118..f03a37eac6a0f 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -170,16 +170,14 @@ jobs: # The ProofWidgets release contains not just the `.js` (which we need in order to build) # but also `.oleans`, which may have been built with the wrong toolchain. # This removes them. + # See discussion at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/nightly-testing/near/411225235 rm -rf .lake/packages/proofwidgets/.lake/build/lib rm -rf .lake/packages/proofwidgets/.lake/build/ir - name: get cache run: | lake exe cache clean - # We've been seeing many failures at this step recently because of network errors. - # As a band-aid, we try twice. - # The 'sleep 1' is small pause to let the network recover. - lake exe cache get || (sleep 1; lake exe cache get) + lake exe cache get - name: build mathlib id: build @@ -190,6 +188,7 @@ jobs: bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build -KCI | tee stdout.log" - name: check for noisy stdout lines + id: noisy run: | ! grep --after-context=1 "stdout:" stdout.log @@ -197,13 +196,14 @@ jobs: run: lake build -KCI MathlibExtras - name: upload cache - if: always() + # We only upload the cache if the build ran (either succeeding or failing), + # but not if it was skipped. + if: ${{ always() && steps.build.outcome == 'success' || steps.build.outcome == 'failure' }} run: | # run this in CI if it gets an incorrect lake hash for existing cache files somehow # lake exe cache pack! || true lake exe cache commit || true - # try twice in case of network errors - lake exe cache put || (sleep 1; lake exe cache put) || true + lake exe cache put || true env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} @@ -220,6 +220,7 @@ jobs: fi - name: build archive + id: archive run: | # Note: we should not be including `Archive` and `Countexamples` in the cache. # We do this for now for the sake of not rebuilding them in every CI run @@ -228,19 +229,19 @@ jobs: # it should be possible to determine whether they need to be built without actually # storing and transferring oleans over the network. # Hopefully a future re-implementation of `cache` will obviate the present need for this hack. - # We retry twice in case of network errors. - lake exe cache get Archive.lean || (sleep 1; lake exe cache get Archive.lean) + lake exe cache get Archive.lean lake build Archive - lake exe cache put Archive.lean || (sleep 1; lake exe cache put Archive.lean) + lake exe cache put Archive.lean env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} - name: build counterexamples + id: counterexamples run: | - lake exe cache get Counterexamples.lean || (sleep 1; lake exe cache get Counterexamples.lean) + lake exe cache get Counterexamples.lean lake build Counterexamples - lake exe cache put Counterexamples.lean || (sleep 1; lake exe cache put Counterexamples.lean) + lake exe cache put Counterexamples.lean env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} @@ -255,6 +256,11 @@ jobs: lake exe graph rm import_graph.dot + - name: verify `lake exe shake` works + # Later, we may want to make output from `shake` a CI error? + run: | + lake exe shake + - name: test mathlib id: test run: | @@ -290,9 +296,12 @@ jobs: TOKEN: ${{ secrets.LEAN_PR_TESTING }} GITHUB_CONTEXT: ${{ toJson(github) }} WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + BUILD_OUTCOME: ${{ steps.build.outcome }} + NOISY_OUTCOME: ${{ steps.noisy.outcome }} + ARCHIVE_OUTCOME: ${{ steps.archive.outcome }} + COUNTEREXAMPLE_OUTCOME: ${{ steps.counterexamples.outcome }} LINT_OUTCOME: ${{ steps.lint.outcome }} TEST_OUTCOME: ${{ steps.test.outcome }} - BUILD_OUTCOME: ${{ steps.build.outcome }} CHECK_OUTCOME: ${{ steps.lean4checker.outcome }} run: | scripts/lean-pr-testing-comments.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 91e950f442f7d..1d385611beb0c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -177,16 +177,14 @@ jobs: # The ProofWidgets release contains not just the `.js` (which we need in order to build) # but also `.oleans`, which may have been built with the wrong toolchain. # This removes them. + # See discussion at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/nightly-testing/near/411225235 rm -rf .lake/packages/proofwidgets/.lake/build/lib rm -rf .lake/packages/proofwidgets/.lake/build/ir - name: get cache run: | lake exe cache clean - # We've been seeing many failures at this step recently because of network errors. - # As a band-aid, we try twice. - # The 'sleep 1' is small pause to let the network recover. - lake exe cache get || (sleep 1; lake exe cache get) + lake exe cache get - name: build mathlib id: build @@ -197,6 +195,7 @@ jobs: bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build -KCI | tee stdout.log" - name: check for noisy stdout lines + id: noisy run: | ! grep --after-context=1 "stdout:" stdout.log @@ -204,13 +203,14 @@ jobs: run: lake build -KCI MathlibExtras - name: upload cache - if: always() + # We only upload the cache if the build ran (either succeeding or failing), + # but not if it was skipped. + if: ${{ always() && steps.build.outcome == 'success' || steps.build.outcome == 'failure' }} run: | # run this in CI if it gets an incorrect lake hash for existing cache files somehow # lake exe cache pack! || true lake exe cache commit || true - # try twice in case of network errors - lake exe cache put || (sleep 1; lake exe cache put) || true + lake exe cache put || true env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} @@ -227,6 +227,7 @@ jobs: fi - name: build archive + id: archive run: | # Note: we should not be including `Archive` and `Countexamples` in the cache. # We do this for now for the sake of not rebuilding them in every CI run @@ -235,19 +236,19 @@ jobs: # it should be possible to determine whether they need to be built without actually # storing and transferring oleans over the network. # Hopefully a future re-implementation of `cache` will obviate the present need for this hack. - # We retry twice in case of network errors. - lake exe cache get Archive.lean || (sleep 1; lake exe cache get Archive.lean) + lake exe cache get Archive.lean lake build Archive - lake exe cache put Archive.lean || (sleep 1; lake exe cache put Archive.lean) + lake exe cache put Archive.lean env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} - name: build counterexamples + id: counterexamples run: | - lake exe cache get Counterexamples.lean || (sleep 1; lake exe cache get Counterexamples.lean) + lake exe cache get Counterexamples.lean lake build Counterexamples - lake exe cache put Counterexamples.lean || (sleep 1; lake exe cache put Counterexamples.lean) + lake exe cache put Counterexamples.lean env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} @@ -262,6 +263,11 @@ jobs: lake exe graph rm import_graph.dot + - name: verify `lake exe shake` works + # Later, we may want to make output from `shake` a CI error? + run: | + lake exe shake + - name: test mathlib id: test run: | @@ -297,9 +303,12 @@ jobs: TOKEN: ${{ secrets.LEAN_PR_TESTING }} GITHUB_CONTEXT: ${{ toJson(github) }} WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + BUILD_OUTCOME: ${{ steps.build.outcome }} + NOISY_OUTCOME: ${{ steps.noisy.outcome }} + ARCHIVE_OUTCOME: ${{ steps.archive.outcome }} + COUNTEREXAMPLE_OUTCOME: ${{ steps.counterexamples.outcome }} LINT_OUTCOME: ${{ steps.lint.outcome }} TEST_OUTCOME: ${{ steps.test.outcome }} - BUILD_OUTCOME: ${{ steps.build.outcome }} CHECK_OUTCOME: ${{ steps.lean4checker.outcome }} run: | scripts/lean-pr-testing-comments.sh diff --git a/.github/workflows/build.yml.in b/.github/workflows/build.yml.in index 2b59b60d39603..42e6c21abe02e 100644 --- a/.github/workflows/build.yml.in +++ b/.github/workflows/build.yml.in @@ -156,16 +156,14 @@ jobs: # The ProofWidgets release contains not just the `.js` (which we need in order to build) # but also `.oleans`, which may have been built with the wrong toolchain. # This removes them. + # See discussion at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/nightly-testing/near/411225235 rm -rf .lake/packages/proofwidgets/.lake/build/lib rm -rf .lake/packages/proofwidgets/.lake/build/ir - name: get cache run: | lake exe cache clean - # We've been seeing many failures at this step recently because of network errors. - # As a band-aid, we try twice. - # The 'sleep 1' is small pause to let the network recover. - lake exe cache get || (sleep 1; lake exe cache get) + lake exe cache get - name: build mathlib id: build @@ -176,6 +174,7 @@ jobs: bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build -KCI | tee stdout.log" - name: check for noisy stdout lines + id: noisy run: | ! grep --after-context=1 "stdout:" stdout.log @@ -183,13 +182,14 @@ jobs: run: lake build -KCI MathlibExtras - name: upload cache - if: always() + # We only upload the cache if the build ran (either succeeding or failing), + # but not if it was skipped. + if: ${{ always() && steps.build.outcome == 'success' || steps.build.outcome == 'failure' }} run: | # run this in CI if it gets an incorrect lake hash for existing cache files somehow # lake exe cache pack! || true lake exe cache commit || true - # try twice in case of network errors - lake exe cache put || (sleep 1; lake exe cache put) || true + lake exe cache put || true env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} @@ -206,6 +206,7 @@ jobs: fi - name: build archive + id: archive run: | # Note: we should not be including `Archive` and `Countexamples` in the cache. # We do this for now for the sake of not rebuilding them in every CI run @@ -214,19 +215,19 @@ jobs: # it should be possible to determine whether they need to be built without actually # storing and transferring oleans over the network. # Hopefully a future re-implementation of `cache` will obviate the present need for this hack. - # We retry twice in case of network errors. - lake exe cache get Archive.lean || (sleep 1; lake exe cache get Archive.lean) + lake exe cache get Archive.lean lake build Archive - lake exe cache put Archive.lean || (sleep 1; lake exe cache put Archive.lean) + lake exe cache put Archive.lean env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} - name: build counterexamples + id: counterexamples run: | - lake exe cache get Counterexamples.lean || (sleep 1; lake exe cache get Counterexamples.lean) + lake exe cache get Counterexamples.lean lake build Counterexamples - lake exe cache put Counterexamples.lean || (sleep 1; lake exe cache put Counterexamples.lean) + lake exe cache put Counterexamples.lean env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} @@ -241,6 +242,11 @@ jobs: lake exe graph rm import_graph.dot + - name: verify `lake exe shake` works + # Later, we may want to make output from `shake` a CI error? + run: | + lake exe shake + - name: test mathlib id: test run: | @@ -276,9 +282,12 @@ jobs: TOKEN: ${{ secrets.LEAN_PR_TESTING }} GITHUB_CONTEXT: ${{ toJson(github) }} WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + BUILD_OUTCOME: ${{ steps.build.outcome }} + NOISY_OUTCOME: ${{ steps.noisy.outcome }} + ARCHIVE_OUTCOME: ${{ steps.archive.outcome }} + COUNTEREXAMPLE_OUTCOME: ${{ steps.counterexamples.outcome }} LINT_OUTCOME: ${{ steps.lint.outcome }} TEST_OUTCOME: ${{ steps.test.outcome }} - BUILD_OUTCOME: ${{ steps.build.outcome }} CHECK_OUTCOME: ${{ steps.lean4checker.outcome }} run: | scripts/lean-pr-testing-comments.sh diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index edaa74ab6c7f2..2627e049125da 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -174,16 +174,14 @@ jobs: # The ProofWidgets release contains not just the `.js` (which we need in order to build) # but also `.oleans`, which may have been built with the wrong toolchain. # This removes them. + # See discussion at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/nightly-testing/near/411225235 rm -rf .lake/packages/proofwidgets/.lake/build/lib rm -rf .lake/packages/proofwidgets/.lake/build/ir - name: get cache run: | lake exe cache clean - # We've been seeing many failures at this step recently because of network errors. - # As a band-aid, we try twice. - # The 'sleep 1' is small pause to let the network recover. - lake exe cache get || (sleep 1; lake exe cache get) + lake exe cache get - name: build mathlib id: build @@ -194,6 +192,7 @@ jobs: bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build -KCI | tee stdout.log" - name: check for noisy stdout lines + id: noisy run: | ! grep --after-context=1 "stdout:" stdout.log @@ -201,13 +200,14 @@ jobs: run: lake build -KCI MathlibExtras - name: upload cache - if: always() + # We only upload the cache if the build ran (either succeeding or failing), + # but not if it was skipped. + if: ${{ always() && steps.build.outcome == 'success' || steps.build.outcome == 'failure' }} run: | # run this in CI if it gets an incorrect lake hash for existing cache files somehow # lake exe cache pack! || true lake exe cache commit || true - # try twice in case of network errors - lake exe cache put || (sleep 1; lake exe cache put) || true + lake exe cache put || true env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} @@ -224,6 +224,7 @@ jobs: fi - name: build archive + id: archive run: | # Note: we should not be including `Archive` and `Countexamples` in the cache. # We do this for now for the sake of not rebuilding them in every CI run @@ -232,19 +233,19 @@ jobs: # it should be possible to determine whether they need to be built without actually # storing and transferring oleans over the network. # Hopefully a future re-implementation of `cache` will obviate the present need for this hack. - # We retry twice in case of network errors. - lake exe cache get Archive.lean || (sleep 1; lake exe cache get Archive.lean) + lake exe cache get Archive.lean lake build Archive - lake exe cache put Archive.lean || (sleep 1; lake exe cache put Archive.lean) + lake exe cache put Archive.lean env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} - name: build counterexamples + id: counterexamples run: | - lake exe cache get Counterexamples.lean || (sleep 1; lake exe cache get Counterexamples.lean) + lake exe cache get Counterexamples.lean lake build Counterexamples - lake exe cache put Counterexamples.lean || (sleep 1; lake exe cache put Counterexamples.lean) + lake exe cache put Counterexamples.lean env: MATHLIB_CACHE_SAS: ${{ secrets.MATHLIB_CACHE_SAS }} MATHLIB_CACHE_S3_TOKEN: ${{ secrets.MATHLIB_CACHE_S3_TOKEN }} @@ -259,6 +260,11 @@ jobs: lake exe graph rm import_graph.dot + - name: verify `lake exe shake` works + # Later, we may want to make output from `shake` a CI error? + run: | + lake exe shake + - name: test mathlib id: test run: | @@ -294,9 +300,12 @@ jobs: TOKEN: ${{ secrets.LEAN_PR_TESTING }} GITHUB_CONTEXT: ${{ toJson(github) }} WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + BUILD_OUTCOME: ${{ steps.build.outcome }} + NOISY_OUTCOME: ${{ steps.noisy.outcome }} + ARCHIVE_OUTCOME: ${{ steps.archive.outcome }} + COUNTEREXAMPLE_OUTCOME: ${{ steps.counterexamples.outcome }} LINT_OUTCOME: ${{ steps.lint.outcome }} TEST_OUTCOME: ${{ steps.test.outcome }} - BUILD_OUTCOME: ${{ steps.build.outcome }} CHECK_OUTCOME: ${{ steps.lean4checker.outcome }} run: | scripts/lean-pr-testing-comments.sh diff --git a/.github/workflows/nightly_detect_failure.yml b/.github/workflows/nightly_detect_failure.yml index cfbeb6032e80e..4317ec39a9e3f 100644 --- a/.github/workflows/nightly_detect_failure.yml +++ b/.github/workflows/nightly_detect_failure.yml @@ -41,7 +41,15 @@ jobs: if [[ $toolchain =~ leanprover/lean4:nightly-([a-zA-Z0-9_-]+) ]]; then version=${BASH_REMATCH[1]} echo "NIGHTLY=$version" >> $GITHUB_ENV - git push origin refs/heads/nightly-testing:refs/heads/nightly-testing-$version + # Check if the remote tag exists + if git ls-remote --tags --exit-code origin "nightly-testing-$version" >/dev/null; then + echo "Tag nightly-testing-$version already exists on the remote." + else + # If the tag does not exist, create and push the tag to remote + echo "Creating tag nightly-testing-$version from the current state of the nightly-testing branch." + git tag nightly-testing-$version + git push origin nightly-testing-$version + fi else echo "Error: The file lean-toolchain does not contain the expected pattern." exit 1 diff --git a/Archive/Arithcc.lean b/Archive/Arithcc.lean index 557ee58d825ae..8dd29d4e48113 100644 --- a/Archive/Arithcc.lean +++ b/Archive/Arithcc.lean @@ -3,8 +3,8 @@ Copyright (c) 2020 Xi Wang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Xi Wang -/ +import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Order.Basic -import Mathlib.Data.Nat.Basic import Mathlib.Tactic.Common #align_import arithcc from "leanprover-community/mathlib"@"eb3595ed8610db8107b75b75ab64ab6390684155" diff --git a/Archive/Examples/IfNormalization/Result.lean b/Archive/Examples/IfNormalization/Result.lean index 73f3849f2967b..c69e47155c3ca 100644 --- a/Archive/Examples/IfNormalization/Result.lean +++ b/Archive/Examples/IfNormalization/Result.lean @@ -99,7 +99,7 @@ def normalize (l : AList (fun _ : ℕ => Bool)) : by_cases w = v <;> ◾⟩ | some b => have i' := normalize l (.ite (lit b) t e); ⟨i'.1, ◾⟩ - termination_by normalize e => e.normSize + termination_by e => e.normSize /- We recall the statement of the if-normalization problem. diff --git a/Archive/Examples/IfNormalization/WithoutAesop.lean b/Archive/Examples/IfNormalization/WithoutAesop.lean index d497e0d6f32ac..1ef597e022111 100644 --- a/Archive/Examples/IfNormalization/WithoutAesop.lean +++ b/Archive/Examples/IfNormalization/WithoutAesop.lean @@ -116,7 +116,7 @@ def normalize' (l : AList (fun _ : ℕ => Bool)) : | some b => have ⟨e', he'⟩ := normalize' l (.ite (lit b) t e) ⟨e', by simp_all⟩ - termination_by normalize' e => e.normSize' + termination_by e' => e'.normSize' example : IfNormalization := ⟨fun e => (normalize' ∅ e).1, diff --git a/Archive/Hairer.lean b/Archive/Hairer.lean index 1811011bedb08..113a2df588ffe 100644 --- a/Archive/Hairer.lean +++ b/Archive/Hairer.lean @@ -4,11 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Sébastien Gouëzel, Patrick Massot, Ruben Van de Velde, Floris Van Doorn, Junyan Xu -/ -import Mathlib.Analysis.Distribution.AEEqOfIntegralContDiff -import Mathlib.RingTheory.MvPolynomial.Basic import Mathlib.Analysis.Analytic.Polynomial import Mathlib.Analysis.Analytic.Uniqueness +import Mathlib.Analysis.Distribution.AEEqOfIntegralContDiff import Mathlib.Data.MvPolynomial.Funext +import Mathlib.RingTheory.MvPolynomial.Basic +import Mathlib.Topology.Algebra.MvPolynomial /-! # Smooth functions whose integral calculates the values of polynomials @@ -25,6 +26,8 @@ open Metric Set MeasureTheory open MvPolynomial hiding support open Function hiding eval +variable {ι : Type*} [Fintype ι] + section normed variable {𝕜 E F : Type*} [NontriviallyNormedField 𝕜] variable [NormedAddCommGroup E] [NormedSpace 𝕜 E] [NormedAddCommGroup F] [NormedSpace 𝕜 F] @@ -43,7 +46,7 @@ namespace SmoothSupportedOn variable {n : ℕ∞} {s : Set E} -instance : FunLike (SmoothSupportedOn 𝕜 E F n s) E (fun _ ↦ F) where +instance : FunLike (SmoothSupportedOn 𝕜 E F n s) E F where coe := Subtype.val coe_injective' := Subtype.coe_injective @@ -65,36 +68,17 @@ lemma hasCompactSupport [ProperSpace E] (f : SmoothSupportedOn 𝕜 E F n (close HasCompactSupport f := HasCompactSupport.of_support_subset_isCompact (isCompact_closedBall 0 1) (support_subset f) -end SmoothSupportedOn - -end normed -open SmoothSupportedOn - -instance {R σ : Type*} [CommSemiring R] [Finite σ] (N : ℕ) : - Module.Finite R (restrictTotalDegree σ R N) := - have : Finite {n : σ →₀ ℕ | ∀ i, n i ≤ N} := by - erw [Finsupp.equivFunOnFinite.subtypeEquivOfSubtype'.finite_iff, Set.finite_coe_iff] - convert Set.Finite.pi fun _ : σ ↦ Set.finite_le_nat N using 1 - ext; rw [mem_univ_pi]; rfl - have : Finite {s : σ →₀ ℕ | s.sum (fun _ e ↦ e) ≤ N} := by - rw [Set.finite_coe_iff] at this ⊢ - exact this.subset fun n hn i ↦ (eq_or_ne (n i) 0).elim - (fun h ↦ h.trans_le N.zero_le) fun h ↦ - (Finset.single_le_sum (fun _ _ ↦ Nat.zero_le _) <| Finsupp.mem_support_iff.mpr h).trans hn - Module.Finite.of_basis (basisRestrictSupport R _) - -variable {ι : Type*} -lemma MvPolynomial.continuous_eval (p : MvPolynomial ι ℝ) : - Continuous fun x ↦ (eval x) p := by - continuity - -variable [Fintype ι] -theorem SmoothSupportedOn.integrable_eval_mul (p : MvPolynomial ι ℝ) +theorem integrable_eval_mul (p : MvPolynomial ι ℝ) (f : SmoothSupportedOn ℝ (EuclideanSpace ℝ ι) ℝ ⊤ (closedBall 0 1)) : Integrable fun (x : EuclideanSpace ℝ ι) ↦ eval x p * f x := (p.continuous_eval.mul (SmoothSupportedOn.contDiff f).continuous).integrable_of_hasCompactSupport (hasCompactSupport f).mul_left +end SmoothSupportedOn + +end normed +open SmoothSupportedOn + variable (ι) /-- Interpreting a multivariate polynomial as an element of the dual of smooth functions supported in the unit ball, via integration against Lebesgue measure. -/ diff --git a/Archive/Imo/Imo1969Q1.lean b/Archive/Imo/Imo1969Q1.lean index e9f7210443165..987d2b6c297fa 100644 --- a/Archive/Imo/Imo1969Q1.lean +++ b/Archive/Imo/Imo1969Q1.lean @@ -63,7 +63,7 @@ theorem int_large {m : ℤ} (h : 1 < m) : 1 < m.natAbs := by theorem not_prime_of_int_mul' {m n : ℤ} {c : ℕ} (hm : 1 < m) (hn : 1 < n) (hc : m * n = (c : ℤ)) : ¬Nat.Prime c := - not_prime_of_int_mul (int_large hm) (int_large hn) hc + not_prime_of_int_mul (int_large hm).ne' (int_large hn).ne' hc #align imo1969_q1.not_prime_of_int_mul' Imo1969Q1.not_prime_of_int_mul' /-- Every natural number of the form `n^4 + 4*m^4` is not prime. -/ diff --git a/Archive/Imo/Imo1998Q2.lean b/Archive/Imo/Imo1998Q2.lean index 610fee510a20e..af5369b89397c 100644 --- a/Archive/Imo/Imo1998Q2.lean +++ b/Archive/Imo/Imo1998Q2.lean @@ -3,10 +3,10 @@ Copyright (c) 2020 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ +import Mathlib.Algebra.BigOperators.Order import Mathlib.Data.Fintype.Prod import Mathlib.Data.Int.Parity -import Mathlib.Algebra.BigOperators.Order -import Mathlib.Tactic.Ring +import Mathlib.GroupTheory.GroupAction.Ring import Mathlib.Tactic.NoncommRing #align_import imo.imo1998_q2 from "leanprover-community/mathlib"@"308826471968962c6b59c7ff82a22757386603e3" diff --git a/Archive/Imo/Imo2005Q4.lean b/Archive/Imo/Imo2005Q4.lean index 808daebbb4698..26dc05f380fce 100644 --- a/Archive/Imo/Imo2005Q4.lean +++ b/Archive/Imo/Imo2005Q4.lean @@ -79,5 +79,5 @@ theorem imo2005_q4 {k : ℕ} (hk : 0 < k) : (∀ n : ℕ, 1 ≤ n → IsCoprime refine h (p - 2) ?_ (find_specified_factor hp hp2 hp3) calc 1 = 3 - 2 := by norm_num - _ ≤ p - 2 := tsub_le_tsub_right (Nat.succ_le_of_lt $ hp.two_le.lt_of_ne' hp2) _ + _ ≤ p - 2 := tsub_le_tsub_right (Nat.succ_le_of_lt <| hp.two_le.lt_of_ne' hp2) _ #align imo2005_q4 imo2005_q4 diff --git a/Archive/Imo/Imo2008Q3.lean b/Archive/Imo/Imo2008Q3.lean index f199a524867c0..3d2c14ae53d91 100644 --- a/Archive/Imo/Imo2008Q3.lean +++ b/Archive/Imo/Imo2008Q3.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Manuel Candales. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Manuel Candales -/ +import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Data.Real.Basic import Mathlib.Data.Real.Sqrt import Mathlib.Data.Nat.Prime diff --git a/Archive/Imo/Imo2013Q1.lean b/Archive/Imo/Imo2013Q1.lean index 1e1d62935567f..1c0b12d05a7dc 100644 --- a/Archive/Imo/Imo2013Q1.lean +++ b/Archive/Imo/Imo2013Q1.lean @@ -8,6 +8,7 @@ import Mathlib.Data.Nat.Parity import Mathlib.Algebra.BigOperators.Pi import Mathlib.Tactic.Ring import Mathlib.Tactic.FieldSimp +import Mathlib.Tactic.Positivity.Basic #align_import imo.imo2013_q1 from "leanprover-community/mathlib"@"308826471968962c6b59c7ff82a22757386603e3" diff --git a/Archive/MiuLanguage/DecisionSuf.lean b/Archive/MiuLanguage/DecisionSuf.lean index 6c7ff233e8c95..80c117d022d98 100644 --- a/Archive/MiuLanguage/DecisionSuf.lean +++ b/Archive/MiuLanguage/DecisionSuf.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Gihan Marasingha -/ import Archive.MiuLanguage.DecisionNec +import Mathlib.Data.Nat.Pow import Mathlib.Tactic.Linarith #align_import miu_language.decision_suf from "leanprover-community/mathlib"@"f694c7dead66f5d4c80f446c796a5aad14707f0e" diff --git a/Archive/Wiedijk100Theorems/BallotProblem.lean b/Archive/Wiedijk100Theorems/BallotProblem.lean index c4a2464181f5b..efc0db6e74ff0 100644 --- a/Archive/Wiedijk100Theorems/BallotProblem.lean +++ b/Archive/Wiedijk100Theorems/BallotProblem.lean @@ -167,14 +167,14 @@ theorem countedSequence_finite : ∀ p q : ℕ, (countedSequence p q).Finite rw [counted_succ_succ, Set.finite_union, Set.finite_image_iff (List.cons_injective.injOn _), Set.finite_image_iff (List.cons_injective.injOn _)] exact ⟨countedSequence_finite _ _, countedSequence_finite _ _⟩ -termination_by _ p q => p + q -- Porting note: Added `termination_by` +termination_by p q => p + q -- Porting note: Added `termination_by` #align ballot.counted_sequence_finite Ballot.countedSequence_finite theorem countedSequence_nonempty : ∀ p q : ℕ, (countedSequence p q).Nonempty | 0, q => by simp | p + 1, 0 => by simp | p + 1, q + 1 => by - rw [counted_succ_succ, union_nonempty, nonempty_image_iff] + rw [counted_succ_succ, union_nonempty, image_nonempty] exact Or.inl (countedSequence_nonempty _ _) #align ballot.counted_sequence_nonempty Ballot.countedSequence_nonempty @@ -211,7 +211,7 @@ theorem count_countedSequence : ∀ p q : ℕ, count (countedSequence p q) = (p count_injective_image List.cons_injective, count_countedSequence _ _] · norm_cast rw [add_assoc, add_comm 1 q, ← Nat.choose_succ_succ, Nat.succ_eq_add_one, add_right_comm] -termination_by _ p q => p + q -- Porting note: Added `termination_by` +termination_by p q => p + q -- Porting note: Added `termination_by` #align ballot.count_counted_sequence Ballot.count_countedSequence theorem first_vote_pos : @@ -231,7 +231,7 @@ theorem first_vote_pos : ((countedSequence_finite _ _).image _) (disjoint_bits _ _), ← counted_succ_succ, condCount_eq_one_of ((countedSequence_finite p (q + 1)).image _) - (nonempty_image_iff.2 (countedSequence_nonempty _ _))] + ((countedSequence_nonempty _ _).image _)] · have : List.cons (-1) '' countedSequence (p + 1) q ∩ {l : List ℤ | l.headI = 1} = ∅ := by ext simp only [mem_inter_iff, mem_image, mem_setOf_eq, mem_empty_iff_false, iff_false_iff, diff --git a/Archive/Wiedijk100Theorems/HeronsFormula.lean b/Archive/Wiedijk100Theorems/HeronsFormula.lean index 81760996b9c26..3a23d77869f7b 100644 --- a/Archive/Wiedijk100Theorems/HeronsFormula.lean +++ b/Archive/Wiedijk100Theorems/HeronsFormula.lean @@ -58,7 +58,7 @@ theorem heron {p1 p2 p3 : P} (h1 : p1 ≠ p2) (h2 : p3 ≠ p2) : cases' div_nonneg_iff.mp frac_nonneg with h h · exact h.left · simpa [h1, h2] using le_antisymm h.right (sq_nonneg _) - have ab2_nonneg : 0 ≤ 2 * a * b := by simp [mul_nonneg, dist_nonneg] + have ab2_nonneg : 0 ≤ 2 * a * b := by positivity calc 1 / 2 * a * b * sin γ = 1 / 2 * a * b * (√ numerator / √ denominator) := by rw [sin_eq_sqrt_one_sub_cos_sq, split_to_frac, sqrt_div numerator_nonneg] <;> diff --git a/Archive/Wiedijk100Theorems/PerfectNumbers.lean b/Archive/Wiedijk100Theorems/PerfectNumbers.lean index f0bd7ac012d17..89a9cb0f8704d 100644 --- a/Archive/Wiedijk100Theorems/PerfectNumbers.lean +++ b/Archive/Wiedijk100Theorems/PerfectNumbers.lean @@ -7,6 +7,7 @@ import Mathlib.NumberTheory.ArithmeticFunction import Mathlib.NumberTheory.LucasLehmer import Mathlib.Algebra.GeomSum import Mathlib.RingTheory.Multiplicity +import Mathlib.Tactic.NormNum.Prime #align_import wiedijk_100_theorems.perfect_numbers from "leanprover-community/mathlib"@"5563b1b49e86e135e8c7b556da5ad2f5ff881cad" diff --git a/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean b/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean index 703bcc6354845..5423cffaa85e5 100644 --- a/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean +++ b/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean @@ -133,7 +133,7 @@ theorem card_le_mul_sum {x k : ℕ} : (card (U x k) : ℝ) ≤ x * ∑ p in P x calc (card (Finset.biUnion P N) : ℝ) ≤ ∑ p in P, (card (N p) : ℝ) := by assumption_mod_cast _ ≤ ∑ p in P, x * (1 / (p : ℝ)) := (sum_le_sum fun p _ => ?_) - _ = x * ∑ p in P, 1 / (p : ℝ) := mul_sum.symm + _ = x * ∑ p in P, 1 / (p : ℝ) := by rw [mul_sum] simp only [mul_one_div, Nat.card_multiples, Nat.cast_div_le] #align theorems_100.card_le_mul_sum Theorems100.card_le_mul_sum diff --git a/Cache/Hashing.lean b/Cache/Hashing.lean index d47b9df7e295c..2cdeb0f145713 100644 --- a/Cache/Hashing.lean +++ b/Cache/Hashing.lean @@ -85,7 +85,7 @@ Computes the hash of a file, which mixes: * The hash of its content * The hashes of the imported files that are part of `Mathlib` -/ -partial def getFileHash (filePath : FilePath) : HashM $ Option UInt64 := do +partial def getFileHash (filePath : FilePath) : HashM <| Option UInt64 := do match (← get).cache.find? filePath with | some hash? => return hash? | none => @@ -105,7 +105,7 @@ partial def getFileHash (filePath : FilePath) : HashM $ Option UInt64 := do return none let rootHash := (← get).rootHash let pathHash := hash filePath.components - let fileHash := hash $ rootHash :: pathHash :: hashFileContents content :: importHashes.toList + let fileHash := hash <| rootHash :: pathHash :: hashFileContents content :: importHashes.toList modifyGet fun stt => (some fileHash, { stt with hashMap := stt.hashMap.insert filePath fileHash diff --git a/Cache/IO.lean b/Cache/IO.lean index eda0ba2e362f1..312fb038622f9 100644 --- a/Cache/IO.lean +++ b/Cache/IO.lean @@ -18,7 +18,7 @@ def System.FilePath.withoutParent (path parent : FilePath) : FilePath := | z@(x :: xs), y :: ys => if x == y then aux xs ys else z | [], _ => [] | x, [] => x - mkFilePath $ aux path.components parent.components + mkFilePath <| aux path.components parent.components def Nat.toHexDigits (n : Nat) : Nat → (res : String := "") → String | 0, s => s @@ -114,8 +114,8 @@ def mathlibDepPath : IO FilePath := do if ← isMathlibRoot then return ⟨"."⟩ else - throw $ IO.userError s!"Mathlib not found in dependencies" - | .error e => throw $ IO.userError s!"Cannot parse lake-manifest.json: {e}" + throw <| IO.userError s!"Mathlib not found in dependencies" + | .error e => throw <| IO.userError s!"Cannot parse lake-manifest.json: {e}" -- TODO this should be generated automatically from the information in `lakefile.lean`. def getPackageDirs : IO PackageDirs := do @@ -129,16 +129,17 @@ def getPackageDirs : IO PackageDirs := do ("Std", LAKEPACKAGESDIR / "std"), ("Cli", LAKEPACKAGESDIR / "Cli"), ("ProofWidgets", LAKEPACKAGESDIR / "proofwidgets"), - ("Qq", LAKEPACKAGESDIR / "Qq") + ("Qq", LAKEPACKAGESDIR / "Qq"), + ("ImportGraph", LAKEPACKAGESDIR / "importGraph") ] initialize pkgDirs : PackageDirs ← getPackageDirs def getPackageDir (path : FilePath) : IO FilePath := match path.withExtension "" |>.components.head? with - | none => throw $ IO.userError "Can't find package directory for empty path" + | none => throw <| IO.userError "Can't find package directory for empty path" | some pkg => match pkgDirs.find? pkg with - | none => throw $ IO.userError s!"Unknown package directory for {pkg}" + | none => throw <| IO.userError s!"Unknown package directory for {pkg}" | some path => return path /-- Runs a terminal command and retrieves its output, passing the lines to `processLine` -/ @@ -155,13 +156,16 @@ where loop h (← processLine a line) /-- Runs a terminal command and retrieves its output -/ -def runCmd (cmd : String) (args : Array String) (throwFailure := true) : IO String := do +def runCmd (cmd : String) (args : Array String) (throwFailure stderrAsErr := true) : IO String := do let out ← IO.Process.output { cmd := cmd, args := args } - if out.exitCode != 0 && throwFailure then throw $ IO.userError out.stderr - else return out.stdout + if (out.exitCode != 0 || stderrAsErr && !out.stderr.isEmpty) && throwFailure then + throw <| IO.userError s!"failure in {cmd} {args}:\n{out.stderr}" + else if !out.stderr.isEmpty then + IO.eprintln out.stderr + return out.stdout -def runCurl (args : Array String) (throwFailure := true) : IO String := do - runCmd (← getCurl) args throwFailure +def runCurl (args : Array String) (throwFailure stderrAsErr := true) : IO String := do + runCmd (← getCurl) (#["--no-progress-meter"] ++ args) throwFailure stderrAsErr def validateCurl : IO Bool := do if (← CURLBIN.pathExists) then return true @@ -178,7 +182,7 @@ def validateCurl : IO Bool := do if kernel == "Linux" && arch ∈ ["x86_64", "aarch64"] then IO.println s!"curl is too old; downloading more recent version" IO.FS.createDirAll IO.CACHEDIR - let _ ← runCmd "curl" #[ + let _ ← runCmd "curl" (stderrAsErr := false) #[ s!"https://github.com/leanprover-community/static-curl/releases/download/v{CURLVERSION}/curl-{arch}-linux-static", "-L", "-o", CURLBIN.toString] let _ ← runCmd "chmod" #["u+x", CURLBIN.toString] @@ -189,8 +193,8 @@ def validateCurl : IO Bool := do else IO.println s!"Warning: recommended `curl` version ≥7.70. Found {v}. Can't use `--parallel`." return false - | _ => throw $ IO.userError "Invalidly formatted version of `curl`" - | _ => throw $ IO.userError "Invalidly formatted response from `curl --version`" + | _ => throw <| IO.userError "Invalidly formatted version of `curl`" + | _ => throw <| IO.userError "Invalidly formatted response from `curl --version`" def Version := Nat × Nat × Nat deriving Inhabited, DecidableEq @@ -206,8 +210,8 @@ def validateLeanTar : IO Unit := do if (← LEANTARBIN.pathExists) then return if let some version ← some <$> runCmd "leantar" #["--version"] <|> pure none then let "leantar" :: v :: _ := version.splitOn " " - | throw $ IO.userError "Invalidly formatted response from `leantar --version`" - let some v := parseVersion v | throw $ IO.userError "Invalidly formatted version of `leantar`" + | throw <| IO.userError "Invalidly formatted response from `leantar --version`" + let some v := parseVersion v | throw <| IO.userError "Invalidly formatted version of `leantar`" -- currently we need exactly one version of leantar, change this to reflect compatibility if v = (parseVersion LEANTARVERSION).get! then return let win := System.Platform.getIsWindows () @@ -217,14 +221,14 @@ def validateLeanTar : IO Unit := do let mut arch ← (·.trim) <$> runCmd "uname" #["-m"] false if arch = "arm64" then arch := "aarch64" unless arch ∈ ["x86_64", "aarch64"] do - throw $ IO.userError s!"unsupported architecture {arch}" + throw <| IO.userError s!"unsupported architecture {arch}" pure <| if System.Platform.getIsOSX () then s!"{arch}-apple-darwin" else s!"{arch}-unknown-linux-musl" IO.println s!"installing leantar {LEANTARVERSION}" IO.FS.createDirAll IO.CACHEDIR let ext := if win then "zip" else "tar.gz" - let _ ← runCmd "curl" #[ + let _ ← runCmd "curl" (stderrAsErr := false) #[ s!"https://github.com/digama0/leangz/releases/download/v{LEANTARVERSION}/leantar-v{LEANTARVERSION}-{target}.{ext}", "-L", "-o", s!"{LEANTARBIN}.{ext}"] let _ ← runCmd "tar" #["-xf", s!"{LEANTARBIN}.{ext}", @@ -234,7 +238,7 @@ def validateLeanTar : IO Unit := do /-- Recursively gets all files from a directory with a certain extension -/ partial def getFilesWithExtension (fp : FilePath) (extension : String) (acc : Array FilePath := #[]) : - IO $ Array FilePath := do + IO <| Array FilePath := do if ← fp.isDir then (← fp.readDir).foldlM (fun acc dir => getFilesWithExtension dir.path extension acc) acc else return if fp.extension == some extension then acc.push fp else acc @@ -266,7 +270,7 @@ def mkDir (path : FilePath) : IO Unit := do Given a path to a Lean file, concatenates the paths to its build files. Each build file also has a `Bool` indicating whether that file is required for caching to proceed. -/ -def mkBuildPaths (path : FilePath) : IO $ List (FilePath × Bool) := do +def mkBuildPaths (path : FilePath) : IO <| List (FilePath × Bool) := do let packageDir ← getPackageDir path return [ -- Note that `packCache` below requires that the `.trace` file is first in this list. @@ -287,7 +291,7 @@ def allExist (paths : List (FilePath × Bool)) : IO Bool := do /-- Compresses build files into the local cache and returns an array with the compressed files -/ def packCache (hashMap : HashMap) (overwrite verbose : Bool) (comment : Option String := none) : - IO $ Array String := do + IO <| Array String := do mkDir CACHEDIR IO.println "Compressing cache" let mut acc := #[] @@ -303,7 +307,7 @@ def packCache (hashMap : HashMap) (overwrite verbose : Bool) (comment : Option S -- in the list generated by `mkBuildPaths`. let trace :: args := (← buildPaths.filterM (·.1.pathExists)) |>.map (·.1.toString) | unreachable! - runCmd (← getLeanTar) $ #[zipPath.toString, trace] ++ + runCmd (← getLeanTar) <| #[zipPath.toString, trace] ++ (if let some c := comment then #["-c", s!"git=mathlib4@{c}"] else #[]) ++ args acc := acc.push (path, zip) for task in tasks do @@ -315,7 +319,7 @@ def packCache (hashMap : HashMap) (overwrite verbose : Bool) (comment : Option S return acc.map (·.2) /-- Gets the set of all cached files -/ -def getLocalCacheSet : IO $ Lean.RBTree String compare := do +def getLocalCacheSet : IO <| Lean.RBTree String compare := do let paths ← getFilesWithExtension CACHEDIR "ltar" return .fromList (paths.data.map (·.withoutParent CACHEDIR |>.toString)) _ @@ -347,7 +351,7 @@ def unpackCache (hashMap : HashMap) (force : Bool) : IO Unit := do config.push <| .mkObj [("file", pathStr), ("base", mathlibDepPath)] stdin.putStr <| Lean.Json.compress <| .arr config let exitCode ← child.wait - if exitCode != 0 then throw $ IO.userError s!"leantar failed with error code {exitCode}" + if exitCode != 0 then throw <| IO.userError s!"leantar failed with error code {exitCode}" IO.println s!"unpacked in {(← IO.monoMsNow) - now} ms" else IO.println "No cache files to decompress" diff --git a/Cache/Main.lean b/Cache/Main.lean index 766c78db56806..b57ba8ebede62 100644 --- a/Cache/Main.lean +++ b/Cache/Main.lean @@ -86,12 +86,12 @@ def main (args : List String) : IO Unit := do getFiles (← hashMemo.filterByFilePaths (toPaths args)) true true goodCurl true | "get-" :: args => getFiles (← hashMemo.filterByFilePaths (toPaths args)) false false goodCurl false - | ["pack"] => discard $ packCache hashMap false false (← getGitCommitHash) - | ["pack!"] => discard $ packCache hashMap true false (← getGitCommitHash) + | ["pack"] => discard <| packCache hashMap false false (← getGitCommitHash) + | ["pack!"] => discard <| packCache hashMap true false (← getGitCommitHash) | ["unpack"] => unpackCache hashMap false | ["unpack!"] => unpackCache hashMap true | ["clean"] => - cleanCache $ hashMap.fold (fun acc _ hash => acc.insert $ CACHEDIR / hash.asLTar) .empty + cleanCache <| hashMap.fold (fun acc _ hash => acc.insert <| CACHEDIR / hash.asLTar) .empty | ["clean!"] => cleanCache -- We allow arguments for `put` and `put!` so they can be added to the `roots`. | "put" :: _ => putFiles (← packCache hashMap false true (← getGitCommitHash)) false (← getToken) diff --git a/Cache/Requests.lean b/Cache/Requests.lean index ffdbec3b9a5e2..e91eaedde320b 100644 --- a/Cache/Requests.lean +++ b/Cache/Requests.lean @@ -24,7 +24,7 @@ def URL : String := def getToken : IO String := do let envVar := if useFROCache then "MATHLIB_CACHE_S3_TOKEN" else "MATHLIB_CACHE_SAS" let some token ← IO.getEnv envVar - | throw $ IO.userError s!"environment variable {envVar} must be set to upload caches" + | throw <| IO.userError s!"environment variable {envVar} must be set to upload caches" return token open System (FilePath) @@ -58,7 +58,7 @@ def mkGetConfigContent (hashMap : IO.HashMap) : IO String := do -- Note we append a '.part' to the filenames here, -- which `downloadFiles` then removes when the download is successful. - pure $ acc ++ s!"url = {mkFileURL URL fileName}\n\ + pure <| acc ++ s!"url = {mkFileURL URL fileName}\n\ -o {(IO.CACHEDIR / (fileName ++ ".part")).toString.quote}\n" /-- Calls `curl` to download a single file from the server to `CACHEDIR` (`.cache`) -/ @@ -87,6 +87,7 @@ def downloadFiles (hashMap : IO.HashMap) (forceDownload : Bool) (parallel : Bool let failed ← if parallel then IO.FS.writeFile IO.CURLCFG (← mkGetConfigContent hashMap) let args := #["--request", "GET", "--parallel", "--fail", "--silent", + "--retry", "5", -- there seem to be some intermittent failures "--write-out", "%{json}\n", "--config", IO.CURLCFG.toString] let (_, success, failed, done) ← IO.runCurlStreaming args (← IO.monoMsNow, 0, 0, 0) fun a line => do @@ -194,17 +195,17 @@ def putFiles (fileNames : Array String) (overwrite : Bool) (token : String) : IO if size > 0 then IO.FS.writeFile IO.CURLCFG (← mkPutConfigContent fileNames token) IO.println s!"Attempting to upload {size} file(s)" - if useFROCache then + let args := if useFROCache then -- TODO: reimplement using HEAD requests? let _ := overwrite - discard $ IO.runCurl #["-s", "-X", "PUT", "--aws-sigv4", "aws:amz:auto:s3", "--user", token, - "--parallel", "-K", IO.CURLCFG.toString] + #["--aws-sigv4", "aws:amz:auto:s3", "--user", token] else if overwrite then - discard $ IO.runCurl #["-s", "-X", "PUT", "-H", "x-ms-blob-type: BlockBlob", "--parallel", - "-K", IO.CURLCFG.toString] + #["-H", "x-ms-blob-type: BlockBlob"] else - discard $ IO.runCurl #["-s", "-X", "PUT", "-H", "x-ms-blob-type: BlockBlob", - "-H", "If-None-Match: *", "--parallel", "-K", IO.CURLCFG.toString] + #["-H", "x-ms-blob-type: BlockBlob", "-H", "If-None-Match: *"] + _ ← IO.runCurl (stderrAsErr := false) (args ++ #[ + "--retry", "5", -- there seem to be some intermittent failures + "-X", "PUT", "--parallel", "-K", IO.CURLCFG.toString]) IO.FS.removeFile IO.CURLCFG else IO.println "No files to upload" @@ -226,17 +227,17 @@ def commit (hashMap : IO.HashMap) (overwrite : Bool) (token : String) : IO Unit let hash ← getGitCommitHash let path := IO.CACHEDIR / hash IO.mkDir IO.CACHEDIR - IO.FS.writeFile path $ ("\n".intercalate $ hashMap.hashes.toList.map toString) ++ "\n" + IO.FS.writeFile path <| ("\n".intercalate <| hashMap.hashes.toList.map toString) ++ "\n" if useFROCache then -- TODO: reimplement using HEAD requests? let _ := overwrite - discard $ IO.runCurl $ #["-T", path.toString, "--aws-sigv4", "aws:amz:auto:s3", - "--user", token, s!"{UPLOAD_URL}/c/{hash}"] + discard <| IO.runCurl #["-T", path.toString, + "--aws-sigv4", "aws:amz:auto:s3", "--user", token, s!"{UPLOAD_URL}/c/{hash}"] else let params := if overwrite then #["-X", "PUT", "-H", "x-ms-blob-type: BlockBlob"] else #["-X", "PUT", "-H", "x-ms-blob-type: BlockBlob", "-H", "If-None-Match: *"] - discard $ IO.runCurl $ params ++ #["-T", path.toString, s!"{URL}/c/{hash}?{token}"] + discard <| IO.runCurl <| params ++ #["-T", path.toString, s!"{URL}/c/{hash}?{token}"] IO.FS.removeFile path end Commit @@ -252,7 +253,7 @@ def QueryType.prefix : QueryType → String | all => default def formatError : IO α := - throw $ IO.userError "Invalid format for curl return" + throw <| IO.userError "Invalid format for curl return" def QueryType.desc : QueryType → String | files => "hosted files" @@ -264,7 +265,7 @@ Retrieves metadata about hosted files: their names and the timestamps of last mo Example: `["f/39476538726384726.tar.gz", "Sat, 24 Dec 2022 17:33:01 GMT"]` -/ -def getFilesInfo (q : QueryType) : IO $ List (String × String) := do +def getFilesInfo (q : QueryType) : IO <| List (String × String) := do if useFROCache then throw <| .userError "FIXME: getFilesInfo is not adapted to FRO cache yet" IO.println s!"Downloading info list of {q.desc}" diff --git a/Counterexamples/CharPZeroNeCharZero.lean b/Counterexamples/CharPZeroNeCharZero.lean index b651338409689..f881074e9bba1 100644 --- a/Counterexamples/CharPZeroNeCharZero.lean +++ b/Counterexamples/CharPZeroNeCharZero.lean @@ -34,7 +34,7 @@ theorem withZero_unit_charP_zero : CharP (WithZero Unit) 0 := #align counterexample.with_zero_unit_char_p_zero Counterexample.withZero_unit_charP_zero theorem withZero_unit_not_charZero : ¬CharZero (WithZero Unit) := fun ⟨h⟩ => - h.ne (by simp : 1 + 1 ≠ 0 + 1) (by simp) + h.ne (by simp : 1 + 1 ≠ 0 + 1) (by set_option simprocs false in simp) #align counterexample.with_zero_unit_not_char_zero Counterexample.withZero_unit_not_charZero end Counterexample diff --git a/Counterexamples/Cyclotomic105.lean b/Counterexamples/Cyclotomic105.lean index 07a1cd6df40d5..f41dd881bc38b 100644 --- a/Counterexamples/Cyclotomic105.lean +++ b/Counterexamples/Cyclotomic105.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Riccardo Brasca -/ import Mathlib.RingTheory.Polynomial.Cyclotomic.Basic +import Mathlib.Tactic.NormNum.Prime #align_import cyclotomic_105 from "leanprover-community/mathlib"@"328375597f2c0dd00522d9c2e5a33b6a6128feeb" diff --git a/Counterexamples/DirectSumIsInternal.lean b/Counterexamples/DirectSumIsInternal.lean index a980c74170e83..c118d5b9ca6aa 100644 --- a/Counterexamples/DirectSumIsInternal.lean +++ b/Counterexamples/DirectSumIsInternal.lean @@ -5,6 +5,7 @@ Authors: Eric Wieser, Kevin Buzzard -/ import Mathlib.Algebra.DirectSum.Module import Mathlib.Algebra.Group.ConjFinite +import Mathlib.Data.Fintype.Lattice import Mathlib.Tactic.FinCases #align_import direct_sum_is_internal from "leanprover-community/mathlib"@"328375597f2c0dd00522d9c2e5a33b6a6128feeb" @@ -87,7 +88,7 @@ theorem withSign.not_injective : intro h -- porting note: `DFinsupp.singleAddHom_apply` doesn't work so we have to unfold dsimp [DirectSum.lof_eq_of, DirectSum.of, DFinsupp.singleAddHom] at h - replace h := FunLike.congr_fun h 1 + replace h := DFunLike.congr_fun h 1 -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [DFinsupp.zero_apply, DFinsupp.add_apply, DFinsupp.single_eq_same, DFinsupp.single_eq_of_ne UnitsInt.one_ne_neg_one.symm, add_zero, Subtype.ext_iff, diff --git a/Counterexamples/Phillips.lean b/Counterexamples/Phillips.lean index 4150b3ea53699..1e1828a7513ef 100644 --- a/Counterexamples/Phillips.lean +++ b/Counterexamples/Phillips.lean @@ -287,8 +287,7 @@ theorem exists_discrete_support_nonpos (f : BoundedAdditiveMeasure α) : refine' ⟨t, fun u => _⟩ calc f (↑u \ ↑s) ≤ S := le_ciSup B _ - _ = 2 * (S / 2) := by ring - _ ≤ 2 * f (↑t \ ↑s) := mul_le_mul_of_nonneg_left ht.le (by norm_num) + _ ≤ 2 * f (↑t \ ↑s) := (div_le_iff' two_pos).1 ht.le choose! F hF using this -- iterate the above construction, by adding at each step a set with measure close to maximal in -- the complement of already chosen points. This is the set `s n` at step `n`. diff --git a/Counterexamples/SeminormLatticeNotDistrib.lean b/Counterexamples/SeminormLatticeNotDistrib.lean index c582a4684ee37..9ec73f995d2fe 100644 --- a/Counterexamples/SeminormLatticeNotDistrib.lean +++ b/Counterexamples/SeminormLatticeNotDistrib.lean @@ -61,21 +61,21 @@ theorem not_distrib : ¬(p ⊔ q1) ⊓ (p ⊔ q2) ≤ p ⊔ q1 ⊓ q2 := by · rcases le_or_lt x.snd (2 / 3) with h2 | h2 · calc 4 / 3 = 4 * (1 - 2 / 3) := by norm_num - _ ≤ 4 * (1 - x.snd) := (mul_le_mul_left zero_lt_four).mpr (sub_le_sub_left h2 _) - _ ≤ 4 * |1 - x.snd| := (mul_le_mul_left zero_lt_four).mpr (le_abs_self _) + _ ≤ 4 * (1 - x.snd) := by gcongr + _ ≤ 4 * |1 - x.snd| := by gcongr; apply le_abs_self _ = q2 ((1, 1) - x) := by simp; rfl _ ≤ (p ⊔ q2) ((1, 1) - x) := le_sup_right _ ≤ (p ⊔ q1) x + (p ⊔ q2) ((1, 1) - x) := le_add_of_nonneg_left (map_nonneg _ _) · calc 4 / 3 = 2 / 3 + (1 - 1 / 3) := by norm_num - _ ≤ x.snd + (1 - x.fst) := add_le_add (le_of_lt h2) (sub_le_sub_left h1 _) + _ ≤ x.snd + (1 - x.fst) := by gcongr _ ≤ |x.snd| + |1 - x.fst| := add_le_add (le_abs_self _) (le_abs_self _) _ ≤ p x + p ((1, 1) - x) := by exact add_le_add le_sup_right le_sup_left _ ≤ (p ⊔ q1) x + (p ⊔ q2) ((1, 1) - x) := add_le_add le_sup_left le_sup_left · calc 4 / 3 = 4 * (1 / 3) := by norm_num - _ ≤ 4 * x.fst := (mul_le_mul_left zero_lt_four).mpr (le_of_lt h1) - _ ≤ 4 * |x.fst| := (mul_le_mul_left zero_lt_four).mpr (le_abs_self _) + _ ≤ 4 * x.fst := by gcongr + _ ≤ 4 * |x.fst| := by gcongr; apply le_abs_self _ = q1 x := rfl _ ≤ (p ⊔ q1) x := le_sup_right _ ≤ (p ⊔ q1) x + (p ⊔ q2) ((1, 1) - x) := le_add_of_nonneg_right (map_nonneg _ _) diff --git a/Counterexamples/SorgenfreyLine.lean b/Counterexamples/SorgenfreyLine.lean index dd630c6794655..93c03f8b4cd2d 100644 --- a/Counterexamples/SorgenfreyLine.lean +++ b/Counterexamples/SorgenfreyLine.lean @@ -118,7 +118,7 @@ theorem nhds_antitone_basis_Ico_inv_pnat (a : ℝₗ) : (𝓝 a).HasAntitoneBasis fun n : ℕ+ => Ico a (a + (n : ℝₗ)⁻¹) := ⟨nhds_basis_Ico_inv_pnat a, monotone_const.Ico <| Antitone.const_add (fun k _l hkl => inv_le_inv_of_le (Nat.cast_pos.2 k.2) - (Nat.mono_cast $ Subtype.coe_le_coe.2 hkl)) _⟩ + (Nat.mono_cast <| Subtype.coe_le_coe.2 hkl)) _⟩ #align counterexample.sorgenfrey_line.nhds_antitone_basis_Ico_inv_pnat Counterexample.SorgenfreyLine.nhds_antitone_basis_Ico_inv_pnat theorem isOpen_iff {s : Set ℝₗ} : IsOpen s ↔ ∀ x ∈ s, ∃ y > x, Ico x y ⊆ s := diff --git a/ImportGraph/Main.lean b/ImportGraph/Main.lean deleted file mode 100644 index 4303bdd12b5b9..0000000000000 --- a/ImportGraph/Main.lean +++ /dev/null @@ -1,102 +0,0 @@ -/- -Copyright (c) 2023 Scott Morrison. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison --/ -import Mathlib.Util.Imports -import Mathlib.Lean.CoreM -import Std.Lean.NameMap -import Std.Lean.IO.Process -import Mathlib.Lean.Name -import Std.Lean.Util.Path -import Cli - -/-! -# `lake exe graph` - -This is a replacement for Lean 3's `leanproject import-graph` tool. --/ - -open Cli - -open Lean Meta - -/-- Write an import graph, represented as a `NameMap (Array Name)` to the ".dot" graph format. -/ -def asDotGraph (graph : NameMap (Array Name)) (header := "import_graph") : String := Id.run do - let mut lines := #[s!"digraph \"{header}\" " ++ "{"] - for (n, is) in graph do - for i in is do - lines := lines.push s!" \"{i}\" -> \"{n}\";" - lines := lines.push "}" - return "\n".intercalate lines.toList - -open Lean Core System - -open IO.FS IO.Process Name in -/-- Implementation of the import graph command line program. -/ -def importGraphCLI (args : Cli.Parsed) : IO UInt32 := do - let to := match args.flag? "to" with - | some to => to.as! ModuleName - | none => `Mathlib -- autodetect the main module from the `lakefile.lean`? - let from? := match args.flag? "from" with - | some fr => some <| fr.as! ModuleName - | none => none - searchPathRef.set compile_time_search_path% - let dotFile ← unsafe withImportModules #[{module := to}] {} (trustLevel := 1024) fun env => do - let mut graph := env.importGraph - if let .some f := from? then - graph := graph.downstreamOf (NameSet.empty.insert f) - if ¬(args.hasFlag "include-deps") then - let p := getModule to - graph := graph.filterMap (fun n i => - if p.isPrefixOf n then (i.filter (isPrefixOf p)) else none) - if args.hasFlag "exclude-meta" then - let filterMeta : Name → Bool := fun n => ( - isPrefixOf `Mathlib.Tactic n ∨ - isPrefixOf `Mathlib.Lean n ∨ - isPrefixOf `Mathlib.Mathport n ∨ - isPrefixOf `Mathlib.Util n) - graph := graph.filterGraph filterMeta (replacement := `«Mathlib.Tactics») - if args.hasFlag "reduce" then - graph := graph.transitiveReduction - return asDotGraph graph - match args.variableArgsAs! String with - | #[] => writeFile "import_graph.dot" dotFile - | outputs => for o in outputs do - let fp : FilePath := o - match fp.extension with - | none - | "dot" => writeFile fp dotFile - | some ext => try - _ ← runCmdWithInput "dot" #["-T" ++ ext, "-o", o] dotFile - catch ex => - IO.eprintln s!"Error occurred while writing out {fp}." - IO.eprintln s!"Make sure you have `graphviz` installed and the file is writable." - throw ex - return 0 - -/-- Setting up command line options and help text for `lake exe graph`. -/ -def graph : Cmd := `[Cli| - graph VIA importGraphCLI; ["0.0.1"] - "Generate representations of a Lean import graph. \ - By default generates the import graph up to `Mathlib`. \ - If you are working in a downstream project, use `lake exe graph --to MyProject`." - - FLAGS: - reduce; "Remove transitively redundant edges." - to : ModuleName; "Only show the upstream imports of the specified module." - "from" : ModuleName; "Only show the downstream dependencies of the specified module." - "exclude-meta"; "Exclude any files starting with `Mathlib.[Tactic|Lean|Util|Mathport]`." - "include-deps"; "Include used files from other projects (e.g. lake packages)" - - ARGS: - ...outputs : String; "Filename(s) for the output. \ - If none are specified, generates `import_graph.dot`. \ - Automatically chooses the format based on the file extension. \ - Currently `.dot` is supported, \ - and if you have `graphviz` installed then any supported output format is allowed." -] - -/-- `lake exe graph` -/ -def main (args : List String) : IO UInt32 := - graph.validate args diff --git a/Mathlib.lean b/Mathlib.lean index 6d47e1ee52f14..44efba7e39770 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1,4 +1,4 @@ -import Mathlib.Algebra.Abs +import Mathlib.Algebra.AddConstMap.Basic import Mathlib.Algebra.AddTorsor import Mathlib.Algebra.Algebra.Basic import Mathlib.Algebra.Algebra.Bilinear @@ -186,6 +186,7 @@ import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.Group.Hom.Instances import Mathlib.Algebra.Group.InjSurj import Mathlib.Algebra.Group.MinimalAxioms +import Mathlib.Algebra.Group.NatPowAssoc import Mathlib.Algebra.Group.Opposite import Mathlib.Algebra.Group.OrderSynonym import Mathlib.Algebra.Group.PNatPowAssoc @@ -247,6 +248,7 @@ import Mathlib.Algebra.Homology.Homotopy import Mathlib.Algebra.Homology.HomotopyCategory import Mathlib.Algebra.Homology.HomotopyCategory.HomComplex import Mathlib.Algebra.Homology.HomotopyCategory.HomComplexShift +import Mathlib.Algebra.Homology.HomotopyCategory.MappingCone import Mathlib.Algebra.Homology.HomotopyCategory.Shift import Mathlib.Algebra.Homology.HomotopyCofiber import Mathlib.Algebra.Homology.ImageToKernel @@ -333,8 +335,10 @@ import Mathlib.Algebra.Module.Submodule.Basic import Mathlib.Algebra.Module.Submodule.Bilinear import Mathlib.Algebra.Module.Submodule.Lattice import Mathlib.Algebra.Module.Submodule.LinearMap +import Mathlib.Algebra.Module.Submodule.Localization import Mathlib.Algebra.Module.Submodule.Map import Mathlib.Algebra.Module.Submodule.Pointwise +import Mathlib.Algebra.Module.Submodule.RestrictScalars import Mathlib.Algebra.Module.Torsion import Mathlib.Algebra.Module.ULift import Mathlib.Algebra.Module.Zlattice @@ -362,14 +366,17 @@ import Mathlib.Algebra.Order.Field.InjSurj import Mathlib.Algebra.Order.Field.Pi import Mathlib.Algebra.Order.Field.Power import Mathlib.Algebra.Order.Floor +import Mathlib.Algebra.Order.Floor.Div import Mathlib.Algebra.Order.Group.Abs import Mathlib.Algebra.Order.Group.Bounds import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Group.DenselyOrdered import Mathlib.Algebra.Order.Group.InjSurj import Mathlib.Algebra.Order.Group.Instances +import Mathlib.Algebra.Order.Group.Lattice import Mathlib.Algebra.Order.Group.MinMax import Mathlib.Algebra.Order.Group.OrderIso +import Mathlib.Algebra.Order.Group.PosPart import Mathlib.Algebra.Order.Group.Prod import Mathlib.Algebra.Order.Group.TypeTags import Mathlib.Algebra.Order.Group.Units @@ -380,7 +387,7 @@ import Mathlib.Algebra.Order.Hom.Ring import Mathlib.Algebra.Order.Interval import Mathlib.Algebra.Order.Invertible import Mathlib.Algebra.Order.Kleene -import Mathlib.Algebra.Order.LatticeGroup +import Mathlib.Algebra.Order.Module.Algebra import Mathlib.Algebra.Order.Module.Defs import Mathlib.Algebra.Order.Module.OrderedSMul import Mathlib.Algebra.Order.Module.Pointwise @@ -416,6 +423,7 @@ import Mathlib.Algebra.Order.Ring.Cone import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Order.Ring.InjSurj import Mathlib.Algebra.Order.Ring.Lemmas +import Mathlib.Algebra.Order.Ring.Pow import Mathlib.Algebra.Order.Ring.Star import Mathlib.Algebra.Order.Ring.WithTop import Mathlib.Algebra.Order.Sub.Basic @@ -556,14 +564,17 @@ import Mathlib.AlgebraicTopology.Quasicategory import Mathlib.AlgebraicTopology.SimplexCategory import Mathlib.AlgebraicTopology.SimplicialObject import Mathlib.AlgebraicTopology.SimplicialSet +import Mathlib.AlgebraicTopology.SingularSet import Mathlib.AlgebraicTopology.SplitSimplicialObject import Mathlib.AlgebraicTopology.TopologicalSimplex import Mathlib.Analysis.Analytic.Basic +import Mathlib.Analysis.Analytic.CPolynomial import Mathlib.Analysis.Analytic.Composition import Mathlib.Analysis.Analytic.Constructions import Mathlib.Analysis.Analytic.Inverse import Mathlib.Analysis.Analytic.IsolatedZeros import Mathlib.Analysis.Analytic.Linear +import Mathlib.Analysis.Analytic.Meromorphic import Mathlib.Analysis.Analytic.Polynomial import Mathlib.Analysis.Analytic.RadiusLiminf import Mathlib.Analysis.Analytic.Uniqueness @@ -641,7 +652,8 @@ import Mathlib.Analysis.Calculus.InverseFunctionTheorem.ContDiff import Mathlib.Analysis.Calculus.InverseFunctionTheorem.Deriv import Mathlib.Analysis.Calculus.InverseFunctionTheorem.FDeriv import Mathlib.Analysis.Calculus.InverseFunctionTheorem.FiniteDimensional -import Mathlib.Analysis.Calculus.IteratedDeriv +import Mathlib.Analysis.Calculus.IteratedDeriv.Defs +import Mathlib.Analysis.Calculus.IteratedDeriv.Lemmas import Mathlib.Analysis.Calculus.LHopital import Mathlib.Analysis.Calculus.LagrangeMultipliers import Mathlib.Analysis.Calculus.LineDeriv.Basic @@ -690,8 +702,9 @@ import Mathlib.Analysis.Convex.Caratheodory import Mathlib.Analysis.Convex.Combination import Mathlib.Analysis.Convex.Complex import Mathlib.Analysis.Convex.Cone.Basic -import Mathlib.Analysis.Convex.Cone.Dual +import Mathlib.Analysis.Convex.Cone.Closure import Mathlib.Analysis.Convex.Cone.Extension +import Mathlib.Analysis.Convex.Cone.InnerDual import Mathlib.Analysis.Convex.Cone.Pointed import Mathlib.Analysis.Convex.Cone.Proper import Mathlib.Analysis.Convex.Contractible @@ -791,6 +804,7 @@ import Mathlib.Analysis.Normed.Group.SemiNormedGroupCat import Mathlib.Analysis.Normed.Group.SemiNormedGroupCat.Completion import Mathlib.Analysis.Normed.Group.SemiNormedGroupCat.Kernels import Mathlib.Analysis.Normed.Group.Seminorm +import Mathlib.Analysis.Normed.Group.Tannery import Mathlib.Analysis.Normed.MulAction import Mathlib.Analysis.Normed.Order.Basic import Mathlib.Analysis.Normed.Order.Lattice @@ -867,6 +881,7 @@ import Mathlib.Analysis.SpecialFunctions.CompareExp import Mathlib.Analysis.SpecialFunctions.Complex.Arg import Mathlib.Analysis.SpecialFunctions.Complex.Circle import Mathlib.Analysis.SpecialFunctions.Complex.Log +import Mathlib.Analysis.SpecialFunctions.Complex.LogBounds import Mathlib.Analysis.SpecialFunctions.Complex.LogDeriv import Mathlib.Analysis.SpecialFunctions.Exp import Mathlib.Analysis.SpecialFunctions.ExpDeriv @@ -1003,6 +1018,7 @@ import Mathlib.CategoryTheory.ConcreteCategory.UnbundledHom import Mathlib.CategoryTheory.Conj import Mathlib.CategoryTheory.ConnectedComponents import Mathlib.CategoryTheory.Core +import Mathlib.CategoryTheory.Countable import Mathlib.CategoryTheory.DifferentialObject import Mathlib.CategoryTheory.DiscreteCategory import Mathlib.CategoryTheory.Elements @@ -1033,6 +1049,7 @@ import Mathlib.CategoryTheory.Functor.Hom import Mathlib.CategoryTheory.Functor.InvIsos import Mathlib.CategoryTheory.Functor.ReflectsIso import Mathlib.CategoryTheory.Functor.Trifunctor +import Mathlib.CategoryTheory.Galois.Basic import Mathlib.CategoryTheory.Generator import Mathlib.CategoryTheory.GlueData import Mathlib.CategoryTheory.GradedObject @@ -1116,6 +1133,7 @@ import Mathlib.CategoryTheory.Limits.Shapes.BinaryProducts import Mathlib.CategoryTheory.Limits.Shapes.Biproducts import Mathlib.CategoryTheory.Limits.Shapes.CommSq import Mathlib.CategoryTheory.Limits.Shapes.ConcreteCategory +import Mathlib.CategoryTheory.Limits.Shapes.Countable import Mathlib.CategoryTheory.Limits.Shapes.Diagonal import Mathlib.CategoryTheory.Limits.Shapes.DisjointCoproduct import Mathlib.CategoryTheory.Limits.Shapes.Equalizers @@ -1272,6 +1290,7 @@ import Mathlib.CategoryTheory.Sites.CoversTop import Mathlib.CategoryTheory.Sites.DenseSubsite import Mathlib.CategoryTheory.Sites.EffectiveEpimorphic import Mathlib.CategoryTheory.Sites.EqualizerSheafCondition +import Mathlib.CategoryTheory.Sites.Equivalence import Mathlib.CategoryTheory.Sites.Grothendieck import Mathlib.CategoryTheory.Sites.InducedTopology import Mathlib.CategoryTheory.Sites.IsSheafFor @@ -1286,6 +1305,7 @@ import Mathlib.CategoryTheory.Sites.RegularExtensive import Mathlib.CategoryTheory.Sites.Sheaf import Mathlib.CategoryTheory.Sites.SheafHom import Mathlib.CategoryTheory.Sites.SheafOfTypes +import Mathlib.CategoryTheory.Sites.Sheafification import Mathlib.CategoryTheory.Sites.Sieves import Mathlib.CategoryTheory.Sites.Spaces import Mathlib.CategoryTheory.Sites.Subsheaf @@ -1350,6 +1370,7 @@ import Mathlib.Combinatorics.Quiver.SingleObj import Mathlib.Combinatorics.Quiver.Subquiver import Mathlib.Combinatorics.Quiver.Symmetric import Mathlib.Combinatorics.Schnirelmann +import Mathlib.Combinatorics.SetFamily.AhlswedeZhang import Mathlib.Combinatorics.SetFamily.CauchyDavenport import Mathlib.Combinatorics.SetFamily.Compression.Down import Mathlib.Combinatorics.SetFamily.Compression.UV @@ -1377,6 +1398,7 @@ import Mathlib.Combinatorics.SimpleGraph.Girth import Mathlib.Combinatorics.SimpleGraph.Hasse import Mathlib.Combinatorics.SimpleGraph.IncMatrix import Mathlib.Combinatorics.SimpleGraph.Init +import Mathlib.Combinatorics.SimpleGraph.Maps import Mathlib.Combinatorics.SimpleGraph.Matching import Mathlib.Combinatorics.SimpleGraph.Metric import Mathlib.Combinatorics.SimpleGraph.Operations @@ -1488,6 +1510,7 @@ import Mathlib.Data.DFinsupp.WellFounded import Mathlib.Data.DList.Basic import Mathlib.Data.DList.Defs import Mathlib.Data.DList.Instances +import Mathlib.Data.ENNReal.Basic import Mathlib.Data.ENat.Basic import Mathlib.Data.ENat.Lattice import Mathlib.Data.Equiv.Functor @@ -1501,6 +1524,7 @@ import Mathlib.Data.Fin.SuccPred import Mathlib.Data.Fin.Tuple.Basic import Mathlib.Data.Fin.Tuple.BubbleSortInduction import Mathlib.Data.Fin.Tuple.Curry +import Mathlib.Data.Fin.Tuple.Finset import Mathlib.Data.Fin.Tuple.Monotone import Mathlib.Data.Fin.Tuple.NatAntidiagonal import Mathlib.Data.Fin.Tuple.Reflection @@ -1534,6 +1558,7 @@ import Mathlib.Data.Finset.Order import Mathlib.Data.Finset.PImage import Mathlib.Data.Finset.Pairwise import Mathlib.Data.Finset.Pi +import Mathlib.Data.Finset.PiAntidiagonal import Mathlib.Data.Finset.PiInduction import Mathlib.Data.Finset.Pointwise import Mathlib.Data.Finset.Pointwise.Interval @@ -1562,8 +1587,8 @@ import Mathlib.Data.Finsupp.Multiset import Mathlib.Data.Finsupp.NeLocus import Mathlib.Data.Finsupp.Notation import Mathlib.Data.Finsupp.Order +import Mathlib.Data.Finsupp.PWO import Mathlib.Data.Finsupp.Pointwise -import Mathlib.Data.Finsupp.Pwo import Mathlib.Data.Finsupp.ToDFinsupp import Mathlib.Data.Finsupp.WellFounded import Mathlib.Data.Fintype.Array @@ -1605,6 +1630,7 @@ import Mathlib.Data.Int.Cast.Lemmas import Mathlib.Data.Int.Cast.Prod import Mathlib.Data.Int.CharZero import Mathlib.Data.Int.ConditionallyCompleteOrder +import Mathlib.Data.Int.Defs import Mathlib.Data.Int.Div import Mathlib.Data.Int.Dvd.Basic import Mathlib.Data.Int.Dvd.Pow @@ -1759,6 +1785,7 @@ import Mathlib.Data.Nat.Choose.Multinomial import Mathlib.Data.Nat.Choose.Sum import Mathlib.Data.Nat.Choose.Vandermonde import Mathlib.Data.Nat.Count +import Mathlib.Data.Nat.Defs import Mathlib.Data.Nat.Digits import Mathlib.Data.Nat.Dist import Mathlib.Data.Nat.EvenOddRec @@ -1893,6 +1920,7 @@ import Mathlib.Data.Rat.Floor import Mathlib.Data.Rat.Init import Mathlib.Data.Rat.Lemmas import Mathlib.Data.Rat.NNRat +import Mathlib.Data.Rat.NNRat.BigOperators import Mathlib.Data.Rat.Order import Mathlib.Data.Rat.Sqrt import Mathlib.Data.Rat.Star @@ -1911,7 +1939,6 @@ import Mathlib.Data.Real.Cardinality import Mathlib.Data.Real.CauSeq import Mathlib.Data.Real.CauSeqCompletion import Mathlib.Data.Real.ConjugateExponents -import Mathlib.Data.Real.ENNReal import Mathlib.Data.Real.ENatENNReal import Mathlib.Data.Real.EReal import Mathlib.Data.Real.GoldenRatio @@ -1937,6 +1964,7 @@ import Mathlib.Data.Set.BoolIndicator import Mathlib.Data.Set.Card import Mathlib.Data.Set.Constructions import Mathlib.Data.Set.Countable +import Mathlib.Data.Set.Defs import Mathlib.Data.Set.Enumerate import Mathlib.Data.Set.Equitable import Mathlib.Data.Set.Finite @@ -1954,6 +1982,7 @@ import Mathlib.Data.Set.Intervals.Monoid import Mathlib.Data.Set.Intervals.Monotone import Mathlib.Data.Set.Intervals.OrdConnected import Mathlib.Data.Set.Intervals.OrdConnectedComponent +import Mathlib.Data.Set.Intervals.OrderEmbedding import Mathlib.Data.Set.Intervals.OrderIso import Mathlib.Data.Set.Intervals.Pi import Mathlib.Data.Set.Intervals.ProjIcc @@ -2057,6 +2086,7 @@ import Mathlib.FieldTheory.Adjoin import Mathlib.FieldTheory.AxGrothendieck import Mathlib.FieldTheory.Cardinality import Mathlib.FieldTheory.ChevalleyWarning +import Mathlib.FieldTheory.Extension import Mathlib.FieldTheory.Finite.Basic import Mathlib.FieldTheory.Finite.GaloisField import Mathlib.FieldTheory.Finite.Polynomial @@ -2134,10 +2164,16 @@ import Mathlib.Geometry.Manifold.Diffeomorph import Mathlib.Geometry.Manifold.Instances.Real import Mathlib.Geometry.Manifold.Instances.Sphere import Mathlib.Geometry.Manifold.Instances.UnitsOfNormedAlgebra +import Mathlib.Geometry.Manifold.IntegralCurve import Mathlib.Geometry.Manifold.InteriorBoundary import Mathlib.Geometry.Manifold.LocalDiffeomorph import Mathlib.Geometry.Manifold.LocalInvariantProperties -import Mathlib.Geometry.Manifold.MFDeriv +import Mathlib.Geometry.Manifold.MFDeriv.Atlas +import Mathlib.Geometry.Manifold.MFDeriv.Basic +import Mathlib.Geometry.Manifold.MFDeriv.Defs +import Mathlib.Geometry.Manifold.MFDeriv.FDeriv +import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions +import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential import Mathlib.Geometry.Manifold.Metrizable import Mathlib.Geometry.Manifold.PartitionOfUnity import Mathlib.Geometry.Manifold.Sheaf.Basic @@ -2218,6 +2254,7 @@ import Mathlib.GroupTheory.Perm.Cycle.Basic import Mathlib.GroupTheory.Perm.Cycle.Concrete import Mathlib.GroupTheory.Perm.Cycle.PossibleTypes import Mathlib.GroupTheory.Perm.Cycle.Type +import Mathlib.GroupTheory.Perm.DomMulAct import Mathlib.GroupTheory.Perm.Fin import Mathlib.GroupTheory.Perm.List import Mathlib.GroupTheory.Perm.Option @@ -2388,6 +2425,7 @@ import Mathlib.LinearAlgebra.Dimension.Finite import Mathlib.LinearAlgebra.Dimension.Finrank import Mathlib.LinearAlgebra.Dimension.Free import Mathlib.LinearAlgebra.Dimension.LinearMap +import Mathlib.LinearAlgebra.Dimension.Localization import Mathlib.LinearAlgebra.Dimension.StrongRankCondition import Mathlib.LinearAlgebra.DirectSum.Finsupp import Mathlib.LinearAlgebra.DirectSum.TensorProduct @@ -2661,6 +2699,7 @@ import Mathlib.MeasureTheory.MeasurableSpace.Defs import Mathlib.MeasureTheory.MeasurableSpace.Invariants import Mathlib.MeasureTheory.Measure.AEDisjoint import Mathlib.MeasureTheory.Measure.AEMeasurable +import Mathlib.MeasureTheory.Measure.AddContent import Mathlib.MeasureTheory.Measure.Complex import Mathlib.MeasureTheory.Measure.Content import Mathlib.MeasureTheory.Measure.Count @@ -2750,6 +2789,7 @@ import Mathlib.NumberTheory.DiophantineApproximation import Mathlib.NumberTheory.DirichletCharacter.Basic import Mathlib.NumberTheory.DirichletCharacter.Bounds import Mathlib.NumberTheory.Divisors +import Mathlib.NumberTheory.EllipticDivisibilitySequence import Mathlib.NumberTheory.EulerProduct.Basic import Mathlib.NumberTheory.EulerProduct.DirichletLSeries import Mathlib.NumberTheory.FLT.Basic @@ -2780,8 +2820,10 @@ import Mathlib.NumberTheory.MaricaSchoenheim import Mathlib.NumberTheory.Modular import Mathlib.NumberTheory.ModularForms.Basic import Mathlib.NumberTheory.ModularForms.CongruenceSubgroups -import Mathlib.NumberTheory.ModularForms.JacobiTheta.Basic +import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold +import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable +import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable import Mathlib.NumberTheory.ModularForms.SlashActions import Mathlib.NumberTheory.ModularForms.SlashInvariantForms import Mathlib.NumberTheory.Multiplicity @@ -2790,6 +2832,7 @@ import Mathlib.NumberTheory.NumberField.CanonicalEmbedding import Mathlib.NumberTheory.NumberField.ClassNumber import Mathlib.NumberTheory.NumberField.Discriminant import Mathlib.NumberTheory.NumberField.Embeddings +import Mathlib.NumberTheory.NumberField.FractionalIdeal import Mathlib.NumberTheory.NumberField.Norm import Mathlib.NumberTheory.NumberField.Units import Mathlib.NumberTheory.Padics.Harmonic @@ -2859,6 +2902,7 @@ import Mathlib.Order.CompleteBooleanAlgebra import Mathlib.Order.CompleteLattice import Mathlib.Order.CompleteLatticeIntervals import Mathlib.Order.CompletePartialOrder +import Mathlib.Order.CompleteSublattice import Mathlib.Order.Concept import Mathlib.Order.ConditionallyCompleteLattice.Basic import Mathlib.Order.ConditionallyCompleteLattice.Finset @@ -2933,6 +2977,7 @@ import Mathlib.Order.Monotone.Extension import Mathlib.Order.Monotone.Monovary import Mathlib.Order.Monotone.Odd import Mathlib.Order.Monotone.Union +import Mathlib.Order.Notation import Mathlib.Order.OmegaCompletePartialOrder import Mathlib.Order.OrdContinuous import Mathlib.Order.OrderIsoNat @@ -2977,6 +3022,8 @@ import Mathlib.Probability.Density import Mathlib.Probability.Distributions.Exponential import Mathlib.Probability.Distributions.Gamma import Mathlib.Probability.Distributions.Gaussian +import Mathlib.Probability.Distributions.Geometric +import Mathlib.Probability.Distributions.Poisson import Mathlib.Probability.IdentDistrib import Mathlib.Probability.Independence.Basic import Mathlib.Probability.Independence.Conditional @@ -3016,6 +3063,7 @@ import Mathlib.Probability.Process.Stopping import Mathlib.Probability.StrongLaw import Mathlib.Probability.Variance import Mathlib.RepresentationTheory.Action.Basic +import Mathlib.RepresentationTheory.Action.Concrete import Mathlib.RepresentationTheory.Action.Limits import Mathlib.RepresentationTheory.Action.Monoidal import Mathlib.RepresentationTheory.Basic @@ -3039,6 +3087,7 @@ import Mathlib.RingTheory.Algebraic import Mathlib.RingTheory.AlgebraicIndependent import Mathlib.RingTheory.Artinian import Mathlib.RingTheory.Bezout +import Mathlib.RingTheory.Binomial import Mathlib.RingTheory.ChainOfDivisors import Mathlib.RingTheory.ClassGroup import Mathlib.RingTheory.Coalgebra @@ -3073,7 +3122,9 @@ import Mathlib.RingTheory.FiniteType import Mathlib.RingTheory.Finiteness import Mathlib.RingTheory.Fintype import Mathlib.RingTheory.Flat -import Mathlib.RingTheory.FractionalIdeal +import Mathlib.RingTheory.FractionalIdeal.Basic +import Mathlib.RingTheory.FractionalIdeal.Norm +import Mathlib.RingTheory.FractionalIdeal.Operations import Mathlib.RingTheory.FreeCommRing import Mathlib.RingTheory.FreeRing import Mathlib.RingTheory.GradedAlgebra.Basic @@ -3111,6 +3162,7 @@ import Mathlib.RingTheory.Localization.AsSubring import Mathlib.RingTheory.Localization.AtPrime import Mathlib.RingTheory.Localization.Away.AdjoinRoot import Mathlib.RingTheory.Localization.Away.Basic +import Mathlib.RingTheory.Localization.BaseChange import Mathlib.RingTheory.Localization.Basic import Mathlib.RingTheory.Localization.Cardinality import Mathlib.RingTheory.Localization.FractionRing @@ -3228,6 +3280,7 @@ import Mathlib.SetTheory.Cardinal.Cofinality import Mathlib.SetTheory.Cardinal.Continuum import Mathlib.SetTheory.Cardinal.CountableCover import Mathlib.SetTheory.Cardinal.Divisibility +import Mathlib.SetTheory.Cardinal.ENat import Mathlib.SetTheory.Cardinal.Finite import Mathlib.SetTheory.Cardinal.Ordinal import Mathlib.SetTheory.Cardinal.SchroederBernstein @@ -3327,6 +3380,7 @@ import Mathlib.Tactic.InferParam import Mathlib.Tactic.Inhabit import Mathlib.Tactic.IntervalCases import Mathlib.Tactic.IrreducibleDef +import Mathlib.Tactic.Lemma import Mathlib.Tactic.LibrarySearch import Mathlib.Tactic.Lift import Mathlib.Tactic.LiftLets @@ -3428,6 +3482,7 @@ import Mathlib.Tactic.ToLevel import Mathlib.Tactic.Trace import Mathlib.Tactic.TryThis import Mathlib.Tactic.TypeCheck +import Mathlib.Tactic.TypeStar import Mathlib.Tactic.UnsetOption import Mathlib.Tactic.Use import Mathlib.Tactic.Variable @@ -3481,6 +3536,7 @@ import Mathlib.Topology.Algebra.Module.StrongTopology import Mathlib.Topology.Algebra.Module.WeakDual import Mathlib.Topology.Algebra.Monoid import Mathlib.Topology.Algebra.MulAction +import Mathlib.Topology.Algebra.MvPolynomial import Mathlib.Topology.Algebra.Nonarchimedean.AdicTopology import Mathlib.Topology.Algebra.Nonarchimedean.Bases import Mathlib.Topology.Algebra.Nonarchimedean.Basic @@ -3521,6 +3577,7 @@ import Mathlib.Topology.Algebra.ValuedField import Mathlib.Topology.Algebra.WithZeroTopology import Mathlib.Topology.Bases import Mathlib.Topology.Basic +import Mathlib.Topology.Bornology.Absorbs import Mathlib.Topology.Bornology.Basic import Mathlib.Topology.Bornology.Constructions import Mathlib.Topology.Bornology.Hom @@ -3561,6 +3618,7 @@ import Mathlib.Topology.ClopenBox import Mathlib.Topology.CompactOpen import Mathlib.Topology.Compactification.OnePoint import Mathlib.Topology.Compactness.Compact +import Mathlib.Topology.Compactness.Lindelof import Mathlib.Topology.Compactness.LocallyCompact import Mathlib.Topology.Compactness.Paracompact import Mathlib.Topology.Compactness.SigmaCompact @@ -3668,6 +3726,7 @@ import Mathlib.Topology.MetricSpace.MetricSeparated import Mathlib.Topology.MetricSpace.PartitionOfUnity import Mathlib.Topology.MetricSpace.PiNat import Mathlib.Topology.MetricSpace.Polish +import Mathlib.Topology.MetricSpace.ProperSpace import Mathlib.Topology.MetricSpace.PseudoMetric import Mathlib.Topology.MetricSpace.ShrinkingLemma import Mathlib.Topology.MetricSpace.ThickenedIndicator @@ -3767,7 +3826,6 @@ import Mathlib.Util.CountHeartbeats import Mathlib.Util.Delaborators import Mathlib.Util.DischargerAsTactic import Mathlib.Util.Export -import Mathlib.Util.Imports import Mathlib.Util.IncludeStr import Mathlib.Util.LongNames import Mathlib.Util.MemoFix diff --git a/Mathlib/Algebra/Abs.lean b/Mathlib/Algebra/Abs.lean deleted file mode 100644 index 5c8563ced1599..0000000000000 --- a/Mathlib/Algebra/Abs.lean +++ /dev/null @@ -1,80 +0,0 @@ -/- -Copyright (c) 2021 Christopher Hoskin. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Christopher Hoskin --/ -import Mathlib.Mathport.Rename -import Mathlib.Tactic.Basic - -#align_import algebra.abs from "leanprover-community/mathlib"@"c4658a649d216f57e99621708b09dcb3dcccbd23" -/-! -# Absolute value - -This file defines a notational class `Abs` which adds the unary operator `abs` and the notation -`|.|`. The concept of an absolute value occurs in lattice ordered groups and in GL and GM spaces. - -Mathematical structures possessing an absolute value often also possess a unique decomposition of -elements into "positive" and "negative" parts which are in some sense "disjoint" (e.g. the Jordan -decomposition of a measure). This file also defines `PosPart` and `NegPart` classes -which add unary operators `pos` and `neg`, representing the maps taking an element to its positive -and negative part respectively along with the notation `⁺` and `⁻`. - -## Notations - -The following notation is introduced: - -* `|.|` for the absolute value; -* `.⁺` for the positive part; -* `.⁻` for the negative part. - -## Tags - -absolute --/ - - -/-- -Absolute value is a unary operator with properties similar to the absolute value of a real number. --/ -class Abs (α : Type*) where - /-- The absolute value function. -/ - abs : α → α - -#align has_abs Abs - -export Abs (abs) - -/-- The positive part of an element admitting a decomposition into positive and negative parts. --/ -class PosPart (α : Type*) where - /-- The positive part function. -/ - pos : α → α - -#align has_pos_part PosPart - -/-- The negative part of an element admitting a decomposition into positive and negative parts. --/ -class NegPart (α : Type*) where - /-- The negative part function. -/ - neg : α → α - -#align has_neg_part NegPart - -@[inherit_doc Abs.abs] -macro:max atomic("|" noWs) a:term noWs "|" : term => `(abs $a) - -/-- Unexpander for the notation `|a|` for `abs a`. -Tries to add discretionary parentheses in unparseable cases. -/ -@[app_unexpander Abs.abs] -def Abs.abs.unexpander : Lean.PrettyPrinter.Unexpander - | `($_ $a) => - match a with - | `(|$_|) | `(-$_) => `(|($a)|) - | _ => `(|$a|) - | _ => throw () - -@[inherit_doc] -postfix:max "⁺" => PosPart.pos - -@[inherit_doc] -postfix:max "⁻" => NegPart.neg diff --git a/Mathlib/Algebra/AddConstMap/Basic.lean b/Mathlib/Algebra/AddConstMap/Basic.lean new file mode 100644 index 0000000000000..1ba93bc3f44f6 --- /dev/null +++ b/Mathlib/Algebra/AddConstMap/Basic.lean @@ -0,0 +1,452 @@ +/- +Copyright (c) 2024 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Algebra.Periodic +import Mathlib.Algebra.Order.Group.Instances + +/-! +# Maps (semi)conjugating a shift to a shift + +Denote by \(S^1\) the unit circle `UnitAddCircle`. +A common way to study a self-map \(f\colon S^1\to S^1\) of degree `1` +is to lift it to a map \(\tilde f\colon \mathbb R\to \mathbb R\) +such that \(\tilde f(x + 1) = \tilde f(x)+1\) for all `x`. + +In this file we define a structure and a typeclass +for bundled maps satisfying `f (x + a) = f x + b`. + +We use parameters `a` and `b` instead of `1` to accomodate for two use cases: + +- maps between circles of different lengths; +- self-maps \(f\colon S^1\to S^1\) of degree other than one, + including orientation-reversing maps. +-/ + +open Function Set + +/-- A bundled map `f : G → H` such that `f (x + a) = f x + b` for all `x`. + +One can think about `f` as a lift to `G` of a map between two `AddCircle`s. -/ +structure AddConstMap (G H : Type*) [Add G] [Add H] (a : G) (b : H) where + /-- The underlying function of an `AddConstMap`. + Use automatic coercion to function instead. -/ + protected toFun : G → H + /-- An `AddConstMap` satisfies `f (x + a) = f x + b`. Use `map_add_const` instead.-/ + map_add_const' (x : G) : toFun (x + a) = toFun x + b + +@[inherit_doc] +scoped [AddConstMap] notation:25 G " →+c[" a ", " b "] " H => AddConstMap G H a b + +/-- Typeclass for maps satisfying `f (x + a) = f x + b`. + +Note that `a` and `b` are `outParam`s, +so one should not add instances like +`[AddConstMapClass F G H a b] : AddConstMapClass F G H (-a) (-b)`. -/ +class AddConstMapClass (F : Type*) (G H : outParam (Type*)) [Add G] [Add H] + (a : outParam G) (b : outParam H) extends DFunLike F G fun _ ↦ H where + /-- A map of `AddConstMapClass` class semiconjugates shift by `a` to the shift by `b`: + `∀ x, f (x + a) = f x + b`. -/ + map_add_const (f : F) (x : G) : f (x + a) = f x + b + +namespace AddConstMapClass + +/-! +### Properties of `AddConstMapClass` maps + +In this section we prove properties like `f (x + n • a) = f x + n • b`. +-/ + +attribute [simp] map_add_const + +variable {F G H : Type*} {a : G} {b : H} + +protected theorem semiconj [Add G] [Add H] [AddConstMapClass F G H a b] (f : F) : + Semiconj f (· + a) (· + b) := + map_add_const f + +@[simp] +theorem map_add_nsmul [AddMonoid G] [AddMonoid H] [AddConstMapClass F G H a b] + (f : F) (x : G) (n : ℕ) : f (x + n • a) = f x + n • b := by + simpa using (AddConstMapClass.semiconj f).iterate_right n x + +@[simp] +theorem map_add_nat' [AddMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) (n : ℕ) : f (x + n) = f x + n • b := by simp [← map_add_nsmul] + +theorem map_add_one [AddMonoidWithOne G] [Add H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) : f (x + 1) = f x + b := map_add_const f x + +@[simp] +theorem map_add_ofNat' [AddMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) (n : ℕ) [n.AtLeastTwo] : + f (x + no_index (OfNat.ofNat n)) = f x + (OfNat.ofNat n : ℕ) • b := + map_add_nat' f x n + +theorem map_add_nat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (x : G) (n : ℕ) : f (x + n) = f x + n := by simp + +theorem map_add_ofNat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (x : G) (n : ℕ) [n.AtLeastTwo] : + f (x + OfNat.ofNat n) = f x + OfNat.ofNat n := map_add_nat f x n + +@[simp] +theorem map_const [AddZeroClass G] [Add H] [AddConstMapClass F G H a b] (f : F) : + f a = f 0 + b := by + simpa using map_add_const f 0 + +theorem map_one [AddZeroClass G] [One G] [Add H] [AddConstMapClass F G H 1 b] (f : F) : + f 1 = f 0 + b := + map_const f + +@[simp] +theorem map_nsmul_const [AddMonoid G] [AddMonoid H] [AddConstMapClass F G H a b] + (f : F) (n : ℕ) : f (n • a) = f 0 + n • b := by + simpa using map_add_nsmul f 0 n + +@[simp] +theorem map_nat' [AddMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] + (f : F) (n : ℕ) : f n = f 0 + n • b := by + simpa using map_add_nat' f 0 n + +theorem map_ofNat' [AddMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] + (f : F) (n : ℕ) [n.AtLeastTwo] : + f (OfNat.ofNat n) = f 0 + (OfNat.ofNat n : ℕ) • b := + map_nat' f n + +theorem map_nat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (n : ℕ) : f n = f 0 + n := by simp + +theorem map_ofNat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (n : ℕ) [n.AtLeastTwo] : + f (OfNat.ofNat n) = f 0 + OfNat.ofNat n := map_nat f n + +@[simp] +theorem map_const_add [AddCommSemigroup G] [Add H] [AddConstMapClass F G H a b] + (f : F) (x : G) : f (a + x) = f x + b := by + rw [add_comm, map_add_const] + +theorem map_one_add [AddCommMonoidWithOne G] [Add H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) : f (1 + x) = f x + b := map_const_add f x + +@[simp] +theorem map_nsmul_add [AddCommMonoid G] [AddMonoid H] [AddConstMapClass F G H a b] + (f : F) (n : ℕ) (x : G) : f (n • a + x) = f x + n • b := by + rw [add_comm, map_add_nsmul] + +@[simp] +theorem map_nat_add' [AddCommMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] + (f : F) (n : ℕ) (x : G) : f (↑n + x) = f x + n • b := by + simpa using map_nsmul_add f n x + +theorem map_ofNat_add' [AddCommMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] + (f : F) (n : ℕ) [n.AtLeastTwo] (x : G) : + f (OfNat.ofNat n + x) = f x + OfNat.ofNat n • b := + map_nat_add' f n x + +theorem map_nat_add [AddCommMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (n : ℕ) (x : G) : f (↑n + x) = f x + n := by simp + +theorem map_ofNat_add [AddCommMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (n : ℕ) [n.AtLeastTwo] (x : G) : + f (OfNat.ofNat n + x) = f x + OfNat.ofNat n := + map_nat_add f n x + +@[simp] +theorem map_sub_nsmul [AddGroup G] [AddGroup H] [AddConstMapClass F G H a b] + (f : F) (x : G) (n : ℕ) : f (x - n • a) = f x - n • b := by + conv_rhs => rw [← sub_add_cancel x (n • a), map_add_nsmul, add_sub_cancel] + +@[simp] +theorem map_sub_const [AddGroup G] [AddGroup H] [AddConstMapClass F G H a b] + (f : F) (x : G) : f (x - a) = f x - b := by + simpa using map_sub_nsmul f x 1 + +theorem map_sub_one [AddGroup G] [One G] [AddGroup H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) : f (x - 1) = f x - b := + map_sub_const f x + +@[simp] +theorem map_sub_nat' [AddGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) (n : ℕ) : f (x - n) = f x - n • b := by + simpa using map_sub_nsmul f x n + +@[simp] +theorem map_sub_ofNat' [AddGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) (n : ℕ) [n.AtLeastTwo] : + f (x - no_index (OfNat.ofNat n)) = f x - OfNat.ofNat n • b := + map_sub_nat' f x n + +@[simp] +theorem map_add_zsmul [AddGroup G] [AddGroup H] [AddConstMapClass F G H a b] + (f : F) (x : G) : ∀ n : ℤ, f (x + n • a) = f x + n • b + | (n : ℕ) => by simp + | .negSucc n => by simp [← sub_eq_add_neg] + +@[simp] +theorem map_zsmul_const [AddGroup G] [AddGroup H] [AddConstMapClass F G H a b] + (f : F) (n : ℤ) : f (n • a) = f 0 + n • b := by + simpa using map_add_zsmul f 0 n + +@[simp] +theorem map_add_int' [AddGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) (n : ℤ) : f (x + n) = f x + n • b := by + rw [← map_add_zsmul f x n, zsmul_one] + +theorem map_add_int [AddGroupWithOne G] [AddGroupWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (x : G) (n : ℤ) : f (x + n) = f x + n := by simp + +@[simp] +theorem map_sub_zsmul [AddGroup G] [AddGroup H] [AddConstMapClass F G H a b] + (f : F) (x : G) (n : ℤ) : f (x - n • a) = f x - n • b := by + simpa [sub_eq_add_neg] using map_add_zsmul f x (-n) + +@[simp] +theorem map_sub_int' [AddGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 b] + (f : F) (x : G) (n : ℤ) : f (x - n) = f x - n • b := by + rw [← map_sub_zsmul, zsmul_one] + +theorem map_sub_int [AddGroupWithOne G] [AddGroupWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (x : G) (n : ℤ) : f (x - n) = f x - n := by simp + +@[simp] +theorem map_zsmul_add [AddCommGroup G] [AddGroup H] [AddConstMapClass F G H a b] + (f : F) (n : ℤ) (x : G) : f (n • a + x) = f x + n • b := by + rw [add_comm, map_add_zsmul] + +@[simp] +theorem map_int_add' [AddCommGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 b] + (f : F) (n : ℤ) (x : G) : f (↑n + x) = f x + n • b := by + rw [← map_zsmul_add, zsmul_one] + +theorem map_int_add [AddCommGroupWithOne G] [AddGroupWithOne H] [AddConstMapClass F G H 1 1] + (f : F) (n : ℤ) (x : G) : f (↑n + x) = f x + n := by simp + +theorem map_fract {R : Type*} [LinearOrderedRing R] [FloorRing R] [AddGroup H] + [AddConstMapClass F R H 1 b] (f : F) (x : R) : + f (Int.fract x) = f x - ⌊x⌋ • b := + map_sub_int' .. + +/-- Auxiliary lemmas for the "monotonicity on a fundamental interval implies monotonicity" lemmas. +We formulate it for any relation so that the proof works both for `Monotone` and `StrictMono`. -/ +protected theorem rel_map_of_Icc [LinearOrderedAddCommGroup G] [Archimedean G] [AddGroup H] + [AddConstMapClass F G H a b] {f : F} {R : H → H → Prop} [IsTrans H R] + [hR : CovariantClass H H (fun x y ↦ y + x) R] (ha : 0 < a) {l : G} + (hf : ∀ x ∈ Icc l (l + a), ∀ y ∈ Icc l (l + a), x < y → R (f x) (f y)) : + ((· < ·) ⇒ R) f f := fun x y hxy ↦ by + replace hR := hR.elim + have ha' : 0 ≤ a := ha.le + -- Shift both points by `m • a` so that `l ≤ x < l + a` + wlog hx : x ∈ Ico l (l + a) generalizing x y + · rcases existsUnique_sub_zsmul_mem_Ico ha x l with ⟨m, hm, -⟩ + suffices R (f (x - m • a)) (f (y - m • a)) by simpa using hR (m • b) this + exact this _ _ (by simpa) hm + · -- Now find `n` such that `l + n • a < y ≤ l + (n + 1) • a` + rcases existsUnique_sub_zsmul_mem_Ioc ha y l with ⟨n, hny, -⟩ + rcases lt_trichotomy n 0 with hn | rfl | hn + · -- Since `l ≤ x ≤ y`, the case `n < 0` is impossible + refine absurd ?_ hxy.not_le + calc + y ≤ l + a + n • a := sub_le_iff_le_add.1 hny.2 + _ = l + (n + 1) • a := by rw [add_comm n, add_smul, one_smul, add_assoc] + _ ≤ l + 0 • a := add_le_add_left (zsmul_le_zsmul ha.le (by omega)) _ + _ ≤ x := by simpa using hx.1 + · -- If `n = 0`, then `l < y ≤ l + a`, hence we can apply the assumption + exact hf x (Ico_subset_Icc_self hx) y (by simpa using Ioc_subset_Icc_self hny) hxy + · -- In the remaining case `0 < n` we use transitivity. + -- If `R = (· < ·)`, then the proof looks like + -- `f x < f (l + a) ≤ f (l + n • a) < f y` + trans f (l + (1 : ℤ) • a) + · rw [one_zsmul] + exact hf x (Ico_subset_Icc_self hx) (l + a) (by simpa) hx.2 + have hy : R (f (l + n • a)) (f y) := by + rw [← sub_add_cancel y (n • a), map_add_zsmul, map_add_zsmul] + refine hR _ <| hf _ ?_ _ (Ioc_subset_Icc_self hny) hny.1; simpa + rw [← Int.add_one_le_iff, zero_add] at hn + rcases hn.eq_or_lt with rfl | hn; · assumption + trans f (l + n • a) + · refine Int.rel_of_forall_rel_succ_of_lt R (f := (f <| l + · • a)) (fun k ↦ ?_) hn + simp_rw [add_comm k 1, add_zsmul, ← add_assoc, one_zsmul, map_add_zsmul] + refine hR (k • b) (hf _ ?_ _ ?_ ?_) <;> simpa + · assumption + +theorem monotone_iff_Icc [LinearOrderedAddCommGroup G] [Archimedean G] [OrderedAddCommGroup H] + [AddConstMapClass F G H a b] {f : F} (ha : 0 < a) (l : G) : + Monotone f ↔ MonotoneOn f (Icc l (l + a)) := + ⟨(Monotone.monotoneOn · _), fun hf ↦ monotone_iff_forall_lt.2 <| + AddConstMapClass.rel_map_of_Icc ha fun _x hx _y hy hxy ↦ hf hx hy hxy.le⟩ + +theorem antitone_iff_Icc [LinearOrderedAddCommGroup G] [Archimedean G] [OrderedAddCommGroup H] + [AddConstMapClass F G H a b] {f : F} (ha : 0 < a) (l : G) : + Antitone f ↔ AntitoneOn f (Icc l (l + a)) := + monotone_iff_Icc (H := Hᵒᵈ) ha l + +theorem strictMono_iff_Icc [LinearOrderedAddCommGroup G] [Archimedean G] [OrderedAddCommGroup H] + [AddConstMapClass F G H a b] {f : F} (ha : 0 < a) (l : G) : + StrictMono f ↔ StrictMonoOn f (Icc l (l + a)) := + ⟨(StrictMono.strictMonoOn · _), AddConstMapClass.rel_map_of_Icc ha⟩ + +theorem strictAnti_iff_Icc [LinearOrderedAddCommGroup G] [Archimedean G] [OrderedAddCommGroup H] + [AddConstMapClass F G H a b] {f : F} (ha : 0 < a) (l : G) : + StrictAnti f ↔ StrictAntiOn f (Icc l (l + a)) := + strictMono_iff_Icc (H := Hᵒᵈ) ha l + +end AddConstMapClass + +open AddConstMapClass + +namespace AddConstMap + +section Add + +variable {G H : Type*} [Add G] [Add H] {a : G} {b : H} + +/-! +### Coercion to function +-/ + +instance : AddConstMapClass (G →+c[a, b] H) G H a b where + coe := AddConstMap.toFun + coe_injective' | ⟨_, _⟩, ⟨_, _⟩, rfl => rfl + map_add_const f := f.map_add_const' + +@[simp] theorem coe_mk (f : G → H) (hf) : ⇑(mk f hf : G →+c[a, b] H) = f := rfl +@[simp] theorem mk_coe (f : G →+c[a, b] H) : mk f f.2 = f := rfl + +@[ext] protected theorem ext {f g : G →+c[a, b] H} (h : ∀ x, f x = g x) : f = g := + DFunLike.ext _ _ h + +initialize_simps_projections AddConstMap (toFun → coe, as_prefix coe) + +/-! +### Constructions about `G →+c[a, b] H` +-/ + +/-- The identity map as `G →+c[a, a] G`. -/ +@[simps (config := .asFn)] +protected def id : G →+c[a, a] G := ⟨id, fun _ ↦ rfl⟩ + +instance : Inhabited (G →+c[a, a] G) := ⟨.id⟩ + +/-- Composition of two `AddConstMap`s. -/ +@[simps (config := .asFn)] +def comp {K : Type*} [Add K] {c : K} (g : H →+c[b, c] K) (f : G →+c[a, b] H) : + G →+c[a, c] K := + ⟨g ∘ f, by simp⟩ + +@[simp] theorem comp_id (f : G →+c[a, b] H) : f.comp .id = f := rfl +@[simp] theorem id_comp (f : G →+c[a, b] H) : .comp .id f = f := rfl + +/-- Change constants `a` and `b` in `(f : G →+c[a, b] H)` to improve definitional equalities. -/ +@[simps (config := .asFn)] +def replaceConsts (f : G →+c[a, b] H) (a' b') (ha : a = a') (hb : b = b') : + G →+c[a', b'] H where + toFun := f + map_add_const' := ha ▸ hb ▸ f.map_add_const' + +/-! +### Additive action on `G →+c[a, b] H` +-/ + +/-- If `f` is an `AddConstMap`, then so is `(c +ᵥ f ·)`. -/ +instance {K : Type*} [VAdd K H] [VAddAssocClass K H H] : VAdd K (G →+c[a, b] H) := + ⟨fun c f ↦ ⟨c +ᵥ ⇑f, fun x ↦ by simp [vadd_add_assoc]⟩⟩ + +@[simp] +theorem coe_vadd {K : Type*} [VAdd K H] [VAddAssocClass K H H] (c : K) (f : G →+c[a, b] H) : + ⇑(c +ᵥ f) = c +ᵥ ⇑f := + rfl + +instance {K : Type*} [AddMonoid K] [AddAction K H] [VAddAssocClass K H H] : + AddAction K (G →+c[a, b] H) := + DFunLike.coe_injective.addAction _ coe_vadd + +/-! +### Monoid structure on endomorphisms `G →+c[a, a] G` +-/ + +instance : Monoid (G →+c[a, a] G) where + mul := comp + one := .id + mul_assoc _ _ _ := rfl + one_mul := id_comp + mul_one := comp_id + +theorem mul_def (f g : G →+c[a, a] G) : f * g = f.comp g := rfl +@[simp] theorem coe_mul (f g : G →+c[a, a] G) : ⇑(f * g) = f ∘ g := rfl + +theorem one_def : (1 : G →+c[a, a] G) = .id := rfl +@[simp] theorem coe_one : ⇑(1 : G →+c[a, a] G) = id := rfl + +theorem coe_pow (f : G →+c[a, a] G) (n : ℕ) : ⇑(f ^ n) = f^[n] := + hom_coe_pow _ rfl (fun _ _ ↦ rfl) _ _ + +theorem pow_apply (f : G →+c[a, a] G) (n : ℕ) (x : G) : (f ^ n) x = f^[n] x := + congr_fun (coe_pow f n) x + +end Add + +section AddZeroClass + +variable {G H K : Type*} [Add G] [AddZeroClass H] {a : G} {b : H} + +/-! +### Multiplicative action on `(b : H) × (G →+c[a, b] H)` + +If `K` acts distributively on `H`, then for each `f : G →+c[a, b] H` +we define `(AddConstMap.smul c f : G →+c[a, c • b] H)`. + +One can show that this defines a multiplicative action of `K` on `(b : H) × (G →+c[a, b] H)` +but we don't do this at the moment because we don't need this. +-/ + +/-- Pointwise scalar multiplication of `f : G →+c[a, b] H` as a map `G →+c[a, c • b] H`. -/ +@[simps (config := .asFn)] +def smul [DistribSMul K H] (c : K) (f : G →+c[a, b] H) : G →+c[a, c • b] H where + toFun := c • ⇑f + map_add_const' x := by simp [smul_add] + +end AddZeroClass + +section AddMonoid + +variable {G : Type*} [AddMonoid G] {a : G} + +/-- The map that sends `c` to a translation by `c` +as a monoid homomorphism from `Multiplicative G` to `G →+c[a, a] G`. -/ +@[simps! (config := .asFn)] +def addLeftHom : Multiplicative G →* (G →+c[a, a] G) where + toFun c := Multiplicative.toAdd c +ᵥ .id + map_one' := by ext; apply zero_add + map_mul' _ _ := by ext; apply add_assoc + +end AddMonoid + +section AddCommGroup + +variable {G H : Type*} [AddCommGroup G] [AddCommGroup H] {a : G} {b : H} + +/-- If `f : G → H` is an `AddConstMap`, then so is `fun x ↦ -f (-x)`. -/ +@[simps! apply_coe] +def conjNeg : (G →+c[a, b] H) ≃ (G →+c[a, b] H) := + Involutive.toPerm (fun f ↦ ⟨fun x ↦ - f (-x), fun _ ↦ by simp [neg_add_eq_sub]⟩) fun _ ↦ + AddConstMap.ext fun _ ↦ by simp + +@[simp] theorem conjNeg_symm : (conjNeg (a := a) (b := b)).symm = conjNeg := rfl + +end AddCommGroup + +section FloorRing + +variable {R G : Type*} [LinearOrderedRing R] [FloorRing R] [AddGroup G] (a : G) + +/-- A map `f : R →+c[1, a] G` is defined by its values on `Set.Ico 0 1`. -/ +def mkFract : (Ico (0 : R) 1 → G) ≃ (R →+c[1, a] G) where + toFun f := ⟨fun x ↦ f ⟨Int.fract x, Int.fract_nonneg _, Int.fract_lt_one _⟩ + ⌊x⌋ • a, fun x ↦ by + simp [add_one_zsmul, add_assoc]⟩ + invFun f x := f x + left_inv _ := by ext x; simp [Int.fract_eq_self.2 x.2, Int.floor_eq_zero_iff.2 x.2] + right_inv f := by ext x; simp [map_fract] + +end FloorRing diff --git a/Mathlib/Algebra/AddTorsor.lean b/Mathlib/Algebra/AddTorsor.lean index d7b1f015f697f..e2b0a03496e8e 100644 --- a/Mathlib/Algebra/AddTorsor.lean +++ b/Mathlib/Algebra/AddTorsor.lean @@ -51,7 +51,7 @@ class AddTorsor (G : outParam (Type*)) (P : Type*) [outParam <| AddGroup G] exte VSub G P where [nonempty : Nonempty P] /-- Torsor subtraction and addition with the same element cancels out. -/ - vsub_vadd' : ∀ p1 p2 : P, (p1 -ᵥ p2 : G) +ᵥ p2 = p1 + vsub_vadd' : ∀ p₁ p₂ : P, (p₁ -ᵥ p₂ : G) +ᵥ p₂ = p₁ /-- Torsor addition and subtraction with the same element cancels out. -/ vadd_vsub' : ∀ (g : G) (p : P), g +ᵥ p -ᵥ p = g #align add_torsor AddTorsor @@ -73,7 +73,7 @@ instance addGroupIsAddTorsor (G : Type*) [AddGroup G] : AddTorsor G G /-- Simplify subtraction for a torsor for an `AddGroup G` over itself. -/ @[simp] -theorem vsub_eq_sub {G : Type*} [AddGroup G] (g1 g2 : G) : g1 -ᵥ g2 = g1 - g2 := +theorem vsub_eq_sub {G : Type*} [AddGroup G] (g₁ g₂ : G) : g₁ -ᵥ g₂ = g₁ - g₂ := rfl #align vsub_eq_sub vsub_eq_sub @@ -84,8 +84,8 @@ variable {G : Type*} {P : Type*} [AddGroup G] [T : AddTorsor G P] /-- Adding the result of subtracting from another point produces that point. -/ @[simp] -theorem vsub_vadd (p1 p2 : P) : p1 -ᵥ p2 +ᵥ p2 = p1 := - AddTorsor.vsub_vadd' p1 p2 +theorem vsub_vadd (p₁ p₂ : P) : p₁ -ᵥ p₂ +ᵥ p₂ = p₁ := + AddTorsor.vsub_vadd' p₁ p₂ #align vsub_vadd vsub_vadd /-- Adding a group element then subtracting the original point @@ -97,13 +97,13 @@ theorem vadd_vsub (g : G) (p : P) : g +ᵥ p -ᵥ p = g := /-- If the same point added to two group elements produces equal results, those group elements are equal. -/ -theorem vadd_right_cancel {g1 g2 : G} (p : P) (h : g1 +ᵥ p = g2 +ᵥ p) : g1 = g2 := by +theorem vadd_right_cancel {g₁ g₂ : G} (p : P) (h : g₁ +ᵥ p = g₂ +ᵥ p) : g₁ = g₂ := by -- Porting note: vadd_vsub g₁ → vadd_vsub g₁ p - rw [← vadd_vsub g1 p, h, vadd_vsub] + rw [← vadd_vsub g₁ p, h, vadd_vsub] #align vadd_right_cancel vadd_right_cancel @[simp] -theorem vadd_right_cancel_iff {g1 g2 : G} (p : P) : g1 +ᵥ p = g2 +ᵥ p ↔ g1 = g2 := +theorem vadd_right_cancel_iff {g₁ g₂ : G} (p : P) : g₁ +ᵥ p = g₂ +ᵥ p ↔ g₁ = g₂ := ⟨vadd_right_cancel p, fun h => h ▸ rfl⟩ #align vadd_right_cancel_iff vadd_right_cancel_iff @@ -116,8 +116,8 @@ theorem vadd_right_injective (p : P) : Function.Injective ((· +ᵥ p) : G → P /-- Adding a group element to a point, then subtracting another point, produces the same result as subtracting the points then adding the group element. -/ -theorem vadd_vsub_assoc (g : G) (p1 p2 : P) : g +ᵥ p1 -ᵥ p2 = g + (p1 -ᵥ p2) := by - apply vadd_right_cancel p2 +theorem vadd_vsub_assoc (g : G) (p₁ p₂ : P) : g +ᵥ p₁ -ᵥ p₂ = g + (p₁ -ᵥ p₂) := by + apply vadd_right_cancel p₂ rw [vsub_vadd, add_vadd, vsub_vadd] #align vadd_vsub_assoc vadd_vsub_assoc @@ -128,14 +128,14 @@ theorem vsub_self (p : P) : p -ᵥ p = (0 : G) := by #align vsub_self vsub_self /-- If subtracting two points produces 0, they are equal. -/ -theorem eq_of_vsub_eq_zero {p1 p2 : P} (h : p1 -ᵥ p2 = (0 : G)) : p1 = p2 := by - rw [← vsub_vadd p1 p2, h, zero_vadd] +theorem eq_of_vsub_eq_zero {p₁ p₂ : P} (h : p₁ -ᵥ p₂ = (0 : G)) : p₁ = p₂ := by + rw [← vsub_vadd p₁ p₂, h, zero_vadd] #align eq_of_vsub_eq_zero eq_of_vsub_eq_zero /-- Subtracting two points produces 0 if and only if they are equal. -/ @[simp] -theorem vsub_eq_zero_iff_eq {p1 p2 : P} : p1 -ᵥ p2 = (0 : G) ↔ p1 = p2 := +theorem vsub_eq_zero_iff_eq {p₁ p₂ : P} : p₁ -ᵥ p₂ = (0 : G) ↔ p₁ = p₂ := Iff.intro eq_of_vsub_eq_zero fun h => h ▸ vsub_self _ #align vsub_eq_zero_iff_eq vsub_eq_zero_iff_eq @@ -145,16 +145,16 @@ theorem vsub_ne_zero {p q : P} : p -ᵥ q ≠ (0 : G) ↔ p ≠ q := /-- Cancellation adding the results of two subtractions. -/ @[simp] -theorem vsub_add_vsub_cancel (p1 p2 p3 : P) : p1 -ᵥ p2 + (p2 -ᵥ p3) = p1 -ᵥ p3 := by - apply vadd_right_cancel p3 +theorem vsub_add_vsub_cancel (p₁ p₂ p₃ : P) : p₁ -ᵥ p₂ + (p₂ -ᵥ p₃) = p₁ -ᵥ p₃ := by + apply vadd_right_cancel p₃ rw [add_vadd, vsub_vadd, vsub_vadd, vsub_vadd] #align vsub_add_vsub_cancel vsub_add_vsub_cancel /-- Subtracting two points in the reverse order produces the negation of subtracting them. -/ @[simp] -theorem neg_vsub_eq_vsub_rev (p1 p2 : P) : -(p1 -ᵥ p2) = p2 -ᵥ p1 := by - refine' neg_eq_of_add_eq_zero_right (vadd_right_cancel p1 _) +theorem neg_vsub_eq_vsub_rev (p₁ p₂ : P) : -(p₁ -ᵥ p₂) = p₂ -ᵥ p₁ := by + refine' neg_eq_of_add_eq_zero_right (vadd_right_cancel p₁ _) rw [vsub_add_vsub_cancel, vsub_self] #align neg_vsub_eq_vsub_rev neg_vsub_eq_vsub_rev @@ -164,21 +164,21 @@ theorem vadd_vsub_eq_sub_vsub (g : G) (p q : P) : g +ᵥ p -ᵥ q = g - (q -ᵥ /-- Subtracting the result of adding a group element produces the same result as subtracting the points and subtracting that group element. -/ -theorem vsub_vadd_eq_vsub_sub (p1 p2 : P) (g : G) : p1 -ᵥ (g +ᵥ p2) = p1 -ᵥ p2 - g := by - rw [← add_right_inj (p2 -ᵥ p1 : G), vsub_add_vsub_cancel, ← neg_vsub_eq_vsub_rev, vadd_vsub, ← +theorem vsub_vadd_eq_vsub_sub (p₁ p₂ : P) (g : G) : p₁ -ᵥ (g +ᵥ p₂) = p₁ -ᵥ p₂ - g := by + rw [← add_right_inj (p₂ -ᵥ p₁ : G), vsub_add_vsub_cancel, ← neg_vsub_eq_vsub_rev, vadd_vsub, ← add_sub_assoc, ← neg_vsub_eq_vsub_rev, neg_add_self, zero_sub] #align vsub_vadd_eq_vsub_sub vsub_vadd_eq_vsub_sub /-- Cancellation subtracting the results of two subtractions. -/ @[simp] -theorem vsub_sub_vsub_cancel_right (p1 p2 p3 : P) : p1 -ᵥ p3 - (p2 -ᵥ p3) = p1 -ᵥ p2 := by +theorem vsub_sub_vsub_cancel_right (p₁ p₂ p₃ : P) : p₁ -ᵥ p₃ - (p₂ -ᵥ p₃) = p₁ -ᵥ p₂ := by rw [← vsub_vadd_eq_vsub_sub, vsub_vadd] #align vsub_sub_vsub_cancel_right vsub_sub_vsub_cancel_right /-- Convert between an equality with adding a group element to a point and an equality of a subtraction of two points with a group element. -/ -theorem eq_vadd_iff_vsub_eq (p1 : P) (g : G) (p2 : P) : p1 = g +ᵥ p2 ↔ p1 -ᵥ p2 = g := +theorem eq_vadd_iff_vsub_eq (p₁ : P) (g : G) (p₂ : P) : p₁ = g +ᵥ p₂ ↔ p₁ -ᵥ p₂ = g := ⟨fun h => h.symm ▸ vadd_vsub _ _, fun h => h ▸ (vsub_vadd _ _).symm⟩ #align eq_vadd_iff_vsub_eq eq_vadd_iff_vsub_eq @@ -206,14 +206,14 @@ theorem vadd_vsub_vadd_cancel_right (v₁ v₂ : G) (p : P) : v₁ +ᵥ p -ᵥ ( /-- If the same point subtracted from two points produces equal results, those points are equal. -/ -theorem vsub_left_cancel {p1 p2 p : P} (h : p1 -ᵥ p = p2 -ᵥ p) : p1 = p2 := by +theorem vsub_left_cancel {p₁ p₂ p : P} (h : p₁ -ᵥ p = p₂ -ᵥ p) : p₁ = p₂ := by rwa [← sub_eq_zero, vsub_sub_vsub_cancel_right, vsub_eq_zero_iff_eq] at h #align vsub_left_cancel vsub_left_cancel /-- The same point subtracted from two points produces equal results if and only if those points are equal. -/ @[simp] -theorem vsub_left_cancel_iff {p1 p2 p : P} : p1 -ᵥ p = p2 -ᵥ p ↔ p1 = p2 := +theorem vsub_left_cancel_iff {p₁ p₂ p : P} : p₁ -ᵥ p = p₂ -ᵥ p ↔ p₁ = p₂ := ⟨vsub_left_cancel, fun h => h ▸ rfl⟩ #align vsub_left_cancel_iff vsub_left_cancel_iff @@ -224,15 +224,15 @@ theorem vsub_left_injective (p : P) : Function.Injective ((· -ᵥ p) : P → G) /-- If subtracting two points from the same point produces equal results, those points are equal. -/ -theorem vsub_right_cancel {p1 p2 p : P} (h : p -ᵥ p1 = p -ᵥ p2) : p1 = p2 := by - refine' vadd_left_cancel (p -ᵥ p2) _ +theorem vsub_right_cancel {p₁ p₂ p : P} (h : p -ᵥ p₁ = p -ᵥ p₂) : p₁ = p₂ := by + refine' vadd_left_cancel (p -ᵥ p₂) _ rw [vsub_vadd, ← h, vsub_vadd] #align vsub_right_cancel vsub_right_cancel /-- Subtracting two points from the same point produces equal results if and only if those points are equal. -/ @[simp] -theorem vsub_right_cancel_iff {p1 p2 p : P} : p -ᵥ p1 = p -ᵥ p2 ↔ p1 = p2 := +theorem vsub_right_cancel_iff {p₁ p₂ p : P} : p -ᵥ p₁ = p -ᵥ p₂ ↔ p₁ = p₂ := ⟨vsub_right_cancel, fun h => h ▸ rfl⟩ #align vsub_right_cancel_iff vsub_right_cancel_iff @@ -253,16 +253,16 @@ variable {G : Type*} {P : Type*} [AddCommGroup G] [AddTorsor G P] /-- Cancellation subtracting the results of two subtractions. -/ @[simp] -theorem vsub_sub_vsub_cancel_left (p1 p2 p3 : P) : p3 -ᵥ p2 - (p3 -ᵥ p1) = p1 -ᵥ p2 := by +theorem vsub_sub_vsub_cancel_left (p₁ p₂ p₃ : P) : p₃ -ᵥ p₂ - (p₃ -ᵥ p₁) = p₁ -ᵥ p₂ := by rw [sub_eq_add_neg, neg_vsub_eq_vsub_rev, add_comm, vsub_add_vsub_cancel] #align vsub_sub_vsub_cancel_left vsub_sub_vsub_cancel_left @[simp] -theorem vadd_vsub_vadd_cancel_left (v : G) (p1 p2 : P) : v +ᵥ p1 -ᵥ (v +ᵥ p2) = p1 -ᵥ p2 := by +theorem vadd_vsub_vadd_cancel_left (v : G) (p₁ p₂ : P) : v +ᵥ p₁ -ᵥ (v +ᵥ p₂) = p₁ -ᵥ p₂ := by rw [vsub_vadd_eq_vsub_sub, vadd_vsub_assoc, add_sub_cancel'] #align vadd_vsub_vadd_cancel_left vadd_vsub_vadd_cancel_left -theorem vsub_vadd_comm (p1 p2 p3 : P) : (p1 -ᵥ p2 : G) +ᵥ p3 = p3 -ᵥ p2 +ᵥ p1 := by +theorem vsub_vadd_comm (p₁ p₂ p₃ : P) : (p₁ -ᵥ p₂ : G) +ᵥ p₃ = p₃ -ᵥ p₂ +ᵥ p₁ := by rw [← @vsub_eq_zero_iff_eq G, vadd_vsub_assoc, vsub_vadd_eq_vsub_sub] simp #align vsub_vadd_comm vsub_vadd_comm @@ -287,7 +287,7 @@ instance instAddTorsor : AddTorsor (G × G') (P × P') where zero_vadd _ := Prod.ext (zero_vadd _ _) (zero_vadd _ _) add_vadd _ _ _ := Prod.ext (add_vadd _ _ _) (add_vadd _ _ _) vsub p₁ p₂ := (p₁.1 -ᵥ p₂.1, p₁.2 -ᵥ p₂.2) - nonempty := Prod.Nonempty + nonempty := Prod.instNonempty vsub_vadd' _ _ := Prod.ext (vsub_vadd _ _) (vsub_vadd _ _) vadd_vsub' _ _ := Prod.ext (vadd_vsub _ _) (vadd_vsub _ _) diff --git a/Mathlib/Algebra/Algebra/Basic.lean b/Mathlib/Algebra/Algebra/Basic.lean index 65c7c472ed9ec..c3f500c67d20b 100644 --- a/Mathlib/Algebra/Algebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.CharZero.Lemmas import Mathlib.Algebra.Module.ULift import Mathlib.LinearAlgebra.Basic import Mathlib.RingTheory.Subring.Basic +import Mathlib.Algebra.Module.Submodule.RestrictScalars #align_import algebra.algebra.basic from "leanprover-community/mathlib"@"36b8aa61ea7c05727161f96a0532897bd72aedab" @@ -314,7 +315,7 @@ it suffices to check the `algebraMap`s agree. theorem algebra_ext {R : Type*} [CommSemiring R] {A : Type*} [Semiring A] (P Q : Algebra R A) (h : ∀ r : R, (haveI := P; algebraMap R A r) = haveI := Q; algebraMap R A r) : P = Q := by - replace h : P.toRingHom = Q.toRingHom := FunLike.ext _ _ h + replace h : P.toRingHom = Q.toRingHom := DFunLike.ext _ _ h have h' : (haveI := P; (· • ·) : R → A → A) = (haveI := Q; (· • ·) : R → A → A) := by funext r a rw [P.smul_def', Q.smul_def', h] diff --git a/Mathlib/Algebra/Algebra/Bilinear.lean b/Mathlib/Algebra/Algebra/Bilinear.lean index c37330043afbc..6e537053fe82f 100644 --- a/Mathlib/Algebra/Algebra/Bilinear.lean +++ b/Mathlib/Algebra/Algebra/Bilinear.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Yury Kudryashov -/ import Mathlib.Algebra.Algebra.Basic -import Mathlib.Algebra.Algebra.Equiv import Mathlib.Algebra.Algebra.NonUnitalHom import Mathlib.Algebra.GroupPower.IterateHom import Mathlib.LinearAlgebra.TensorProduct @@ -196,7 +195,12 @@ theorem _root_.Algebra.coe_lmul_eq_mul : ⇑(Algebra.lmul R A) = mul R A := #align algebra.coe_lmul_eq_mul Algebra.coe_lmul_eq_mul theorem _root_.Algebra.lmul_injective : Function.Injective (Algebra.lmul R A) := - fun a₁ a₂ h ↦ by simpa using FunLike.congr_fun h 1 + fun a₁ a₂ h ↦ by simpa using DFunLike.congr_fun h 1 + +theorem _root_.Algebra.lmul_isUnit_iff {x : A} : + IsUnit (Algebra.lmul R A x) ↔ IsUnit x := by + rw [Module.End_isUnit_iff, Iff.comm] + exact IsUnit.isUnit_iff_mulLeft_bijective @[simp] theorem mulLeft_eq_zero_iff (a : A) : mulLeft R a = 0 ↔ a = 0 := by diff --git a/Mathlib/Algebra/Algebra/Equiv.lean b/Mathlib/Algebra/Algebra/Equiv.lean index b4f4504c49961..14934fb09187d 100644 --- a/Mathlib/Algebra/Algebra/Equiv.lean +++ b/Mathlib/Algebra/Algebra/Equiv.lean @@ -61,7 +61,7 @@ instance (priority := 100) toAlgHomClass (F R A B : Type*) [CommSemiring R] [Sem AlgHomClass F R A B := { h with coe := (⇑) - coe_injective' := FunLike.coe_injective + coe_injective' := DFunLike.coe_injective map_zero := map_zero map_one := map_one } #align alg_equiv_class.to_alg_hom_class AlgEquivClass.toAlgHomClass @@ -130,7 +130,7 @@ instance : EquivLike (A₁ ≃ₐ[R] A₂) A₁ A₂ where obtain ⟨⟨g,_⟩,_⟩ := g congr --- Porting note: the default simps projection was `e.toEquiv.toFun`, it should be `FunLike.coe` +-- Porting note: the default simps projection was `e.toEquiv.toFun`, it should be `DFunLike.coe` /-- See Note [custom simps projection] -/ def Simps.apply (e : A₁ ≃ₐ[R] A₂) : A₁ → A₂ := e @@ -149,23 +149,23 @@ protected theorem coe_coe {F : Type*} [AlgEquivClass F R A₁ A₂] (f : F) : @[ext] theorem ext {f g : A₁ ≃ₐ[R] A₂} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align alg_equiv.ext AlgEquiv.ext protected theorem congr_arg {f : A₁ ≃ₐ[R] A₂} {x x' : A₁} : x = x' → f x = f x' := - FunLike.congr_arg f + DFunLike.congr_arg f #align alg_equiv.congr_arg AlgEquiv.congr_arg protected theorem congr_fun {f g : A₁ ≃ₐ[R] A₂} (h : f = g) (x : A₁) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align alg_equiv.congr_fun AlgEquiv.congr_fun protected theorem ext_iff {f g : A₁ ≃ₐ[R] A₂} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align alg_equiv.ext_iff AlgEquiv.ext_iff theorem coe_fun_injective : @Function.Injective (A₁ ≃ₐ[R] A₂) (A₁ → A₂) fun e => (e : A₁ → A₂) := - FunLike.coe_injective + DFunLike.coe_injective #align alg_equiv.coe_fun_injective AlgEquiv.coe_fun_injective -- Porting note: Made to CoeOut instance from Coe, not dangerous anymore @@ -270,7 +270,7 @@ theorem toAlgHom_eq_coe : e.toAlgHom = e := #align alg_equiv.to_alg_hom_eq_coe AlgEquiv.toAlgHom_eq_coe @[simp, norm_cast] -theorem coe_algHom : FunLike.coe (e.toAlgHom) = FunLike.coe e := +theorem coe_algHom : DFunLike.coe (e.toAlgHom) = DFunLike.coe e := rfl #align alg_equiv.coe_alg_hom AlgEquiv.coe_algHom diff --git a/Mathlib/Algebra/Algebra/Hom.lean b/Mathlib/Algebra/Algebra/Hom.lean index 3c70be3a6ef74..6e0444e32720b 100644 --- a/Mathlib/Algebra/Algebra/Hom.lean +++ b/Mathlib/Algebra/Algebra/Hom.lean @@ -97,7 +97,7 @@ variable [CommSemiring R] [Semiring A] [Semiring B] [Semiring C] [Semiring D] variable [Algebra R A] [Algebra R B] [Algebra R C] [Algebra R D] --- Porting note: we don't port specialized `CoeFun` instances if there is `FunLike` instead +-- Porting note: we don't port specialized `CoeFun` instances if there is `DFunLike` instead #noalign alg_hom.has_coe_to_fun -- Porting note: This instance is moved. @@ -192,11 +192,11 @@ theorem coe_toAddMonoidHom (f : A →ₐ[R] B) : ⇑(f : A →+ B) = f := variable (φ : A →ₐ[R] B) theorem coe_fn_injective : @Function.Injective (A →ₐ[R] B) (A → B) (↑) := - FunLike.coe_injective + DFunLike.coe_injective #align alg_hom.coe_fn_injective AlgHom.coe_fn_injective theorem coe_fn_inj {φ₁ φ₂ : A →ₐ[R] B} : (φ₁ : A → B) = φ₂ ↔ φ₁ = φ₂ := - FunLike.coe_fn_eq + DFunLike.coe_fn_eq #align alg_hom.coe_fn_inj AlgHom.coe_fn_inj theorem coe_ringHom_injective : Function.Injective ((↑) : (A →ₐ[R] B) → A →+* B) := fun φ₁ φ₂ H => @@ -212,20 +212,20 @@ theorem coe_addMonoidHom_injective : Function.Injective ((↑) : (A →ₐ[R] B) #align alg_hom.coe_add_monoid_hom_injective AlgHom.coe_addMonoidHom_injective protected theorem congr_fun {φ₁ φ₂ : A →ₐ[R] B} (H : φ₁ = φ₂) (x : A) : φ₁ x = φ₂ x := - FunLike.congr_fun H x + DFunLike.congr_fun H x #align alg_hom.congr_fun AlgHom.congr_fun protected theorem congr_arg (φ : A →ₐ[R] B) {x y : A} (h : x = y) : φ x = φ y := - FunLike.congr_arg φ h + DFunLike.congr_arg φ h #align alg_hom.congr_arg AlgHom.congr_arg @[ext] theorem ext {φ₁ φ₂ : A →ₐ[R] B} (H : ∀ x, φ₁ x = φ₂ x) : φ₁ = φ₂ := - FunLike.ext _ _ H + DFunLike.ext _ _ H #align alg_hom.ext AlgHom.ext theorem ext_iff {φ₁ φ₂ : A →ₐ[R] B} : φ₁ = φ₂ ↔ ∀ x, φ₁ x = φ₂ x := - FunLike.ext_iff + DFunLike.ext_iff #align alg_hom.ext_iff AlgHom.ext_iff @[simp] @@ -511,7 +511,7 @@ def toIntAlgHom [Ring R] [Ring S] [Algebra ℤ R] [Algebra ℤ S] (f : R →+* S lemma toIntAlgHom_injective [Ring R] [Ring S] [Algebra ℤ R] [Algebra ℤ S] : Function.Injective (RingHom.toIntAlgHom : (R →+* S) → _) := - fun _ _ e ↦ FunLike.ext _ _ (fun x ↦ FunLike.congr_fun e x) + fun _ _ e ↦ DFunLike.ext _ _ (fun x ↦ DFunLike.congr_fun e x) /-- Reinterpret a `RingHom` as a `ℚ`-algebra homomorphism. This actually yields an equivalence, see `RingHom.equivRatAlgHom`. -/ diff --git a/Mathlib/Algebra/Algebra/NonUnitalHom.lean b/Mathlib/Algebra/Algebra/NonUnitalHom.lean index 9e18cdd8c4c60..3fb160150cc76 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalHom.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalHom.lean @@ -119,12 +119,12 @@ variable [NonUnitalNonAssocSemiring B] [DistribMulAction R B] variable [NonUnitalNonAssocSemiring C] [DistribMulAction R C] --- Porting note: Replaced with FunLike instance +-- Porting note: Replaced with DFunLike instance -- /-- see Note [function coercion] -/ -- instance : CoeFun (A →ₙₐ[R] B) fun _ => A → B := -- ⟨toFun⟩ -instance : FunLike (A →ₙₐ[R] B) A fun _ => B where +instance : FunLike (A →ₙₐ[R] B) A B where coe f := f.toFun coe_injective' := by rintro ⟨⟨⟨f, _⟩, _⟩, _⟩ ⟨⟨⟨g, _⟩, _⟩, _⟩ h; congr @@ -217,7 +217,7 @@ theorem to_distribMulActionHom_injective {f g : A →ₙₐ[R] B} theorem to_mulHom_injective {f g : A →ₙₐ[R] B} (h : (f : A →ₙ* B) = (g : A →ₙ* B)) : f = g := by ext a - exact FunLike.congr_fun h a + exact DFunLike.congr_fun h a #align non_unital_alg_hom.to_mul_hom_injective NonUnitalAlgHom.to_mulHom_injective @[norm_cast] diff --git a/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean b/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean index ef4d357684623..2cd81fe6a75e4 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean @@ -5,7 +5,7 @@ Authors: Jireh Loreaux -/ import Mathlib.Algebra.Algebra.NonUnitalHom import Mathlib.Data.Set.UnionLift -import Mathlib.LinearAlgebra.Finsupp +import Mathlib.LinearAlgebra.Span import Mathlib.RingTheory.NonUnitalSubring.Basic /-! @@ -974,7 +974,7 @@ def center : NonUnitalSubalgebra R A := theorem coe_center : (center R A : Set A) = Set.center A := rfl -/-- The center of a non-unital algebra is a commutative and associative -/ +/-- The center of a non-unital algebra is commutative and associative -/ instance center.instNonUnitalCommSemiring : NonUnitalCommSemiring (center R A) := NonUnitalSubsemiring.center.instNonUnitalCommSemiring _ diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index b21a322ed6707..16528e9752c06 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -405,6 +405,21 @@ lemma mul_mem_smul_iff {S} [CommRing S] [Algebra R S] {x : S} {p : Submodule R S x * y ∈ x • p ↔ y ∈ p := show Exists _ ↔ _ by simp [mul_cancel_left_mem_nonZeroDivisors hx] +variable (M N) in +theorem mul_smul_mul_eq_smul_mul_smul (x y : R) : (x * y) • (M * N) = (x • M) * (y • N) := by + ext + refine ⟨?_, fun hx ↦ Submodule.mul_induction_on hx ?_ fun _ _ hx hy ↦ Submodule.add_mem _ hx hy⟩ + · rintro ⟨_, hx, rfl⟩ + rw [DistribMulAction.toLinearMap_apply] + refine Submodule.mul_induction_on hx (fun m hm n hn ↦ ?_) (fun _ _ hn hm ↦ ?_) + · rw [← smul_mul_smul x y m n] + exact mul_mem_mul (smul_mem_pointwise_smul m x M hm) (smul_mem_pointwise_smul n y N hn) + · rw [smul_add] + exact Submodule.add_mem _ hn hm + · rintro _ ⟨m, hm, rfl⟩ _ ⟨n, hn, rfl⟩ + erw [smul_mul_smul x y m n] + exact smul_mem_pointwise_smul _ _ _ (mul_mem_mul hm hn) + /-- Sub-R-modules of an R-algebra form an idempotent semiring. -/ instance idemSemiring : IdemSemiring (Submodule R A) := { toAddSubmonoid_injective.semigroup _ fun m n : Submodule R A => mul_toAddSubmonoid m n, diff --git a/Mathlib/Algebra/Algebra/Prod.lean b/Mathlib/Algebra/Algebra/Prod.lean index 4d498a19d4173..3a4f44aee8065 100644 --- a/Mathlib/Algebra/Algebra/Prod.lean +++ b/Mathlib/Algebra/Algebra/Prod.lean @@ -93,7 +93,7 @@ theorem snd_prod (f : A →ₐ[R] B) (g : A →ₐ[R] C) : (snd R B C).comp (pro @[simp] theorem prod_fst_snd : prod (fst R A B) (snd R A B) = 1 := - FunLike.coe_injective Pi.prod_fst_snd + DFunLike.coe_injective Pi.prod_fst_snd #align alg_hom.prod_fst_snd AlgHom.prod_fst_snd /-- Taking the product of two maps with the same domain is equivalent to taking the product of diff --git a/Mathlib/Algebra/Algebra/RestrictScalars.lean b/Mathlib/Algebra/Algebra/RestrictScalars.lean index 0716caba53603..7a1ee2d14446b 100644 --- a/Mathlib/Algebra/Algebra/RestrictScalars.lean +++ b/Mathlib/Algebra/Algebra/RestrictScalars.lean @@ -125,7 +125,7 @@ The preferred way of setting this up is -/ instance RestrictScalars.opModule [Module Sᵐᵒᵖ M] : Module Rᵐᵒᵖ (RestrictScalars R S M) := letI : Module Sᵐᵒᵖ (RestrictScalars R S M) := ‹Module Sᵐᵒᵖ M› - Module.compHom M (RingHom.op $ algebraMap R S) + Module.compHom M (RingHom.op <| algebraMap R S) #align restrict_scalars.op_module RestrictScalars.opModule instance RestrictScalars.isCentralScalar [Module S M] [Module Sᵐᵒᵖ M] [IsCentralScalar S M] : diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean index 926ec1c367fc0..32b947810285b 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean @@ -360,7 +360,8 @@ section /-! `Subalgebra`s inherit structure from their `Submodule` coercions. -/ -instance module' [Semiring R'] [SMul R' R] [Module R' A] [IsScalarTower R' R A] : Module R' S := +instance (priority := low) module' [Semiring R'] [SMul R' R] [Module R' A] [IsScalarTower R' R A] : + Module R' S := S.toSubmodule.module' #align subalgebra.module' Subalgebra.module' @@ -499,7 +500,7 @@ theorem mem_map {S : Subalgebra R A} {f : A →ₐ[R] B} {y : B} : y ∈ map f S #align subalgebra.mem_map Subalgebra.mem_map theorem map_toSubmodule {S : Subalgebra R A} {f : A →ₐ[R] B} : - (toSubmodule $ S.map f) = S.toSubmodule.map f.toLinearMap := + (toSubmodule <| S.map f) = S.toSubmodule.map f.toLinearMap := SetLike.coe_injective rfl #align subalgebra.map_to_submodule Subalgebra.map_toSubmodule @@ -744,7 +745,7 @@ noncomputable def ofInjectiveField {E F : Type*} [DivisionRing E] [Semiring F] [ #align alg_equiv.of_injective_field AlgEquiv.ofInjectiveField /-- Given an equivalence `e : A ≃ₐ[R] B` of `R`-algebras and a subalgebra `S` of `A`, -`subalgebra_map` is the induced equivalence between `S` and `S.map e` -/ +`subalgebraMap` is the induced equivalence between `S` and `S.map e` -/ @[simps!] def subalgebraMap (e : A ≃ₐ[R] B) (S : Subalgebra R A) : S ≃ₐ[R] S.map (e : A →ₐ[R] B) := { e.toRingEquiv.subsemiringMap S.toSubsemiring with @@ -1099,6 +1100,25 @@ theorem equivOfEq_trans (S T U : Subalgebra R A) (hST : S = T) (hTU : T = U) : (equivOfEq S T hST).trans (equivOfEq T U hTU) = equivOfEq S U (hST.trans hTU) := rfl #align subalgebra.equiv_of_eq_trans Subalgebra.equivOfEq_trans +section equivMapOfInjective + +variable (f : A →ₐ[R] B) + +theorem range_comp_val : (f.comp S.val).range = S.map f := by + rw [AlgHom.range_comp, range_val] + +variable (hf : Function.Injective f) + +/-- A subalgebra is isomorphic to its image under an injective `AlgHom` -/ +noncomputable def equivMapOfInjective : S ≃ₐ[R] S.map f := + (AlgEquiv.ofInjective (f.comp S.val) (hf.comp Subtype.val_injective)).trans + (equivOfEq _ _ (range_comp_val S f)) + +@[simp] +theorem coe_equivMapOfInjective_apply (x : S) : ↑(equivMapOfInjective S f hf x) = f x := rfl + +end equivMapOfInjective + section Prod variable (S₁ : Subalgebra R B) diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Tower.lean b/Mathlib/Algebra/Algebra/Subalgebra/Tower.lean index 8baa168f368e9..c05bf5835b606 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Tower.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Tower.lean @@ -100,7 +100,7 @@ theorem coe_restrictScalars {U : Subalgebra S A} : (restrictScalars R U : Set A) @[simp] theorem restrictScalars_top : restrictScalars R (⊤ : Subalgebra S A) = ⊤ := - SetLike.coe_injective $ by dsimp -- porting note: why does `rfl` not work instead of `by dsimp`? + SetLike.coe_injective <| by dsimp -- porting note: why does `rfl` not work instead of `by dsimp`? #align subalgebra.restrict_scalars_top Subalgebra.restrictScalars_top @[simp] diff --git a/Mathlib/Algebra/Algebra/Tower.lean b/Mathlib/Algebra/Algebra/Tower.lean index dc89d28b24128..895e7aa2ca980 100644 --- a/Mathlib/Algebra/Algebra/Tower.lean +++ b/Mathlib/Algebra/Algebra/Tower.lean @@ -305,39 +305,31 @@ theorem smul_mem_span_smul_of_mem {s : Set S} {t : Set A} {k : S} (hks : k ∈ s fun b c hc => by rw [IsScalarTower.smul_assoc]; exact smul_mem _ _ hc #align submodule.smul_mem_span_smul_of_mem Submodule.smul_mem_span_smul_of_mem -variable [SMulCommClass R S A] - -theorem smul_mem_span_smul {s : Set S} (hs : span R s = ⊤) {t : Set A} {k : S} {x : A} - (hx : x ∈ span R t) : k • x ∈ span R (s • t) := - span_induction hx (fun x hx => smul_mem_span_smul_of_mem (hs.symm ▸ mem_top) hx) - (by rw [smul_zero]; exact zero_mem _) - (fun x y ihx ihy => by rw [smul_add]; exact add_mem ihx ihy) - fun c x hx => smul_comm c k x ▸ smul_mem _ _ hx -#align submodule.smul_mem_span_smul Submodule.smul_mem_span_smul - -theorem smul_mem_span_smul' {s : Set S} (hs : span R s = ⊤) {t : Set A} {k : S} {x : A} - (hx : x ∈ span R (s • t)) : k • x ∈ span R (s • t) := - span_induction hx - (fun x hx => by - let ⟨p, _hp, q, hq, hpq⟩ := Set.mem_smul.1 hx - rw [← hpq, smul_smul] - exact smul_mem_span_smul_of_mem (hs.symm ▸ mem_top) hq) - (by rw [smul_zero]; exact zero_mem _) - (fun x y ihx ihy => by rw [smul_add]; exact add_mem ihx ihy) - fun c x hx => smul_comm c k x ▸ smul_mem _ _ hx -#align submodule.smul_mem_span_smul' Submodule.smul_mem_span_smul' - theorem span_smul_of_span_eq_top {s : Set S} (hs : span R s = ⊤) (t : Set A) : span R (s • t) = (span S t).restrictScalars R := le_antisymm - (span_le.2 fun _x hx => - let ⟨p, _q, _hps, hqt, hpqx⟩ := Set.mem_smul.1 hx - hpqx ▸ (span S t).smul_mem p (subset_span hqt)) - fun _p hp => - span_induction hp (fun x hx => one_smul S x ▸ smul_mem_span_smul hs (subset_span hx)) - (zero_mem _) (fun _ _ => add_mem) fun _k _x hx => smul_mem_span_smul' hs hx + (span_le.2 fun _x ⟨p, _hps, _q, hqt, hpqx⟩ ↦ hpqx ▸ (span S t).smul_mem p (subset_span hqt)) + fun p hp ↦ closure_induction hp (zero_mem _) (fun _ _ ↦ add_mem) fun s0 y hy ↦ by + refine span_induction (hs ▸ mem_top : s0 ∈ span R s) + (fun x hx ↦ subset_span ⟨x, hx, y, hy, rfl⟩) ?_ ?_ ?_ + · rw [zero_smul]; apply zero_mem + · intro _ _; rw [add_smul]; apply add_mem + · intro r s0 hy; rw [IsScalarTower.smul_assoc]; exact smul_mem _ r hy #align submodule.span_smul_of_span_eq_top Submodule.span_smul_of_span_eq_top +-- The following two lemmas were originally used to prove `span_smul_of_span_eq_top` +-- but are now not needed. +theorem smul_mem_span_smul' {s : Set S} (hs : span R s = ⊤) {t : Set A} {k : S} {x : A} + (hx : x ∈ span R (s • t)) : k • x ∈ span R (s • t) := by + rw [span_smul_of_span_eq_top hs] at hx ⊢; exact (span S t).smul_mem k hx +#align submodule.smul_mem_span_smul' Submodule.smul_mem_span_smul' + +theorem smul_mem_span_smul {s : Set S} (hs : span R s = ⊤) {t : Set A} {k : S} {x : A} + (hx : x ∈ span R t) : k • x ∈ span R (s • t) := by + rw [span_smul_of_span_eq_top hs] + exact (span S t).smul_mem k (span_le_restrictScalars R S t hx) +#align submodule.smul_mem_span_smul Submodule.smul_mem_span_smul + end Module section Algebra @@ -353,7 +345,7 @@ theorem span_algebraMap_image (a : Set R) : #align submodule.span_algebra_map_image Submodule.span_algebraMap_image theorem span_algebraMap_image_of_tower {S T : Type*} [CommSemiring S] [Semiring T] [Module R S] - [IsScalarTower R S S] [Algebra R T] [Algebra S T] [IsScalarTower R S T] (a : Set S) : + [Algebra R T] [Algebra S T] [IsScalarTower R S T] (a : Set S) : Submodule.span R (algebraMap S T '' a) = (Submodule.span R a).map ((Algebra.linearMap S T).restrictScalars R) := (Submodule.span_image <| (Algebra.linearMap S T).restrictScalars R).trans rfl diff --git a/Mathlib/Algebra/Algebra/Unitization.lean b/Mathlib/Algebra/Algebra/Unitization.lean index f36570339b4ac..2bd3530201c5d 100644 --- a/Mathlib/Algebra/Algebra/Unitization.lean +++ b/Mathlib/Algebra/Algebra/Unitization.lean @@ -674,7 +674,7 @@ theorem algHom_ext {F : Type*} [AlgHomClass F S (Unitization R A) B] {φ ψ : F} (h : ∀ a : A, φ a = ψ a) (h' : ∀ r, φ (algebraMap R (Unitization R A) r) = ψ (algebraMap R (Unitization R A) r)) : φ = ψ := by - refine FunLike.ext φ ψ (fun x ↦ ?_) + refine DFunLike.ext φ ψ (fun x ↦ ?_) induction x using Unitization.ind simp only [map_add, ← algebraMap_eq_inl, h, h'] #align unitization.alg_hom_ext Unitization.algHom_ext @@ -759,7 +759,7 @@ theorem starAlgHom_ext {φ ψ : Unitization R A →⋆ₐ[R] C} (h : (φ : Unitization R A →⋆ₙₐ[R] C).comp (Unitization.inrNonUnitalStarAlgHom R A) = (ψ : Unitization R A →⋆ₙₐ[R] C).comp (Unitization.inrNonUnitalStarAlgHom R A)) : φ = ψ := - Unitization.algHom_ext'' <| FunLike.congr_fun h + Unitization.algHom_ext'' <| DFunLike.congr_fun h /-- Non-unital star algebra homomorphisms from `A` into a unital star `R`-algebra `C` lift uniquely to `Unitization R A →⋆ₐ[R] C`. This is the universal property of the unitization. -/ diff --git a/Mathlib/Algebra/Associated.lean b/Mathlib/Algebra/Associated.lean index 1c909dcee25d0..5856f136c40e0 100644 --- a/Mathlib/Algebra/Associated.lean +++ b/Mathlib/Algebra/Associated.lean @@ -535,7 +535,7 @@ theorem Associated.mul_right [CommMonoid α] {a b : α} (h : a ~ᵤ b) (c : α) #align associated.mul_right Associated.mul_right theorem Associated.pow_pow [CommMonoid α] {a b : α} {n : ℕ} (h : a ~ᵤ b) : a ^ n ~ᵤ b ^ n := by - induction' n with n ih; + induction' n with n ih · simp [h]; rfl convert h.mul_mul ih <;> rw [pow_succ] #align associated.pow_pow Associated.pow_pow @@ -706,10 +706,6 @@ section UniqueUnits variable [Monoid α] [Unique αˣ] -theorem units_eq_one (u : αˣ) : u = 1 := - Subsingleton.elim u 1 -#align units_eq_one units_eq_one - theorem associated_iff_eq {x y : α} : x ~ᵤ y ↔ x = y := by constructor · rintro ⟨c, rfl⟩ diff --git a/Mathlib/Algebra/BigOperators/Basic.lean b/Mathlib/Algebra/BigOperators/Basic.lean index 5135ec83a96d8..3fe274291f54a 100644 --- a/Mathlib/Algebra/BigOperators/Basic.lean +++ b/Mathlib/Algebra/BigOperators/Basic.lean @@ -5,16 +5,13 @@ Authors: Johannes Hölzl -/ import Mathlib.Algebra.BigOperators.Multiset.Lemmas import Mathlib.Algebra.Function.Indicator -import Mathlib.Algebra.Group.Equiv.Basic -import Mathlib.Algebra.Group.Pi -import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Algebra.Ring.Opposite import Mathlib.Data.Finset.Powerset import Mathlib.Data.Finset.Sigma import Mathlib.Data.Finset.Sum -import Mathlib.Data.Fintype.Basic -import Mathlib.Data.Multiset.Powerset -import Mathlib.Data.Set.Pairwise.Basic +import Mathlib.Data.Fintype.Pi +import Mathlib.Data.Int.Cast.Lemmas +import Mathlib.Data.Set.Image #align_import algebra.big_operators.basic from "leanprover-community/mathlib"@"65a1391a0106c9204fe45bc73a039f056558cb83" @@ -375,12 +372,26 @@ theorem prod_map (s : Finset α) (e : α ↪ γ) (f : γ → β) : #align finset.prod_map Finset.prod_map #align finset.sum_map Finset.sum_map +@[to_additive] +lemma prod_attach (s : Finset α) (f : α → β) : ∏ x in s.attach, f x = ∏ x in s, f x := by + classical rw [← prod_image $ Subtype.coe_injective.injOn _, attach_image_val] +#align finset.prod_attach Finset.prod_attach +#align finset.sum_attach Finset.sum_attach + @[to_additive (attr := congr)] theorem prod_congr (h : s₁ = s₂) : (∀ x ∈ s₂, f x = g x) → s₁.prod f = s₂.prod g := by rw [h]; exact fold_congr #align finset.prod_congr Finset.prod_congr #align finset.sum_congr Finset.sum_congr +@[to_additive] +theorem prod_eq_one {f : α → β} {s : Finset α} (h : ∀ x ∈ s, f x = 1) : ∏ x in s, f x = 1 := + calc + ∏ x in s, f x = ∏ _x in s, 1 := Finset.prod_congr rfl h + _ = 1 := Finset.prod_const_one +#align finset.prod_eq_one Finset.prod_eq_one +#align finset.sum_eq_zero Finset.sum_eq_zero + @[to_additive] theorem prod_disjUnion (h) : ∏ x in s₁.disjUnion s₂ h, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x := by @@ -449,6 +460,40 @@ theorem _root_.Equiv.Perm.prod_comp' (σ : Equiv.Perm α) (s : Finset α) (f : #align equiv.perm.prod_comp' Equiv.Perm.prod_comp' #align equiv.perm.sum_comp' Equiv.Perm.sum_comp' +/-- A product over all subsets of `s ∪ {x}` is obtained by multiplying the product over all subsets +of `s`, and over all subsets of `s` to which one adds `x`. -/ +@[to_additive "A sum over all subsets of `s ∪ {x}` is obtained by summing the sum over all subsets +of `s`, and over all subsets of `s` to which one adds `x`."] +lemma prod_powerset_insert [DecidableEq α] (ha : a ∉ s) (f : Finset α → β) : + ∏ t in (insert a s).powerset, f t = + (∏ t in s.powerset, f t) * ∏ t in s.powerset, f (insert a t) := by + rw [powerset_insert, prod_union, prod_image] + · exact insert_erase_invOn.2.injOn.mono fun t ht ↦ not_mem_mono (mem_powerset.1 ht) ha + · aesop (add simp [disjoint_left, insert_subset_iff]) +#align finset.prod_powerset_insert Finset.prod_powerset_insert +#align finset.sum_powerset_insert Finset.sum_powerset_insert + +/-- A product over all subsets of `s ∪ {x}` is obtained by multiplying the product over all subsets +of `s`, and over all subsets of `s` to which one adds `x`. -/ +@[to_additive "A sum over all subsets of `s ∪ {x}` is obtained by summing the sum over all subsets +of `s`, and over all subsets of `s` to which one adds `x`."] +lemma prod_powerset_cons (ha : a ∉ s) (f : Finset α → β) : + ∏ t in (s.cons a ha).powerset, f t = (∏ t in s.powerset, f t) * + ∏ t in s.powerset.attach, f (cons a t $ not_mem_mono (mem_powerset.1 t.2) ha) := by + classical + simp_rw [cons_eq_insert] + rw [prod_powerset_insert ha, prod_attach _ fun t ↦ f (insert a t)] + +/-- A product over `powerset s` is equal to the double product over sets of subsets of `s` with +`card s = k`, for `k = 1, ..., card s`. -/ +@[to_additive "A sum over `powerset s` is equal to the double sum over sets of subsets of `s` with + `card s = k`, for `k = 1, ..., card s`"] +lemma prod_powerset (s : Finset α) (f : Finset α → β) : + ∏ t in powerset s, f t = ∏ j in range (card s + 1), ∏ t in powersetCard j s, f t := by + rw [powerset_card_disjiUnion, prod_disjiUnion] +#align finset.prod_powerset Finset.prod_powerset +#align finset.sum_powerset Finset.sum_powerset + end CommMonoid end Finset @@ -499,6 +544,22 @@ theorem prod_sdiff [DecidableEq α] (h : s₁ ⊆ s₂) : #align finset.prod_sdiff Finset.prod_sdiff #align finset.sum_sdiff Finset.sum_sdiff +@[to_additive] +theorem prod_subset_one_on_sdiff [DecidableEq α] (h : s₁ ⊆ s₂) (hg : ∀ x ∈ s₂ \ s₁, g x = 1) + (hfg : ∀ x ∈ s₁, f x = g x) : ∏ i in s₁, f i = ∏ i in s₂, g i := by + rw [← prod_sdiff h, prod_eq_one hg, one_mul] + exact prod_congr rfl hfg +#align finset.prod_subset_one_on_sdiff Finset.prod_subset_one_on_sdiff +#align finset.sum_subset_zero_on_sdiff Finset.sum_subset_zero_on_sdiff + +@[to_additive] +theorem prod_subset (h : s₁ ⊆ s₂) (hf : ∀ x ∈ s₂, x ∉ s₁ → f x = 1) : + ∏ x in s₁, f x = ∏ x in s₂, f x := + haveI := Classical.decEq α + prod_subset_one_on_sdiff h (by simpa) fun _ _ => rfl +#align finset.prod_subset Finset.prod_subset +#align finset.sum_subset Finset.sum_subset + @[to_additive (attr := simp)] theorem prod_disj_sum (s : Finset α) (t : Finset γ) (f : Sum α γ → β) : ∏ x in s.disjSum t, f x = (∏ x in s, f (Sum.inl x)) * ∏ x in t, f (Sum.inr x) := by @@ -652,6 +713,14 @@ lemma prod_bijective (e : ι → κ) (he : e.Bijective) (hst : ∀ i, i ∈ s (hfg : ∀ i ∈ s, f i = g (e i)) : ∏ i in s, f i = ∏ i in t, g i := prod_equiv (.ofBijective e he) hst hfg +@[to_additive] +lemma prod_of_injOn (e : ι → κ) (he : Set.InjOn e s) (hest : Set.MapsTo e s t) + (h' : ∀ i ∈ t, i ∉ e '' s → g i = 1) (h : ∀ i ∈ s, f i = g (e i)) : + ∏ i in s, f i = ∏ j in t, g j := by + classical + exact (prod_nbij e (fun a ↦ mem_image_of_mem e) he (by simp [Set.surjOn_image]) h).trans <| + prod_subset (image_subset_iff.2 hest) <| by simpa using h' + variable [DecidableEq κ] @[to_additive] @@ -685,6 +754,21 @@ lemma prod_fiberwise' (s : Finset ι) (g : ι → κ) (f : κ → α) : end bij +/-- Taking a product over `univ.pi t` is the same as taking the product over `Fintype.piFinset t`. +`univ.pi t` and `Fintype.piFinset t` are essentially the same `Finset`, but differ +in the type of their element, `univ.pi t` is a `Finset (Π a ∈ univ, t a)` and +`Fintype.piFinset t` is a `Finset (Π a, t a)`. -/ +@[to_additive "Taking a sum over `univ.pi t` is the same as taking the sum over +`Fintype.piFinset t`. `univ.pi t` and `Fintype.piFinset t` are essentially the same `Finset`, +but differ in the type of their element, `univ.pi t` is a `Finset (Π a ∈ univ, t a)` and +`Fintype.piFinset t` is a `Finset (Π a, t a)`."] +lemma prod_univ_pi [DecidableEq ι] [Fintype ι] {κ : ι → Type*} (t : ∀ i, Finset (κ i)) + (f : (∀ i ∈ (univ : Finset ι), κ i) → β) : + ∏ x in univ.pi t, f x = ∏ x in Fintype.piFinset t, f fun a _ ↦ x a := by + apply prod_nbij' (fun x i ↦ x i $ mem_univ _) (fun x i _ ↦ x i) <;> simp +#align finset.prod_univ_pi Finset.prod_univ_pi +#align finset.sum_univ_pi Finset.sum_univ_pi + @[to_additive (attr := simp)] lemma prod_diag [DecidableEq α] (s : Finset α) (f : α × α → β) : ∏ i in s.diag, f i = ∏ i in s, f (i, i) := by @@ -813,30 +897,6 @@ theorem prod_hom_rel [CommMonoid γ] {r : β → γ → Prop} {f : α → β} {g #align finset.prod_hom_rel Finset.prod_hom_rel #align finset.sum_hom_rel Finset.sum_hom_rel -@[to_additive] -theorem prod_eq_one {f : α → β} {s : Finset α} (h : ∀ x ∈ s, f x = 1) : ∏ x in s, f x = 1 := - calc - ∏ x in s, f x = ∏ _x in s, 1 := Finset.prod_congr rfl h - _ = 1 := Finset.prod_const_one -#align finset.prod_eq_one Finset.prod_eq_one -#align finset.sum_eq_zero Finset.sum_eq_zero - -@[to_additive] -theorem prod_subset_one_on_sdiff [DecidableEq α] (h : s₁ ⊆ s₂) (hg : ∀ x ∈ s₂ \ s₁, g x = 1) - (hfg : ∀ x ∈ s₁, f x = g x) : ∏ i in s₁, f i = ∏ i in s₂, g i := by - rw [← prod_sdiff h, prod_eq_one hg, one_mul] - exact prod_congr rfl hfg -#align finset.prod_subset_one_on_sdiff Finset.prod_subset_one_on_sdiff -#align finset.sum_subset_zero_on_sdiff Finset.sum_subset_zero_on_sdiff - -@[to_additive] -theorem prod_subset (h : s₁ ⊆ s₂) (hf : ∀ x ∈ s₂, x ∉ s₁ → f x = 1) : - ∏ x in s₁, f x = ∏ x in s₂, f x := - haveI := Classical.decEq α - prod_subset_one_on_sdiff h (by simpa) fun _ _ => rfl -#align finset.prod_subset Finset.prod_subset -#align finset.sum_subset Finset.sum_subset - @[to_additive] theorem prod_filter_of_ne {p : α → Prop} [DecidablePred p] (hp : ∀ x ∈ s, f x ≠ 1 → p x) : ∏ x in s.filter p, f x = ∏ x in s, f x := @@ -896,7 +956,7 @@ theorem prod_eq_single {s : Finset α} {f : α → β} (a : α) (h₀ : ∀ b @[to_additive] lemma prod_union_eq_left [DecidableEq α] (hs : ∀ a ∈ s₂, a ∉ s₁ → f a = 1) : ∏ a in s₁ ∪ s₂, f a = ∏ a in s₁, f a := - Eq.symm $ + Eq.symm <| prod_subset (subset_union_left _ _) fun _a ha ha' ↦ hs _ ((mem_union.1 ha).resolve_left ha') ha' @[to_additive] @@ -946,16 +1006,6 @@ theorem prod_eq_mul {s : Finset α} {f : α → β} (a b : α) (hn : a ≠ b) #align finset.prod_eq_mul Finset.prod_eq_mul #align finset.sum_eq_add Finset.sum_eq_add -@[to_additive] -theorem prod_attach (s : Finset α) (f : α → β) : ∏ x in s.attach, f x = ∏ x in s, f x := - haveI := Classical.decEq α - calc - ∏ x in s.attach, f x.val = ∏ x in s.attach.image Subtype.val, f x := by - { rw [prod_image]; exact fun x _ y _ => Subtype.eq } - _ = _ := by rw [attach_image_val] -#align finset.prod_attach Finset.prod_attach -#align finset.sum_attach Finset.sum_attach - -- Porting note: simpNF linter complains that LHS doesn't simplify, but it does /-- A product over `s.subtype p` equals one over `s.filter p`. -/ @[to_additive (attr := simp, nolint simpNF) @@ -1050,21 +1100,21 @@ theorem prod_congr_set {α : Type*} [CommMonoid α] {β : Type*} [Fintype β] (s theorem prod_apply_dite {s : Finset α} {p : α → Prop} {hp : DecidablePred p} [DecidablePred fun x => ¬p x] (f : ∀ x : α, p x → γ) (g : ∀ x : α, ¬p x → γ) (h : γ → β) : (∏ x in s, h (if hx : p x then f x hx else g x hx)) = - (∏ x in (s.filter p).attach, h (f x.1 $ by simpa using (mem_filter.mp x.2).2)) * - ∏ x in (s.filter fun x => ¬p x).attach, h (g x.1 $ by simpa using (mem_filter.mp x.2).2) := + (∏ x in (s.filter p).attach, h (f x.1 <| by simpa using (mem_filter.mp x.2).2)) * + ∏ x in (s.filter fun x => ¬p x).attach, h (g x.1 <| by simpa using (mem_filter.mp x.2).2) := calc (∏ x in s, h (if hx : p x then f x hx else g x hx)) = (∏ x in s.filter p, h (if hx : p x then f x hx else g x hx)) * - ∏ x in s.filter fun x => ¬p x, h (if hx : p x then f x hx else g x hx) := + ∏ x in s.filter (¬p ·), h (if hx : p x then f x hx else g x hx) := (prod_filter_mul_prod_filter_not s p _).symm _ = (∏ x in (s.filter p).attach, h (if hx : p x.1 then f x.1 hx else g x.1 hx)) * - ∏ x in (s.filter fun x => ¬p x).attach, h (if hx : p x.1 then f x.1 hx else g x.1 hx) := + ∏ x in (s.filter (¬p ·)).attach, h (if hx : p x.1 then f x.1 hx else g x.1 hx) := congr_arg₂ _ (prod_attach _ _).symm (prod_attach _ _).symm - _ = (∏ x in (s.filter p).attach, h (f x.1 $ by simpa using (mem_filter.mp x.2).2)) * - ∏ x in (s.filter fun x ↦ ¬p x).attach, h (g x.1 $ by simpa using (mem_filter.mp x.2).2) := + _ = (∏ x in (s.filter p).attach, h (f x.1 <| by simpa using (mem_filter.mp x.2).2)) * + ∏ x in (s.filter (¬p ·)).attach, h (g x.1 <| by simpa using (mem_filter.mp x.2).2) := congr_arg₂ _ (prod_congr rfl fun x _hx ↦ - congr_arg h (dif_pos $ by simpa using (mem_filter.mp x.2).2)) - (prod_congr rfl fun x _hx => congr_arg h (dif_neg $ by simpa using (mem_filter.mp x.2).2)) + congr_arg h (dif_pos <| by simpa using (mem_filter.mp x.2).2)) + (prod_congr rfl fun x _hx => congr_arg h (dif_neg <| by simpa using (mem_filter.mp x.2).2)) #align finset.prod_apply_dite Finset.prod_apply_dite #align finset.sum_apply_dite Finset.sum_apply_dite @@ -1073,7 +1123,7 @@ theorem prod_apply_ite {s : Finset α} {p : α → Prop} {_hp : DecidablePred p} (h : γ → β) : (∏ x in s, h (if p x then f x else g x)) = (∏ x in s.filter p, h (f x)) * ∏ x in s.filter fun x => ¬p x, h (g x) := - (prod_apply_dite _ _ _).trans $ congr_arg₂ _ (prod_attach _ (h ∘ f)) (prod_attach _ (h ∘ g)) + (prod_apply_dite _ _ _).trans <| congr_arg₂ _ (prod_attach _ (h ∘ f)) (prod_attach _ (h ∘ g)) #align finset.prod_apply_ite Finset.prod_apply_ite #align finset.sum_apply_ite Finset.sum_apply_ite @@ -1261,7 +1311,7 @@ lemma prod_mulIndicator_subset_of_eq_one [One α] (f : ι → α) (g : ι → α calc _ = ∏ i in s, g i (mulIndicator ↑s f i) := by rw [prod_subset h fun i _ hn ↦ by simp [hn, hg]] -- Porting note: This did not use to need the implicit argument - _ = _ := prod_congr rfl fun i hi ↦ congr_arg _ $ mulIndicator_of_mem (α := ι) hi f + _ = _ := prod_congr rfl fun i hi ↦ congr_arg _ <| mulIndicator_of_mem (α := ι) hi f #align set.prod_mul_indicator_subset_of_eq_one Finset.prod_mulIndicator_subset_of_eq_one #align set.sum_indicator_subset_of_eq_zero Finset.sum_indicator_subset_of_eq_zero @@ -1279,7 +1329,7 @@ lemma prod_mulIndicator_subset (f : ι → β) {s t : Finset ι} (h : s ⊆ t) : lemma prod_mulIndicator_eq_prod_filter (s : Finset ι) (f : ι → κ → β) (t : ι → Set κ) (g : ι → κ) [DecidablePred fun i ↦ g i ∈ t i] : ∏ i in s, mulIndicator (t i) (f i) (g i) = ∏ i in s.filter fun i ↦ g i ∈ t i, f i (g i) := by - refine (prod_filter_mul_prod_filter_not s (fun i ↦ g i ∈ t i) _).symm.trans $ + refine (prod_filter_mul_prod_filter_not s (fun i ↦ g i ∈ t i) _).symm.trans <| Eq.trans (congr_arg₂ (· * ·) ?_ ?_) (mul_one _) · exact prod_congr rfl fun x hx ↦ mulIndicator_of_mem (mem_filter.1 hx).2 _ · exact prod_eq_one fun x hx ↦ mulIndicator_of_not_mem (mem_filter.1 hx).2 _ @@ -1306,9 +1356,9 @@ lemma mulIndicator_biUnion (s : Finset ι) (t : ι → Set κ) {f : κ → β} : classical refine Finset.induction_on s (by simp) fun i s hi ih hs ↦ funext fun j ↦ ?_ rw [prod_insert hi, set_biUnion_insert, mulIndicator_union_of_not_mem_inter, - ih (hs.subset $ subset_insert _ _)] + ih (hs.subset <| subset_insert _ _)] simp only [not_exists, exists_prop, mem_iUnion, mem_inter_iff, not_and] - exact fun hji i' hi' hji' ↦ (ne_of_mem_of_not_mem hi' hi).symm $ + exact fun hji i' hi' hji' ↦ (ne_of_mem_of_not_mem hi' hi).symm <| hs.elim_set (mem_insert_self _ _) (mem_insert_of_mem hi') _ hji hji' #align set.mul_indicator_finset_bUnion Finset.mulIndicator_biUnion #align set.indicator_finset_bUnion Finset.indicator_biUnion @@ -1333,7 +1383,7 @@ theorem prod_bij_ne_one {s : Finset α} {t : Finset γ} {f : α → β} {g : γ calc ∏ x in s, f x = ∏ x in s.filter fun x => f x ≠ 1, f x := by rw [prod_filter_ne_one] _ = ∏ x in t.filter fun x => g x ≠ 1, g x := - prod_bij (fun a ha => i a (mem_filter.mp ha).1 $ by simpa using (mem_filter.mp ha).2) + prod_bij (fun a ha => i a (mem_filter.mp ha).1 <| by simpa using (mem_filter.mp ha).2) ?_ ?_ ?_ ?_ _ = ∏ x in t, g x := prod_filter_ne_one _ · intros a ha @@ -1642,6 +1692,12 @@ theorem prod_pow (s : Finset α) (n : ℕ) (f : α → β) : ∏ x in s, f x ^ n #align finset.prod_pow Finset.prod_pow #align finset.sum_nsmul Finset.sum_nsmul +@[to_additive sum_nsmul_assoc] +lemma prod_pow_eq_pow_sum (s : Finset ι) (f : ι → ℕ) (a : β) : + ∏ i in s, a ^ f i = a ^ ∑ i in s, f i := + cons_induction (by simp) (fun _ _ _ _ ↦ by simp [prod_cons, sum_cons, pow_add, *]) s +#align finset.prod_pow_eq_pow_sum Finset.prod_pow_eq_pow_sum + /-- A product over `Finset.powersetCard` which only depends on the size of the sets is constant. -/ @[to_additive "A sum over `Finset.powersetCard` which only depends on the size of the sets is constant."] @@ -1864,7 +1920,7 @@ theorem prod_ite_one (s : Finset α) (p : α → Prop) [DecidablePred p] split_ifs with h · obtain ⟨i, hi, hpi⟩ := h rw [prod_eq_single_of_mem _ hi, if_pos hpi] - exact fun j hj hji ↦ if_neg fun hpj ↦ hji $ h _ hj _ hi hpj hpi + exact fun j hj hji ↦ if_neg fun hpj ↦ hji <| h _ hj _ hi hpj hpi · push_neg at h rw [prod_eq_one] exact fun i hi => if_neg (h i hi) @@ -1909,8 +1965,8 @@ theorem prod_dvd_prod_of_dvd {S : Finset α} (g1 g2 : α → β) (h : ∀ a ∈ classical induction' S using Finset.induction_on' with a T _haS _hTS haT IH · simp - rw [Finset.prod_insert haT, Finset.prod_insert haT] - exact mul_dvd_mul (h a $ T.mem_insert_self a) (IH fun b hb ↦ h b $ Finset.mem_insert_of_mem hb) + · rw [Finset.prod_insert haT, prod_insert haT] + exact mul_dvd_mul (h a <| T.mem_insert_self a) <| IH fun b hb ↦ h b <| mem_insert_of_mem hb #align finset.prod_dvd_prod_of_dvd Finset.prod_dvd_prod_of_dvd theorem prod_dvd_prod_of_subset {ι M : Type*} [CommMonoid M] (s t : Finset ι) (f : ι → M) @@ -2109,7 +2165,7 @@ theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] : lemma support_prod_subset (s : Finset ι) (f : ι → α → β) : support (fun x ↦ ∏ i in s, f i x) ⊆ ⋂ i ∈ s, support (f i) := - fun _ hx ↦ Set.mem_iInter₂.2 fun _ hi H ↦ hx $ prod_eq_zero hi H + fun _ hx ↦ Set.mem_iInter₂.2 fun _ hi H ↦ hx <| prod_eq_zero hi H #align function.support_prod_subset Finset.support_prod_subset variable [Nontrivial β] [NoZeroDivisors β] @@ -2208,6 +2264,11 @@ lemma _root_.Equiv.prod_comp (e : ι ≃ κ) (g : κ → α) : ∏ i, g (e i) = #align equiv.prod_comp Equiv.prod_comp #align equiv.sum_comp Equiv.sum_comp +@[to_additive] +lemma prod_of_injective (e : ι → κ) (hf : Injective e) (f : ι → α) (g : κ → α) + (h' : ∀ i ∉ Set.range e, g i = 1) (h : ∀ i, f i = g (e i)) : ∏ i, f i = ∏ j, g j := + prod_of_injOn e (hf.injOn _) (by simp) (by simpa using h') (fun i _ ↦ h i) + @[to_additive] lemma prod_fiberwise [DecidableEq κ] [Fintype ι] (g : ι → κ) (f : ι → α) : ∏ j, ∏ i : {i // g i = j}, f i = ∏ i, f i := by @@ -2260,6 +2321,18 @@ theorem prod_subtype_mul_prod_subtype {α β : Type*} [Fintype α] [CommMonoid end Fintype +namespace Finset +variable [Fintype ι] [CommMonoid α] + +@[to_additive (attr := simp)] +lemma prod_attach_univ (f : {i // i ∈ @univ ι _} → α) : + ∏ i in univ.attach, f i = ∏ i, f ⟨i, mem_univ _⟩ := + Fintype.prod_equiv (Equiv.subtypeUnivEquiv mem_univ) _ _ $ by simp +#align finset.prod_attach_univ Finset.prod_attach_univ +#align finset.sum_attach_univ Finset.sum_attach_univ + +end Finset + namespace List @[to_additive] diff --git a/Mathlib/Algebra/BigOperators/Fin.lean b/Mathlib/Algebra/BigOperators/Fin.lean index 8b922c04e0418..67978eeb1880b 100644 --- a/Mathlib/Algebra/BigOperators/Fin.lean +++ b/Mathlib/Algebra/BigOperators/Fin.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Fintype.BigOperators import Mathlib.Data.Fintype.Fin import Mathlib.Data.List.FinRange import Mathlib.Logic.Equiv.Fin +import Mathlib.Algebra.BigOperators.Ring #align_import algebra.big_operators.fin from "leanprover-community/mathlib"@"cc5dd6244981976cc9da7afc4eee5682b037a013" @@ -230,7 +231,7 @@ theorem partialProd_zero (f : Fin n → α) : partialProd f 0 = 1 := by simp [pa @[to_additive] theorem partialProd_succ (f : Fin n → α) (j : Fin n) : partialProd f j.succ = partialProd f (Fin.castSucc j) * f j := by - simp [partialProd, List.take_succ, List.ofFnNthVal, dif_pos j.is_lt, ← Option.coe_def] + simp [partialProd, List.take_succ, List.ofFnNthVal, dif_pos j.is_lt] #align fin.partial_prod_succ Fin.partialProd_succ #align fin.partial_sum_succ Fin.partialSum_succ @@ -417,7 +418,7 @@ def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ /- refine' Eq.trans _ (ih (a / x) (Nat.div_lt_of_lt_mul <| a.is_lt.trans_eq _)) swap - · convert Fin.prod_univ_succ (Fin.cons x xs : ∀ _, ℕ) + · convert Fin.prod_univ_succ (Fin.cons x xs : _ → ℕ) simp_rw [Fin.cons_succ] congr with i congr with j diff --git a/Mathlib/Algebra/BigOperators/Finsupp.lean b/Mathlib/Algebra/BigOperators/Finsupp.lean index 6abd5300cd09d..e0903fc7b93d5 100644 --- a/Mathlib/Algebra/BigOperators/Finsupp.lean +++ b/Mathlib/Algebra/BigOperators/Finsupp.lean @@ -480,7 +480,7 @@ theorem liftAddHom_singleAddHom [AddCommMonoid M] : @[simp] theorem sum_single [AddCommMonoid M] (f : α →₀ M) : f.sum single = f := - FunLike.congr_fun liftAddHom_singleAddHom f + DFunLike.congr_fun liftAddHom_singleAddHom f #align finsupp.sum_single Finsupp.sum_single /-- The `Finsupp` version of `Finset.univ_sum_single` -/ @@ -488,7 +488,7 @@ theorem sum_single [AddCommMonoid M] (f : α →₀ M) : f.sum single = f := theorem univ_sum_single [Fintype α] [AddCommMonoid M] (f : α →₀ M) : ∑ a : α, single a (f a) = f := by classical - refine FunLike.coe_injective ?_ + refine DFunLike.coe_injective ?_ simp_rw [coe_finset_sum, single_eq_pi_single, Finset.univ_sum_single] @[simp] diff --git a/Mathlib/Algebra/BigOperators/Intervals.lean b/Mathlib/Algebra/BigOperators/Intervals.lean index 7568f0062b5df..7950703d58253 100644 --- a/Mathlib/Algebra/BigOperators/Intervals.lean +++ b/Mathlib/Algebra/BigOperators/Intervals.lean @@ -13,26 +13,72 @@ import Mathlib.Tactic.Linarith /-! # Results about big operators over intervals -We prove results about big operators over intervals (mostly the `ℕ`-valued `Ico m n`). +We prove results about big operators over intervals. -/ - -universe u v w - -open BigOperators open Nat +open scoped BigOperators + +variable {α M : Type*} namespace Finset +section PartialOrder +variable [PartialOrder α] [CommMonoid M] {f : α → M} {a b : α} -section Generic +section LocallyFiniteOrder +variable [LocallyFiniteOrder α] + +@[to_additive] +lemma mul_prod_Ico_eq_prod_Icc (h : a ≤ b) : f b * ∏ x in Ico a b, f x = ∏ x in Icc a b, f x := by + rw [Icc_eq_cons_Ico h, prod_cons] + +@[to_additive] +lemma prod_Ico_mul_eq_prod_Icc (h : a ≤ b) : (∏ x in Ico a b, f x) * f b = ∏ x in Icc a b, f x := by + rw [mul_comm, mul_prod_Ico_eq_prod_Icc h] + +@[to_additive] +lemma mul_prod_Ioc_eq_prod_Icc (h : a ≤ b) : f a * ∏ x in Ioc a b, f x = ∏ x in Icc a b, f x := by + rw [Icc_eq_cons_Ioc h, prod_cons] + +@[to_additive] +lemma prod_Ioc_mul_eq_prod_Icc (h : a ≤ b) : (∏ x in Ioc a b, f x) * f a = ∏ x in Icc a b, f x := by + rw [mul_comm, mul_prod_Ioc_eq_prod_Icc h] + +end LocallyFiniteOrder -variable {α : Type u} {β : Type v} {γ : Type w} {s₂ s₁ s : Finset α} {a : α} {g f : α → β} +section LocallyFiniteOrderTop +variable [LocallyFiniteOrderTop α] -variable [CommMonoid β] +@[to_additive] +lemma mul_prod_Ioi_eq_prod_Ici (a : α) : f a * ∏ x in Ioi a, f x = ∏ x in Ici a, f x := by + rw [Ici_eq_cons_Ioi, prod_cons] + +@[to_additive] +lemma prod_Ioi_mul_eq_prod_Ici (a : α) : (∏ x in Ioi a, f x) * f a = ∏ x in Ici a, f x := by + rw [mul_comm, mul_prod_Ioi_eq_prod_Ici] + +end LocallyFiniteOrderTop + +section LocallyFiniteOrderBot +variable [LocallyFiniteOrderBot α] + +@[to_additive] +lemma mul_prod_Iio_eq_prod_Iic (a : α) : f a * ∏ x in Iio a, f x = ∏ x in Iic a, f x := by + rw [Iic_eq_cons_Iio, prod_cons] + +@[to_additive] +lemma prod_Iio_mul_eq_prod_Iic (a : α) : (∏ x in Iio a, f x) * f a = ∏ x in Iic a, f x := by + rw [mul_comm, mul_prod_Iio_eq_prod_Iic] + +end LocallyFiniteOrderBot +end PartialOrder + +section Generic +variable [CommMonoid M] {s₂ s₁ s : Finset α} {a : α} {g f : α → M} @[to_additive] theorem prod_Ico_add' [OrderedCancelAddCommMonoid α] [ExistsAddOfLE α] [LocallyFiniteOrder α] - (f : α → β) (a b c : α) : (∏ x in Ico a b, f (x + c)) = ∏ x in Ico (a + c) (b + c), f x := by + (f : α → M) (a b c : α) : (∏ x in Ico a b, f (x + c)) = ∏ x in Ico (a + c) (b + c), f x := by rw [← map_add_right_Ico, prod_map] rfl #align finset.prod_Ico_add' Finset.prod_Ico_add' @@ -40,21 +86,21 @@ theorem prod_Ico_add' [OrderedCancelAddCommMonoid α] [ExistsAddOfLE α] [Locall @[to_additive] theorem prod_Ico_add [OrderedCancelAddCommMonoid α] [ExistsAddOfLE α] [LocallyFiniteOrder α] - (f : α → β) (a b c : α) : (∏ x in Ico a b, f (c + x)) = ∏ x in Ico (a + c) (b + c), f x := by + (f : α → M) (a b c : α) : (∏ x in Ico a b, f (c + x)) = ∏ x in Ico (a + c) (b + c), f x := by convert prod_Ico_add' f a b c using 2 rw [add_comm] #align finset.prod_Ico_add Finset.prod_Ico_add #align finset.sum_Ico_add Finset.sum_Ico_add @[to_additive] -theorem prod_Ico_succ_top {a b : ℕ} (hab : a ≤ b) (f : ℕ → β) : +theorem prod_Ico_succ_top {a b : ℕ} (hab : a ≤ b) (f : ℕ → M) : (∏ k in Ico a (b + 1), f k) = (∏ k in Ico a b, f k) * f b := by rw [Nat.Ico_succ_right_eq_insert_Ico hab, prod_insert right_not_mem_Ico, mul_comm] #align finset.prod_Ico_succ_top Finset.prod_Ico_succ_top #align finset.sum_Ico_succ_top Finset.sum_Ico_succ_top @[to_additive] -theorem prod_eq_prod_Ico_succ_bot {a b : ℕ} (hab : a < b) (f : ℕ → β) : +theorem prod_eq_prod_Ico_succ_bot {a b : ℕ} (hab : a < b) (f : ℕ → M) : ∏ k in Ico a b, f k = f a * ∏ k in Ico (a + 1) b, f k := by have ha : a ∉ Ico (a + 1) b := by simp rw [← prod_insert ha, Nat.Ico_insert_succ_left hab] @@ -62,14 +108,14 @@ theorem prod_eq_prod_Ico_succ_bot {a b : ℕ} (hab : a < b) (f : ℕ → β) : #align finset.sum_eq_sum_Ico_succ_bot Finset.sum_eq_sum_Ico_succ_bot @[to_additive] -theorem prod_Ico_consecutive (f : ℕ → β) {m n k : ℕ} (hmn : m ≤ n) (hnk : n ≤ k) : +theorem prod_Ico_consecutive (f : ℕ → M) {m n k : ℕ} (hmn : m ≤ n) (hnk : n ≤ k) : ((∏ i in Ico m n, f i) * ∏ i in Ico n k, f i) = ∏ i in Ico m k, f i := Ico_union_Ico_eq_Ico hmn hnk ▸ Eq.symm (prod_union (Ico_disjoint_Ico_consecutive m n k)) #align finset.prod_Ico_consecutive Finset.prod_Ico_consecutive #align finset.sum_Ico_consecutive Finset.sum_Ico_consecutive @[to_additive] -theorem prod_Ioc_consecutive (f : ℕ → β) {m n k : ℕ} (hmn : m ≤ n) (hnk : n ≤ k) : +theorem prod_Ioc_consecutive (f : ℕ → M) {m n k : ℕ} (hmn : m ≤ n) (hnk : n ≤ k) : ((∏ i in Ioc m n, f i) * ∏ i in Ioc n k, f i) = ∏ i in Ioc m k, f i := by rw [← Ioc_union_Ioc_eq_Ioc hmn hnk, prod_union] apply disjoint_left.2 fun x hx h'x => _ @@ -79,14 +125,14 @@ theorem prod_Ioc_consecutive (f : ℕ → β) {m n k : ℕ} (hmn : m ≤ n) (hnk #align finset.sum_Ioc_consecutive Finset.sum_Ioc_consecutive @[to_additive] -theorem prod_Ioc_succ_top {a b : ℕ} (hab : a ≤ b) (f : ℕ → β) : +theorem prod_Ioc_succ_top {a b : ℕ} (hab : a ≤ b) (f : ℕ → M) : (∏ k in Ioc a (b + 1), f k) = (∏ k in Ioc a b, f k) * f (b + 1) := by rw [← prod_Ioc_consecutive _ hab (Nat.le_succ b), Nat.Ioc_succ_singleton, prod_singleton] #align finset.prod_Ioc_succ_top Finset.prod_Ioc_succ_top #align finset.sum_Ioc_succ_top Finset.sum_Ioc_succ_top @[to_additive] -theorem prod_range_mul_prod_Ico (f : ℕ → β) {m n : ℕ} (h : m ≤ n) : +theorem prod_range_mul_prod_Ico (f : ℕ → M) {m n : ℕ} (h : m ≤ n) : ((∏ k in range m, f k) * ∏ k in Ico m n, f k) = ∏ k in range n, f k := Nat.Ico_zero_eq_range ▸ Nat.Ico_zero_eq_range ▸ prod_Ico_consecutive f m.zero_le h #align finset.prod_range_mul_prod_Ico Finset.prod_range_mul_prod_Ico @@ -132,7 +178,7 @@ theorem sum_Ico_Ico_comm {M : Type*} [AddCommMonoid M] (a b : ℕ) (f : ℕ → #align finset.sum_Ico_Ico_comm Finset.sum_Ico_Ico_comm @[to_additive] -theorem prod_Ico_eq_prod_range (f : ℕ → β) (m n : ℕ) : +theorem prod_Ico_eq_prod_range (f : ℕ → M) (m n : ℕ) : ∏ k in Ico m n, f k = ∏ k in range (n - m), f (m + k) := by by_cases h : m ≤ n · rw [← Nat.Ico_zero_eq_range, prod_Ico_add, zero_add, tsub_add_cancel_of_le h] @@ -141,7 +187,7 @@ theorem prod_Ico_eq_prod_range (f : ℕ → β) (m n : ℕ) : #align finset.prod_Ico_eq_prod_range Finset.prod_Ico_eq_prod_range #align finset.sum_Ico_eq_sum_range Finset.sum_Ico_eq_sum_range -theorem prod_Ico_reflect (f : ℕ → β) (k : ℕ) {m n : ℕ} (h : m ≤ n + 1) : +theorem prod_Ico_reflect (f : ℕ → M) (k : ℕ) {m n : ℕ} (h : m ≤ n + 1) : (∏ j in Ico k m, f (n - j)) = ∏ j in Ico (n + 1 - m) (n + 1 - k), f j := by have : ∀ i < m, i ≤ n := by intro i hi @@ -164,7 +210,7 @@ theorem sum_Ico_reflect {δ : Type*} [AddCommMonoid δ] (f : ℕ → δ) (k : @prod_Ico_reflect (Multiplicative δ) _ f k m n h #align finset.sum_Ico_reflect Finset.sum_Ico_reflect -theorem prod_range_reflect (f : ℕ → β) (n : ℕ) : +theorem prod_range_reflect (f : ℕ → M) (n : ℕ) : (∏ j in range n, f (n - 1 - j)) = ∏ j in range n, f j := by cases n · simp @@ -216,13 +262,13 @@ end Generic section Nat -variable {β : Type*} +variable {M : Type*} -variable (f g : ℕ → β) {m n : ℕ} +variable (f g : ℕ → M) {m n : ℕ} section Group -variable [CommGroup β] +variable [CommGroup M] @[to_additive] theorem prod_range_succ_div_prod : ((∏ i in range (n + 1), f i) / ∏ i in range n, f i) = f n := diff --git a/Mathlib/Algebra/BigOperators/Multiset/Basic.lean b/Mathlib/Algebra/BigOperators/Multiset/Basic.lean index ac6ac8f1b3d49..29b922f906915 100644 --- a/Mathlib/Algebra/BigOperators/Multiset/Basic.lean +++ b/Mathlib/Algebra/BigOperators/Multiset/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ +import Mathlib.Algebra.Order.Group.Abs import Mathlib.Data.List.BigOperators.Basic import Mathlib.Data.Multiset.Basic diff --git a/Mathlib/Algebra/BigOperators/Order.lean b/Mathlib/Algebra/BigOperators/Order.lean index a6d7806a0c6e2..cb1b71f7a7dc1 100644 --- a/Mathlib/Algebra/BigOperators/Order.lean +++ b/Mathlib/Algebra/BigOperators/Order.lean @@ -690,7 +690,7 @@ variable [LinearOrderedCommSemiring α] [ExistsAddOfLE α] lemma sum_mul_sq_le_sq_mul_sq (s : Finset ι) (f g : ι → α) : (∑ i in s, f i * g i) ^ 2 ≤ (∑ i in s, f i ^ 2) * ∑ i in s, g i ^ 2 := by nontriviality α - obtain h' | h' := (sum_nonneg fun _ _ ↦ sq_nonneg $ g _).eq_or_lt + obtain h' | h' := (sum_nonneg fun _ _ ↦ sq_nonneg <| g _).eq_or_lt · have h'' : ∀ i ∈ s, g i = 0 := fun i hi ↦ by simpa using (sum_eq_zero_iff_of_nonneg fun i _ ↦ sq_nonneg (g i)).1 h'.symm i hi rw [← h', sum_congr rfl (show ∀ i ∈ s, f i * g i = 0 from fun i hi ↦ by simp [h'' i hi])] @@ -753,11 +753,11 @@ lemma one_le_prod (hf : 1 ≤ f) : 1 ≤ ∏ i, f i := Finset.one_le_prod' λ _ @[to_additive] lemma prod_eq_one_iff_of_one_le (hf : 1 ≤ f) : ∏ i, f i = 1 ↔ f = 1 := - (Finset.prod_eq_one_iff_of_one_le' fun i _ ↦ hf i).trans $ by simp [Function.funext_iff] + (Finset.prod_eq_one_iff_of_one_le' fun i _ ↦ hf i).trans <| by simp [Function.funext_iff] @[to_additive] lemma prod_eq_one_iff_of_le_one (hf : f ≤ 1) : ∏ i, f i = 1 ↔ f = 1 := - (Finset.prod_eq_one_iff_of_le_one' fun i _ ↦ hf i).trans $ by simp [Function.funext_iff] + (Finset.prod_eq_one_iff_of_le_one' fun i _ ↦ hf i).trans <| by simp [Function.funext_iff] end OrderedCommMonoid @@ -774,11 +774,11 @@ theorem prod_strictMono' : StrictMono fun f : ι → M ↦ ∏ x, f x := @[to_additive sum_pos] lemma one_lt_prod (hf : 1 < f) : 1 < ∏ i, f i := - Finset.one_lt_prod' (λ _ _ ↦ hf.le _) $ by simpa using (Pi.lt_def.1 hf).2 + Finset.one_lt_prod' (λ _ _ ↦ hf.le _) <| by simpa using (Pi.lt_def.1 hf).2 @[to_additive] lemma prod_lt_one (hf : f < 1) : ∏ i, f i < 1 := - Finset.prod_lt_one' (λ _ _ ↦ hf.le _) $ by simpa using (Pi.lt_def.1 hf).2 + Finset.prod_lt_one' (λ _ _ ↦ hf.le _) <| by simpa using (Pi.lt_def.1 hf).2 @[to_additive sum_pos_iff_of_nonneg] lemma one_lt_prod_iff_of_one_le (hf : 1 ≤ f) : 1 < ∏ i, f i ↔ 1 < f := by diff --git a/Mathlib/Algebra/BigOperators/Pi.lean b/Mathlib/Algebra/BigOperators/Pi.lean index 8818132d24f12..833da3e43b2f0 100644 --- a/Mathlib/Algebra/BigOperators/Pi.lean +++ b/Mathlib/Algebra/BigOperators/Pi.lean @@ -106,7 +106,7 @@ note [partially-applied ext lemmas]. -/ explained in note [partially-applied ext lemmas]."] theorem MonoidHom.functions_ext' [Finite I] (M : Type*) [CommMonoid M] (g h : (∀ i, Z i) →* M) (H : ∀ i, g.comp (MonoidHom.single Z i) = h.comp (MonoidHom.single Z i)) : g = h := - g.functions_ext M h fun i => FunLike.congr_fun (H i) + g.functions_ext M h fun i => DFunLike.congr_fun (H i) #align monoid_hom.functions_ext' MonoidHom.functions_ext' #align add_monoid_hom.functions_ext' AddMonoidHom.functions_ext' diff --git a/Mathlib/Algebra/BigOperators/Ring.lean b/Mathlib/Algebra/BigOperators/Ring.lean index a49c66756c97f..5525f5782fdae 100644 --- a/Mathlib/Algebra/BigOperators/Ring.lean +++ b/Mathlib/Algebra/BigOperators/Ring.lean @@ -5,8 +5,7 @@ Authors: Johannes Hölzl -/ import Mathlib.Algebra.BigOperators.Basic import Mathlib.Algebra.Field.Defs -import Mathlib.Data.Finset.Pi -import Mathlib.Data.Finset.Powerset +import Mathlib.Data.Fintype.Powerset #align_import algebra.big_operators.ring from "leanprover-community/mathlib"@"b2c89893177f66a48daf993b7ba5ef7cddeff8c9" @@ -17,87 +16,69 @@ We prove results about big operators that involve some interaction between multiplicative and additive structures on the values being combined. -/ - -universe u v w - -open BigOperators - -variable {α : Type u} {β : Type v} {γ : Type w} +open Fintype +open scoped BigOperators namespace Finset +variable {ι α : Type*} {κ : ι → Type*} {s s₁ s₂ : Finset ι} {i : ι} {a : α} {f g : ι → α} -variable {s s₁ s₂ : Finset α} {a : α} {b : β} {f g : α → β} - -section CommMonoid - -variable [CommMonoid β] - -open Classical - -theorem prod_pow_eq_pow_sum {x : β} {f : α → ℕ} : - ∀ {s : Finset α}, ∏ i in s, x ^ f i = x ^ ∑ x in s, f x := by - apply Finset.induction - · simp - · intro a s has H - rw [Finset.prod_insert has, Finset.sum_insert has, pow_add, H] -#align finset.prod_pow_eq_pow_sum Finset.prod_pow_eq_pow_sum +section NonUnitalNonAssocSemiring +variable [NonUnitalNonAssocSemiring α] -end CommMonoid - -section Semiring - -variable [NonUnitalNonAssocSemiring β] - -theorem sum_mul : (∑ x in s, f x) * b = ∑ x in s, f x * b := - map_sum (AddMonoidHom.mulRight b) _ s +lemma sum_mul (s : Finset ι) (f : ι → α) (a : α) : + (∑ i in s, f i) * a = ∑ i in s, f i * a := map_sum (AddMonoidHom.mulRight a) _ s #align finset.sum_mul Finset.sum_mul -theorem mul_sum : (b * ∑ x in s, f x) = ∑ x in s, b * f x := - map_sum (AddMonoidHom.mulLeft b) _ s +lemma mul_sum (s : Finset ι) (f : ι → α) (a : α) : + a * ∑ i in s, f i = ∑ i in s, a * f i := map_sum (AddMonoidHom.mulLeft a) _ s #align finset.mul_sum Finset.mul_sum -theorem sum_mul_sum {ι₁ : Type*} {ι₂ : Type*} (s₁ : Finset ι₁) (s₂ : Finset ι₂) (f₁ : ι₁ → β) - (f₂ : ι₂ → β) : - ((∑ x₁ in s₁, f₁ x₁) * ∑ x₂ in s₂, f₂ x₂) = ∑ p in s₁ ×ˢ s₂, f₁ p.1 * f₂ p.2 := by - rw [sum_product, sum_mul, sum_congr rfl] - intros - rw [mul_sum] +lemma sum_mul_sum {κ : Type*} (s : Finset ι) (t : Finset κ) (f : ι → α) (g : κ → α) : + (∑ i in s, f i) * ∑ j in t, g j = ∑ i in s, ∑ j in t, f i * g j := by + simp_rw [sum_mul, ← mul_sum] #align finset.sum_mul_sum Finset.sum_mul_sum -end Semiring +lemma sum_range_succ_mul_sum_range_succ (m n : ℕ) (f g : ℕ → α) : + (∑ i in range (m + 1), f i) * ∑ i in range (n + 1), g i = + (∑ i in range m, f i) * ∑ i in range n, g i + + f m * ∑ i in range n, g i + (∑ i in range m, f i) * g n + f m * g n := by + simp only [add_mul, mul_add, add_assoc, sum_range_succ] +#align finset.sum_range_succ_mul_sum_range_succ Finset.sum_range_succ_mul_sum_range_succ + +end NonUnitalNonAssocSemiring -section Semiring +section NonUnitalSemiring +variable [NonUnitalSemiring α] -theorem dvd_sum [NonUnitalSemiring β] - {b : β} {s : Finset α} {f : α → β} (h : ∀ x ∈ s, b ∣ f x) : b ∣ ∑ x in s, f x := +lemma dvd_sum (h : ∀ i ∈ s, a ∣ f i) : a ∣ ∑ i in s, f i := Multiset.dvd_sum fun y hy => by rcases Multiset.mem_map.1 hy with ⟨x, hx, rfl⟩; exact h x hx #align finset.dvd_sum Finset.dvd_sum -variable [NonAssocSemiring β] +end NonUnitalSemiring + +section NonAssocSemiring +variable [NonAssocSemiring α] [DecidableEq ι] -theorem sum_mul_boole [DecidableEq α] (s : Finset α) (f : α → β) (a : α) : - (∑ x in s, f x * ite (a = x) 1 0) = ite (a ∈ s) (f a) 0 := by simp +lemma sum_mul_boole (s : Finset ι) (f : ι → α) (i : ι) : + ∑ j in s, f j * ite (i = j) 1 0 = ite (i ∈ s) (f i) 0 := by simp #align finset.sum_mul_boole Finset.sum_mul_boole -theorem sum_boole_mul [DecidableEq α] (s : Finset α) (f : α → β) (a : α) : - (∑ x in s, ite (a = x) 1 0 * f x) = ite (a ∈ s) (f a) 0 := by simp +lemma sum_boole_mul (s : Finset ι) (f : ι → α) (i : ι) : + ∑ j in s, ite (i = j) 1 0 * f i = ite (i ∈ s) (f i) 0 := by simp #align finset.sum_boole_mul Finset.sum_boole_mul -end Semiring - -theorem sum_div [DivisionSemiring β] {s : Finset α} {f : α → β} {b : β} : - (∑ x in s, f x) / b = ∑ x in s, f x / b := by simp only [div_eq_mul_inv, sum_mul] -#align finset.sum_div Finset.sum_div +end NonAssocSemiring section CommSemiring +variable [CommSemiring α] -variable [CommSemiring β] +section DecidableEq +variable [DecidableEq ι] [∀ i, DecidableEq (κ i)] /-- The product over a sum can be written as a sum over the product of sets, `Finset.Pi`. `Finset.prod_univ_sum` is an alternative statement when the product is over `univ`. -/ -theorem prod_sum {δ : α → Type*} [DecidableEq α] [∀ a, DecidableEq (δ a)] {s : Finset α} - {t : ∀ a, Finset (δ a)} {f : ∀ a, δ a → β} : - (∏ a in s, ∑ b in t a, f a b) = ∑ p in s.pi t, ∏ x in s.attach, f x.1 (p x.1 x.2) := by +lemma prod_sum (s : Finset ι) (t : ∀ i, Finset (κ i)) (f : ∀ i, κ i → α) : + ∏ a in s, ∑ b in t a, f a b = ∑ p in s.pi t, ∏ x in s.attach, f x.1 (p x.1 x.2) := by induction' s using Finset.induction with a s ha ih · rw [pi_empty, sum_singleton] rfl @@ -126,18 +107,32 @@ theorem prod_sum {δ : α → Type*} [DecidableEq α] [∀ a, DecidableEq (δ a) Subtype.exists, exists_prop, exists_eq_right] using ha #align finset.prod_sum Finset.prod_sum -/-- The product of `f a + g a` over all of `s` is the sum - over the powerset of `s` of the product of `f` over a subset `t` times - the product of `g` over the complement of `t` -/ -theorem prod_add [DecidableEq α] (f g : α → β) (s : Finset α) : - ∏ a in s, (f a + g a) = ∑ t in s.powerset, (∏ a in t, f a) * ∏ a in s \ t, g a := by +/-- The product over `univ` of a sum can be written as a sum over the product of sets, +`Fintype.piFinset`. `Finset.prod_sum` is an alternative statement when the product is not +over `univ`. -/ +lemma prod_univ_sum [Fintype ι] (t : ∀ i, Finset (κ i)) (f : ∀ i, κ i → α) : + ∏ i, ∑ j in t i, f i j = ∑ x in piFinset t, ∏ i, f i (x i) := by + simp only [prod_attach_univ, prod_sum, Finset.sum_univ_pi] +#align finset.prod_univ_sum Finset.prod_univ_sum + +lemma sum_prod_piFinset {κ : Type*} [Fintype ι] (s : Finset κ) (g : ι → κ → α) : + ∑ f in piFinset fun _ : ι ↦ s, ∏ i, g i (f i) = ∏ i, ∑ j in s, g i j := by + classical rw [← prod_univ_sum] + +lemma sum_pow' (s : Finset ι) (f : ι → α) (n : ℕ) : + (∑ a in s, f a) ^ n = ∑ p in piFinset fun _i : Fin n ↦ s, ∏ i, f (p i) := by + classical convert @prod_univ_sum (Fin n) _ _ _ _ _ _ (fun _i ↦ s) fun _i d ↦ f d; simp + +/-- The product of `f a + g a` over all of `s` is the sum over the powerset of `s` of the product of +`f` over a subset `t` times the product of `g` over the complement of `t` -/ +theorem prod_add (f g : ι → α) (s : Finset ι) : + ∏ i in s, (f i + g i) = ∑ t in s.powerset, (∏ i in t, f i) * ∏ i in s \ t, g i := by classical calc - ∏ a in s, (f a + g a) = - ∏ a in s, ∑ p in ({True, False} : Finset Prop), if p then f a else g a := by simp + ∏ i in s, (f i + g i) = + ∏ i in s, ∑ p in ({True, False} : Finset Prop), if p then f i else g i := by simp _ = ∑ p in (s.pi fun _ => {True, False} : Finset (∀ a ∈ s, Prop)), - ∏ a in s.attach, if p a.1 a.2 then f a.1 else g a.1 := - prod_sum + ∏ a in s.attach, if p a.1 a.2 then f a.1 else g a.1 := prod_sum _ _ _ _ = ∑ t in s.powerset, (∏ a in t, f a) * ∏ a in s \ t, g a := sum_bij' (fun f _ ↦ s.filter fun a ↦ ∃ h : a ∈ s, f a h) @@ -154,9 +149,10 @@ theorem prod_add [DecidableEq α] (f g : α → β) (s : Finset α) : tauto) #align finset.prod_add Finset.prod_add +end DecidableEq + /-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/ -theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι) - (f g : ι → R) : +theorem prod_add_ordered [LinearOrder ι] [CommSemiring α] (s : Finset ι) (f g : ι → α) : ∏ i in s, (f i + g i) = (∏ i in s, f i) + ∑ i in s, @@ -179,28 +175,9 @@ theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : F exact mt (fun ha => (mem_filter.1 ha).1) ha' #align finset.prod_add_ordered Finset.prod_add_ordered -/-- `∏ i, (f i - g i) = (∏ i, f i) - ∑ i, g i * (∏ j < i, f j - g j) * (∏ j > i, f j)`. -/ -theorem prod_sub_ordered {ι R : Type*} [CommRing R] [LinearOrder ι] (s : Finset ι) (f g : ι → R) : - ∏ i in s, (f i - g i) = - (∏ i in s, f i) - - ∑ i in s, - g i * (∏ j in s.filter (· < i), (f j - g j)) * ∏ j in s.filter fun j => i < j, f j := by - simp only [sub_eq_add_neg] - convert prod_add_ordered s f fun i => -g i - simp -#align finset.prod_sub_ordered Finset.prod_sub_ordered - -/-- `∏ i, (1 - f i) = 1 - ∑ i, f i * (∏ j < i, 1 - f j)`. This formula is useful in construction of -a partition of unity from a collection of “bump” functions. -/ -theorem prod_one_sub_ordered {ι R : Type*} [CommRing R] [LinearOrder ι] (s : Finset ι) - (f : ι → R) : ∏ i in s, (1 - f i) = 1 - ∑ i in s, f i * ∏ j in s.filter (· < i), (1 - f j) := by - rw [prod_sub_ordered] - simp -#align finset.prod_one_sub_ordered Finset.prod_one_sub_ordered - /-- Summing `a^s.card * b^(n-s.card)` over all finite subsets `s` of a `Finset` gives `(a + b)^s.card`.-/ -theorem sum_pow_mul_eq_add_pow {α R : Type*} [CommSemiring R] (a b : R) (s : Finset α) : +theorem sum_pow_mul_eq_add_pow (a b : α) (s : Finset ι) : (∑ t in s.powerset, a ^ t.card * b ^ (s.card - t.card)) = (a + b) ^ s.card := by classical rw [← prod_const, prod_add] @@ -208,19 +185,46 @@ theorem sum_pow_mul_eq_add_pow {α R : Type*} [CommSemiring R] (a b : R) (s : Fi rw [prod_const, prod_const, ← card_sdiff (mem_powerset.1 ht)] #align finset.sum_pow_mul_eq_add_pow Finset.sum_pow_mul_eq_add_pow +/-- Summing `a^s.card * b^(n-s.card)` over all finite subsets `s` of a fintype of cardinality `n` +gives `(a + b)^n`. The "good" proof involves expanding along all coordinates using the fact that +`x^n` is multilinear, but multilinear maps are only available now over rings, so we give instead +a proof reducing to the usual binomial theorem to have a result over semirings. -/ +lemma _root_.Fintype.sum_pow_mul_eq_add_pow (ι : Type*) [Fintype ι] (a b : α) : + ∑ s : Finset ι, a ^ s.card * b ^ (Fintype.card ι - s.card) = (a + b) ^ Fintype.card ι := + Finset.sum_pow_mul_eq_add_pow _ _ _ +#align fintype.sum_pow_mul_eq_add_pow Fintype.sum_pow_mul_eq_add_pow + @[norm_cast] -theorem prod_natCast (s : Finset α) (f : α → ℕ) : ↑(∏ x in s, f x : ℕ) = ∏ x in s, (f x : β) := - (Nat.castRingHom β).map_prod f s +theorem prod_natCast (s : Finset ι) (f : ι → ℕ) : ↑(∏ i in s, f i : ℕ) = ∏ i in s, (f i : α) := + (Nat.castRingHom α).map_prod f s #align finset.prod_nat_cast Finset.prod_natCast end CommSemiring section CommRing +variable [CommRing α] -variable {R : Type*} [CommRing R] +/-- `∏ i, (f i - g i) = (∏ i, f i) - ∑ i, g i * (∏ j < i, f j - g j) * (∏ j > i, f j)`. -/ +lemma prod_sub_ordered [LinearOrder ι] (s : Finset ι) (f g : ι → α) : + ∏ i in s, (f i - g i) = + (∏ i in s, f i) - + ∑ i in s, + g i * (∏ j in s.filter (· < i), (f j - g j)) * ∏ j in s.filter fun j => i < j, f j := by + simp only [sub_eq_add_neg] + convert prod_add_ordered s f fun i => -g i + simp +#align finset.prod_sub_ordered Finset.prod_sub_ordered + +/-- `∏ i, (1 - f i) = 1 - ∑ i, f i * (∏ j < i, 1 - f j)`. This formula is useful in construction of +a partition of unity from a collection of “bump” functions. -/ +theorem prod_one_sub_ordered [LinearOrder ι] (s : Finset ι) (f : ι → α) : + ∏ i in s, (1 - f i) = 1 - ∑ i in s, f i * ∏ j in s.filter (· < i), (1 - f j) := by + rw [prod_sub_ordered] + simp +#align finset.prod_one_sub_ordered Finset.prod_one_sub_ordered theorem prod_range_cast_nat_sub (n k : ℕ) : - ∏ i in range k, (n - i : R) = (∏ i in range k, (n - i) : ℕ) := by + ∏ i in range k, (n - i : α) = (∏ i in range k, (n - i) : ℕ) := by rw [prod_natCast] rcases le_or_lt k n with hkn | hnk · exact prod_congr rfl fun i hi => (Nat.cast_sub <| (mem_range.1 hi).le.trans hkn).symm @@ -230,44 +234,12 @@ theorem prod_range_cast_nat_sub (n k : ℕ) : end CommRing -/-- A product over all subsets of `s ∪ {x}` is obtained by multiplying the product over all subsets -of `s`, and over all subsets of `s` to which one adds `x`. -/ -@[to_additive - "A sum over all subsets of `s ∪ {x}` is obtained by summing the sum over all subsets - of `s`, and over all subsets of `s` to which one adds `x`."] -theorem prod_powerset_insert [DecidableEq α] [CommMonoid β] {s : Finset α} {x : α} (h : x ∉ s) - (f : Finset α → β) : - (∏ a in (insert x s).powerset, f a) = - (∏ a in s.powerset, f a) * ∏ t in s.powerset, f (insert x t) := by - rw [powerset_insert, Finset.prod_union, Finset.prod_image] - · intro t₁ h₁ t₂ h₂ heq - rw [← Finset.erase_insert (not_mem_of_mem_powerset_of_not_mem h₁ h), ← - Finset.erase_insert (not_mem_of_mem_powerset_of_not_mem h₂ h), heq] - · rw [Finset.disjoint_iff_ne] - intro t₁ h₁ t₂ h₂ - rcases Finset.mem_image.1 h₂ with ⟨t₃, _h₃, H₃₂⟩ - rw [← H₃₂] - exact ne_insert_of_not_mem _ _ (not_mem_of_mem_powerset_of_not_mem h₁ h) -#align finset.prod_powerset_insert Finset.prod_powerset_insert -#align finset.sum_powerset_insert Finset.sum_powerset_insert - -/-- A product over `powerset s` is equal to the double product over sets of subsets of `s` with -`card s = k`, for `k = 1, ..., card s`. -/ -@[to_additive - "A sum over `powerset s` is equal to the double sum over sets of subsets of `s` with - `card s = k`, for `k = 1, ..., card s`"] -theorem prod_powerset [CommMonoid β] (s : Finset α) (f : Finset α → β) : - ∏ t in powerset s, f t = ∏ j in range (card s + 1), ∏ t in powersetCard j s, f t := by - rw [powerset_card_disjiUnion, prod_disjiUnion] -#align finset.prod_powerset Finset.prod_powerset -#align finset.sum_powerset Finset.sum_powerset - -theorem sum_range_succ_mul_sum_range_succ [NonUnitalNonAssocSemiring β] (n k : ℕ) (f g : ℕ → β) : - ((∑ i in range (n + 1), f i) * ∑ i in range (k + 1), g i) = - (((∑ i in range n, f i) * ∑ i in range k, g i) + f n * ∑ i in range k, g i) + - (∑ i in range n, f i) * g k + - f n * g k := by - simp only [add_mul, mul_add, add_assoc, sum_range_succ] -#align finset.sum_range_succ_mul_sum_range_succ Finset.sum_range_succ_mul_sum_range_succ +section DivisionSemiring +variable [DivisionSemiring α] + +lemma sum_div (s : Finset ι) (f : ι → α) (a : α) : + (∑ i in s, f i) / a = ∑ i in s, f i / a := by simp only [div_eq_mul_inv, sum_mul] +#align finset.sum_div Finset.sum_div +end DivisionSemiring end Finset diff --git a/Mathlib/Algebra/Bounds.lean b/Mathlib/Algebra/Bounds.lean index 3aeaddf1701e2..97ca6605490a5 100644 --- a/Mathlib/Algebra/Bounds.lean +++ b/Mathlib/Algebra/Bounds.lean @@ -88,6 +88,16 @@ theorem IsLUB.inv (h : IsLUB s a) : IsGLB s⁻¹ a⁻¹ := #align is_lub.inv IsLUB.inv #align is_lub.neg IsLUB.neg +@[to_additive] +lemma BddBelow.range_inv {α : Type*} {f : α → G} (hf : BddBelow (range f)) : + BddAbove (range (fun x => (f x)⁻¹)) := + hf.range_comp (OrderIso.inv G).monotone + +@[to_additive] +lemma BddAbove.range_inv {α : Type*} {f : α → G} (hf : BddAbove (range f)) : + BddBelow (range (fun x => (f x)⁻¹)) := + BddBelow.range_inv (G := Gᵒᵈ) hf + end InvNeg section mul_add @@ -135,6 +145,17 @@ theorem BddBelow.mul {s t : Set M} (hs : BddBelow s) (ht : BddBelow t) : BddBelo #align bdd_below.mul BddBelow.mul #align bdd_below.add BddBelow.add +@[to_additive] +lemma BddAbove.range_mul {α : Type*} {f g : α → M} (hf : BddAbove (range f)) + (hg : BddAbove (range g)) : BddAbove (range (fun x => f x * g x)) := + BddAbove.range_comp (f := fun x => (⟨f x, g x⟩ : M × M)) + (bddAbove_range_prod.mpr ⟨hf, hg⟩) (Monotone.mul' monotone_fst monotone_snd) + +@[to_additive] +lemma BddBelow.range_mul {α : Type*} {f g : α → M} (hf : BddBelow (range f)) + (hg : BddBelow (range g)) : BddBelow (range (fun x => f x * g x)) := + BddAbove.range_mul (M := Mᵒᵈ) hf hg + end mul_add section ConditionallyCompleteLattice @@ -145,23 +166,23 @@ variable {ι G : Type*} [Group G] [ConditionallyCompleteLattice G] [CovariantClass G G (Function.swap (· * ·)) (· ≤ ·)] [Nonempty ι] {f : ι → G} @[to_additive] -theorem ciSup_mul (hf : BddAbove (Set.range f)) (a : G) : (⨆ i, f i) * a = ⨆ i, f i * a := +theorem ciSup_mul (hf : BddAbove (range f)) (a : G) : (⨆ i, f i) * a = ⨆ i, f i * a := (OrderIso.mulRight a).map_ciSup hf #align csupr_mul ciSup_mul #align csupr_add ciSup_add @[to_additive] -theorem ciSup_div (hf : BddAbove (Set.range f)) (a : G) : (⨆ i, f i) / a = ⨆ i, f i / a := by +theorem ciSup_div (hf : BddAbove (range f)) (a : G) : (⨆ i, f i) / a = ⨆ i, f i / a := by simp only [div_eq_mul_inv, ciSup_mul hf] #align csupr_div ciSup_div #align csupr_sub ciSup_sub @[to_additive] -theorem ciInf_mul (hf : BddBelow (Set.range f)) (a : G) : (⨅ i, f i) * a = ⨅ i, f i * a := +theorem ciInf_mul (hf : BddBelow (range f)) (a : G) : (⨅ i, f i) * a = ⨅ i, f i * a := (OrderIso.mulRight a).map_ciInf hf @[to_additive] -theorem ciInf_div (hf : BddBelow (Set.range f)) (a : G) : (⨅ i, f i) / a = ⨅ i, f i / a := by +theorem ciInf_div (hf : BddBelow (range f)) (a : G) : (⨅ i, f i) / a = ⨅ i, f i / a := by simp only [div_eq_mul_inv, ciInf_mul hf] end Right @@ -172,13 +193,13 @@ variable {ι G : Type*} [Group G] [ConditionallyCompleteLattice G] [CovariantClass G G (· * ·) (· ≤ ·)] [Nonempty ι] {f : ι → G} @[to_additive] -theorem mul_ciSup (hf : BddAbove (Set.range f)) (a : G) : (a * ⨆ i, f i) = ⨆ i, a * f i := +theorem mul_ciSup (hf : BddAbove (range f)) (a : G) : (a * ⨆ i, f i) = ⨆ i, a * f i := (OrderIso.mulLeft a).map_ciSup hf #align mul_csupr mul_ciSup #align add_csupr add_ciSup @[to_additive] -theorem mul_ciInf (hf : BddBelow (Set.range f)) (a : G) : (a * ⨅ i, f i) = ⨅ i, a * f i := +theorem mul_ciInf (hf : BddBelow (range f)) (a : G) : (a * ⨅ i, f i) = ⨅ i, a * f i := (OrderIso.mulLeft a).map_ciInf hf end Left diff --git a/Mathlib/Algebra/Category/AlgebraCat/Limits.lean b/Mathlib/Algebra/Category/AlgebraCat/Limits.lean index 3fce38163c59a..6da939ff3be35 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Limits.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Limits.lean @@ -100,7 +100,7 @@ def limitConeIsLimit (F : J ⥤ AlgebraCatMax.{v, w} R) : IsLimit (limitCone.{v, _⟩, _⟩, _, _⟩, _⟩) (fun s => _) · intro j j' f - exact FunLike.congr_fun (Cone.w s f) v + exact DFunLike.congr_fun (Cone.w s f) v · -- Porting note: we could add a custom `ext` lemma here. apply Subtype.ext ext j diff --git a/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean b/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean index a274031e4c7cf..0e7f3bd65ed71 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.CategoryTheory.Monoidal.Braided import Mathlib.CategoryTheory.Monoidal.Transport import Mathlib.Algebra.Category.AlgebraCat.Basic import Mathlib.Algebra.Category.ModuleCat.Monoidal.Basic diff --git a/Mathlib/Algebra/Category/FGModuleCat/Basic.lean b/Mathlib/Algebra/Category/FGModuleCat/Basic.lean index e4bc23931c6ca..6acbfd0056465 100644 --- a/Mathlib/Algebra/Category/FGModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/FGModuleCat/Basic.lean @@ -213,8 +213,8 @@ instance (V W : FGModuleCat K) : Module.Finite K (V ⟶ W) := (by infer_instance : Module.Finite K (V →ₗ[K] W)) instance closedPredicateModuleFinite : - MonoidalCategory.ClosedPredicate fun V : ModuleCat.{u} K => Module.Finite K V where - prop_ihom := @fun X Y hX hY => @Module.Finite.linearMap K X Y _ _ _ _ _ _ _ hX hY + MonoidalCategory.ClosedPredicate fun V : ModuleCat.{u} K ↦ Module.Finite K V where + prop_ihom {X Y} _ _ := Module.Finite.linearMap K K X Y #align fgModule.closed_predicate_module_finite FGModuleCat.closedPredicateModuleFinite instance : MonoidalClosed (FGModuleCat K) := by diff --git a/Mathlib/Algebra/Category/FGModuleCat/Limits.lean b/Mathlib/Algebra/Category/FGModuleCat/Limits.lean index 1b15a6a924836..50b522b59214b 100644 --- a/Mathlib/Algebra/Category/FGModuleCat/Limits.lean +++ b/Mathlib/Algebra/Category/FGModuleCat/Limits.lean @@ -68,10 +68,14 @@ set_option linter.uppercaseLean3 false in instance : CreatesLimitsOfShape J (forget₂ (FGModuleCat k) (ModuleCat.{v} k)) where CreatesLimit {F} := forget₂CreatesLimit F -instance : HasFiniteLimits (FGModuleCat k) where - out _ _ _ := hasLimitsOfShape_of_hasLimitsOfShape_createsLimitsOfShape +instance (J : Type) [Category J] [FinCategory J] : + HasLimitsOfShape J (FGModuleCat.{v} k) := + hasLimitsOfShape_of_hasLimitsOfShape_createsLimitsOfShape (forget₂ (FGModuleCat k) (ModuleCat.{v} k)) +instance : HasFiniteLimits (FGModuleCat k) where + out _ _ _ := inferInstance + instance : PreservesFiniteLimits (forget₂ (FGModuleCat k) (ModuleCat.{v} k)) where preservesFiniteLimits _ _ _ := inferInstance diff --git a/Mathlib/Algebra/Category/GroupCat/Adjunctions.lean b/Mathlib/Algebra/Category/GroupCat/Adjunctions.lean index 1e2ae1e10e500..8859515e7524a 100644 --- a/Mathlib/Algebra/Category/GroupCat/Adjunctions.lean +++ b/Mathlib/Algebra/Category/GroupCat/Adjunctions.lean @@ -91,7 +91,7 @@ the monomorphisms in `AddCommGroup` are just the injective functions. -/ -- Porting note: had to elaborate instance of Mono rather than just using `apply_instance`. example {G H : AddCommGroupCat.{u}} (f : G ⟶ H) [Mono f] : Function.Injective f := - (mono_iff_injective (FunLike.coe f)).mp (Functor.map_mono (forget AddCommGroupCat) f) + (mono_iff_injective (DFunLike.coe f)).mp (Functor.map_mono (forget AddCommGroupCat) f) end AddCommGroupCat diff --git a/Mathlib/Algebra/Category/GroupCat/Basic.lean b/Mathlib/Algebra/Category/GroupCat/Basic.lean index 5690b845346c6..7b9c0e6acaad2 100644 --- a/Mathlib/Algebra/Category/GroupCat/Basic.lean +++ b/Mathlib/Algebra/Category/GroupCat/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ import Mathlib.Algebra.Category.MonCat.Basic +import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.CategoryTheory.Endomorphism #align_import algebra.category.Group.basic from "leanprover-community/mathlib"@"524793de15bc4c52ee32d254e7d7867c7176b3af" @@ -65,8 +66,8 @@ instance {X Y : GroupCat} : CoeFun (X ⟶ Y) fun _ => X → Y where coe (f : X →* Y) := f @[to_additive] -instance FunLike_instance (X Y : GroupCat) : FunLike (X ⟶ Y) X (fun _ => Y) := - show FunLike (X →* Y) X (fun _ => Y) from inferInstance +instance FunLike_instance (X Y : GroupCat) : FunLike (X ⟶ Y) X Y := + show FunLike (X →* Y) X Y from inferInstance -- porting note: added @[to_additive (attr := simp)] @@ -214,8 +215,8 @@ instance {X Y : CommGroupCat} : CoeFun (X ⟶ Y) fun _ => X → Y where coe (f : X →* Y) := f @[to_additive] -instance FunLike_instance (X Y : CommGroupCat) : FunLike (X ⟶ Y) X (fun _ => Y) := - show FunLike (X →* Y) X (fun _ => Y) from inferInstance +instance FunLike_instance (X Y : CommGroupCat) : FunLike (X ⟶ Y) X Y := + show FunLike (X →* Y) X Y from inferInstance -- porting note: added @[to_additive (attr := simp)] diff --git a/Mathlib/Algebra/Category/GroupCat/Biproducts.lean b/Mathlib/Algebra/Category/GroupCat/Biproducts.lean index 71f3eee22a2ae..bbd3d58fce77f 100644 --- a/Mathlib/Algebra/Category/GroupCat/Biproducts.lean +++ b/Mathlib/Algebra/Category/GroupCat/Biproducts.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Group.Pi import Mathlib.Algebra.Category.GroupCat.Preadditive import Mathlib.CategoryTheory.Preadditive.Biproducts import Mathlib.Algebra.Category.GroupCat.Limits +import Mathlib.Tactic.CategoryTheory.Elementwise #align_import algebra.category.Group.biproducts from "leanprover-community/mathlib"@"234ddfeaa5572bc13716dd215c6444410a679a8e" diff --git a/Mathlib/Algebra/Category/GroupCat/Colimits.lean b/Mathlib/Algebra/Category/GroupCat/Colimits.lean index 8a8b7e6c38c80..4ea00d249667c 100644 --- a/Mathlib/Algebra/Category/GroupCat/Colimits.lean +++ b/Mathlib/Algebra/Category/GroupCat/Colimits.lean @@ -202,7 +202,7 @@ def descFun (s : Cocone F) : ColimitType.{w} F → s.pt := by | symm _ _ _ r_ih => exact r_ih.symm | trans _ _ _ _ _ r_ih_h r_ih_k => exact Eq.trans r_ih_h r_ih_k | map j j' f x => simpa only [descFunLift, Functor.const_obj_obj] using - FunLike.congr_fun (s.ι.naturality f) x + DFunLike.congr_fun (s.ι.naturality f) x | zero => simp | neg => simp | add => simp @@ -227,10 +227,10 @@ def descMorphism (s : Cocone F) : colimit.{w} F ⟶ s.pt where /-- Evidence that the proposed colimit is the colimit. -/ def colimitCoconeIsColimit : IsColimit (colimitCocone.{w} F) where desc s := descMorphism F s - uniq s m w := FunLike.ext _ _ fun x => Quot.inductionOn x fun x => by + uniq s m w := DFunLike.ext _ _ fun x => Quot.inductionOn x fun x => by change (m : ColimitType F →+ s.pt) _ = (descMorphism F s : ColimitType F →+ s.pt) _ induction x using Prequotient.recOn with - | of j x => exact FunLike.congr_fun (w j) x + | of j x => exact DFunLike.congr_fun (w j) x | zero => dsimp only [quot_zero] rw [map_zero, map_zero] diff --git a/Mathlib/Algebra/Category/GroupCat/EpiMono.lean b/Mathlib/Algebra/Category/GroupCat/EpiMono.lean index 9d76286c3f7b4..1bdf26f314b15 100644 --- a/Mathlib/Algebra/Category/GroupCat/EpiMono.lean +++ b/Mathlib/Algebra/Category/GroupCat/EpiMono.lean @@ -305,7 +305,7 @@ theorem agree : f.range = { x | h x = g x } := by simp [g_apply_infinity f] have eq2 : g b (fromCoset ⟨f.range, 1, one_leftCoset _⟩) = fromCoset ⟨b • ↑f.range, b, rfl⟩ := rfl - exact (fromCoset_ne_of_nin_range _ r).symm (by rw [← eq1, ← eq2, FunLike.congr_fun hb]) + exact (fromCoset_ne_of_nin_range _ r).symm (by rw [← eq1, ← eq2, DFunLike.congr_fun hb]) #align Group.surjective_of_epi_auxs.agree GroupCat.SurjectiveOfEpiAuxs.agree theorem comp_eq : (f ≫ show B ⟶ GroupCat.of SX' from g) = f ≫ show B ⟶ GroupCat.of SX' from h := by @@ -320,7 +320,7 @@ theorem comp_eq : (f ≫ show B ⟶ GroupCat.of SX' from g) = f ≫ show B ⟶ G theorem g_ne_h (x : B) (hx : x ∉ f.range) : g ≠ h := by intro r replace r := - FunLike.congr_fun (FunLike.congr_fun r x) (fromCoset ⟨f.range, ⟨1, one_leftCoset _⟩⟩) + DFunLike.congr_fun (DFunLike.congr_fun r x) (fromCoset ⟨f.range, ⟨1, one_leftCoset _⟩⟩) change _ = ((τ).symm.trans (g x)).trans τ _ at r rw [g_apply_fromCoset, MonoidHom.coe_mk] at r simp only [MonoidHom.coe_range, Subtype.coe_mk, Equiv.symm_swap, Equiv.toFun_as_coe, diff --git a/Mathlib/Algebra/Category/GroupCat/FilteredColimits.lean b/Mathlib/Algebra/Category/GroupCat/FilteredColimits.lean index 4c0e2815bf413..e51d7def42c6b 100644 --- a/Mathlib/Algebra/Category/GroupCat/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/GroupCat/FilteredColimits.lean @@ -146,14 +146,14 @@ def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where MonCat.FilteredColimits.colimitDesc.{v, u} (F ⋙ forget₂ GroupCat MonCat.{max v u}) ((forget₂ GroupCat MonCat).mapCocone t) fac t j := - FunLike.coe_injective <| + DFunLike.coe_injective <| (Types.colimitCoconeIsColimit.{v, u} (F ⋙ forget GroupCat)).fac ((forget GroupCat).mapCocone t) j uniq t _ h := - FunLike.coe_injective' <| + DFunLike.coe_injective' <| (Types.colimitCoconeIsColimit.{v, u} (F ⋙ forget GroupCat)).uniq ((forget GroupCat).mapCocone t) _ - fun j => funext fun x => FunLike.congr_fun (h j) x + fun j => funext fun x => DFunLike.congr_fun (h j) x #align Group.filtered_colimits.colimit_cocone_is_colimit GroupCat.FilteredColimits.colimitCoconeIsColimit #align AddGroup.filtered_colimits.colimit_cocone_is_colimit AddGroupCat.FilteredColimits.colimitCoconeIsColimit @@ -230,13 +230,13 @@ def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where (F ⋙ forget₂ CommGroupCat GroupCat.{max v u})).desc ((forget₂ CommGroupCat GroupCat.{max v u}).mapCocone t) fac t j := - FunLike.coe_injective <| + DFunLike.coe_injective <| (Types.colimitCoconeIsColimit.{v, u} (F ⋙ forget CommGroupCat)).fac ((forget CommGroupCat).mapCocone t) j uniq t _ h := - FunLike.coe_injective <| + DFunLike.coe_injective <| (Types.colimitCoconeIsColimit.{v, u} (F ⋙ forget CommGroupCat)).uniq - ((forget CommGroupCat).mapCocone t) _ fun j => funext fun x => FunLike.congr_fun (h j) x + ((forget CommGroupCat).mapCocone t) _ fun j => funext fun x => DFunLike.congr_fun (h j) x #align CommGroup.filtered_colimits.colimit_cocone_is_colimit CommGroupCat.FilteredColimits.colimitCoconeIsColimit #align AddCommGroup.filtered_colimits.colimit_cocone_is_colimit AddCommGroupCat.FilteredColimits.colimitCoconeIsColimit diff --git a/Mathlib/Algebra/Category/GroupCat/Injective.lean b/Mathlib/Algebra/Category/GroupCat/Injective.lean index 40db9194562ca..ab8668b4387c9 100644 --- a/Mathlib/Algebra/Category/GroupCat/Injective.lean +++ b/Mathlib/Algebra/Category/GroupCat/Injective.lean @@ -160,7 +160,7 @@ lemma toNext_inj : Function.Injective <| toNext A_ := AddMonoidHom.comp ⟨⟨ULift.up, rfl⟩, fun _ _ ↦ rfl⟩ toRatCircle.toAddMonoidHom let g : of (ℤ ∙ a) ⟶ A_ := AddSubgroupClass.subtype _ have : Mono g := (mono_iff_injective _).mpr Subtype.val_injective - (FunLike.congr_fun (Injective.comp_factorThru f g) _).symm.trans (congr_fun h0 _) + (DFunLike.congr_fun (Injective.comp_factorThru f g) _).symm.trans (congr_fun h0 _) /-- An injective presentation of `A`: `A → ∏_{A →+ ℚ/ℤ}, ℚ/ℤ`. -/ @[simps] def presentation : InjectivePresentation A_ where diff --git a/Mathlib/Algebra/Category/GroupCat/Kernels.lean b/Mathlib/Algebra/Category/GroupCat/Kernels.lean index 6c31088d5667c..425ccccaa958d 100644 --- a/Mathlib/Algebra/Category/GroupCat/Kernels.lean +++ b/Mathlib/Algebra/Category/GroupCat/Kernels.lean @@ -27,9 +27,9 @@ def kernelCone : KernelFork f := def kernelIsLimit : IsLimit <| kernelCone f := Fork.IsLimit.mk _ (fun s => (by exact Fork.ι s : _ →+ G).codRestrict _ fun c => f.mem_ker.mpr <| - by exact FunLike.congr_fun s.condition c) + by exact DFunLike.congr_fun s.condition c) (fun _ => by rfl) - (fun _ _ h => ext fun x => Subtype.ext_iff_val.mpr <| by exact FunLike.congr_fun h x) + (fun _ _ h => ext fun x => Subtype.ext_iff_val.mpr <| by exact DFunLike.congr_fun h x) /-- The cokernel cocone induced by the projection onto the quotient. -/ def cokernelCocone : CokernelCofork f := diff --git a/Mathlib/Algebra/Category/GroupCat/Limits.lean b/Mathlib/Algebra/Category/GroupCat/Limits.lean index ca8dbab5f1708..172b301d6d58a 100644 --- a/Mathlib/Algebra/Category/GroupCat/Limits.lean +++ b/Mathlib/Algebra/Category/GroupCat/Limits.lean @@ -7,7 +7,6 @@ import Mathlib.Algebra.Category.MonCat.Limits import Mathlib.Algebra.Category.GroupCat.Preadditive import Mathlib.CategoryTheory.Over import Mathlib.GroupTheory.Subgroup.Basic -import Mathlib.CategoryTheory.ConcreteCategory.Elementwise import Mathlib.CategoryTheory.ConcreteCategory.ReflectsIso #align_import algebra.category.Group.limits from "leanprover-community/mathlib"@"70fd9563a21e7b963887c9360bd29b2393e6225a" @@ -404,7 +403,7 @@ agrees with the usual group-theoretical kernel. def kernelIsoKer {G H : AddCommGroupCat.{u}} (f : G ⟶ H) : kernel f ≅ AddCommGroupCat.of f.ker where hom := - { toFun := fun g => ⟨kernel.ι f g, FunLike.congr_fun (kernel.condition f) g⟩ + { toFun := fun g => ⟨kernel.ι f g, DFunLike.congr_fun (kernel.condition f) g⟩ map_zero' := by refine Subtype.ext ?_ simp [(AddSubgroup.coe_zero _).symm] @@ -415,7 +414,7 @@ def kernelIsoKer {G H : AddCommGroupCat.{u}} (f : G ⟶ H) : simp } inv := kernel.lift f (AddSubgroup.subtype f.ker) <| by -- porting note : used to be `tidy`, but `aesop` can't do it - refine FunLike.ext _ _ ?_ + refine DFunLike.ext _ _ ?_ rintro ⟨x, (hx : f _ = 0)⟩ exact hx hom_inv_id := by @@ -425,7 +424,7 @@ def kernelIsoKer {G H : AddCommGroupCat.{u}} (f : G ⟶ H) : ext x dsimp generalize_proofs _ h1 h2 - erw [FunLike.congr_fun (kernel.lift_ι f _ h1) ⟨_, h2⟩] + erw [DFunLike.congr_fun (kernel.lift_ι f _ h1) ⟨_, h2⟩] rfl inv_hom_id := by apply AddCommGroupCat.ext @@ -434,7 +433,7 @@ def kernelIsoKer {G H : AddCommGroupCat.{u}} (f : G ⟶ H) : refine Subtype.ext ?_ simp only [ZeroHom.coe_mk, Function.comp_apply, id_eq] generalize_proofs _ h1 h2 - erw [FunLike.congr_fun (kernel.lift_ι f _ h1) ⟨_, mem⟩] + erw [DFunLike.congr_fun (kernel.lift_ι f _ h1) ⟨_, mem⟩] rfl set_option linter.uppercaseLean3 false in #align AddCommGroup.kernel_iso_ker AddCommGroupCat.kernelIsoKer diff --git a/Mathlib/Algebra/Category/GroupWithZeroCat.lean b/Mathlib/Algebra/Category/GroupWithZeroCat.lean index 125c94c5718da..6a8721b27d612 100644 --- a/Mathlib/Algebra/Category/GroupWithZeroCat.lean +++ b/Mathlib/Algebra/Category/GroupWithZeroCat.lean @@ -53,12 +53,12 @@ instance : LargeCategory.{u} GroupWithZeroCat where assoc _ _ _ := MonoidWithZeroHom.comp_assoc _ _ _ -- porting note: was not necessary in mathlib -instance {M N : GroupWithZeroCat} : FunLike (M ⟶ N) M (fun _ => N) := +instance {M N : GroupWithZeroCat} : FunLike (M ⟶ N) M N := ⟨fun f => f.toFun, fun f g h => by cases f cases g congr - apply FunLike.coe_injective' + apply DFunLike.coe_injective' exact h⟩ -- porting note: added @@ -71,7 +71,7 @@ instance groupWithZeroConcreteCategory : ConcreteCategory GroupWithZeroCat where forget := { obj := fun G => G map := fun f => f.toFun } - forget_faithful := ⟨fun h => FunLike.coe_injective h⟩ + forget_faithful := ⟨fun h => DFunLike.coe_injective h⟩ -- porting note: added @[simp] lemma forget_map (f : X ⟶ Y) : (forget GroupWithZeroCat).map f = f := rfl diff --git a/Mathlib/Algebra/Category/ModuleCat/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Basic.lean index 4db004123d7a7..2df80c3a65dca 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Basic.lean @@ -123,7 +123,7 @@ instance {M : ModuleCat.{v} R} : Module R ((forget (ModuleCat R)).obj M) := -- porting note: added to ease automation @[ext] lemma ext {M N : ModuleCat.{v} R} {f₁ f₂ : M ⟶ N} (h : ∀ (x : M), f₁ x = f₂ x) : f₁ = f₂ := - FunLike.ext _ _ h + DFunLike.ext _ _ h instance hasForgetToAddCommGroup : HasForget₂ (ModuleCat R) AddCommGroupCat where forget₂ := diff --git a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean index 327de68231ce1..17d4268584829 100644 --- a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean @@ -87,7 +87,7 @@ def restrictScalars {R : Type u₁} {S : Type u₂} [Ring R] [Ring S] (f : R → instance {R : Type u₁} {S : Type u₂} [Ring R] [Ring S] (f : R →+* S) : CategoryTheory.Faithful (restrictScalars.{v} f) where map_injective h := - LinearMap.ext fun x => by simpa only using FunLike.congr_fun h x + LinearMap.ext fun x => by simpa only using DFunLike.congr_fun h x instance {R : Type u₁} {S : Type u₂} [Ring R] [Ring S] (f : R →+* S) : (restrictScalars.{v} f).PreservesMonomorphisms where diff --git a/Mathlib/Algebra/Category/ModuleCat/Free.lean b/Mathlib/Algebra/Category/ModuleCat/Free.lean index 1070a9f4c3f89..a8d0f6a9c1a1d 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Free.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Free.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Dagur Asgeirsson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Dagur Asgeirsson -/ -import Mathlib.LinearAlgebra.Dimension.Finite +import Mathlib.LinearAlgebra.Dimension.Free import Mathlib.Algebra.Homology.ShortComplex.ModuleCat /-! @@ -138,7 +138,7 @@ theorem span_rightExact {w : ι' → S.X₃} (hv : ⊤ ≤ span R (range v)) simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, Sum.elim_comp_inr] rw [ModuleCat.epi_iff_surjective] at hE rw [← Function.comp.assoc, Function.RightInverse.comp_eq_id (Function.rightInverse_invFun hE), - Function.comp.left_id] + Function.id_comp] end Span diff --git a/Mathlib/Algebra/Category/ModuleCat/Injective.lean b/Mathlib/Algebra/Category/ModuleCat/Injective.lean index 470a758c8274a..a6e64c91ae2ad 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Injective.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Injective.lean @@ -3,11 +3,10 @@ Copyright (c) 2023 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jujian Zhang -/ -import Mathlib.Algebra.Category.ModuleCat.Abelian import Mathlib.Algebra.Category.ModuleCat.ChangeOfRings -import Mathlib.Algebra.Category.GroupCat.Abelian import Mathlib.Algebra.Category.GroupCat.Injective import Mathlib.Algebra.Category.GroupCat.ZModuleEquivalence +import Mathlib.Logic.Equiv.TransferInstance /-! # Category of $R$-modules has enough injectives diff --git a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean index 852fcef106ae2..2188fc2d9c9d8 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean @@ -5,7 +5,6 @@ Authors: Kevin Buzzard, Scott Morrison, Jakob von Raumer -/ import Mathlib.Algebra.Category.ModuleCat.Basic import Mathlib.LinearAlgebra.TensorProduct -import Mathlib.CategoryTheory.Linear.Yoneda import Mathlib.CategoryTheory.Monoidal.Linear #align_import algebra.category.Module.monoidal.basic from "leanprover-community/mathlib"@"74403a3b2551b0970855e14ef5e8fd0d6af1bfc2" diff --git a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean index b58421dd4d2b1..5f1e80ccbe24d 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Closed.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Buzzard, Scott Morrison, Jakob von Raumer -/ import Mathlib.CategoryTheory.Closed.Monoidal +import Mathlib.CategoryTheory.Linear.Yoneda import Mathlib.Algebra.Category.ModuleCat.Monoidal.Symmetric #align_import algebra.category.Module.monoidal.closed from "leanprover-community/mathlib"@"74403a3b2551b0970855e14ef5e8fd0d6af1bfc2" @@ -64,10 +65,10 @@ set_option linter.uppercaseLean3 false in open MonoidalCategory --- porting note: `CoeFun` was replaced by `FunLike` --- I can't seem to express the function coercion here without writing `@FunLike.coe`. +-- porting note: `CoeFun` was replaced by `DFunLike` +-- I can't seem to express the function coercion here without writing `@DFunLike.coe`. theorem monoidalClosed_curry {M N P : ModuleCat.{u} R} (f : M ⊗ N ⟶ P) (x : M) (y : N) : - @FunLike.coe _ _ _ LinearMap.instFunLike + @DFunLike.coe _ _ _ LinearMap.instFunLike ((MonoidalClosed.curry f : N →ₗ[R] M →ₗ[R] P) y) x = f (x ⊗ₜ[R] y) := rfl set_option linter.uppercaseLean3 false in @@ -77,7 +78,7 @@ set_option linter.uppercaseLean3 false in theorem monoidalClosed_uncurry {M N P : ModuleCat.{u} R} (f : N ⟶ M ⟶[ModuleCat.{u} R] P) (x : M) (y : N) : MonoidalClosed.uncurry f (x ⊗ₜ[R] y) = - @FunLike.coe _ _ _ LinearMap.instFunLike (f y) x := + @DFunLike.coe _ _ _ LinearMap.instFunLike (f y) x := rfl set_option linter.uppercaseLean3 false in #align Module.monoidal_closed_uncurry ModuleCat.monoidalClosed_uncurry diff --git a/Mathlib/Algebra/Category/MonCat/Basic.lean b/Mathlib/Algebra/Category/MonCat/Basic.lean index 2a6e9a084ce38..a7a8f72fc69dc 100644 --- a/Mathlib/Algebra/Category/MonCat/Basic.lean +++ b/Mathlib/Algebra/Category/MonCat/Basic.lean @@ -86,8 +86,8 @@ instance {X Y : MonCat} : CoeFun (X ⟶ Y) fun _ => X → Y where coe (f : X →* Y) := f @[to_additive] -instance Hom_FunLike (X Y : MonCat) : FunLike (X ⟶ Y) X (fun _ => Y) := - show FunLike (X →* Y) X (fun _ => Y) by infer_instance +instance Hom_FunLike (X Y : MonCat) : FunLike (X ⟶ Y) X Y := + show FunLike (X →* Y) X Y by infer_instance -- porting note: added @[to_additive (attr := simp)] @@ -208,8 +208,8 @@ instance {X Y : CommMonCat} : CoeFun (X ⟶ Y) fun _ => X → Y where coe (f : X →* Y) := f @[to_additive] -instance Hom_FunLike (X Y : CommMonCat) : FunLike (X ⟶ Y) X (fun _ => Y) := - show FunLike (X →* Y) X (fun _ => Y) by infer_instance +instance Hom_FunLike (X Y : CommMonCat) : FunLike (X ⟶ Y) X Y := + show FunLike (X →* Y) X Y by infer_instance -- porting note: added @[to_additive (attr := simp)] diff --git a/Mathlib/Algebra/Category/MonCat/Colimits.lean b/Mathlib/Algebra/Category/MonCat/Colimits.lean index c5cb673d113c9..abb23cd66826e 100644 --- a/Mathlib/Algebra/Category/MonCat/Colimits.lean +++ b/Mathlib/Algebra/Category/MonCat/Colimits.lean @@ -254,7 +254,7 @@ def colimitIsColimit : IsColimit (colimitCocone F) where · rw [quot_one, map_one] rfl · rw [quot_mul, map_mul, hx, hy] - dsimp [descMorphism, FunLike.coe, descFun] + dsimp [descMorphism, DFunLike.coe, descFun] simp only [← quot_mul, descFunLift] set_option linter.uppercaseLean3 false in #align Mon.colimits.colimit_is_colimit MonCat.Colimits.colimitIsColimit diff --git a/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean b/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean index 558a44344ea96..ee60640685b6a 100644 --- a/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean @@ -330,7 +330,7 @@ def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where uniq t m h := MonoidHom.ext fun y => congr_fun ((Types.colimitCoconeIsColimit (F ⋙ forget MonCat)).uniq ((forget MonCat).mapCocone t) ((forget MonCat).map m) - fun j => funext fun x => FunLike.congr_fun (i := MonCat.Hom_FunLike _ _) (h j) x) y + fun j => funext fun x => DFunLike.congr_fun (i := MonCat.Hom_FunLike _ _) (h j) x) y #align Mon.filtered_colimits.colimit_cocone_is_colimit MonCat.FilteredColimits.colimitCoconeIsColimit #align AddMon.filtered_colimits.colimit_cocone_is_colimit AddMonCat.FilteredColimits.colimitCoconeIsColimit @@ -405,15 +405,15 @@ def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where MonCat.FilteredColimits.colimitDesc.{v, u} (F ⋙ forget₂ CommMonCat MonCat.{max v u}) ((forget₂ CommMonCat MonCat.{max v u}).mapCocone t) fac t j := - FunLike.coe_injective (i := CommMonCat.Hom_FunLike _ _) <| + DFunLike.coe_injective (i := CommMonCat.Hom_FunLike _ _) <| (Types.colimitCoconeIsColimit.{v, u} (F ⋙ forget CommMonCat.{max v u})).fac ((forget CommMonCat).mapCocone t) j uniq t m h := - FunLike.coe_injective (i := CommMonCat.Hom_FunLike _ _) <| + DFunLike.coe_injective (i := CommMonCat.Hom_FunLike _ _) <| (Types.colimitCoconeIsColimit.{v, u} (F ⋙ forget CommMonCat.{max v u})).uniq ((forget CommMonCat.{max v u}).mapCocone t) ((forget CommMonCat.{max v u}).map m) fun j => funext fun x => - FunLike.congr_fun (i := CommMonCat.Hom_FunLike _ _) (h j) x + DFunLike.congr_fun (i := CommMonCat.Hom_FunLike _ _) (h j) x #align CommMon.filtered_colimits.colimit_cocone_is_colimit CommMonCat.FilteredColimits.colimitCoconeIsColimit #align AddCommMon.filtered_colimits.colimit_cocone_is_colimit AddCommMonCat.FilteredColimits.colimitCoconeIsColimit diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index a2bfc229e5ca6..dd9cc141d2497 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -5,7 +5,6 @@ Authors: Scott Morrison, Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.Category.GroupCat.Basic import Mathlib.CategoryTheory.ConcreteCategory.ReflectsIso -import Mathlib.CategoryTheory.Elementwise import Mathlib.Algebra.Ring.Equiv #align_import algebra.category.Ring.basic from "leanprover-community/mathlib"@"34b2a989ad80bce3a5de749d935a4f23726e26e9" @@ -106,8 +105,8 @@ set_option linter.uppercaseLean3 false in @[simp] lemma RingEquiv_coe_eq {X Y : Type _} [Semiring X] [Semiring Y] (e : X ≃+* Y) : - (@FunLike.coe (SemiRingCat.of X ⟶ SemiRingCat.of Y) _ (fun _ => (forget SemiRingCat).obj _) - ConcreteCategory.funLike (e : X →+* Y) : X → Y) = ↑e := + (@DFunLike.coe (SemiRingCat.of X ⟶ SemiRingCat.of Y) _ (fun _ => (forget SemiRingCat).obj _) + ConcreteCategory.instFunLike (e : X →+* Y) : X → Y) = ↑e := rfl instance : Inhabited SemiRingCat := @@ -245,8 +244,8 @@ set_option linter.uppercaseLean3 false in @[simp] lemma RingEquiv_coe_eq {X Y : Type _} [Ring X] [Ring Y] (e : X ≃+* Y) : - (@FunLike.coe (RingCat.of X ⟶ RingCat.of Y) _ (fun _ => (forget RingCat).obj _) - ConcreteCategory.funLike (e : X →+* Y) : X → Y) = ↑e := + (@DFunLike.coe (RingCat.of X ⟶ RingCat.of Y) _ (fun _ => (forget RingCat).obj _) + ConcreteCategory.instFunLike (e : X →+* Y) : X → Y) = ↑e := rfl instance hasForgetToSemiRingCat : HasForget₂ RingCat SemiRingCat := @@ -328,9 +327,9 @@ set_option linter.uppercaseLean3 false in @[simp] lemma RingEquiv_coe_eq {X Y : Type _} [CommSemiring X] [CommSemiring Y] (e : X ≃+* Y) : - (@FunLike.coe (CommSemiRingCat.of X ⟶ CommSemiRingCat.of Y) _ + (@DFunLike.coe (CommSemiRingCat.of X ⟶ CommSemiRingCat.of Y) _ (fun _ => (forget CommSemiRingCat).obj _) - ConcreteCategory.funLike (e : X →+* Y) : X → Y) = ↑e := + ConcreteCategory.instFunLike (e : X →+* Y) : X → Y) = ↑e := rfl -- Porting note: I think this is now redundant. @@ -444,8 +443,8 @@ set_option linter.uppercaseLean3 false in @[simp] lemma RingEquiv_coe_eq {X Y : Type _} [CommRing X] [CommRing Y] (e : X ≃+* Y) : - (@FunLike.coe (CommRingCat.of X ⟶ CommRingCat.of Y) _ (fun _ => (forget CommRingCat).obj _) - ConcreteCategory.funLike (e : X →+* Y) : X → Y) = ↑e := + (@DFunLike.coe (CommRingCat.of X ⟶ CommRingCat.of Y) _ (fun _ => (forget CommRingCat).obj _) + ConcreteCategory.instFunLike (e : X →+* Y) : X → Y) = ↑e := rfl -- Porting note: I think this is now redundant. diff --git a/Mathlib/Algebra/Category/Ring/Colimits.lean b/Mathlib/Algebra/Category/Ring/Colimits.lean index eacda8088c946..a0f02a616df9f 100644 --- a/Mathlib/Algebra/Category/Ring/Colimits.lean +++ b/Mathlib/Algebra/Category/Ring/Colimits.lean @@ -5,7 +5,6 @@ Authors: Scott Morrison -/ import Mathlib.Algebra.Category.Ring.Basic import Mathlib.CategoryTheory.Limits.HasLimits -import Mathlib.CategoryTheory.ConcreteCategory.Elementwise #align_import algebra.category.Ring.colimits from "leanprover-community/mathlib"@"70fd9563a21e7b963887c9360bd29b2393e6225a" diff --git a/Mathlib/Algebra/Category/SemigroupCat/Basic.lean b/Mathlib/Algebra/Category/SemigroupCat/Basic.lean index 653066329e4b7..2d2818f30baa5 100644 --- a/Mathlib/Algebra/Category/SemigroupCat/Basic.lean +++ b/Mathlib/Algebra/Category/SemigroupCat/Basic.lean @@ -7,7 +7,6 @@ import Mathlib.Algebra.PEmptyInstances import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.CategoryTheory.ConcreteCategory.BundledHom import Mathlib.CategoryTheory.Functor.ReflectsIso -import Mathlib.CategoryTheory.Elementwise #align_import algebra.category.Semigroup.basic from "leanprover-community/mathlib"@"47b51515e69f59bca5cf34ef456e6000fe205a69" @@ -51,7 +50,7 @@ namespace MagmaCat instance bundledHom : BundledHom @MulHom := ⟨@MulHom.toFun, @MulHom.id, @MulHom.comp, --Porting note : was `@MulHom.coe_inj` which is deprecated - by intros; apply @FunLike.coe_injective, by aesop_cat, by aesop_cat⟩ + by intros; apply @DFunLike.coe_injective, by aesop_cat, by aesop_cat⟩ #align Magma.bundled_hom MagmaCat.bundledHom #align AddMagma.bundled_hom AddMagmaCat.bundledHom @@ -98,8 +97,8 @@ theorem coe_of (R : Type u) [Mul R] : (MagmaCat.of R : Type u) = R := @[to_additive (attr := simp)] lemma mulEquiv_coe_eq {X Y : Type _} [Mul X] [Mul Y] (e : X ≃* Y) : - (@FunLike.coe (MagmaCat.of X ⟶ MagmaCat.of Y) _ (fun _ => (forget MagmaCat).obj _) - ConcreteCategory.funLike (e : X →ₙ* Y) : X → Y) = ↑e := + (@DFunLike.coe (MagmaCat.of X ⟶ MagmaCat.of Y) _ (fun _ => (forget MagmaCat).obj _) + ConcreteCategory.instFunLike (e : X →ₙ* Y) : X → Y) = ↑e := rfl /-- Typecheck a `MulHom` as a morphism in `MagmaCat`. -/ @@ -183,8 +182,8 @@ theorem coe_of (R : Type u) [Semigroup R] : (SemigroupCat.of R : Type u) = R := @[to_additive (attr := simp)] lemma mulEquiv_coe_eq {X Y : Type _} [Semigroup X] [Semigroup Y] (e : X ≃* Y) : - (@FunLike.coe (SemigroupCat.of X ⟶ SemigroupCat.of Y) _ (fun _ => (forget SemigroupCat).obj _) - ConcreteCategory.funLike (e : X →ₙ* Y) : X → Y) = ↑e := + (@DFunLike.coe (SemigroupCat.of X ⟶ SemigroupCat.of Y) _ (fun _ => (forget SemigroupCat).obj _) + ConcreteCategory.instFunLike (e : X →ₙ* Y) : X → Y) = ↑e := rfl /-- Typecheck a `MulHom` as a morphism in `SemigroupCat`. -/ diff --git a/Mathlib/Algebra/CharP/Basic.lean b/Mathlib/Algebra/CharP/Basic.lean index 5b8f1392cf593..b76940d255a13 100644 --- a/Mathlib/Algebra/CharP/Basic.lean +++ b/Mathlib/Algebra/CharP/Basic.lean @@ -442,6 +442,25 @@ theorem sum_pow_char {ι : Type*} (s : Finset ι) (f : ι → R) : (frobenius R p).map_sum _ _ #align sum_pow_char sum_pow_char +variable (n : ℕ) + +theorem list_sum_pow_char_pow (l : List R) : l.sum ^ p ^ n = (l.map (· ^ p ^ n : R → R)).sum := by + induction n with + | zero => simp_rw [pow_zero, pow_one, List.map_id'] + | succ n ih => simp_rw [pow_succ', pow_mul, ih, list_sum_pow_char, List.map_map]; rfl + +theorem multiset_sum_pow_char_pow (s : Multiset R) : + s.sum ^ p ^ n = (s.map (· ^ p ^ n : R → R)).sum := by + induction n with + | zero => simp_rw [pow_zero, pow_one, Multiset.map_id'] + | succ n ih => simp_rw [pow_succ', pow_mul, ih, multiset_sum_pow_char, Multiset.map_map]; rfl + +theorem sum_pow_char_pow {ι : Type*} (s : Finset ι) (f : ι → R) : + (∑ i in s, f i) ^ p ^ n = ∑ i in s, f i ^ p ^ n := by + induction n with + | zero => simp_rw [pow_zero, pow_one] + | succ n ih => simp_rw [pow_succ', pow_mul, ih, sum_pow_char] + end CommSemiring section CommRing @@ -540,6 +559,12 @@ theorem char_is_prime_or_zero (p : ℕ) [hc : CharP R p] : Nat.Prime p ∨ p = 0 | m + 2, hc => Or.inl (@char_is_prime_of_two_le R _ _ (m + 2) hc (Nat.le_add_left 2 m)) #align char_p.char_is_prime_or_zero CharP.char_is_prime_or_zero +theorem exists' (R : Type*) [NonAssocRing R] [NoZeroDivisors R] [Nontrivial R] : + CharZero R ∨ ∃ p : ℕ, Fact p.Prime ∧ CharP R p := by + obtain ⟨p, hchar⟩ := CharP.exists R + rcases char_is_prime_or_zero R p with h | rfl + exacts [Or.inr ⟨p, Fact.mk h, hchar⟩, Or.inl (charP_to_charZero R)] + theorem char_is_prime_of_pos (p : ℕ) [NeZero p] [CharP R p] : Fact p.Prime := ⟨(CharP.char_is_prime_or_zero R _).resolve_right <| NeZero.ne p⟩ #align char_p.char_is_prime_of_pos CharP.char_is_prime_of_pos diff --git a/Mathlib/Algebra/CharP/ExpChar.lean b/Mathlib/Algebra/CharP/ExpChar.lean index 9ea5a40c02362..dee7f0f8d924e 100644 --- a/Mathlib/Algebra/CharP/ExpChar.lean +++ b/Mathlib/Algebra/CharP/ExpChar.lean @@ -46,11 +46,37 @@ class inductive ExpChar (R : Type u) [Semiring R] : ℕ → Prop #align exp_char ExpChar #align exp_char.prime ExpChar.prime +variable {R} in +/-- The exponential characteristic is unique. -/ +theorem ExpChar.eq {p q : ℕ} (hp : ExpChar R p) (hq : ExpChar R q) : p = q := by + cases' hp with hp _ hp' hp + · cases' hq with hq _ hq' hq + exacts [rfl, False.elim (Nat.not_prime_zero (CharP.eq R hq (CharP.ofCharZero R) ▸ hq'))] + · cases' hq with hq _ hq' hq + exacts [False.elim (Nat.not_prime_zero (CharP.eq R hp (CharP.ofCharZero R) ▸ hp')), + CharP.eq R hp hq] + +theorem ExpChar.congr {p : ℕ} (q : ℕ) [hq : ExpChar R q] (h : q = p) : ExpChar R p := h ▸ hq + +/-- Noncomputable function that outputs the unique exponential characteristic of a semiring. -/ +noncomputable def ringExpChar (R : Type*) [NonAssocSemiring R] : ℕ := max (ringChar R) 1 + +theorem ringExpChar.eq (q : ℕ) [h : ExpChar R q] : ringExpChar R = q := by + cases' h with _ _ h _ + · haveI := CharP.ofCharZero R + rw [ringExpChar, ringChar.eq R 0]; rfl + rw [ringExpChar, ringChar.eq R q] + exact Nat.max_eq_left h.one_lt.le + +@[simp] +theorem ringExpChar.eq_one (R : Type*) [NonAssocSemiring R] [CharZero R] : ringExpChar R = 1 := by + rw [ringExpChar, ringChar.eq_zero, max_eq_right zero_le_one] + /-- The exponential characteristic is one if the characteristic is zero. -/ theorem expChar_one_of_char_zero (q : ℕ) [hp : CharP R 0] [hq : ExpChar R q] : q = 1 := by cases' hq with q hq_one hq_prime hq_hchar · rfl - · exact False.elim (lt_irrefl _ ((hp.eq R hq_hchar).symm ▸ hq_prime : (0 : ℕ).Prime).pos) + · exact False.elim <| hq_prime.ne_zero <| hq_hchar.eq R hp #align exp_char_one_of_char_zero expChar_one_of_char_zero /-- The characteristic equals the exponential characteristic iff the former is prime. -/ @@ -100,7 +126,8 @@ theorem char_prime_of_ne_zero {p : ℕ} [hp : CharP R p] (p_ne_zero : p ≠ 0) : · contradiction #align char_prime_of_ne_zero char_prime_of_ne_zero -/-- The exponential characteristic is a prime number or one. -/ +/-- The exponential characteristic is a prime number or one. +See also `CharP.char_is_prime_or_zero`. -/ theorem expChar_is_prime_or_one (q : ℕ) [hq : ExpChar R q] : Nat.Prime q ∨ q = 1 := by cases hq with | zero => exact .inr rfl @@ -123,10 +150,24 @@ end Nontrivial end Semiring theorem ExpChar.exists [Ring R] [IsDomain R] : ∃ q, ExpChar R q := by - obtain ⟨p, h⟩ := CharP.exists R - by_cases hp : p = 0 - · exact ⟨1, by rw [hp] at h; haveI := CharP.charP_to_charZero R; exact .zero⟩ - exact ⟨p, haveI := NeZero.mk hp; .prime (CharP.char_is_prime_of_pos R p).out⟩ + obtain _ | ⟨p, ⟨hp⟩, _⟩ := CharP.exists' R + exacts [⟨1, .zero⟩, ⟨p, .prime hp⟩] + +theorem ExpChar.exists_unique [Ring R] [IsDomain R] : ∃! q, ExpChar R q := + let ⟨q, H⟩ := ExpChar.exists R + ⟨q, H, fun _ H2 ↦ ExpChar.eq H2 H⟩ + +instance ringExpChar.expChar [Ring R] [IsDomain R] : ExpChar R (ringExpChar R) := by + obtain ⟨q, _⟩ := ExpChar.exists R + rwa [ringExpChar.eq R q] + +variable {R} in +theorem ringExpChar.of_eq [Ring R] [IsDomain R] {q : ℕ} (h : ringExpChar R = q) : ExpChar R q := + h ▸ ringExpChar.expChar R + +variable {R} in +theorem ringExpChar.eq_iff [Ring R] [IsDomain R] {q : ℕ} : ringExpChar R = q ↔ ExpChar R q := + ⟨ringExpChar.of_eq, fun _ ↦ ringExpChar.eq R q⟩ /-- If a ring homomorphism `R →+* A` is injective then `A` has the same exponential characteristic as `R`. -/ @@ -202,3 +243,47 @@ theorem ExpChar.neg_one_pow_expChar_pow [Ring R] (q n : ℕ) [hR : ExpChar R q] cases' hR with _ _ hprime _ · simp only [one_pow, pow_one] haveI := Fact.mk hprime; exact CharP.neg_one_pow_char_pow R q n + +section BigOperators + +open BigOperators + +variable {R} + +variable [CommSemiring R] (q : ℕ) [hR : ExpChar R q] (n : ℕ) + +theorem list_sum_pow_expChar (l : List R) : l.sum ^ q = (l.map (· ^ q : R → R)).sum := by + cases hR with + | zero => simp_rw [pow_one, List.map_id'] + | prime hprime => haveI := Fact.mk hprime; exact list_sum_pow_char q l + +theorem multiset_sum_pow_expChar (s : Multiset R) : s.sum ^ q = (s.map (· ^ q : R → R)).sum := by + cases hR with + | zero => simp_rw [pow_one, Multiset.map_id'] + | prime hprime => haveI := Fact.mk hprime; exact multiset_sum_pow_char q s + +theorem sum_pow_expChar {ι : Type*} (s : Finset ι) (f : ι → R) : + (∑ i in s, f i) ^ q = ∑ i in s, f i ^ q := by + cases hR with + | zero => simp_rw [pow_one] + | prime hprime => haveI := Fact.mk hprime; exact sum_pow_char q s f + +theorem list_sum_pow_expChar_pow (l : List R) : + l.sum ^ q ^ n = (l.map (· ^ q ^ n : R → R)).sum := by + cases hR with + | zero => simp_rw [one_pow, pow_one, List.map_id'] + | prime hprime => haveI := Fact.mk hprime; exact list_sum_pow_char_pow q n l + +theorem multiset_sum_pow_expChar_pow (s : Multiset R) : + s.sum ^ q ^ n = (s.map (· ^ q ^ n : R → R)).sum := by + cases hR with + | zero => simp_rw [one_pow, pow_one, Multiset.map_id'] + | prime hprime => haveI := Fact.mk hprime; exact multiset_sum_pow_char_pow q n s + +theorem sum_pow_expChar_pow {ι : Type*} (s : Finset ι) (f : ι → R) : + (∑ i in s, f i) ^ q ^ n = ∑ i in s, f i ^ q ^ n := by + cases hR with + | zero => simp_rw [one_pow, pow_one] + | prime hprime => haveI := Fact.mk hprime; exact sum_pow_char_pow q n s f + +end BigOperators diff --git a/Mathlib/Algebra/CharP/MixedCharZero.lean b/Mathlib/Algebra/CharP/MixedCharZero.lean index dbe396976206c..4d4d7a84776a7 100644 --- a/Mathlib/Algebra/CharP/MixedCharZero.lean +++ b/Mathlib/Algebra/CharP/MixedCharZero.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Jon Eugster. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jon Eugster -/ -import Mathlib.Algebra.CharP.Algebra import Mathlib.Algebra.CharP.LocalRing import Mathlib.RingTheory.Ideal.Quotient import Mathlib.Tactic.FieldSimp diff --git a/Mathlib/Algebra/CharZero/Defs.lean b/Mathlib/Algebra/CharZero/Defs.lean index 3653f16065358..03ac87801f1ef 100644 --- a/Mathlib/Algebra/CharZero/Defs.lean +++ b/Mathlib/Algebra/CharZero/Defs.lean @@ -7,6 +7,7 @@ import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Data.Int.Cast.Defs import Mathlib.Tactic.Cases import Mathlib.Algebra.NeZero +import Mathlib.Logic.Function.Basic #align_import algebra.char_zero.defs from "leanprover-community/mathlib"@"d6aae1bcbd04b8de2022b9b83a5b5b10e10c777d" diff --git a/Mathlib/Algebra/CharZero/Lemmas.lean b/Mathlib/Algebra/CharZero/Lemmas.lean index f00f06e0726b4..ae9d601259d40 100644 --- a/Mathlib/Algebra/CharZero/Lemmas.lean +++ b/Mathlib/Algebra/CharZero/Lemmas.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Function.Support -import Mathlib.Algebra.GroupPower.Lemmas +import Mathlib.Algebra.Order.Monoid.WithTop import Mathlib.Data.Nat.Cast.Field #align_import algebra.char_zero.lemmas from "leanprover-community/mathlib"@"acee671f47b8e7972a1eb6f4eed74b4b3abce829" diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean b/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean index 27f58562ab426..6d32f6f4da035 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean @@ -6,7 +6,6 @@ Authors: Kevin Kappelmann import Mathlib.Algebra.ContinuedFractions.Computation.Approximations import Mathlib.Algebra.ContinuedFractions.ConvergentsEquiv import Mathlib.Algebra.Order.Archimedean -import Mathlib.Algebra.Algebra.Basic import Mathlib.Tactic.GCongr import Mathlib.Topology.Order.Basic @@ -123,8 +122,8 @@ theorem of_convergence_epsilon : have B_ineq : (fib (n + 1) : K) ≤ B := haveI : ¬g.TerminatedAt (n - 1) := mt (terminated_stable n.pred_le) not_terminated_at_n succ_nth_fib_le_of_nth_denom (Or.inr this) - have zero_lt_B : 0 < B := B_ineq.trans_lt' $ mod_cast fib_pos.2 n.succ_pos - have nB_pos : 0 < nB := nB_ineq.trans_lt' $ mod_cast fib_pos.2 $ succ_pos _ + have zero_lt_B : 0 < B := B_ineq.trans_lt' <| mod_cast fib_pos.2 n.succ_pos + have nB_pos : 0 < nB := nB_ineq.trans_lt' <| mod_cast fib_pos.2 <| succ_pos _ have zero_lt_mul_conts : 0 < B * nB := by positivity suffices 1 < ε * (B * nB) from (div_lt_iff zero_lt_mul_conts).mpr this -- use that `N' ≥ n` was obtained from the archimedean property to show the following diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean b/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean index 8c9291700e31f..c3c27e7dabb76 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean @@ -6,6 +6,7 @@ Authors: Kevin Kappelmann import Mathlib.Algebra.ContinuedFractions.Computation.CorrectnessTerminating import Mathlib.Data.Nat.Fib.Basic import Mathlib.Tactic.Monotonicity +import Mathlib.Algebra.GroupPower.Order import Std.Tactic.SolveByElim #align_import algebra.continued_fractions.computation.approximations from "leanprover-community/mathlib"@"a7e36e48519ab281320c4d192da6a7b348ce40ad" @@ -434,10 +435,10 @@ theorem sub_convergents_eq {ifp : IntFractPair K} · simp [n_eq_zero, le_refl] · exact Or.inr not_terminated_at_pred_n fib_le_of_continuantsAux_b this - have zero_lt_B : 0 < B := B_ineq.trans_lt' $ cast_pos.2 $ fib_pos.2 n.succ_pos + have zero_lt_B : 0 < B := B_ineq.trans_lt' <| cast_pos.2 <| fib_pos.2 n.succ_pos have : 0 ≤ pB := (cast_nonneg _).trans pB_ineq have : 0 < ifp.fr := - ifp_fr_ne_zero.lt_of_le' $ IntFractPair.nth_stream_fr_nonneg stream_nth_eq + ifp_fr_ne_zero.lt_of_le' <| IntFractPair.nth_stream_fr_nonneg stream_nth_eq have : pB + ifp.fr⁻¹ * B ≠ 0 := by positivity -- finally, let's do the rewriting calc @@ -495,7 +496,7 @@ theorem abs_sub_convergents_le (not_terminated_at_n : ¬(of v).TerminatedAt n) : haveI : ¬g.TerminatedAt (n - 1) := mt (terminated_stable n.pred_le) not_terminated_at_n fib_le_of_continuantsAux_b <| Or.inr this have zero_lt_conts_b : 0 < conts.b := - conts_b_ineq.trans_lt' $ mod_cast fib_pos.2 n.succ_pos + conts_b_ineq.trans_lt' <| mod_cast fib_pos.2 n.succ_pos -- `denom'` is positive, so we can remove `|⬝|` from our goal suffices 1 / denom' ≤ 1 / denom by have : |(-1) ^ n / denom'| = 1 / denom' := by @@ -518,7 +519,7 @@ theorem abs_sub_convergents_le (not_terminated_at_n : ¬(of v).TerminatedAt n) : suffices 0 < denom ∧ denom ≤ denom' from div_le_div_of_le_left zero_le_one this.left this.right constructor · have : 0 < pred_conts.b + gp.b * conts.b := - nextConts_b_ineq.trans_lt' $ mod_cast fib_pos.2 $ succ_pos _ + nextConts_b_ineq.trans_lt' <| mod_cast fib_pos.2 <| succ_pos _ solve_by_elim [mul_pos] · -- we can cancel multiplication by `conts.b` and addition with `pred_conts.b` suffices : gp.b * conts.b ≤ ifp_n.fr⁻¹ * conts.b diff --git a/Mathlib/Algebra/CovariantAndContravariant.lean b/Mathlib/Algebra/CovariantAndContravariant.lean index dbf7f5923f66d..942eacb855158 100644 --- a/Mathlib/Algebra/CovariantAndContravariant.lean +++ b/Mathlib/Algebra/CovariantAndContravariant.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.Algebra.Group.Defs +import Mathlib.Algebra.Group.Basic import Mathlib.Order.Basic import Mathlib.Order.Monotone.Basic diff --git a/Mathlib/Algebra/DirectLimit.lean b/Mathlib/Algebra/DirectLimit.lean index 8a95287928f40..5602d72fc5ffc 100644 --- a/Mathlib/Algebra/DirectLimit.lean +++ b/Mathlib/Algebra/DirectLimit.lean @@ -213,7 +213,7 @@ def map (g : (i : ι) → G i →ₗ[R] G' i) (hg : ∀ i j h, g j ∘ₗ f i j @[simp] lemma map_id [IsDirected ι (· ≤ ·)] : map (fun i ↦ LinearMap.id) (fun _ _ _ ↦ rfl) = LinearMap.id (R := R) (M := DirectLimit G f) := - FunLike.ext _ _ fun x ↦ (isEmpty_or_nonempty ι).elim (fun _ ↦ Subsingleton.elim _ _) fun _ ↦ + DFunLike.ext _ _ fun x ↦ (isEmpty_or_nonempty ι).elim (fun _ ↦ Subsingleton.elim _ _) fun _ ↦ x.induction_on fun i g ↦ by simp lemma map_comp [IsDirected ι (· ≤ ·)] @@ -225,7 +225,7 @@ lemma map_comp [IsDirected ι (· ≤ ·)] (map (fun i ↦ g₂ i ∘ₗ g₁ i) fun i j h ↦ by rw [LinearMap.comp_assoc, hg₁ i, ← LinearMap.comp_assoc, hg₂ i, LinearMap.comp_assoc] : DirectLimit G f →ₗ[R] DirectLimit G'' f'') := - FunLike.ext _ _ fun x ↦ (isEmpty_or_nonempty ι).elim (fun _ ↦ Subsingleton.elim _ _) fun _ ↦ + DFunLike.ext _ _ fun x ↦ (isEmpty_or_nonempty ι).elim (fun _ ↦ Subsingleton.elim _ _) fun _ ↦ x.induction_on fun i g ↦ by simp open LinearEquiv LinearMap in @@ -474,7 +474,7 @@ def map (g : (i : ι) → G i →+ G' i) lift _ _ _ (fun i ↦ (of _ _ _).comp (g i)) fun i j h g ↦ by cases isEmpty_or_nonempty ι · exact Subsingleton.elim _ _ - · have eq1 := FunLike.congr_fun (hg i j h) g + · have eq1 := DFunLike.congr_fun (hg i j h) g simp only [AddMonoidHom.coe_comp, Function.comp_apply] at eq1 ⊢ rw [eq1, of_f] @@ -486,7 +486,7 @@ def map (g : (i : ι) → G i →+ G' i) @[simp] lemma map_id [IsDirected ι (· ≤ ·)] : map (fun i ↦ AddMonoidHom.id _) (fun _ _ _ ↦ rfl) = AddMonoidHom.id (DirectLimit G f) := - FunLike.ext _ _ fun x ↦ (isEmpty_or_nonempty ι).elim (fun _ ↦ Subsingleton.elim _ _) fun _ ↦ + DFunLike.ext _ _ fun x ↦ (isEmpty_or_nonempty ι).elim (fun _ ↦ Subsingleton.elim _ _) fun _ ↦ x.induction_on fun i g ↦ by simp lemma map_comp [IsDirected ι (· ≤ ·)] @@ -499,7 +499,7 @@ lemma map_comp [IsDirected ι (· ≤ ·)] rw [AddMonoidHom.comp_assoc, hg₁ i, ← AddMonoidHom.comp_assoc, hg₂ i, AddMonoidHom.comp_assoc] : DirectLimit G f →+ DirectLimit G'' f'') := - FunLike.ext _ _ fun x ↦ (isEmpty_or_nonempty ι).elim (fun _ ↦ Subsingleton.elim _ _) fun _ ↦ + DFunLike.ext _ _ fun x ↦ (isEmpty_or_nonempty ι).elim (fun _ ↦ Subsingleton.elim _ _) fun _ ↦ x.induction_on fun i g ↦ by simp /-- @@ -512,8 +512,8 @@ def congr [IsDirected ι (· ≤ ·)] (he : ∀ i j h, (e j).toAddMonoidHom.comp (f i j h) = (f' i j h).comp (e i)) : DirectLimit G f ≃+ DirectLimit G' f' := AddMonoidHom.toAddEquiv (map (e ·) he) - (map (fun i ↦ (e i).symm) fun i j h ↦ FunLike.ext _ _ fun x ↦ by - have eq1 := FunLike.congr_fun (he i j h) ((e i).symm x) + (map (fun i ↦ (e i).symm) fun i j h ↦ DFunLike.ext _ _ fun x ↦ by + have eq1 := DFunLike.congr_fun (he i j h) ((e i).symm x) simp only [AddMonoidHom.coe_comp, AddEquiv.coe_toAddMonoidHom, Function.comp_apply, AddMonoidHom.coe_coe, AddEquiv.apply_symm_apply] at eq1 ⊢ simp [← eq1, of_f]) @@ -719,7 +719,7 @@ theorem of.zero_exact_aux [Nonempty ι] [IsDirected ι (· ≤ ·)] {x : FreeCom have := DirectedSystem.map_map (fun i j h => f' i j h) hij (le_refl j : j ≤ j) rw [this] exact sub_self _ - exacts [Or.inr rfl, Or.inl rfl] + exacts [Or.inl rfl, Or.inr rfl] · refine' ⟨i, {⟨i, 1⟩}, _, isSupported_sub (isSupported_of.2 rfl) isSupported_one, _⟩ · rintro k (rfl | h) rfl @@ -863,7 +863,7 @@ theorem lift_of (i x) : lift G f P g Hg (of G f i x) = g i x := theorem lift_unique [IsDirected ι (· ≤ ·)] (F : DirectLimit G f →+* P) (x) : F x = lift G f P (fun i => F.comp <| of G f i) (fun i j hij x => by simp [of_f]) x := by cases isEmpty_or_nonempty ι - · apply FunLike.congr_fun + · apply DFunLike.congr_fun apply Ideal.Quotient.ringHom_ext refine FreeCommRing.hom_ext fun ⟨i, _⟩ ↦ ?_ exact IsEmpty.elim' inferInstance i @@ -898,7 +898,7 @@ def map (g : (i : ι) → G i →+* G' i) (hg : ∀ i j h, (g j).comp (f i j h) = (f' i j h).comp (g i)) : DirectLimit G (fun _ _ h ↦ f _ _ h) →+* DirectLimit G' fun _ _ h ↦ f' _ _ h := lift _ _ _ (fun i ↦ (of _ _ _).comp (g i)) fun i j h g ↦ by - have eq1 := FunLike.congr_fun (hg i j h) g + have eq1 := DFunLike.congr_fun (hg i j h) g simp only [RingHom.coe_comp, Function.comp_apply] at eq1 ⊢ rw [eq1, of_f] @@ -911,7 +911,7 @@ def map (g : (i : ι) → G i →+* G' i) @[simp] lemma map_id [IsDirected ι (· ≤ ·)] : map (fun i ↦ RingHom.id _) (fun _ _ _ ↦ rfl) = RingHom.id (DirectLimit G fun _ _ h ↦ f _ _ h) := - FunLike.ext _ _ fun x ↦ x.induction_on fun i g ↦ by simp + DFunLike.ext _ _ fun x ↦ x.induction_on fun i g ↦ by simp lemma map_comp [IsDirected ι (· ≤ ·)] (g₁ : (i : ι) → G i →+* G' i) (g₂ : (i : ι) → G' i →+* G'' i) @@ -922,7 +922,7 @@ lemma map_comp [IsDirected ι (· ≤ ·)] (map (fun i ↦ (g₂ i).comp (g₁ i)) fun i j h ↦ by rw [RingHom.comp_assoc, hg₁ i, ← RingHom.comp_assoc, hg₂ i, RingHom.comp_assoc] : DirectLimit G (fun _ _ h ↦ f _ _ h) →+* DirectLimit G'' fun _ _ h ↦ f'' _ _ h) := - FunLike.ext _ _ fun x ↦ x.induction_on fun i g ↦ by simp + DFunLike.ext _ _ fun x ↦ x.induction_on fun i g ↦ by simp /-- Consider direct limits `lim G` and `lim G'` with direct system `f` and `f'` respectively, any @@ -935,13 +935,13 @@ def congr [IsDirected ι (· ≤ ·)] DirectLimit G (fun _ _ h ↦ f _ _ h) ≃+* DirectLimit G' fun _ _ h ↦ f' _ _ h := RingEquiv.ofHomInv (map (e ·) he) - (map (fun i ↦ (e i).symm) fun i j h ↦ FunLike.ext _ _ fun x ↦ by - have eq1 := FunLike.congr_fun (he i j h) ((e i).symm x) + (map (fun i ↦ (e i).symm) fun i j h ↦ DFunLike.ext _ _ fun x ↦ by + have eq1 := DFunLike.congr_fun (he i j h) ((e i).symm x) simp only [RingEquiv.toRingHom_eq_coe, RingHom.coe_comp, RingHom.coe_coe, Function.comp_apply, RingEquiv.apply_symm_apply] at eq1 ⊢ simp [← eq1, of_f]) - (FunLike.ext _ _ fun x ↦ x.induction_on <| by simp) - (FunLike.ext _ _ fun x ↦ x.induction_on <| by simp) + (DFunLike.ext _ _ fun x ↦ x.induction_on <| by simp) + (DFunLike.ext _ _ fun x ↦ x.induction_on <| by simp) lemma congr_apply_of [IsDirected ι (· ≤ ·)] (e : (i : ι) → G i ≃+* G' i) diff --git a/Mathlib/Algebra/DirectSum/Algebra.lean b/Mathlib/Algebra/DirectSum/Algebra.lean index e1e9c2b14c5b0..35e606e426872 100644 --- a/Mathlib/Algebra/DirectSum/Algebra.lean +++ b/Mathlib/Algebra/DirectSum/Algebra.lean @@ -81,14 +81,14 @@ instance : Algebra R (⨁ i, A i) where apply DFinsupp.single_eq_of_sigma_eq (GAlgebra.map_mul a b) commutes' r x := by change AddMonoidHom.mul (DirectSum.of _ _ _) x = AddMonoidHom.mul.flip (DirectSum.of _ _ _) x - apply FunLike.congr_fun _ x + apply DFunLike.congr_fun _ x ext i xi : 2 dsimp only [AddMonoidHom.comp_apply, AddMonoidHom.mul_apply, AddMonoidHom.flip_apply] rw [of_mul_of, of_mul_of] apply DFinsupp.single_eq_of_sigma_eq (GAlgebra.commutes r ⟨i, xi⟩) smul_def' r x := by change DistribMulAction.toAddMonoidHom _ r x = AddMonoidHom.mul (DirectSum.of _ _ _) x - apply FunLike.congr_fun _ x + apply DFunLike.congr_fun _ x ext i xi : 2 dsimp only [AddMonoidHom.comp_apply, DistribMulAction.toAddMonoidHom_apply, AddMonoidHom.mul_apply] diff --git a/Mathlib/Algebra/DirectSum/Basic.lean b/Mathlib/Algebra/DirectSum/Basic.lean index bdddfdbc4bc7c..5ac350040d99f 100644 --- a/Mathlib/Algebra/DirectSum/Basic.lean +++ b/Mathlib/Algebra/DirectSum/Basic.lean @@ -23,7 +23,8 @@ This notation is in the `DirectSum` locale, accessible after `open DirectSum`. * https://en.wikipedia.org/wiki/Direct_sum -/ -open BigOperators +open Function +open scoped BigOperators universe u v w u₁ @@ -47,8 +48,8 @@ instance [∀ i, AddCommMonoid (β i)] : Inhabited (DirectSum ι β) := instance [∀ i, AddCommMonoid (β i)] : AddCommMonoid (DirectSum ι β) := inferInstanceAs (AddCommMonoid (Π₀ i, β i)) -instance [∀ i, AddCommMonoid (β i)] : FunLike (DirectSum ι β) _ fun i : ι => β i := - inferInstanceAs (FunLike (Π₀ i, β i) _ _) +instance [∀ i, AddCommMonoid (β i)] : DFunLike (DirectSum ι β) _ fun i : ι => β i := + inferInstanceAs (DFunLike (Π₀ i, β i) _ _) instance [∀ i, AddCommMonoid (β i)] : CoeFun (DirectSum ι β) fun _ => ∀ i : ι, β i := inferInstanceAs (CoeFun (Π₀ i, β i) fun _ => ∀ i : ι, β i) @@ -183,7 +184,7 @@ See note [partially-applied ext lemmas]. -/ @[ext high] theorem addHom_ext' {γ : Type*} [AddMonoid γ] ⦃f g : (⨁ i, β i) →+ γ⦄ (H : ∀ i : ι, f.comp (of _ i) = g.comp (of _ i)) : f = g := - addHom_ext fun i => FunLike.congr_fun <| H i + addHom_ext fun i => DFunLike.congr_fun <| H i #align direct_sum.add_hom_ext' DirectSum.addHom_ext' variable {γ : Type u₁} [AddCommMonoid γ] @@ -213,6 +214,12 @@ theorem toAddMonoid.unique (f : ⨁ i, β i) : ψ f = toAddMonoid (fun i => ψ.c simp [toAddMonoid, of] #align direct_sum.to_add_monoid.unique DirectSum.toAddMonoid.unique +lemma toAddMonoid_injective : Injective (toAddMonoid : (∀ i, β i →+ γ) → (⨁ i, β i) →+ γ) := + DFinsupp.liftAddHom.injective + +@[simp] lemma toAddMonoid_inj {f g : ∀ i, β i →+ γ} : toAddMonoid f = toAddMonoid g ↔ f = g := + toAddMonoid_injective.eq_iff + end ToAddMonoid section FromAddMonoid diff --git a/Mathlib/Algebra/DirectSum/Decomposition.lean b/Mathlib/Algebra/DirectSum/Decomposition.lean index 8de190c040407..0f7e915dbb508 100644 --- a/Mathlib/Algebra/DirectSum/Decomposition.lean +++ b/Mathlib/Algebra/DirectSum/Decomposition.lean @@ -72,8 +72,8 @@ abbrev Decomposition.ofAddHom (decompose : M →+ ⨁ i, ℳ i) (h_left_inv : (DirectSum.coeAddMonoidHom ℳ).comp decompose = .id _) (h_right_inv : decompose.comp (DirectSum.coeAddMonoidHom ℳ) = .id _) : Decomposition ℳ where decompose' := decompose - left_inv := FunLike.congr_fun h_left_inv - right_inv := FunLike.congr_fun h_right_inv + left_inv := DFunLike.congr_fun h_left_inv + right_inv := DFunLike.congr_fun h_right_inv /-- Noncomputably conjure a decomposition instance from a `DirectSum.IsInternal` proof. -/ noncomputable def IsInternal.chooseDecomposition (h : IsInternal ℳ) : @@ -143,6 +143,10 @@ theorem decompose_of_mem_ne {x : M} {i j : ι} (hx : x ∈ ℳ i) (hij : i ≠ j rw [decompose_of_mem _ hx, DirectSum.of_eq_of_ne _ _ _ _ hij, ZeroMemClass.coe_zero] #align direct_sum.decompose_of_mem_ne DirectSum.decompose_of_mem_ne +theorem degree_eq_of_mem_mem {x : M} {i j : ι} (hxi : x ∈ ℳ i) (hxj : x ∈ ℳ j) (hx : x ≠ 0) : + i = j := by + contrapose! hx; rw [← decompose_of_mem_same ℳ hxj, decompose_of_mem_ne ℳ hxi hx] + /-- If `M` is graded by `ι` with degree `i` component `ℳ i`, then it is isomorphic as an additive monoid to a direct sum of components. -/ -- Porting note: deleted [simps] and added the corresponding lemmas by hand @@ -255,8 +259,8 @@ abbrev Decomposition.ofLinearMap (decompose : M →ₗ[R] ⨁ i, ℳ i) (h_left_inv : DirectSum.coeLinearMap ℳ ∘ₗ decompose = .id) (h_right_inv : decompose ∘ₗ DirectSum.coeLinearMap ℳ = .id) : Decomposition ℳ where decompose' := decompose - left_inv := FunLike.congr_fun h_left_inv - right_inv := FunLike.congr_fun h_right_inv + left_inv := DFunLike.congr_fun h_left_inv + right_inv := DFunLike.congr_fun h_right_inv variable [Decomposition ℳ] @@ -290,7 +294,7 @@ theorem decompose_lhom_ext {N} [AddCommMonoid N] [Module R N] ⦃f g : M →ₗ[ LinearMap.ext <| (decomposeLinearEquiv ℳ).symm.surjective.forall.mpr <| suffices f ∘ₗ (decomposeLinearEquiv ℳ).symm = (g ∘ₗ (decomposeLinearEquiv ℳ).symm : (⨁ i, ℳ i) →ₗ[R] N) from - FunLike.congr_fun this + DFunLike.congr_fun this linearMap_ext _ fun i => by simp_rw [LinearMap.comp_assoc, decomposeLinearEquiv_symm_comp_lof ℳ i, h] diff --git a/Mathlib/Algebra/DirectSum/Internal.lean b/Mathlib/Algebra/DirectSum/Internal.lean index 8b55b806c4736..110efc5a25771 100644 --- a/Mathlib/Algebra/DirectSum/Internal.lean +++ b/Mathlib/Algebra/DirectSum/Internal.lean @@ -33,7 +33,7 @@ needed. In the future there will likely be a data-carrying, constructive, typecl When `CompleteLattice.Independent (Set.range A)` (a weaker condition than `DirectSum.IsInternal A`), these provide a grading of `⨆ i, A i`, and the mapping `⨁ i, A i →+ ⨆ i, A i` can be obtained as -`DirectSum.toAddMonoid (fun i ↦ AddSubmonoid.inclusion $ le_iSup A i)`. +`DirectSum.toAddMonoid (fun i ↦ AddSubmonoid.inclusion <| le_iSup A i)`. ## tags diff --git a/Mathlib/Algebra/DirectSum/LinearMap.lean b/Mathlib/Algebra/DirectSum/LinearMap.lean index a9aed2d4a03b9..4d4d3e32a0f65 100644 --- a/Mathlib/Algebra/DirectSum/LinearMap.lean +++ b/Mathlib/Algebra/DirectSum/LinearMap.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ +import Mathlib.LinearAlgebra.FreeModule.Finite.Basic import Mathlib.LinearAlgebra.FreeModule.PID import Mathlib.LinearAlgebra.Eigenspace.Basic import Mathlib.LinearAlgebra.Trace @@ -17,8 +18,6 @@ domain and codomain. open Set BigOperators DirectSum -attribute [local instance] Module.free_of_finite_type_torsion_free' - variable {ι R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] {N : ι → Submodule R M} [DecidableEq ι] (h : IsInternal N) diff --git a/Mathlib/Algebra/DirectSum/Module.lean b/Mathlib/Algebra/DirectSum/Module.lean index a72253ccbc9d9..f6162f5e33486 100644 --- a/Mathlib/Algebra/DirectSum/Module.lean +++ b/Mathlib/Algebra/DirectSum/Module.lean @@ -103,7 +103,7 @@ variable (R ι N) /-- The linear map constructed using the universal property of the coproduct. -/ def toModule : (⨁ i, M i) →ₗ[R] N := - FunLike.coe (DFinsupp.lsum ℕ) φ + DFunLike.coe (DFinsupp.lsum ℕ) φ #align direct_sum.to_module DirectSum.toModule /-- Coproducts in the categories of modules and additive monoids commute with the forgetful functor diff --git a/Mathlib/Algebra/DirectSum/Ring.lean b/Mathlib/Algebra/DirectSum/Ring.lean index 66c5dbc753cd1..c42da7cd863fc 100644 --- a/Mathlib/Algebra/DirectSum/Ring.lean +++ b/Mathlib/Algebra/DirectSum/Ring.lean @@ -67,7 +67,7 @@ instances for: If `CompleteLattice.independent (Set.range A)`, these provide a gradation of `⨆ i, A i`, and the mapping `⨁ i, A i →+ ⨆ i, A i` can be obtained as -`DirectSum.toMonoid (fun i ↦ AddSubmonoid.inclusion $ le_iSup A i)`. +`DirectSum.toMonoid (fun i ↦ AddSubmonoid.inclusion <| le_iSup A i)`. ## tags @@ -226,7 +226,7 @@ variable [∀ i, AddCommMonoid (A i)] [AddMonoid ι] [GSemiring A] open AddMonoidHom (flipHom coe_comp compHom flip_apply) private nonrec theorem one_mul (x : ⨁ i, A i) : 1 * x = x := by - suffices mulHom A One.one = AddMonoidHom.id (⨁ i, A i) from FunLike.congr_fun this x + suffices mulHom A One.one = AddMonoidHom.id (⨁ i, A i) from DFunLike.congr_fun this x apply addHom_ext; intro i xi simp only [One.one] rw [mulHom_of_of] @@ -235,7 +235,7 @@ private nonrec theorem one_mul (x : ⨁ i, A i) : 1 * x = x := by -- Porting note: `suffices` is very slow here. private nonrec theorem mul_one (x : ⨁ i, A i) : x * 1 = x := by - suffices (mulHom A).flip One.one = AddMonoidHom.id (⨁ i, A i) from FunLike.congr_fun this x + suffices (mulHom A).flip One.one = AddMonoidHom.id (⨁ i, A i) from DFunLike.congr_fun this x apply addHom_ext; intro i xi simp only [One.one] rw [flip_apply, mulHom_of_of] @@ -248,7 +248,7 @@ private theorem mul_assoc (a b c : ⨁ i, A i) : a * b * c = a * (b * c) := by -- (`fun a b c => a * b * c` as a bundled hom) = (`fun a b c => a * (b * c)` as a bundled hom) suffices (mulHom A).compHom.comp (mulHom A) = (AddMonoidHom.compHom flipHom <| (mulHom A).flip.compHom.comp (mulHom A)).flip by - have sol := FunLike.congr_fun (FunLike.congr_fun (FunLike.congr_fun this a) b) c + have sol := DFunLike.congr_fun (DFunLike.congr_fun (DFunLike.congr_fun this a) b) c have aux : ∀ a b, (mulHom A) a b = a * b := fun _ _ ↦ rfl simp only [coe_comp, Function.comp_apply, AddMonoidHom.compHom_apply_apply, aux, flip_apply, AddMonoidHom.flipHom_apply] at sol diff --git a/Mathlib/Algebra/Divisibility/Prod.lean b/Mathlib/Algebra/Divisibility/Prod.lean index f671281fe9c9f..0dcdb1da28529 100644 --- a/Mathlib/Algebra/Divisibility/Prod.lean +++ b/Mathlib/Algebra/Divisibility/Prod.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ - import Mathlib.Algebra.Divisibility.Basic import Mathlib.Algebra.Group.Prod diff --git a/Mathlib/Algebra/DualNumber.lean b/Mathlib/Algebra/DualNumber.lean index 03a90e2a4815b..aaed9e2dce5ff 100644 --- a/Mathlib/Algebra/DualNumber.lean +++ b/Mathlib/Algebra/DualNumber.lean @@ -108,7 +108,7 @@ nonrec theorem algHom_ext' ⦃f g : A[ε] →ₐ[R] B⦄ algHom_ext' hinl (by ext a show f (inr a) = g (inr a) - simpa only [inr_eq_smul_eps] using FunLike.congr_fun hinr a) + simpa only [inr_eq_smul_eps] using DFunLike.congr_fun hinr a) /-- For two `R`-algebra morphisms out of `R[ε]` to agree, it suffices for them to agree on `ε`. -/ @[ext 1200] diff --git a/Mathlib/Algebra/EuclideanDomain/Defs.lean b/Mathlib/Algebra/EuclideanDomain/Defs.lean index 2cfb9c7d7ce64..7e2bc786c1d1d 100644 --- a/Mathlib/Algebra/EuclideanDomain/Defs.lean +++ b/Mathlib/Algebra/EuclideanDomain/Defs.lean @@ -186,7 +186,7 @@ theorem GCD.induction {P : R → R → Prop} (a b : R) (H0 : ∀ x, P 0 x) else have _ := mod_lt b a0 H1 _ _ a0 (GCD.induction (b % a) a H0 H1) -termination_by _ => a +termination_by a #align euclidean_domain.gcd.induction EuclideanDomain.GCD.induction end @@ -202,7 +202,7 @@ def gcd (a b : R) : R := else have _ := mod_lt b a0 gcd (b % a) a -termination_by _ => a +termination_by a #align euclidean_domain.gcd EuclideanDomain.gcd @[simp] @@ -226,7 +226,7 @@ def xgcdAux (r s t r' s' t' : R) : R × R × R := let q := r' / r have _ := mod_lt r' _hr xgcdAux (r' % r) (s' - q * s) (t' - q * t) r s t -termination_by _ => r +termination_by r #align euclidean_domain.xgcd_aux EuclideanDomain.xgcdAux @[simp] diff --git a/Mathlib/Algebra/EuclideanDomain/Instances.lean b/Mathlib/Algebra/EuclideanDomain/Instances.lean index 87c43b6a42342..a9ae72c47a1a4 100644 --- a/Mathlib/Algebra/EuclideanDomain/Instances.lean +++ b/Mathlib/Algebra/EuclideanDomain/Instances.lean @@ -33,7 +33,7 @@ instance Int.euclideanDomain : EuclideanDomain ℤ := not_lt_of_ge <| by rw [← mul_one a.natAbs, Int.natAbs_mul] rw [← Int.natAbs_pos] at b0 - exact Nat.mul_le_mul_of_nonneg_left b0 } + exact Nat.mul_le_mul_left _ b0 } -- see Note [lower instance priority] instance (priority := 100) Field.toEuclideanDomain {K : Type*} [Field K] : EuclideanDomain K := diff --git a/Mathlib/Algebra/Exact.lean b/Mathlib/Algebra/Exact.lean index 29e518b1e26f1..2e43879a40e65 100644 --- a/Mathlib/Algebra/Exact.lean +++ b/Mathlib/Algebra/Exact.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Antoine Chambert-Loir -/ -import Mathlib.LinearAlgebra.Quotient +import Mathlib.LinearAlgebra.Basic /-! # Exactness of a pair @@ -60,7 +60,7 @@ lemma LinearMap.exact_iff : Exact f g ↔ LinearMap.ker g = LinearMap.range f := Iff.symm <| SetLike.ext_iff lemma Exact.linearMap_comp_eq_zero (h : Exact f g) : g.comp f = 0 := - FunLike.coe_injective h.comp_eq_zero + DFunLike.coe_injective h.comp_eq_zero end LinearMap diff --git a/Mathlib/Algebra/Field/Basic.lean b/Mathlib/Algebra/Field/Basic.lean index 720e6cc73e8ce..94a8f28485fd1 100644 --- a/Mathlib/Algebra/Field/Basic.lean +++ b/Mathlib/Algebra/Field/Basic.lean @@ -118,6 +118,7 @@ theorem neg_div (a b : K) : -b / a = -(b / a) := by theorem neg_div' (a b : K) : -(b / a) = -b / a := by simp [neg_div] #align neg_div' neg_div' +@[simp] theorem neg_div_neg_eq (a b : K) : -a / -b = a / b := by rw [div_neg_eq_neg_div, neg_div, neg_neg] #align neg_div_neg_eq neg_div_neg_eq diff --git a/Mathlib/Algebra/Field/Opposite.lean b/Mathlib/Algebra/Field/Opposite.lean index e6747ca45234c..f316f3e7da0f4 100644 --- a/Mathlib/Algebra/Field/Opposite.lean +++ b/Mathlib/Algebra/Field/Opposite.lean @@ -44,7 +44,7 @@ instance divisionSemiring [DivisionSemiring α] : DivisionSemiring αᵐᵒᵖ : instance divisionRing [DivisionRing α] : DivisionRing αᵐᵒᵖ := { MulOpposite.divisionSemiring α, MulOpposite.ring α, MulOpposite.ratCast α with - ratCast_mk := fun a b hb h => unop_injective $ by + ratCast_mk := fun a b hb h => unop_injective <| by rw [unop_ratCast, Rat.cast_def, unop_mul, unop_inv, unop_natCast, unop_intCast, Int.commute_cast, div_eq_mul_inv] } @@ -63,7 +63,7 @@ instance divisionSemiring [DivisionSemiring α] : DivisionSemiring αᵃᵒᵖ : instance divisionRing [DivisionRing α] : DivisionRing αᵃᵒᵖ := { AddOpposite.ring α, AddOpposite.groupWithZero α, AddOpposite.ratCast α with - ratCast_mk := fun a b hb h => unop_injective $ by + ratCast_mk := fun a b hb h => unop_injective <| by rw [unop_ratCast, Rat.cast_def, unop_mul, unop_inv, unop_natCast, unop_intCast, div_eq_mul_inv] } diff --git a/Mathlib/Algebra/Field/ULift.lean b/Mathlib/Algebra/Field/ULift.lean index c500dc340d5e2..244e62c26cb4f 100644 --- a/Mathlib/Algebra/Field/ULift.lean +++ b/Mathlib/Algebra/Field/ULift.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Field.Basic -import Mathlib.Algebra.Ring.ULift +import Mathlib.Algebra.Group.ULift #align_import algebra.field.ulift from "leanprover-community/mathlib"@"13e18cfa070ea337ea960176414f5ae3a1534aae" diff --git a/Mathlib/Algebra/Free.lean b/Mathlib/Algebra/Free.lean index a9cb30b036d8e..ed850ff640854 100644 --- a/Mathlib/Algebra/Free.lean +++ b/Mathlib/Algebra/Free.lean @@ -81,7 +81,7 @@ def recOnMul {C : FreeMagma α → Sort l} (x) (ih1 : ∀ x, C (of x)) @[to_additive (attr := ext 1100)] theorem hom_ext {β : Type v} [Mul β] {f g : FreeMagma α →ₙ* β} (h : f ∘ of = g ∘ of) : f = g := - (FunLike.ext _ _) fun x ↦ recOnMul x (congr_fun h) <| by intros; simp only [map_mul, *] + (DFunLike.ext _ _) fun x ↦ recOnMul x (congr_fun h) <| by intros; simp only [map_mul, *] #align free_magma.hom_ext FreeMagma.hom_ext end FreeMagma @@ -390,7 +390,7 @@ variable {β : Type v} [Semigroup β] (f : α →ₙ* β) @[to_additive (attr := ext 1100)] theorem hom_ext {f g : AssocQuotient α →ₙ* β} (h : f.comp of = g.comp of) : f = g := - (FunLike.ext _ _) fun x => AssocQuotient.induction_on x <| FunLike.congr_fun h + (DFunLike.ext _ _) fun x => AssocQuotient.induction_on x <| DFunLike.congr_fun h #align magma.assoc_quotient.hom_ext Magma.AssocQuotient.hom_ext /-- Lifts a magma homomorphism `α → β` to a semigroup homomorphism `Magma.AssocQuotient α → β` @@ -403,8 +403,8 @@ def lift : (α →ₙ* β) ≃ (AssocQuotient α →ₙ* β) where Quot.liftOn x f <| by rintro a b (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only [map_mul, mul_assoc] map_mul' := fun x y ↦ Quot.induction_on₂ x y (map_mul f) } invFun f := f.comp of - left_inv f := (FunLike.ext _ _) fun x ↦ rfl - right_inv f := hom_ext <| (FunLike.ext _ _) fun x ↦ rfl + left_inv f := (DFunLike.ext _ _) fun x ↦ rfl + right_inv f := hom_ext <| (DFunLike.ext _ _) fun x ↦ rfl #align magma.assoc_quotient.lift Magma.AssocQuotient.lift @[to_additive (attr := simp)] @@ -511,7 +511,7 @@ protected def recOnMul {C : FreeSemigroup α → Sort l} (x) (ih1 : ∀ x, C (of @[to_additive (attr := ext 1100)] theorem hom_ext {β : Type v} [Mul β] {f g : FreeSemigroup α →ₙ* β} (h : f ∘ of = g ∘ of) : f = g := - (FunLike.ext _ _) fun x ↦ + (DFunLike.ext _ _) fun x ↦ FreeSemigroup.recOnMul x (congr_fun h) fun x y hx hy ↦ by simp only [map_mul, *] #align free_semigroup.hom_ext FreeSemigroup.hom_ext @@ -731,7 +731,7 @@ theorem toFreeSemigroup_comp_map (f : α → β) : @[to_additive] theorem toFreeSemigroup_map (f : α → β) (x : FreeMagma α) : toFreeSemigroup (map f x) = FreeSemigroup.map f (toFreeSemigroup x) := - FunLike.congr_fun (toFreeSemigroup_comp_map f) x + DFunLike.congr_fun (toFreeSemigroup_comp_map f) x #align free_magma.to_free_semigroup_map FreeMagma.toFreeSemigroup_map @[to_additive (attr := simp)] diff --git a/Mathlib/Algebra/FreeAlgebra.lean b/Mathlib/Algebra/FreeAlgebra.lean index c0a84fc39b2e0..5b1c2c5e014aa 100644 --- a/Mathlib/Algebra/FreeAlgebra.lean +++ b/Mathlib/Algebra/FreeAlgebra.lean @@ -6,7 +6,6 @@ Authors: Scott Morrison, Adam Topaz, Eric Wieser import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Algebra.Algebra.Tower import Mathlib.Algebra.MonoidAlgebra.Basic -import Mathlib.Algebra.Free import Mathlib.RingTheory.Adjoin.Basic #align_import algebra.free_algebra from "leanprover-community/mathlib"@"6623e6af705e97002a9054c1c05a980180276fc1" diff --git a/Mathlib/Algebra/FreeMonoid/Basic.lean b/Mathlib/Algebra/FreeMonoid/Basic.lean index c6f9728026773..fba031cfb0298 100644 --- a/Mathlib/Algebra/FreeMonoid/Basic.lean +++ b/Mathlib/Algebra/FreeMonoid/Basic.lean @@ -31,10 +31,6 @@ def FreeMonoid (α) := List α namespace FreeMonoid --- Porting note: TODO. Check this is still needed -@[to_additive] -instance [DecidableEq α] : DecidableEq (FreeMonoid α) := instDecidableEqList - /-- The identity equivalence between `FreeMonoid α` and `List α`. -/ @[to_additive "The identity equivalence between `FreeAddMonoid α` and `List α`."] def toList : FreeMonoid α ≃ List α := Equiv.refl _ @@ -85,8 +81,8 @@ instance : CancelMonoid (FreeMonoid α) mul_one := List.append_nil one_mul := List.nil_append mul_assoc := List.append_assoc - mul_left_cancel _ _ _ := List.append_left_cancel - mul_right_cancel _ _ _ := List.append_right_cancel + mul_left_cancel _ _ _ := List.append_cancel_left + mul_right_cancel _ _ _ := List.append_cancel_right @[to_additive] instance : Inhabited (FreeMonoid α) := ⟨1⟩ @@ -275,7 +271,7 @@ theorem comp_lift (g : M →* N) (f : α → M) : g.comp (lift f) = lift (g ∘ @[to_additive] theorem hom_map_lift (g : M →* N) (f : α → M) (x : FreeMonoid α) : g (lift f x) = lift (g ∘ f) x := - FunLike.ext_iff.1 (comp_lift g f) x + DFunLike.ext_iff.1 (comp_lift g f) x #align free_monoid.hom_map_lift FreeMonoid.hom_map_lift #align free_add_monoid.hom_map_lift FreeAddMonoid.hom_map_lift @@ -355,7 +351,7 @@ theorem map_id : map (@id α) = MonoidHom.id (FreeMonoid α) := hom_eq fun _ ↦ @[to_additive] instance uniqueUnits : Unique (FreeMonoid α)ˣ where uniq u := Units.ext <| toList.injective <| - have : toList u.val ++ toList u.inv = [] := FunLike.congr_arg toList u.val_inv + have : toList u.val ++ toList u.inv = [] := DFunLike.congr_arg toList u.val_inv (List.append_eq_nil.mp this).1 end FreeMonoid diff --git a/Mathlib/Algebra/FreeMonoid/Count.lean b/Mathlib/Algebra/FreeMonoid/Count.lean index 0930e6a4643ce..5e98aa8ec3082 100644 --- a/Mathlib/Algebra/FreeMonoid/Count.lean +++ b/Mathlib/Algebra/FreeMonoid/Count.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.FreeMonoid.Basic -import Mathlib.Data.List.Count #align_import algebra.free_monoid.count from "leanprover-community/mathlib"@"a2d2e18906e2b62627646b5d5be856e6a642062f" diff --git a/Mathlib/Algebra/Function/Indicator.lean b/Mathlib/Algebra/Function/Indicator.lean index d526c432bf782..460f69c531a13 100644 --- a/Mathlib/Algebra/Function/Indicator.lean +++ b/Mathlib/Algebra/Function/Indicator.lean @@ -380,6 +380,7 @@ theorem mulIndicator_union_of_disjoint (h : Disjoint s t) (f : α → M) : #align set.mul_indicator_union_of_disjoint Set.mulIndicator_union_of_disjoint #align set.indicator_union_of_disjoint Set.indicator_union_of_disjoint +open scoped symmDiff in @[to_additive] theorem mulIndicator_symmDiff (s t : Set α) (f : α → M) : mulIndicator (s ∆ t) f = mulIndicator (s \ t) f * mulIndicator (t \ s) f := @@ -532,6 +533,7 @@ theorem mulIndicator_diff' (h : s ⊆ t) (f : α → G) : rw [mulIndicator_diff h, div_eq_mul_inv] #align set.indicator_diff Set.indicator_diff +open scoped symmDiff in @[to_additive] theorem apply_mulIndicator_symmDiff {g : G → β} (hg : ∀ x, g x⁻¹ = g x) (s t : Set α) (f : α → G) (x : α): diff --git a/Mathlib/Algebra/Function/Support.lean b/Mathlib/Algebra/Function/Support.lean index 7aa21a278e370..db6a792703cb0 100644 --- a/Mathlib/Algebra/Function/Support.lean +++ b/Mathlib/Algebra/Function/Support.lean @@ -138,7 +138,7 @@ theorem range_subset_insert_image_mulSupport (f : α → M) : @[to_additive] lemma range_eq_image_or_of_mulSupport_subset {f : α → M} {k : Set α} (h : mulSupport f ⊆ k) : range f = f '' k ∨ range f = insert 1 (f '' k) := by - apply (wcovby_insert _ _).eq_or_eq (image_subset_range _ _) + apply (wcovBy_insert _ _).eq_or_eq (image_subset_range _ _) exact (range_subset_insert_image_mulSupport f).trans (insert_subset_insert (image_subset f h)) @[to_additive (attr := simp)] diff --git a/Mathlib/Algebra/GCDMonoid/Basic.lean b/Mathlib/Algebra/GCDMonoid/Basic.lean index 588b3f640a193..996392c72d6ff 100644 --- a/Mathlib/Algebra/GCDMonoid/Basic.lean +++ b/Mathlib/Algebra/GCDMonoid/Basic.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Jens Wagemaker -/ import Mathlib.Algebra.Associated -import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Algebra.Ring.Regular import Mathlib.Tactic.Common diff --git a/Mathlib/Algebra/GeomSum.lean b/Mathlib/Algebra/GeomSum.lean index 6d6d69b4eb1c5..dc236ddadfa79 100644 --- a/Mathlib/Algebra/GeomSum.lean +++ b/Mathlib/Algebra/GeomSum.lean @@ -191,7 +191,7 @@ theorem geom_sum₂_mul [CommRing α] (x y : α) (n : ℕ) : theorem Commute.sub_dvd_pow_sub_pow [Ring α] {x y : α} (h : Commute x y) (n : ℕ) : x - y ∣ x ^ n - y ^ n := - Dvd.intro _ $ h.mul_geom_sum₂ _ + Dvd.intro _ <| h.mul_geom_sum₂ _ theorem sub_dvd_pow_sub_pow [CommRing α] (x y : α) (n : ℕ) : x - y ∣ x ^ n - y ^ n := (Commute.all x y).sub_dvd_pow_sub_pow n @@ -591,14 +591,15 @@ variable {m n : ℕ} {s : Finset ℕ} `m ≥ 2` is less than `m ^ n`. -/ lemma Nat.geomSum_eq (hm : 2 ≤ m) (n : ℕ) : ∑ k in range n, m ^ k = (m ^ n - 1) / (m - 1) := by - refine (Nat.div_eq_of_eq_mul_left (tsub_pos_iff_lt.2 hm) $ tsub_eq_of_eq_add ?_).symm - simpa only [tsub_add_cancel_of_le $ one_le_two.trans hm, eq_comm] using geom_sum_mul_add (m - 1) n + refine (Nat.div_eq_of_eq_mul_left (tsub_pos_iff_lt.2 hm) <| tsub_eq_of_eq_add ?_).symm + simpa only [tsub_add_cancel_of_le (one_le_two.trans hm), eq_comm] using geom_sum_mul_add (m - 1) n /-- If all the elements of a finset of naturals are less than `n`, then the sum of their powers of `m ≥ 2` is less than `m ^ n`. -/ lemma Nat.geomSum_lt (hm : 2 ≤ m) (hs : ∀ k ∈ s, k < n) : ∑ k in s, m ^ k < m ^ n := calc - ∑ k in s, m ^ k ≤ ∑ k in range n, m ^ k := sum_le_sum_of_subset fun k hk ↦ mem_range.2 $ hs _ hk + ∑ k in s, m ^ k ≤ ∑ k in range n, m ^ k := sum_le_sum_of_subset fun k hk ↦ + mem_range.2 <| hs _ hk _ = (m ^ n - 1) / (m - 1) := Nat.geomSum_eq hm _ _ ≤ m ^ n - 1 := Nat.div_le_self _ _ _ < m ^ n := tsub_lt_self (by positivity) zero_lt_one diff --git a/Mathlib/Algebra/Group/Basic.lean b/Mathlib/Algebra/Group/Basic.lean index 89e25c2caf288..9cc7b2c117dbc 100644 --- a/Mathlib/Algebra/Group/Basic.lean +++ b/Mathlib/Algebra/Group/Basic.lean @@ -4,8 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Simon Hudon, Mario Carneiro -/ import Mathlib.Algebra.Group.Defs -import Mathlib.Tactic.SimpRw +import Mathlib.Logic.Function.Basic import Mathlib.Tactic.Cases +import Mathlib.Tactic.SimpRw +import Mathlib.Tactic.SplitIfs #align_import algebra.group.basic from "leanprover-community/mathlib"@"a07d750983b94c530ab69a726862c2ab6802b38c" @@ -24,14 +26,66 @@ universe u variable {α β G : Type*} +section IsLeftCancelMul + +variable [Mul G] [IsLeftCancelMul G] + +@[to_additive] +theorem mul_right_injective (a : G) : Injective (a * ·) := fun _ _ ↦ mul_left_cancel +#align mul_right_injective mul_right_injective +#align add_right_injective add_right_injective + +@[to_additive (attr := simp)] +theorem mul_right_inj (a : G) {b c : G} : a * b = a * c ↔ b = c := + (mul_right_injective a).eq_iff +#align mul_right_inj mul_right_inj +#align add_right_inj add_right_inj + +@[to_additive] +theorem mul_ne_mul_right (a : G) {b c : G} : a * b ≠ a * c ↔ b ≠ c := + (mul_right_injective a).ne_iff +#align mul_ne_mul_right mul_ne_mul_right +#align add_ne_add_right add_ne_add_right + +end IsLeftCancelMul + +section IsRightCancelMul + +variable [Mul G] [IsRightCancelMul G] + +@[to_additive] +theorem mul_left_injective (a : G) : Function.Injective (· * a) := fun _ _ ↦ mul_right_cancel +#align mul_left_injective mul_left_injective +#align add_left_injective add_left_injective + +@[to_additive (attr := simp)] +theorem mul_left_inj (a : G) {b c : G} : b * a = c * a ↔ b = c := + (mul_left_injective a).eq_iff +#align mul_left_inj mul_left_inj +#align add_left_inj add_left_inj + +@[to_additive] +theorem mul_ne_mul_left (a : G) {b c : G} : b * a ≠ c * a ↔ b ≠ c := + (mul_left_injective a).ne_iff +#align mul_ne_mul_left mul_ne_mul_left +#align add_ne_add_left add_ne_add_left + +end IsRightCancelMul + section Semigroup +variable [Semigroup α] + +@[to_additive] +instance Semigroup.to_isAssociative : IsAssociative α (· * ·) := ⟨mul_assoc⟩ +#align semigroup.to_is_associative Semigroup.to_isAssociative +#align add_semigroup.to_is_associative AddSemigroup.to_isAssociative /-- Composing two multiplications on the left by `y` then `x` is equal to a multiplication on the left by `x * y`. -/ @[to_additive (attr := simp) "Composing two additions on the left by `y` then `x` is equal to an addition on the left by `x + y`."] -theorem comp_mul_left [Semigroup α] (x y : α) : (x * ·) ∘ (y * ·) = (x * y * ·) := by +theorem comp_mul_left (x y : α) : (x * ·) ∘ (y * ·) = (x * y * ·) := by ext z simp [mul_assoc] #align comp_mul_left comp_mul_left @@ -42,7 +96,7 @@ is equal to a multiplication on the right by `y * x`. -/ @[to_additive (attr := simp) "Composing two additions on the right by `y` and `x` is equal to an addition on the right by `y + x`."] -theorem comp_mul_right [Semigroup α] (x y : α) : (· * x) ∘ (· * y) = (· * (y * x)) := by +theorem comp_mul_right (x y : α) : (· * x) ∘ (· * y) = (· * (y * x)) := by ext z simp [mul_assoc] #align comp_mul_right comp_mul_right @@ -50,6 +104,11 @@ theorem comp_mul_right [Semigroup α] (x y : α) : (· * x) ∘ (· * y) = (· * end Semigroup +@[to_additive] +instance CommMagma.to_isCommutative [CommMagma G] : IsCommutative G (· * ·) := ⟨mul_comm⟩ +#align comm_semigroup.to_is_commutative CommMagma.to_isCommutative +#align add_comm_semigroup.to_is_commutative AddCommMagma.to_isCommutative + section MulOneClass variable {M : Type u} [MulOneClass M] @@ -1055,3 +1114,27 @@ theorem multiplicative_of_isTotal (p : α → Prop) (hswap : ∀ {a b}, p a → exacts [⟨pa, pb⟩, ⟨pb, pc⟩, ⟨pa, pc⟩] #align multiplicative_of_is_total multiplicative_of_isTotal #align additive_of_is_total additive_of_isTotal + +section ite +variable {α β : Type*} [Pow α β] + +@[to_additive (attr := simp) dite_smul] +lemma pow_dite (p : Prop) [Decidable p] (a : α) (b : p → β) (c : ¬ p → β) : + a ^ (if h : p then b h else c h) = if h : p then a ^ b h else a ^ c h := by split_ifs <;> rfl + +@[to_additive (attr := simp) smul_dite] +lemma dite_pow (p : Prop) [Decidable p] (a : p → α) (b : ¬ p → α) (c : β) : + (if h : p then a h else b h) ^ c = if h : p then a h ^ c else b h ^ c := by split_ifs <;> rfl + +@[to_additive (attr := simp) ite_smul] +lemma pow_ite (p : Prop) [Decidable p] (a : α) (b c : β) : + a ^ (if p then b else c) = if p then a ^ b else a ^ c := pow_dite _ _ _ _ + +@[to_additive (attr := simp) smul_ite] +lemma ite_pow (p : Prop) [Decidable p] (a b : α) (c : β) : + (if p then a else b) ^ c = if p then a ^ c else b ^ c := dite_pow _ _ _ _ + +set_option linter.existingAttributeWarning false in +attribute [to_additive (attr := simp)] dite_smul smul_dite ite_smul smul_ite + +end ite diff --git a/Mathlib/Algebra/Group/Commute/Defs.lean b/Mathlib/Algebra/Group/Commute/Defs.lean index 0cf1cc337e983..bd1e121ee007a 100644 --- a/Mathlib/Algebra/Group/Commute/Defs.lean +++ b/Mathlib/Algebra/Group/Commute/Defs.lean @@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Neil Strickland, Yury Kudryashov -/ import Mathlib.Algebra.Group.Semiconj.Defs +import Mathlib.Data.Nat.Defs +import Mathlib.Init.Algebra.Classes #align_import algebra.group.commute from "leanprover-community/mathlib"@"05101c3df9d9cfe9430edc205860c79b6d660102" @@ -209,12 +211,6 @@ theorem pow_pow_self (a : M) (m n : ℕ) : Commute (a ^ m) (a ^ n) := #align add_commute.nsmul_nsmul_self AddCommute.nsmul_nsmul_selfₓ -- `MulOneClass.toHasMul` vs. `MulOneClass.toMul` -@[to_additive succ_nsmul'] -theorem _root_.pow_succ' (a : M) (n : ℕ) : a ^ (n + 1) = a ^ n * a := - (pow_succ a n).trans (self_pow _ _) -#align pow_succ' pow_succ' -#align succ_nsmul' succ_nsmul' - end Monoid section DivisionMonoid @@ -253,6 +249,25 @@ end Group end Commute +section Monoid +variable {M : Type*} [Monoid M] {n : ℕ} + +@[to_additive succ_nsmul'] +lemma pow_succ' (a : M) (n : ℕ) : a ^ (n + 1) = a ^ n * a := + (pow_succ a n).trans (Commute.self_pow _ _) +#align pow_succ' pow_succ' +#align succ_nsmul' succ_nsmul' + +@[to_additive] +lemma mul_pow_sub_one (hn : n ≠ 0) (a : M) : a * a ^ (n - 1) = a ^ n := by + rw [← pow_succ, Nat.sub_add_cancel $ Nat.one_le_iff_ne_zero.2 hn] + +@[to_additive] +lemma pow_sub_one_mul (hn : n ≠ 0) (a : M) : a ^ (n - 1) * a = a ^ n := by + rw [← pow_succ', Nat.sub_add_cancel $ Nat.one_le_iff_ne_zero.2 hn] + +end Monoid + section CommGroup variable [CommGroup G] (a b : G) diff --git a/Mathlib/Algebra/Group/Commute/Units.lean b/Mathlib/Algebra/Group/Commute/Units.lean index e047ec8da22da..1f388b811cec8 100644 --- a/Mathlib/Algebra/Group/Commute/Units.lean +++ b/Mathlib/Algebra/Group/Commute/Units.lean @@ -13,14 +13,12 @@ import Mathlib.Algebra.Group.Semiconj.Units -/ - -variable {G : Type*} - -namespace Commute +variable {M : Type*} section Monoid +variable [Monoid M] {n : ℕ} {a b : M} {u u₁ u₂ : Mˣ} -variable {M : Type*} [Monoid M] {a b : M} {u u₁ u₂ : Mˣ} +namespace Commute @[to_additive] theorem units_inv_right : Commute a u → Commute a ↑u⁻¹ := @@ -64,10 +62,12 @@ theorem units_val_iff : Commute (u₁ : M) u₂ ↔ Commute u₁ u₂ := #align commute.units_coe_iff Commute.units_val_iff #align add_commute.add_units_coe_iff AddCommute.addUnits_val_iff +end Commute + /-- If the product of two commuting elements is a unit, then the left multiplier is a unit. -/ @[to_additive "If the sum of two commuting elements is an additive unit, then the left summand is an additive unit."] -def _root_.Units.leftOfMul (u : Mˣ) (a b : M) (hu : a * b = u) (hc : Commute a b) : Mˣ where +def Units.leftOfMul (u : Mˣ) (a b : M) (hu : a * b = u) (hc : Commute a b) : Mˣ where val := a inv := b * ↑u⁻¹ val_inv := by rw [← mul_assoc, hu, u.mul_inv] @@ -80,23 +80,82 @@ def _root_.Units.leftOfMul (u : Mˣ) (a b : M) (hu : a * b = u) (hc : Commute a /-- If the product of two commuting elements is a unit, then the right multiplier is a unit. -/ @[to_additive "If the sum of two commuting elements is an additive unit, then the right summand is an additive unit."] -def _root_.Units.rightOfMul (u : Mˣ) (a b : M) (hu : a * b = u) (hc : Commute a b) : Mˣ := +def Units.rightOfMul (u : Mˣ) (a b : M) (hu : a * b = u) (hc : Commute a b) : Mˣ := u.leftOfMul b a (hc.eq ▸ hu) hc.symm #align units.right_of_mul Units.rightOfMul #align add_units.right_of_add AddUnits.rightOfAdd @[to_additive] -theorem isUnit_mul_iff (h : Commute a b) : IsUnit (a * b) ↔ IsUnit a ∧ IsUnit b := +theorem Commute.isUnit_mul_iff (h : Commute a b) : IsUnit (a * b) ↔ IsUnit a ∧ IsUnit b := ⟨fun ⟨u, hu⟩ => ⟨(u.leftOfMul a b hu.symm h).isUnit, (u.rightOfMul a b hu.symm h).isUnit⟩, fun H => H.1.mul H.2⟩ #align commute.is_unit_mul_iff Commute.isUnit_mul_iff #align add_commute.is_add_unit_add_iff AddCommute.isAddUnit_add_iff @[to_additive (attr := simp)] -theorem _root_.isUnit_mul_self_iff : IsUnit (a * a) ↔ IsUnit a := +theorem isUnit_mul_self_iff : IsUnit (a * a) ↔ IsUnit a := (Commute.refl a).isUnit_mul_iff.trans and_self_iff #align is_unit_mul_self_iff isUnit_mul_self_iff #align is_add_unit_add_self_iff isAddUnit_add_self_iff +@[to_additive (attr := simp)] +lemma Commute.units_zpow_right (h : Commute a u) (m : ℤ) : Commute a ↑(u ^ m) := + SemiconjBy.units_zpow_right h m +#align commute.units_zpow_right Commute.units_zpow_right +#align add_commute.add_units_zsmul_right AddCommute.addUnits_zsmul_right + +@[to_additive (attr := simp)] +lemma Commute.units_zpow_left (h : Commute ↑u a) (m : ℤ) : Commute ↑(u ^ m) a := + (h.symm.units_zpow_right m).symm +#align commute.units_zpow_left Commute.units_zpow_left +#align add_commute.add_units_zsmul_left AddCommute.addUnits_zsmul_left + +/-- If a natural power of `x` is a unit, then `x` is a unit. -/ +@[to_additive "If a natural multiple of `x` is an additive unit, then `x` is an additive unit."] +def Units.ofPow (u : Mˣ) (x : M) {n : ℕ} (hn : n ≠ 0) (hu : x ^ n = u) : Mˣ := + u.leftOfMul x (x ^ (n - 1)) + (by rwa [← _root_.pow_succ, Nat.sub_add_cancel (Nat.succ_le_of_lt <| Nat.pos_of_ne_zero hn)]) + (Commute.self_pow _ _) +#align units.of_pow Units.ofPow +#align add_units.of_nsmul AddUnits.ofNSMul + +@[to_additive (attr := simp)] lemma isUnit_pow_iff (hn : n ≠ 0) : IsUnit (a ^ n) ↔ IsUnit a := + ⟨fun ⟨u, hu⟩ ↦ (u.ofPow a hn hu.symm).isUnit, IsUnit.pow n⟩ +#align is_unit_pow_iff isUnit_pow_iff +#align is_add_unit_nsmul_iff isAddUnit_nsmul_iff + +@[to_additive] +lemma isUnit_pow_succ_iff : IsUnit (a ^ (n + 1)) ↔ IsUnit a := isUnit_pow_iff n.succ_ne_zero +#align is_unit_pow_succ_iff isUnit_pow_succ_iff +#align is_add_unit_nsmul_succ_iff isAddUnit_nsmul_succ_iff + +/-- If `a ^ n = 1`, `n ≠ 0`, then `a` is a unit. -/ +@[to_additive (attr := simps!) "If `n • x = 0`, `n ≠ 0`, then `x` is an additive unit."] +def Units.ofPowEqOne (a : M) (n : ℕ) (ha : a ^ n = 1) (hn : n ≠ 0) : Mˣ := Units.ofPow 1 a hn ha +#align units.of_pow_eq_one Units.ofPowEqOne +#align add_units.of_nsmul_eq_zero AddUnits.ofNSMulEqZero + +@[to_additive (attr := simp)] +lemma Units.pow_ofPowEqOne (ha : a ^ n = 1) (hn : n ≠ 0) : + Units.ofPowEqOne _ n ha hn ^ n = 1 := Units.ext <| by simp [ha] +#align units.pow_of_pow_eq_one Units.pow_ofPowEqOne +#align add_units.nsmul_of_nsmul_eq_zero AddUnits.nsmul_ofNSMulEqZero + +@[to_additive] +lemma isUnit_ofPowEqOne (ha : a ^ n = 1) (hn : n ≠ 0) : IsUnit a := + (Units.ofPowEqOne _ n ha hn).isUnit +#align is_unit_of_pow_eq_one isUnit_ofPowEqOne +#align is_add_unit_of_nsmul_eq_zero isAddUnit_ofNSMulEqZero + end Monoid -end Commute + +section DivisionMonoid +variable [DivisionMonoid M] {a b c d : M} + +@[to_additive] +lemma Commute.div_eq_div_iff_of_isUnit (hbd : Commute b d) (hb : IsUnit b) (hd : IsUnit d) : + a / b = c / d ↔ a * d = c * b := by + rw [← (hb.mul hd).mul_left_inj, ← mul_assoc, hb.div_mul_cancel, ← mul_assoc, hbd.right_comm, + hd.div_mul_cancel] + +end DivisionMonoid diff --git a/Mathlib/Algebra/Group/Conj.lean b/Mathlib/Algebra/Group/Conj.lean index 2f7ca4622f96d..d9626874b66ba 100644 --- a/Mathlib/Algebra/Group/Conj.lean +++ b/Mathlib/Algebra/Group/Conj.lean @@ -4,9 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Chris Hughes, Michael Howes -/ import Mathlib.Algebra.Group.Aut -import Mathlib.Algebra.Group.Hom.Defs -import Mathlib.Algebra.Group.Semiconj.Defs -import Mathlib.Algebra.GroupWithZero.Basic +import Mathlib.Algebra.Group.Semiconj.Units #align_import algebra.group.conj from "leanprover-community/mathlib"@"0743cc5d9d86bcd1bba10f480e948a257d65056f" diff --git a/Mathlib/Algebra/Group/Defs.lean b/Mathlib/Algebra/Group/Defs.lean index 5871222cc782d..21534c8fd115f 100644 --- a/Mathlib/Algebra/Group/Defs.lean +++ b/Mathlib/Algebra/Group/Defs.lean @@ -3,10 +3,13 @@ Copyright (c) 2014 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Simon Hudon, Mario Carneiro -/ -import Mathlib.Init.ZeroOne import Mathlib.Init.Data.Int.Basic -import Mathlib.Logic.Function.Basic -import Mathlib.Tactic.Basic +import Mathlib.Init.ZeroOne +import Mathlib.Tactic.Lemma +import Mathlib.Tactic.TypeStar +import Mathlib.Tactic.Simps.Basic +import Mathlib.Tactic.ToAdditive +import Mathlib.Util.AssertExists #align_import algebra.group.defs from "leanprover-community/mathlib"@"48fb5b5280e7c81672afc9524185ae994553ebf4" @@ -25,12 +28,15 @@ The file does not contain any lemmas except for For basic lemmas about these classes see `Algebra.Group.Basic`. -We also introduce notation classes `lul` and `VAdd` for multiplicative and additive +We also introduce notation classes `SMul` and `VAdd` for multiplicative and additive actions and register the following instances: - `Pow M ℕ`, for monoids `M`, and `Pow G ℤ` for groups `G`; - `SMul ℕ M` for additive monoids `M`, and `SMul ℤ G` for additive groups `G`. +`SMul` is typically, but not exclusively, used for scalar multiplication-like operators. +See the module `Algebra.AddTorsor` for a motivating example for the name `VAdd` (vector addition)`. + ## Notation - `+`, `-`, `*`, `/`, `^` : the usual arithmetic operations; the underlying functions are @@ -220,27 +226,10 @@ theorem mul_left_cancel : a * b = a * c → b = c := @[to_additive] theorem mul_left_cancel_iff : a * b = a * c ↔ b = c := - ⟨mul_left_cancel, congr_arg _⟩ + ⟨mul_left_cancel, congrArg _⟩ #align mul_left_cancel_iff mul_left_cancel_iff #align add_left_cancel_iff add_left_cancel_iff -@[to_additive] -theorem mul_right_injective (a : G) : Injective (a * ·) := fun _ _ ↦ mul_left_cancel -#align mul_right_injective mul_right_injective -#align add_right_injective add_right_injective - -@[to_additive (attr := simp)] -theorem mul_right_inj (a : G) {b c : G} : a * b = a * c ↔ b = c := - (mul_right_injective a).eq_iff -#align mul_right_inj mul_right_inj -#align add_right_inj add_right_inj - -@[to_additive] -theorem mul_ne_mul_right (a : G) {b c : G} : a * b ≠ a * c ↔ b ≠ c := - (mul_right_injective a).ne_iff -#align mul_ne_mul_right mul_ne_mul_right -#align add_ne_add_right add_ne_add_right - end IsLeftCancelMul section IsRightCancelMul @@ -255,27 +244,10 @@ theorem mul_right_cancel : a * b = c * b → a = c := @[to_additive] theorem mul_right_cancel_iff : b * a = c * a ↔ b = c := - ⟨mul_right_cancel, congr_arg (· * a)⟩ + ⟨mul_right_cancel, congrArg (· * a)⟩ #align mul_right_cancel_iff mul_right_cancel_iff #align add_right_cancel_iff add_right_cancel_iff -@[to_additive] -theorem mul_left_injective (a : G) : Function.Injective (· * a) := fun _ _ ↦ mul_right_cancel -#align mul_left_injective mul_left_injective -#align add_left_injective add_left_injective - -@[to_additive (attr := simp)] -theorem mul_left_inj (a : G) {b c : G} : b * a = c * a ↔ b = c := - (mul_left_injective a).eq_iff -#align mul_left_inj mul_left_inj -#align add_left_inj add_left_inj - -@[to_additive] -theorem mul_ne_mul_left (a : G) {b c : G} : b * a ≠ c * a ↔ b ≠ c := - (mul_left_injective a).ne_iff -#align mul_ne_mul_left mul_ne_mul_left -#align add_ne_add_left add_ne_add_left - end IsRightCancelMul end Mul @@ -310,12 +282,6 @@ theorem mul_assoc : ∀ a b c : G, a * b * c = a * (b * c) := #align mul_assoc mul_assoc #align add_assoc add_assoc -@[to_additive] -instance Semigroup.to_isAssociative : IsAssociative G (· * ·) := - ⟨mul_assoc⟩ -#align semigroup.to_is_associative Semigroup.to_isAssociative -#align add_semigroup.to_is_associative AddSemigroup.to_isAssociative - end Semigroup /-- A commutative addition is a type with an addition which commutes-/ @@ -358,11 +324,6 @@ theorem mul_comm : ∀ a b : G, a * b = b * a := CommMagma.mul_comm #align mul_comm mul_comm #align add_comm add_comm -@[to_additive] -instance CommMagma.to_isCommutative : IsCommutative G (· * ·) := ⟨mul_comm⟩ -#align comm_semigroup.to_is_commutative CommMagma.to_isCommutative -#align add_comm_semigroup.to_is_commutative AddCommMagma.to_isCommutative - /-- Any `CommMagma G` that satisfies `IsRightCancelMul G` also satisfies `IsLeftCancelMul G`. -/ @[to_additive AddCommMagma.IsRightCancelAdd.toIsLeftCancelAdd "Any `AddCommMagma G` that satisfies `IsRightCancelAdd G` also satisfies `IsLeftCancelAdd G`."] @@ -992,7 +953,7 @@ theorem zpow_ofNat (a : G) : ∀ n : ℕ, a ^ (n : ℤ) = a ^ n | 0 => (zpow_zero _).trans (pow_zero _).symm | n + 1 => calc a ^ (↑(n + 1) : ℤ) = a * a ^ (n : ℤ) := DivInvMonoid.zpow_succ' _ _ - _ = a * a ^ n := congr_arg (a * ·) (zpow_ofNat a n) + _ = a * a ^ n := congrArg (a * ·) (zpow_ofNat a n) _ = a ^ (n + 1) := (pow_succ _ _).symm #align zpow_coe_nat zpow_ofNat #align zpow_of_nat zpow_ofNat @@ -1230,12 +1191,6 @@ instance (priority := 100) Group.toCancelMonoid : CancelMonoid G := end Group -@[to_additive] -theorem Group.toDivInvMonoid_injective {G : Type*} : - Function.Injective (@Group.toDivInvMonoid G) := by rintro ⟨⟩ ⟨⟩ ⟨⟩; rfl -#align group.to_div_inv_monoid_injective Group.toDivInvMonoid_injective -#align add_group.to_sub_neg_add_monoid_injective AddGroup.toSubNegAddMonoid_injective - /-- An additive commutative group is an additive group with commutative `(+)`. -/ class AddCommGroup (G : Type u) extends AddGroup G, AddCommMonoid G #align add_comm_group AddCommGroup @@ -1247,12 +1202,6 @@ class CommGroup (G : Type u) extends Group G, CommMonoid G attribute [to_additive existing] CommGroup.toCommMonoid -@[to_additive] -theorem CommGroup.toGroup_injective {G : Type u} : Function.Injective (@CommGroup.toGroup G) := by - rintro ⟨⟩ ⟨⟩ ⟨⟩; rfl -#align comm_group.to_group_injective CommGroup.toGroup_injective -#align add_comm_group.to_add_group_injective AddCommGroup.toAddGroup_injective - section CommGroup variable [CommGroup G] @@ -1317,3 +1266,6 @@ initialize_simps_projections Group initialize_simps_projections AddGroup initialize_simps_projections CommGroup initialize_simps_projections AddCommGroup + +assert_not_exists Function.Injective +assert_not_exists IsCommutative diff --git a/Mathlib/Algebra/Group/Embedding.lean b/Mathlib/Algebra/Group/Embedding.lean index 201064e794f6f..640621ad8f42c 100644 --- a/Mathlib/Algebra/Group/Embedding.lean +++ b/Mathlib/Algebra/Group/Embedding.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.Algebra.Group.Defs +import Mathlib.Algebra.Group.Basic import Mathlib.Logic.Embedding.Basic #align_import algebra.hom.embedding from "leanprover-community/mathlib"@"70d50ecfd4900dd6d328da39ab7ebd516abe4025" diff --git a/Mathlib/Algebra/Group/Equiv/Basic.lean b/Mathlib/Algebra/Group/Equiv/Basic.lean index c273f4b33d342..1615d92c99c78 100644 --- a/Mathlib/Algebra/Group/Equiv/Basic.lean +++ b/Mathlib/Algebra/Group/Equiv/Basic.lean @@ -128,7 +128,7 @@ variable (F) @[to_additive] instance (priority := 100) instMulHomClass (F : Type*) [Mul M] [Mul N] [h : MulEquivClass F M N] : MulHomClass F M N := - { h with coe := h.coe, coe_injective' := FunLike.coe_injective' } + { h with coe := h.coe, coe_injective' := DFunLike.coe_injective' } -- See note [lower instance priority] @[to_additive] @@ -195,7 +195,7 @@ instance [Mul α] [Mul β] [MulEquivClass F α β] : CoeTC F (α ≃* β) := @[to_additive] theorem MulEquivClass.toMulEquiv_injective [Mul α] [Mul β] [MulEquivClass F α β] : Function.Injective ((↑) : F → α ≃* β) := - fun _ _ e ↦ FunLike.ext _ _ fun a ↦ congr_arg (fun e : α ≃* β ↦ e.toFun a) e + fun _ _ e ↦ DFunLike.ext _ _ fun a ↦ congr_arg (fun e : α ≃* β ↦ e.toFun a) e namespace MulEquiv @@ -482,13 +482,13 @@ theorem symm_comp_eq {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) : @[to_additive (attr := simp)] theorem symm_trans_self (e : M ≃* N) : e.symm.trans e = refl N := - FunLike.ext _ _ e.apply_symm_apply + DFunLike.ext _ _ e.apply_symm_apply #align mul_equiv.symm_trans_self MulEquiv.symm_trans_self #align add_equiv.symm_trans_self AddEquiv.symm_trans_self @[to_additive (attr := simp)] theorem self_trans_symm (e : M ≃* N) : e.trans e.symm = refl M := - FunLike.ext _ _ e.symm_apply_apply + DFunLike.ext _ _ e.symm_apply_apply #align mul_equiv.self_trans_symm MulEquiv.self_trans_symm #align add_equiv.self_trans_symm AddEquiv.self_trans_symm @@ -511,13 +511,13 @@ same underlying function. -/ @[to_additive (attr := ext) "Two additive isomorphisms agree if they are defined by the same underlying function."] theorem ext {f g : MulEquiv M N} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align mul_equiv.ext MulEquiv.ext #align add_equiv.ext AddEquiv.ext @[to_additive] theorem ext_iff {f g : MulEquiv M N} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align mul_equiv.ext_iff MulEquiv.ext_iff #align add_equiv.ext_iff AddEquiv.ext_iff @@ -535,13 +535,13 @@ theorem mk_coe' (e : M ≃* N) (f h₁ h₂ h₃) : (MulEquiv.mk ⟨f, e, h₁, @[to_additive] protected theorem congr_arg {f : MulEquiv M N} {x x' : M} : x = x' → f x = f x' := - FunLike.congr_arg f + DFunLike.congr_arg f #align mul_equiv.congr_arg MulEquiv.congr_arg #align add_equiv.congr_arg AddEquiv.congr_arg @[to_additive] protected theorem congr_fun {f g : MulEquiv M N} (h : f = g) (x : M) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align mul_equiv.congr_fun MulEquiv.congr_fun #align add_equiv.congr_fun AddEquiv.congr_fun @@ -762,8 +762,8 @@ def MulHom.toMulEquiv [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M) (h₁ (h₂ : f.comp g = MulHom.id _) : M ≃* N where toFun := f invFun := g - left_inv := FunLike.congr_fun h₁ - right_inv := FunLike.congr_fun h₂ + left_inv := DFunLike.congr_fun h₁ + right_inv := DFunLike.congr_fun h₂ map_mul' := f.map_mul #align mul_hom.to_mul_equiv MulHom.toMulEquiv #align add_hom.to_add_equiv AddHom.toAddEquiv @@ -798,8 +798,8 @@ def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N where toFun := f invFun := g - left_inv := FunLike.congr_fun h₁ - right_inv := FunLike.congr_fun h₂ + left_inv := DFunLike.congr_fun h₁ + right_inv := DFunLike.congr_fun h₂ map_mul' := f.map_mul #align monoid_hom.to_mul_equiv MonoidHom.toMulEquiv #align add_monoid_hom.to_add_equiv AddMonoidHom.toAddEquiv diff --git a/Mathlib/Algebra/Group/Ext.lean b/Mathlib/Algebra/Group/Ext.lean index 73e8643a4473c..5941bfbe9346b 100644 --- a/Mathlib/Algebra/Group/Ext.lean +++ b/Mathlib/Algebra/Group/Ext.lean @@ -27,6 +27,8 @@ former uses `HMul.hMul` which is the canonical spelling. monoid, group, extensionality -/ +open Function + universe u @[to_additive (attr := ext)] @@ -152,6 +154,12 @@ theorem DivInvMonoid.ext {M : Type*} ⦃m₁ m₂ : DivInvMonoid M⦄ #align div_inv_monoid.ext DivInvMonoid.ext #align sub_neg_monoid.ext SubNegMonoid.ext +@[to_additive] +lemma Group.toDivInvMonoid_injective {G : Type*} : Injective (@Group.toDivInvMonoid G) := by + rintro ⟨⟩ ⟨⟩ ⟨⟩; rfl +#align group.to_div_inv_monoid_injective Group.toDivInvMonoid_injective +#align add_group.to_sub_neg_add_monoid_injective AddGroup.toSubNegAddMonoid_injective + @[to_additive (attr := ext)] theorem Group.ext {G : Type*} ⦃g₁ g₂ : Group G⦄ (h_mul : g₁.mul = g₂.mul) : g₁ = g₂ := by have h₁ : g₁.one = g₂.one := congr_arg (·.one) (Monoid.ext h_mul) @@ -165,6 +173,12 @@ theorem Group.ext {G : Type*} ⦃g₁ g₂ : Group G⦄ (h_mul : g₁.mul = g₂ #align group.ext Group.ext #align add_group.ext AddGroup.ext +@[to_additive] +lemma CommGroup.toGroup_injective {G : Type*} : Injective (@CommGroup.toGroup G) := by + rintro ⟨⟩ ⟨⟩ ⟨⟩; rfl +#align comm_group.to_group_injective CommGroup.toGroup_injective +#align add_comm_group.to_add_group_injective AddCommGroup.toAddGroup_injective + @[to_additive (attr := ext)] theorem CommGroup.ext {G : Type*} ⦃g₁ g₂ : CommGroup G⦄ (h_mul : g₁.mul = g₂.mul) : g₁ = g₂ := CommGroup.toGroup_injective <| Group.ext h_mul diff --git a/Mathlib/Algebra/Group/Freiman.lean b/Mathlib/Algebra/Group/Freiman.lean index b21494c14e899..7889c49f99a7f 100644 --- a/Mathlib/Algebra/Group/Freiman.lean +++ b/Mathlib/Algebra/Group/Freiman.lean @@ -88,7 +88,7 @@ notation:25 (name := «FreimanHomLocal≺») A " →*[" n:25 "] " β:0 => Freima /-- `AddFreimanHomClass F A β n` states that `F` is a type of `n`-ary sums-preserving morphisms. You should extend this class when you extend `AddFreimanHom`. -/ class AddFreimanHomClass (F : Type*) (A : outParam <| Set α) (β : outParam <| Type*) - [AddCommMonoid α] [AddCommMonoid β] (n : ℕ) [FunLike F α fun _ => β] : Prop where + [AddCommMonoid α] [AddCommMonoid β] (n : ℕ) [FunLike F α β] : Prop where /-- An additive `n`-Freiman homomorphism preserves sums of `n` elements. -/ map_sum_eq_map_sum' (f : F) {s t : Multiset α} (hsA : ∀ ⦃x⦄, x ∈ s → x ∈ A) (htA : ∀ ⦃x⦄, x ∈ t → x ∈ A) (hs : Multiset.card s = n) (ht : Multiset.card t = n) @@ -102,7 +102,7 @@ You should extend this class when you extend `FreimanHom`. -/ "`AddFreimanHomClass F A β n` states that `F` is a type of `n`-ary sums-preserving morphisms. You should extend this class when you extend `AddFreimanHom`."] class FreimanHomClass (F : Type*) (A : outParam <| Set α) (β : outParam <| Type*) [CommMonoid α] - [CommMonoid β] (n : ℕ) [FunLike F α fun _ => β] : Prop where + [CommMonoid β] (n : ℕ) [FunLike F α β] : Prop where /-- An `n`-Freiman homomorphism preserves products of `n` elements. -/ map_prod_eq_map_prod' (f : F) {s t : Multiset α} (hsA : ∀ ⦃x⦄, x ∈ s → x ∈ A) (htA : ∀ ⦃x⦄, x ∈ t → x ∈ A) (hs : Multiset.card s = n) (ht : Multiset.card t = n) @@ -110,7 +110,7 @@ class FreimanHomClass (F : Type*) (A : outParam <| Set α) (β : outParam <| Typ (s.map f).prod = (t.map f).prod #align freiman_hom_class FreimanHomClass -variable [FunLike F α fun _ => β] +variable [FunLike F α β] section CommMonoid @@ -125,7 +125,7 @@ see also Algebra.Hom.Group for similar -/ " Turn an element of a type `F` satisfying `AddFreimanHomClass F A β n` into an actual `AddFreimanHom`. This is declared as the default coercion from `F` to `AddFreimanHom A β n`."] def _root_.FreimanHomClass.toFreimanHom [FreimanHomClass F A β n] (f : F) : A →*[n] β where - toFun := FunLike.coe f + toFun := DFunLike.coe f map_prod_eq_map_prod' := FreimanHomClass.map_prod_eq_map_prod' f /-- Any type satisfying `SMulHomClass` can be cast into `MulActionHom` via @@ -154,11 +154,11 @@ theorem map_mul_map_eq_map_mul_map [FreimanHomClass F A β 2] (f : F) (ha : a namespace FreimanHom @[to_additive] -instance funLike : FunLike (A →*[n] β) α fun _ => β where +instance instFunLike : FunLike (A →*[n] β) α β where coe := toFun coe_injective' f g h := by cases f; cases g; congr -#align freiman_hom.fun_like FreimanHom.funLike -#align add_freiman_hom.fun_like AddFreimanHom.funLike +#align freiman_hom.fun_like FreimanHom.instFunLike +#align add_freiman_hom.fun_like AddFreimanHom.instFunLike @[to_additive addFreimanHomClass] instance freimanHomClass : FreimanHomClass (A →*[n] β) A β n where @@ -167,7 +167,7 @@ instance freimanHomClass : FreimanHomClass (A →*[n] β) A β n where #align add_freiman_hom.freiman_hom_class AddFreimanHom.addFreimanHomClass -- porting note: not helpful in lean4 --- /-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` -- directly. -/ -- @[to_additive -- "Helper instance for when there's too many metavariables to apply @@ -186,7 +186,7 @@ theorem toFun_eq_coe (f : A →*[n] β) : f.toFun = f := @[to_additive (attr := ext)] theorem ext ⦃f g : A →*[n] β⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align freiman_hom.ext FreimanHom.ext #align add_freiman_hom.ext AddFreimanHom.ext @@ -254,7 +254,7 @@ theorem comp_assoc (f : A →*[n] β) (g : B →*[n] γ) (h : C →*[n] δ) {hf @[to_additive (attr := simp)] theorem cancel_right {g₁ g₂ : B →*[n] γ} {f : A →*[n] β} (hf : Function.Surjective f) {hg₁ hg₂} : g₁.comp f hg₁ = g₂.comp f hg₂ ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun h => h ▸ rfl⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => h ▸ rfl⟩ #align freiman_hom.cancel_right FreimanHom.cancel_right #align add_freiman_hom.cancel_right AddFreimanHom.cancel_right @@ -477,7 +477,7 @@ theorem MonoidHom.toFreimanHom_coe (f : α →* β) : (f.toFreimanHom A n : α @[to_additive AddMonoidHom.toAddFreimanHom_injective] theorem MonoidHom.toFreimanHom_injective : Function.Injective (MonoidHom.toFreimanHom A n : (α →* β) → A →*[n] β) := fun f g h => - by rwa [toFreimanHom, toFreimanHom, FreimanHom.mk.injEq, FunLike.coe_fn_eq] at h + by rwa [toFreimanHom, toFreimanHom, FreimanHom.mk.injEq, DFunLike.coe_fn_eq] at h #align monoid_hom.to_freiman_hom_injective MonoidHom.toFreimanHom_injective #align add_monoid_hom.to_freiman_hom_injective AddMonoidHom.toAddFreimanHom_injective @@ -553,7 +553,7 @@ theorem FreimanHom.toFreimanHom_coe (h : m ≤ n) (f : A →*[n] β) : @[to_additive AddFreimanHom.toAddFreimanHom_injective] theorem FreimanHom.toFreimanHom_injective (h : m ≤ n) : Function.Injective (FreimanHom.toFreimanHom h : (A →*[n] β) → A →*[m] β) := fun f g hfg => - FreimanHom.ext <| by convert FunLike.ext_iff.1 hfg using 0 + FreimanHom.ext <| by convert DFunLike.ext_iff.1 hfg using 0 #align freiman_hom.to_freiman_hom_injective FreimanHom.toFreimanHom_injective #align add_freiman_hom.to_freiman_hom_injective AddFreimanHom.toAddFreimanHom_injective diff --git a/Mathlib/Algebra/Group/Hom/Defs.lean b/Mathlib/Algebra/Group/Hom/Defs.lean index f8a707bc23a78..c603f8ee4b8c6 100644 --- a/Mathlib/Algebra/Group/Hom/Defs.lean +++ b/Mathlib/Algebra/Group/Hom/Defs.lean @@ -91,7 +91,7 @@ structure ZeroHom (M : Type*) (N : Type*) [Zero M] [Zero N] where You should extend this typeclass when you extend `ZeroHom`. -/ class ZeroHomClass (F : Type*) (M N : outParam (Type*)) [Zero M] [Zero N] - extends FunLike F M fun _ => N where + extends DFunLike F M fun _ => N where /-- The proposition that the function preserves 0 -/ map_zero : ∀ f : F, f 0 = 0 #align zero_hom_class ZeroHomClass @@ -120,7 +120,7 @@ structure AddHom (M : Type*) (N : Type*) [Add M] [Add N] where You should declare an instance of this typeclass when you extend `AddHom`. -/ class AddHomClass (F : Type*) (M N : outParam (Type*)) [Add M] [Add N] - extends FunLike F M fun _ => N where + extends DFunLike F M fun _ => N where /-- The proposition that the function preserves addition -/ map_add : ∀ (f : F) (x y : M), f (x + y) = f x + f y #align add_hom_class AddHomClass @@ -185,7 +185,7 @@ You should extend this typeclass when you extend `OneHom`. -/ @[to_additive] class OneHomClass (F : Type*) (M N : outParam (Type*)) [One M] [One N] - extends FunLike F M fun _ => N where + extends DFunLike F M fun _ => N where /-- The proposition that the function preserves 1 -/ map_one : ∀ f : F, f 1 = 1 #align one_hom_class OneHomClass @@ -208,7 +208,7 @@ theorem map_one [OneHomClass F M N] (f : F) : f 1 = 1 := @[to_additive] theorem Subsingleton.of_oneHomClass [Subsingleton M] [OneHomClass F M N] : Subsingleton F where - allEq f g := FunLike.ext _ _ fun x ↦ by simp [Subsingleton.elim x 1] + allEq f g := DFunLike.ext _ _ fun x ↦ by simp [Subsingleton.elim x 1] @[to_additive] instance [Subsingleton M] : Subsingleton (OneHom M N) := .of_oneHomClass @@ -281,7 +281,7 @@ You should declare an instance of this typeclass when you extend `MulHom`. -/ @[to_additive] class MulHomClass (F : Type*) (M N : outParam (Type*)) [Mul M] [Mul N] - extends FunLike F M fun _ => N where + extends DFunLike F M fun _ => N where /-- The proposition that the function preserves multiplication -/ map_mul : ∀ (f : F) (x y : M), f (x * y) = f x * f y #align mul_hom_class MulHomClass @@ -363,7 +363,7 @@ instance MonoidHom.monoidHomClass : MonoidHomClass (M →* N) M N where cases f cases g congr - apply FunLike.coe_injective' + apply DFunLike.coe_injective' exact h map_mul := MonoidHom.map_mul' map_one f := f.toOneHom.map_one' @@ -496,7 +496,7 @@ instance MonoidWithZeroHom.monoidWithZeroHomClass : MonoidWithZeroHomClass (M cases f cases g congr - apply FunLike.coe_injective' + apply DFunLike.coe_injective' exact h map_mul := MonoidWithZeroHom.map_mul' map_one := MonoidWithZeroHom.map_one' @@ -630,25 +630,25 @@ theorem MonoidWithZeroHom.toMonoidHom_coe [MulZeroOneClass M] [MulZeroOneClass N @[to_additive (attr := ext)] theorem OneHom.ext [One M] [One N] ⦃f g : OneHom M N⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align one_hom.ext OneHom.ext #align zero_hom.ext ZeroHom.ext @[to_additive (attr := ext)] theorem MulHom.ext [Mul M] [Mul N] ⦃f g : M →ₙ* N⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align mul_hom.ext MulHom.ext #align add_hom.ext AddHom.ext @[to_additive (attr := ext)] theorem MonoidHom.ext [MulOneClass M] [MulOneClass N] ⦃f g : M →* N⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align monoid_hom.ext MonoidHom.ext #align add_monoid_hom.ext AddMonoidHom.ext @[ext] theorem MonoidWithZeroHom.ext [MulZeroOneClass M] [MulZeroOneClass N] ⦃f g : M →*₀ N⦄ - (h : ∀ x, f x = g x) : f = g := FunLike.ext _ _ h + (h : ∀ x, f x = g x) : f = g := DFunLike.ext _ _ h #align monoid_with_zero_hom.ext MonoidWithZeroHom.ext @@ -673,112 +673,112 @@ end MonoidHom section Deprecated -/-- Deprecated: use `FunLike.congr_fun` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.congr_fun` instead."] +/-- Deprecated: use `DFunLike.congr_fun` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.congr_fun` instead."] theorem OneHom.congr_fun [One M] [One N] {f g : OneHom M N} (h : f = g) (x : M) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align one_hom.congr_fun OneHom.congr_fun #align zero_hom.congr_fun ZeroHom.congr_fun -/-- Deprecated: use `FunLike.congr_fun` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.congr_fun` instead."] +/-- Deprecated: use `DFunLike.congr_fun` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.congr_fun` instead."] theorem MulHom.congr_fun [Mul M] [Mul N] {f g : M →ₙ* N} (h : f = g) (x : M) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align mul_hom.congr_fun MulHom.congr_fun #align add_hom.congr_fun AddHom.congr_fun -/-- Deprecated: use `FunLike.congr_fun` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.congr_fun` instead."] +/-- Deprecated: use `DFunLike.congr_fun` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.congr_fun` instead."] theorem MonoidHom.congr_fun [MulOneClass M] [MulOneClass N] {f g : M →* N} (h : f = g) (x : M) : - f x = g x := FunLike.congr_fun h x + f x = g x := DFunLike.congr_fun h x #align monoid_hom.congr_fun MonoidHom.congr_fun #align add_monoid_hom.congr_fun AddMonoidHom.congr_fun -/-- Deprecated: use `FunLike.congr_fun` instead. -/ +/-- Deprecated: use `DFunLike.congr_fun` instead. -/ @[deprecated] theorem MonoidWithZeroHom.congr_fun [MulZeroOneClass M] [MulZeroOneClass N] {f g : M →*₀ N} - (h : f = g) (x : M) : f x = g x := FunLike.congr_fun h x + (h : f = g) (x : M) : f x = g x := DFunLike.congr_fun h x #align monoid_with_zero_hom.congr_fun MonoidWithZeroHom.congr_fun -/-- Deprecated: use `FunLike.congr_arg` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.congr_arg` instead."] +/-- Deprecated: use `DFunLike.congr_arg` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.congr_arg` instead."] theorem OneHom.congr_arg [One M] [One N] (f : OneHom M N) {x y : M} (h : x = y) : f x = f y := - FunLike.congr_arg f h + DFunLike.congr_arg f h #align one_hom.congr_arg OneHom.congr_arg #align zero_hom.congr_arg ZeroHom.congr_arg -/-- Deprecated: use `FunLike.congr_arg` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.congr_arg` instead."] +/-- Deprecated: use `DFunLike.congr_arg` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.congr_arg` instead."] theorem MulHom.congr_arg [Mul M] [Mul N] (f : M →ₙ* N) {x y : M} (h : x = y) : f x = f y := - FunLike.congr_arg f h + DFunLike.congr_arg f h #align mul_hom.congr_arg MulHom.congr_arg #align add_hom.congr_arg AddHom.congr_arg -/-- Deprecated: use `FunLike.congr_arg` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.congr_arg` instead."] +/-- Deprecated: use `DFunLike.congr_arg` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.congr_arg` instead."] theorem MonoidHom.congr_arg [MulOneClass M] [MulOneClass N] (f : M →* N) {x y : M} (h : x = y) : - f x = f y := FunLike.congr_arg f h + f x = f y := DFunLike.congr_arg f h #align monoid_hom.congr_arg MonoidHom.congr_arg #align add_monoid_hom.congr_arg AddMonoidHom.congr_arg -/-- Deprecated: use `FunLike.congr_arg` instead. -/ +/-- Deprecated: use `DFunLike.congr_arg` instead. -/ @[deprecated] theorem MonoidWithZeroHom.congr_arg [MulZeroOneClass M] [MulZeroOneClass N] (f : M →*₀ N) {x y : M} - (h : x = y) : f x = f y := FunLike.congr_arg f h + (h : x = y) : f x = f y := DFunLike.congr_arg f h #align monoid_with_zero_hom.congr_arg MonoidWithZeroHom.congr_arg -/-- Deprecated: use `FunLike.coe_injective` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.coe_injective` instead."] +/-- Deprecated: use `DFunLike.coe_injective` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.coe_injective` instead."] theorem OneHom.coe_inj [One M] [One N] ⦃f g : OneHom M N⦄ (h : (f : M → N) = g) : f = g := - FunLike.coe_injective h + DFunLike.coe_injective h #align one_hom.coe_inj OneHom.coe_inj #align zero_hom.coe_inj ZeroHom.coe_inj -/-- Deprecated: use `FunLike.coe_injective` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.coe_injective` instead."] +/-- Deprecated: use `DFunLike.coe_injective` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.coe_injective` instead."] theorem MulHom.coe_inj [Mul M] [Mul N] ⦃f g : M →ₙ* N⦄ (h : (f : M → N) = g) : f = g := - FunLike.coe_injective h + DFunLike.coe_injective h #align mul_hom.coe_inj MulHom.coe_inj #align add_hom.coe_inj AddHom.coe_inj -/-- Deprecated: use `FunLike.coe_injective` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.coe_injective` instead."] +/-- Deprecated: use `DFunLike.coe_injective` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.coe_injective` instead."] theorem MonoidHom.coe_inj [MulOneClass M] [MulOneClass N] ⦃f g : M →* N⦄ (h : (f : M → N) = g) : - f = g := FunLike.coe_injective h + f = g := DFunLike.coe_injective h #align monoid_hom.coe_inj MonoidHom.coe_inj #align add_monoid_hom.coe_inj AddMonoidHom.coe_inj -/-- Deprecated: use `FunLike.coe_injective` instead. -/ +/-- Deprecated: use `DFunLike.coe_injective` instead. -/ @[deprecated] theorem MonoidWithZeroHom.coe_inj [MulZeroOneClass M] [MulZeroOneClass N] ⦃f g : M →*₀ N⦄ - (h : (f : M → N) = g) : f = g := FunLike.coe_injective h + (h : (f : M → N) = g) : f = g := DFunLike.coe_injective h #align monoid_with_zero_hom.coe_inj MonoidWithZeroHom.coe_inj -/-- Deprecated: use `FunLike.ext_iff` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.ext_iff` instead."] +/-- Deprecated: use `DFunLike.ext_iff` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.ext_iff` instead."] theorem OneHom.ext_iff [One M] [One N] {f g : OneHom M N} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align one_hom.ext_iff OneHom.ext_iff #align zero_hom.ext_iff ZeroHom.ext_iff -/-- Deprecated: use `FunLike.ext_iff` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.ext_iff` instead."] +/-- Deprecated: use `DFunLike.ext_iff` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.ext_iff` instead."] theorem MulHom.ext_iff [Mul M] [Mul N] {f g : M →ₙ* N} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align mul_hom.ext_iff MulHom.ext_iff #align add_hom.ext_iff AddHom.ext_iff -/-- Deprecated: use `FunLike.ext_iff` instead. -/ -@[to_additive (attr := deprecated) "Deprecated: use `FunLike.ext_iff` instead."] +/-- Deprecated: use `DFunLike.ext_iff` instead. -/ +@[to_additive (attr := deprecated) "Deprecated: use `DFunLike.ext_iff` instead."] theorem MonoidHom.ext_iff [MulOneClass M] [MulOneClass N] {f g : M →* N} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align monoid_hom.ext_iff MonoidHom.ext_iff #align add_monoid_hom.ext_iff AddMonoidHom.ext_iff -/-- Deprecated: use `FunLike.ext_iff` instead. -/ +/-- Deprecated: use `DFunLike.ext_iff` instead. -/ @[deprecated] theorem MonoidWithZeroHom.ext_iff [MulZeroOneClass M] [MulZeroOneClass N] {f g : M →*₀ N} : - f = g ↔ ∀ x, f x = g x := FunLike.ext_iff + f = g ↔ ∀ x, f x = g x := DFunLike.ext_iff #align monoid_with_zero_hom.ext_iff MonoidWithZeroHom.ext_iff end Deprecated @@ -830,7 +830,7 @@ theorem OneHom.coe_copy {_ : One M} {_ : One N} (f : OneHom M N) (f' : M → N) @[to_additive] theorem OneHom.coe_copy_eq {_ : One M} {_ : One N} (f : OneHom M N) (f' : M → N) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align one_hom.coe_copy_eq OneHom.coe_copy_eq #align zero_hom.coe_copy_eq ZeroHom.coe_copy_eq @@ -856,7 +856,7 @@ theorem MulHom.coe_copy {_ : Mul M} {_ : Mul N} (f : M →ₙ* N) (f' : M → N) @[to_additive] theorem MulHom.coe_copy_eq {_ : Mul M} {_ : Mul N} (f : M →ₙ* N) (f' : M → N) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align mul_hom.coe_copy_eq MulHom.coe_copy_eq #align add_hom.coe_copy_eq AddHom.coe_copy_eq @@ -881,7 +881,7 @@ theorem MonoidHom.coe_copy {_ : MulOneClass M} {_ : MulOneClass N} (f : M →* N @[to_additive] theorem MonoidHom.copy_eq {_ : MulOneClass M} {_ : MulOneClass N} (f : M →* N) (f' : M → N) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align monoid_hom.copy_eq MonoidHom.copy_eq #align add_monoid_hom.copy_eq AddMonoidHom.copy_eq @@ -900,7 +900,7 @@ theorem MonoidWithZeroHom.coe_copy {_ : MulZeroOneClass M} {_ : MulZeroOneClass theorem MonoidWithZeroHom.copy_eq {_ : MulZeroOneClass M} {_ : MulZeroOneClass N} (f : M →*₀ N) (f' : M → N) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align monoid_with_zero_hom.copy_eq MonoidWithZeroHom.copy_eq @[to_additive] @@ -1144,14 +1144,14 @@ theorem MonoidWithZeroHom.comp_assoc {Q : Type*} [MulZeroOneClass M] [MulZeroOne @[to_additive] theorem OneHom.cancel_right [One M] [One N] [One P] {g₁ g₂ : OneHom N P} {f : OneHom M N} (hf : Function.Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => OneHom.ext <| hf.forall.2 (FunLike.ext_iff.1 h), fun h => h ▸ rfl⟩ + ⟨fun h => OneHom.ext <| hf.forall.2 (DFunLike.ext_iff.1 h), fun h => h ▸ rfl⟩ #align one_hom.cancel_right OneHom.cancel_right #align zero_hom.cancel_right ZeroHom.cancel_right @[to_additive] theorem MulHom.cancel_right [Mul M] [Mul N] [Mul P] {g₁ g₂ : N →ₙ* P} {f : M →ₙ* N} (hf : Function.Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => MulHom.ext <| hf.forall.2 (FunLike.ext_iff.1 h), fun h => h ▸ rfl⟩ + ⟨fun h => MulHom.ext <| hf.forall.2 (DFunLike.ext_iff.1 h), fun h => h ▸ rfl⟩ #align mul_hom.cancel_right MulHom.cancel_right #align add_hom.cancel_right AddHom.cancel_right @@ -1159,14 +1159,14 @@ theorem MulHom.cancel_right [Mul M] [Mul N] [Mul P] {g₁ g₂ : N →ₙ* P} {f theorem MonoidHom.cancel_right [MulOneClass M] [MulOneClass N] [MulOneClass P] {g₁ g₂ : N →* P} {f : M →* N} (hf : Function.Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => MonoidHom.ext <| hf.forall.2 (FunLike.ext_iff.1 h), fun h => h ▸ rfl⟩ + ⟨fun h => MonoidHom.ext <| hf.forall.2 (DFunLike.ext_iff.1 h), fun h => h ▸ rfl⟩ #align monoid_hom.cancel_right MonoidHom.cancel_right #align add_monoid_hom.cancel_right AddMonoidHom.cancel_right theorem MonoidWithZeroHom.cancel_right [MulZeroOneClass M] [MulZeroOneClass N] [MulZeroOneClass P] {g₁ g₂ : N →*₀ P} {f : M →*₀ N} (hf : Function.Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => MonoidWithZeroHom.ext <| hf.forall.2 (FunLike.ext_iff.1 h), fun h => h ▸ rfl⟩ + ⟨fun h => MonoidWithZeroHom.ext <| hf.forall.2 (DFunLike.ext_iff.1 h), fun h => h ▸ rfl⟩ #align monoid_with_zero_hom.cancel_right MonoidWithZeroHom.cancel_right @[to_additive] @@ -1227,7 +1227,7 @@ end theorem MonoidWithZeroHom.toZeroHom_injective [MulZeroOneClass M] [MulZeroOneClass N] : Function.Injective (MonoidWithZeroHom.toZeroHom : (M →*₀ N) → ZeroHom M N) := - fun _ _ h => MonoidWithZeroHom.ext <| (FunLike.ext_iff (F := ZeroHom M N)).mp h + fun _ _ h => MonoidWithZeroHom.ext <| (DFunLike.ext_iff (F := ZeroHom M N)).mp h #align monoid_with_zero_hom.to_zero_hom_injective MonoidWithZeroHom.toZeroHom_injective @[to_additive (attr := simp)] diff --git a/Mathlib/Algebra/Group/Hom/Instances.lean b/Mathlib/Algebra/Group/Hom/Instances.lean index cae4b2cc6ef35..e91e19fc63be0 100644 --- a/Mathlib/Algebra/Group/Hom/Instances.lean +++ b/Mathlib/Algebra/Group/Hom/Instances.lean @@ -122,7 +122,7 @@ namespace MonoidHom @[to_additive] theorem ext_iff₂ {_ : MulOneClass M} {_ : MulOneClass N} {_ : CommMonoid P} {f g : M →* N →* P} : f = g ↔ ∀ x y, f x y = g x y := - FunLike.ext_iff.trans <| forall_congr' fun _ => FunLike.ext_iff + DFunLike.ext_iff.trans <| forall_congr' fun _ => DFunLike.ext_iff #align monoid_hom.ext_iff₂ MonoidHom.ext_iff₂ #align add_monoid_hom.ext_iff₂ AddMonoidHom.ext_iff₂ @@ -333,11 +333,11 @@ theorem AddMonoidHom.map_mul_iff (f : R →+ S) : lemma AddMonoidHom.mulLeft_eq_mulRight_iff_forall_commute {a : R} : mulLeft a = mulRight a ↔ ∀ b, Commute a b := - FunLike.ext_iff + DFunLike.ext_iff lemma AddMonoidHom.mulRight_eq_mulLeft_iff_forall_commute {b : R} : mulRight b = mulLeft b ↔ ∀ a, Commute a b := - FunLike.ext_iff + DFunLike.ext_iff /-- The left multiplication map: `(a, b) ↦ a * b`. See also `AddMonoidHom.mulLeft`. -/ @[simps!] diff --git a/Mathlib/Algebra/Group/NatPowAssoc.lean b/Mathlib/Algebra/Group/NatPowAssoc.lean new file mode 100644 index 0000000000000..0d145e4f20167 --- /dev/null +++ b/Mathlib/Algebra/Group/NatPowAssoc.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2023 Scott Carnahan. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Carnahan +-/ + +import Mathlib.Algebra.Group.Defs +import Mathlib.Algebra.GroupPower.Basic +import Mathlib.Algebra.Group.Prod +import Mathlib.Algebra.Group.Pi +import Mathlib.GroupTheory.GroupAction.Prod +import Mathlib.Data.Int.Basic +import Mathlib.Data.Nat.Cast.Basic + +/-! +# Typeclasses for power-associative structures + +In this file we define power-associativity for algebraic structures with a multiplication operation. +The class is a Prop-valued mixin named `NatPowAssoc`. + +## Results + +- `npow_add` a defining property: `x ^ (k + n) = x ^ k * x ^ n` +- `npow_one` a defining property: `x ^ 1 = x` +- `npow_assoc` strictly positive powers of an element have associative multiplication. +- `npow_comm` `x ^ m * x ^ n = x ^ n * x ^ m` for strictly positive `m` and `n`. +- `npow_mul` `x ^ (m * n) = (x ^ m) ^ n` for strictly positive `m` and `n`. +- `npow_eq_pow` monoid exponentiation coincides with semigroup exponentiation. + +## Instances + +We also produce the following instances: + +- `NatPowAssoc` for Monoids, Pi types and products. + +## Todo + +* to_additive? + +-/ + +variable {M : Type*} + +/-- A mixin for power-associative multiplication. -/ +class NatPowAssoc (M : Type*) [MulOneClass M] [Pow M ℕ] : Prop where + /-- Multiplication is power-associative. -/ + protected npow_add : ∀ (k n: ℕ) (x : M), x ^ (k + n) = x ^ k * x ^ n + /-- Exponent zero is one. -/ + protected npow_zero : ∀ (x : M), x ^ 0 = 1 + /-- Exponent one is identity. -/ + protected npow_one : ∀ (x : M), x ^ 1 = x + +section MulOneClass + +variable [MulOneClass M] [Pow M ℕ] [NatPowAssoc M] + +theorem npow_add (k n : ℕ) (x : M) : x ^ (k + n) = x ^ k * x ^ n := + NatPowAssoc.npow_add k n x + +@[simp] +theorem npow_zero (x : M) : x ^ 0 = 1 := + NatPowAssoc.npow_zero x + +@[simp] +theorem npow_one (x : M) : x ^ 1 = x := + NatPowAssoc.npow_one x + +theorem npow_mul_assoc (k m n : ℕ) (x : M) : + (x ^ k * x ^ m) * x ^ n = x ^ k * (x ^ m * x ^ n) := by + simp only [← npow_add, add_assoc] + +theorem npow_mul_comm (m n : ℕ) (x : M) : + x ^ m * x ^ n = x ^ n * x ^ m := by simp only [← npow_add, add_comm] + +theorem npow_mul (x : M) (m n : ℕ) : x ^ (m * n) = (x ^ m) ^ n := by + induction n with + | zero => rw [npow_zero, Nat.mul_zero, npow_zero] + | succ n ih => rw [← Nat.add_one, mul_add, npow_add, ih, mul_one, npow_add, npow_one] + +theorem npow_mul' (x : M) (m n : ℕ) : x ^ (m * n) = (x ^ n) ^ m := by + rw [mul_comm] + exact npow_mul x n m + +end MulOneClass + +instance Pi.instNatPowAssoc {ι : Type*} {α : ι → Type*} [∀ i, MulOneClass <| α i] [∀ i, Pow (α i) ℕ] + [∀ i, NatPowAssoc <| α i] : NatPowAssoc (∀ i, α i) where + npow_add _ _ _ := by ext; simp [npow_add] + npow_zero _ := by ext; simp + npow_one _ := by ext; simp + +instance Prod.instNatPowAssoc {N : Type*} [MulOneClass M] [Pow M ℕ] [NatPowAssoc M] [MulOneClass N] + [Pow N ℕ] [NatPowAssoc N] : NatPowAssoc (M × N) where + npow_add _ _ _ := by ext <;> simp [npow_add] + npow_zero _ := by ext <;> simp + npow_one _ := by ext <;> simp + +section Monoid + +variable [Monoid M] + +instance Monoid.PowAssoc [Monoid M] : NatPowAssoc M where + npow_add _ _ _ := pow_add _ _ _ + npow_zero _ := pow_zero _ + npow_one _ := pow_one _ + +@[simp, norm_cast] +theorem Nat.cast_npow (R : Type*) [NonAssocSemiring R] [Pow R ℕ] [NatPowAssoc R] (n m : ℕ) : + (↑(n ^ m) : R) = (↑n : R) ^ m := by + induction' m with m ih + · simp only [pow_zero, Nat.cast_one, npow_zero] + · rw [← Nat.add_one, npow_add, npow_add, Nat.cast_mul, ih, npow_one, npow_one] + +@[simp, norm_cast] +theorem Int.cast_npow (R : Type*) [NonAssocRing R] [Pow R ℕ] [NatPowAssoc R] + (n : ℤ) : ∀(m : ℕ), @Int.cast R NonAssocRing.toIntCast (n ^ m) = (n : R) ^ m + | 0 => by + rw [pow_zero, npow_zero, Int.cast_one] + | m + 1 => by + rw [npow_add, npow_one, Int.cast_mul, Int.cast_npow R n m, npow_add, npow_one] + +end Monoid diff --git a/Mathlib/Algebra/Group/Opposite.lean b/Mathlib/Algebra/Group/Opposite.lean index 70eb2124c42a3..98b06ee499763 100644 --- a/Mathlib/Algebra/Group/Opposite.lean +++ b/Mathlib/Algebra/Group/Opposite.lean @@ -369,8 +369,8 @@ instance addCommMonoidWithOne [AddCommMonoidWithOne α] : AddCommMonoidWithOne instance addCommGroupWithOne [AddCommGroupWithOne α] : AddCommGroupWithOne αᵃᵒᵖ := { AddOpposite.addCommMonoidWithOne α, AddOpposite.addCommGroup α, AddOpposite.intCast α with - intCast_ofNat := λ _ ↦ congr_arg op $ Int.cast_ofNat _ - intCast_negSucc := λ _ ↦ congr_arg op $ Int.cast_negSucc _ } + intCast_ofNat := λ _ ↦ congr_arg op <| Int.cast_ofNat _ + intCast_negSucc := λ _ ↦ congr_arg op <| Int.cast_negSucc _ } variable {α} @@ -695,7 +695,7 @@ theorem AddMonoidHom.mul_op_ext {α β} [AddZeroClass α] [AddZeroClass β] (f g f.comp (opAddEquiv : α ≃+ αᵐᵒᵖ).toAddMonoidHom = g.comp (opAddEquiv : α ≃+ αᵐᵒᵖ).toAddMonoidHom) : f = g := - AddMonoidHom.ext <| MulOpposite.rec' fun x => (FunLike.congr_fun h : _) x + AddMonoidHom.ext <| MulOpposite.rec' fun x => (DFunLike.congr_fun h : _) x #align add_monoid_hom.mul_op_ext AddMonoidHom.mul_op_ext end Ext diff --git a/Mathlib/Algebra/Group/PNatPowAssoc.lean b/Mathlib/Algebra/Group/PNatPowAssoc.lean index 56f7b7342fcbb..0139823c74387 100644 --- a/Mathlib/Algebra/Group/PNatPowAssoc.lean +++ b/Mathlib/Algebra/Group/PNatPowAssoc.lean @@ -33,7 +33,7 @@ powers are considered. ## Todo * `NatPowAssoc` for `MulOneClass` - more or less the same flow -* It seems unlikely that anyone will want `NatSMulAssoc` and `PNatSmulAssoc` as additive versions of +* It seems unlikely that anyone will want `NatSMulAssoc` and `PNatSMulAssoc` as additive versions of power-associativity, but we have found that it is not hard to write. -/ @@ -67,8 +67,8 @@ theorem ppow_mul_comm (m n : ℕ+) (x : M) : theorem ppow_mul (x : M) (m n : ℕ+) : x ^ (m * n) = (x ^ m) ^ n := by refine PNat.recOn n ?_ fun k hk ↦ ?_ - rw [ppow_one, mul_one] - rw [ppow_add, ppow_one, mul_add, ppow_add, mul_one, hk] + · rw [ppow_one, mul_one] + · rw [ppow_add, ppow_one, mul_add, ppow_add, mul_one, hk] theorem ppow_mul' (x : M) (m n : ℕ+) : x ^ (m * n) = (x ^ n) ^ m := by rw [mul_comm] @@ -78,8 +78,8 @@ end Mul instance Pi.instPNatPowAssoc {ι : Type*} {α : ι → Type*} [∀ i, Mul <| α i] [∀ i, Pow (α i) ℕ+] [∀ i, PNatPowAssoc <| α i] : PNatPowAssoc (∀ i, α i) where - ppow_add _ _ _ := by ext; simp [ppow_add] - ppow_one _ := by ext; simp + ppow_add _ _ _ := by ext; simp [ppow_add] + ppow_one _ := by ext; simp instance Prod.instPNatPowAssoc {N : Type*} [Mul M] [Pow M ℕ+] [PNatPowAssoc M] [Mul N] [Pow N ℕ+] [PNatPowAssoc N] : PNatPowAssoc (M × N) where @@ -89,5 +89,5 @@ instance Prod.instPNatPowAssoc {N : Type*} [Mul M] [Pow M ℕ+] [PNatPowAssoc M] theorem ppow_eq_pow [Monoid M] [Pow M ℕ+] [PNatPowAssoc M] (x : M) (n : ℕ+) : x ^ n = x ^ (n : ℕ) := by refine PNat.recOn n ?_ fun k hk ↦ ?_ - rw [ppow_one, PNat.one_coe, pow_one] - rw [ppow_add, ppow_one, PNat.add_coe, pow_add, PNat.one_coe, pow_one, ← hk] + · rw [ppow_one, PNat.one_coe, pow_one] + · rw [ppow_add, ppow_one, PNat.add_coe, pow_add, PNat.one_coe, pow_one, ← hk] diff --git a/Mathlib/Algebra/Group/Semiconj/Defs.lean b/Mathlib/Algebra/Group/Semiconj/Defs.lean index f1e617cc8fdbe..bcd2698ed13bd 100644 --- a/Mathlib/Algebra/Group/Semiconj/Defs.lean +++ b/Mathlib/Algebra/Group/Semiconj/Defs.lean @@ -6,6 +6,7 @@ Authors: Yury Kudryashov Some proofs and docs came from `algebra/commute` (c) Neil Strickland -/ import Mathlib.Algebra.Group.Defs +import Mathlib.Init.Logic import Mathlib.Tactic.Cases #align_import algebra.group.semiconj from "leanprover-community/mathlib"@"a148d797a1094ab554ad4183a4ad6f130358ef64" diff --git a/Mathlib/Algebra/Group/Semiconj/Units.lean b/Mathlib/Algebra/Group/Semiconj/Units.lean index b2a42301446fa..43ccc2565d886 100644 --- a/Mathlib/Algebra/Group/Semiconj/Units.lean +++ b/Mathlib/Algebra/Group/Semiconj/Units.lean @@ -29,6 +29,8 @@ This file provides only basic operations (`mul_left`, `mul_right`, `inv_right` e operations (`pow_right`, field inverse etc) are in the files that define corresponding notions. -/ +open scoped Int + variable {M G : Type*} namespace SemiconjBy @@ -87,12 +89,34 @@ theorem units_val_iff {a x y : Mˣ} : SemiconjBy (a : M) x y ↔ SemiconjBy a x #align semiconj_by.units_coe_iff SemiconjBy.units_val_iff #align add_semiconj_by.add_units_coe_iff AddSemiconjBy.addUnits_val_iff +@[to_additive (attr := simp)] +lemma units_zpow_right {a : M} {x y : Mˣ} (h : SemiconjBy a x y) : + ∀ m : ℤ, SemiconjBy a ↑(x ^ m) ↑(y ^ m) + | (n : ℕ) => by simp only [zpow_ofNat, Units.val_pow_eq_pow_val, h, pow_right] + | -[n+1] => by simp only [zpow_negSucc, Units.val_pow_eq_pow_val, units_inv_right, h, pow_right] +#align semiconj_by.units_zpow_right SemiconjBy.units_zpow_right +#align add_semiconj_by.add_units_zsmul_right AddSemiconjBy.addUnits_zsmul_right + end Monoid end SemiconjBy +namespace Units +variable [Monoid M] + /-- `a` semiconjugates `x` to `a * x * a⁻¹`. -/ @[to_additive "`a` semiconjugates `x` to `a + x + -a`."] -theorem Units.mk_semiconjBy [Monoid M] (u : Mˣ) (x : M) : SemiconjBy (↑u) x (u * x * ↑u⁻¹) := by +lemma mk_semiconjBy (u : Mˣ) (x : M) : SemiconjBy (↑u) x (u * x * ↑u⁻¹) := by unfold SemiconjBy; rw [Units.inv_mul_cancel_right] #align units.mk_semiconj_by Units.mk_semiconjBy #align add_units.mk_semiconj_by AddUnits.mk_addSemiconjBy + +lemma conj_pow (u : Mˣ) (x : M) (n : ℕ) : + ((↑u : M) * x * (↑u⁻¹ : M)) ^ n = (u : M) * x ^ n * (↑u⁻¹ : M) := + eq_divp_iff_mul_eq.2 ((u.mk_semiconjBy x).pow_right n).eq.symm +#align units.conj_pow Units.conj_pow + +lemma conj_pow' (u : Mˣ) (x : M) (n : ℕ) : + ((↑u⁻¹ : M) * x * (u : M)) ^ n = (↑u⁻¹ : M) * x ^ n * (u : M) := u⁻¹.conj_pow x n +#align units.conj_pow' Units.conj_pow' + +end Units diff --git a/Mathlib/Algebra/Group/TypeTags.lean b/Mathlib/Algebra/Group/TypeTags.lean index fb2246c659fdc..86280ae676ffa 100644 --- a/Mathlib/Algebra/Group/TypeTags.lean +++ b/Mathlib/Algebra/Group/TypeTags.lean @@ -5,7 +5,6 @@ Authors: Mario Carneiro -/ import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Data.Finite.Defs -import Mathlib.Logic.Equiv.Defs import Mathlib.Logic.Nontrivial.Basic #align_import algebra.group.type_tags from "leanprover-community/mathlib"@"2e0975f6a25dd3fbfb9e41556a77f075f6269748" diff --git a/Mathlib/Algebra/Group/UniqueProds.lean b/Mathlib/Algebra/Group/UniqueProds.lean index e1185c20cc2a5..3ef5b61b879af 100644 --- a/Mathlib/Algebra/Group/UniqueProds.lean +++ b/Mathlib/Algebra/Group/UniqueProds.lean @@ -472,11 +472,11 @@ end UniqueProds instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, UniqueSums (G i)] : UniqueSums (Π₀ i, G i) := UniqueSums.addHom_image_of_injective - DFinsupp.coeFnAddMonoidHom.toAddHom FunLike.coe_injective inferInstance + DFinsupp.coeFnAddMonoidHom.toAddHom DFunLike.coe_injective inferInstance instance {ι G} [AddZeroClass G] [UniqueSums G] : UniqueSums (ι →₀ G) := UniqueSums.addHom_image_of_injective - Finsupp.coeFnAddHom.toAddHom FunLike.coe_injective inferInstance + Finsupp.coeFnAddHom.toAddHom DFunLike.coe_injective inferInstance namespace TwoUniqueProds @@ -611,11 +611,11 @@ end TwoUniqueProds instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, TwoUniqueSums (G i)] : TwoUniqueSums (Π₀ i, G i) := TwoUniqueSums.addHom_image_of_injective - DFinsupp.coeFnAddMonoidHom.toAddHom FunLike.coe_injective inferInstance + DFinsupp.coeFnAddMonoidHom.toAddHom DFunLike.coe_injective inferInstance instance {ι G} [AddZeroClass G] [TwoUniqueSums G] : TwoUniqueSums (ι →₀ G) := TwoUniqueSums.addHom_image_of_injective - Finsupp.coeFnAddHom.toAddHom FunLike.coe_injective inferInstance + Finsupp.coeFnAddHom.toAddHom DFunLike.coe_injective inferInstance /-- Any `ℚ`-vector space has `TwoUniqueSums`, because it is isomorphic to some `(Basis.ofVectorSpaceIndex ℚ G) →₀ ℚ` by choosing a basis, and `ℚ` already has diff --git a/Mathlib/Algebra/Group/Units.lean b/Mathlib/Algebra/Group/Units.lean index f544279f1dee8..3f72c3e06036e 100644 --- a/Mathlib/Algebra/Group/Units.lean +++ b/Mathlib/Algebra/Group/Units.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Mario Carneiro, Johannes Hölzl, Chris Hughes, Jens Wagemaker, Jon Eugster -/ import Mathlib.Algebra.Group.Basic +import Mathlib.Algebra.GroupPower.Basic import Mathlib.Logic.Unique import Mathlib.Tactic.Nontriviality import Mathlib.Tactic.Lift @@ -28,6 +29,9 @@ See also `Prime`, `Associated`, and `Irreducible` in `Mathlib.Algebra.Associated We provide `Mˣ` as notation for `Units M`, resembling the notation $R^{\times}$ for the units of a ring, which is common in mathematics. +## TODO + +The results here should be used to golf the basic `Group` lemmas. -/ @@ -97,7 +101,7 @@ theorem unique_one {α : Type*} [Unique α] [One α] : default = (1 : α) := end HasElem namespace Units - +section Monoid variable [Monoid α] -- Porting note: unclear whether this should be a `CoeHead` or `CoeTail` @@ -185,7 +189,7 @@ theorem copy_eq (u : αˣ) (val hv inv hi) : u.copy val hv inv hi = u := /-- Units of a monoid form have a multiplication and multiplicative identity. -/ @[to_additive "Additive units of an additive monoid have an addition and an additive identity."] -instance : MulOneClass αˣ where +instance instMulOneClass : MulOneClass αˣ where mul u₁ u₂ := ⟨u₁.val * u₂.val, u₂.inv * u₁.inv, by rw [mul_assoc, ← mul_assoc u₂.val, val_inv, one_mul, val_inv], @@ -194,23 +198,6 @@ instance : MulOneClass αˣ where one_mul u := ext <| one_mul (u : α) mul_one u := ext <| mul_one (u : α) -/-- Units of a monoid form a group. -/ -@[to_additive "Additive units of an additive monoid form an additive group."] -instance : Group αˣ := - { (inferInstance : MulOneClass αˣ) with - mul_assoc := fun _ _ _ => ext <| mul_assoc _ _ _, - inv := Inv.inv, mul_left_inv := fun u => ext u.inv_val } - -/-- Units of a commutative monoid form a commutative group. -/ -@[to_additive "Additive units of an additive commutative monoid form -an additive commutative group."] -instance instCommGroupUnits {α} [CommMonoid α] : CommGroup αˣ := - -- note: the original ported file had `{ (inferInstance : Group αˣ) with ... }` - -- and this was removed because it was causing slowdowns: see lean4#2387 - { mul_comm := fun _ _ => ext <| mul_comm _ _ } -#align units.comm_group Units.instCommGroupUnits -#align add_units.add_comm_group AddUnits.instAddCommGroupAddUnits - /-- Units of a monoid are inhabited because `1` is a unit. -/ @[to_additive "Additive units of an additive monoid are inhabited because `0` is an additive unit."] instance : Inhabited αˣ := @@ -270,6 +257,11 @@ theorem mul_inv : (a * ↑a⁻¹ : α) = 1 := #align units.mul_inv Units.mul_inv #align add_units.add_neg AddUnits.add_neg +@[to_additive] lemma commute_coe_inv : Commute (a : α) ↑a⁻¹ := by + rw [Commute, SemiconjBy, inv_mul, mul_inv] + +@[to_additive] lemma commute_inv_coe : Commute ↑a⁻¹ (a : α) := a.commute_coe_inv.symm + @[to_additive] theorem inv_mul_of_eq {a : α} (h : ↑u = a) : ↑u⁻¹ * a = 1 := by rw [← h, u.inv_mul] #align units.inv_mul_of_eq Units.inv_mul_of_eq @@ -374,6 +366,49 @@ protected theorem eq_inv_of_mul_eq_one_right {a : α} (h : a * u = 1) : a = ↑u #align units.eq_inv_of_mul_eq_one_right Units.eq_inv_of_mul_eq_one_right #align add_units.eq_neg_of_add_eq_zero_right AddUnits.eq_neg_of_add_eq_zero_right +@[to_additive] +instance instMonoid : Monoid αˣ := + { (inferInstance : MulOneClass αˣ) with + mul_assoc := fun _ _ _ => ext <| mul_assoc _ _ _, + npow := fun n a ↦ + { val := a ^ n + inv := a⁻¹ ^ n + val_inv := by rw [← a.commute_coe_inv.mul_pow]; simp + inv_val := by rw [← a.commute_inv_coe.mul_pow]; simp } + npow_zero := fun a ↦ by ext; simp + npow_succ := fun n a ↦ by ext; simp [pow_succ] } + +/-- Units of a monoid form a group. -/ +@[to_additive "Additive units of an additive monoid form an additive group."] +instance instGroup : Group αˣ := + { (inferInstance : Monoid αˣ) with + inv := Inv.inv + mul_left_inv := fun u => ext u.inv_val + div := fun a b ↦ + { val := a * b⁻¹ + inv := b * a⁻¹ + val_inv := by rw [mul_assoc, inv_mul_cancel_left, mul_inv] + inv_val := by rw [mul_assoc, inv_mul_cancel_left, mul_inv] } + zpow := fun n a ↦ match n, a with + | Int.ofNat n, a => a ^ n + | Int.negSucc n, a => (a ^ n.succ)⁻¹ + zpow_zero' := fun a ↦ by simp + zpow_succ' := fun n a ↦ by simp [pow_succ] + zpow_neg' := fun n a ↦ by simp } + +/-- Units of a commutative monoid form a commutative group. -/ +@[to_additive "Additive units of an additive commutative monoid form +an additive commutative group."] +instance instCommGroupUnits {α} [CommMonoid α] : CommGroup αˣ where + mul_comm := fun _ _ => ext <| mul_comm _ _ +#align units.comm_group Units.instCommGroupUnits +#align add_units.add_comm_group AddUnits.instAddCommGroupAddUnits + +@[to_additive (attr := simp, norm_cast)] +lemma val_pow_eq_pow_val (n : ℕ) : ↑(a ^ n) = (a ^ n : α) := rfl +#align units.coe_pow Units.val_pow_eq_pow_val +#align add_units.coe_nsmul AddUnits.val_nsmul_eq_nsmul_val + @[to_additive (attr := simp)] theorem mul_inv_eq_one {a : α} : a * ↑u⁻¹ = 1 ↔ a = u := ⟨inv_inv u ▸ Units.eq_inv_of_mul_eq_one_right, fun h => mul_inv_of_eq h.symm⟩ @@ -402,11 +437,21 @@ theorem inv_unique {u₁ u₂ : αˣ} (h : (↑u₁ : α) = ↑u₂) : (↑u₁ #align units.inv_unique Units.inv_unique #align add_units.neg_unique AddUnits.neg_unique -@[to_additive (attr := simp)] -theorem val_inv_eq_inv_val {M : Type*} [DivisionMonoid M] (u : Units M) : ↑u⁻¹ = (u⁻¹ : M) := +end Monoid + +section DivisionMonoid +variable [DivisionMonoid α] + +@[to_additive (attr := simp, norm_cast)] lemma val_inv_eq_inv_val (u : αˣ) : ↑u⁻¹ = (u⁻¹ : α) := Eq.symm <| inv_eq_of_mul_eq_one_right u.mul_inv #align units.coe_inv Units.val_inv_eq_inv_val +@[to_additive (attr := simp, norm_cast)] +lemma val_div_eq_div_val : ∀ u₁ u₂ : αˣ, ↑(u₁ / u₂) = (u₁ / u₂ : α) := by simp [div_eq_mul_inv] +#align units.coe_div Units.val_div_eq_div_val +#align add_units.coe_sub AddUnits.val_neg_eq_neg_val + +end DivisionMonoid end Units /-- For `a, b` in a `CommMonoid` such that `a * b = 1`, makes a unit out of `a`. -/ @@ -629,20 +674,42 @@ theorem isUnit_of_mul_eq_one [CommMonoid M] (a b : M) (h : a * b = 1) : IsUnit a #align is_unit_of_mul_eq_one isUnit_of_mul_eq_one #align is_add_unit_of_add_eq_zero isAddUnit_of_add_eq_zero +section Monoid +variable [Monoid M] {a b : M} + @[to_additive IsAddUnit.exists_neg] -theorem IsUnit.exists_right_inv [Monoid M] {a : M} (h : IsUnit a) : ∃ b, a * b = 1 := by +lemma IsUnit.exists_right_inv (h : IsUnit a) : ∃ b, a * b = 1 := by rcases h with ⟨⟨a, b, hab, _⟩, rfl⟩ exact ⟨b, hab⟩ #align is_unit.exists_right_inv IsUnit.exists_right_inv #align is_add_unit.exists_neg IsAddUnit.exists_neg @[to_additive IsAddUnit.exists_neg'] -theorem IsUnit.exists_left_inv [Monoid M] {a : M} (h : IsUnit a) : ∃ b, b * a = 1 := by +lemma IsUnit.exists_left_inv [Monoid M] {a : M} (h : IsUnit a) : ∃ b, b * a = 1 := by rcases h with ⟨⟨a, b, _, hba⟩, rfl⟩ exact ⟨b, hba⟩ #align is_unit.exists_left_inv IsUnit.exists_left_inv #align is_add_unit.exists_neg' IsAddUnit.exists_neg' +@[to_additive] lemma IsUnit.mul : IsUnit a → IsUnit b → IsUnit (a * b) := by + rintro ⟨x, rfl⟩ ⟨y, rfl⟩; exact ⟨x * y, rfl⟩ +#align is_unit.mul IsUnit.mul +#align is_add_unit.add IsAddUnit.add + +@[to_additive] lemma IsUnit.pow (n : ℕ) : IsUnit a → IsUnit (a ^ n) := by + rintro ⟨u, rfl⟩; exact ⟨u ^ n, rfl⟩ +#align is_unit.pow IsUnit.pow +#align is_add_unit.nsmul IsAddUnit.nsmul + +theorem units_eq_one [Unique Mˣ] (u : Mˣ) : u = 1 := + Subsingleton.elim u 1 +#align units_eq_one units_eq_one + +@[to_additive] lemma isUnit_iff_eq_one [Unique Mˣ] {x : M} : IsUnit x ↔ x = 1 := + ⟨fun ⟨u, hu⟩ ↦ by rw [← hu, Subsingleton.elim u 1, Units.val_one], fun h ↦ h ▸ isUnit_one⟩ + +end Monoid + @[to_additive] theorem isUnit_iff_exists_inv [CommMonoid M] {a : M} : IsUnit a ↔ ∃ b, a * b = 1 := ⟨fun h => h.exists_right_inv, fun ⟨b, hab⟩ => isUnit_of_mul_eq_one _ b hab⟩ @@ -655,13 +722,6 @@ theorem isUnit_iff_exists_inv' [CommMonoid M] {a : M} : IsUnit a ↔ ∃ b, b * #align is_unit_iff_exists_inv' isUnit_iff_exists_inv' #align is_add_unit_iff_exists_neg' isAddUnit_iff_exists_neg' -@[to_additive] -theorem IsUnit.mul [Monoid M] {x y : M} : IsUnit x → IsUnit y → IsUnit (x * y) := by - rintro ⟨x, rfl⟩ ⟨y, rfl⟩ - exact ⟨x * y, Units.val_mul _ _⟩ -#align is_unit.mul IsUnit.mul -#align is_add_unit.add IsAddUnit.add - /-- Multiplication by a `u : Mˣ` on the right doesn't affect `IsUnit`. -/ @[to_additive (attr := simp) "Addition of a `u : AddUnits M` on the right doesn't affect `IsAddUnit`."] @@ -796,9 +856,24 @@ protected theorem mul_left_injective (h : IsUnit b) : Injective (· * b) := #align is_unit.mul_left_injective IsUnit.mul_left_injective #align is_add_unit.add_left_injective IsAddUnit.add_left_injective +@[to_additive] +theorem isUnit_iff_mulLeft_bijective {a : M} : + IsUnit a ↔ Function.Bijective (a * ·) := + ⟨fun h ↦ ⟨h.mul_right_injective, fun y ↦ ⟨h.unit⁻¹ * y, by simp [← mul_assoc]⟩⟩, fun h ↦ + ⟨⟨a, _, (h.2 1).choose_spec, h.1 + (by simpa [mul_assoc] using congr_arg (· * a) (h.2 1).choose_spec)⟩, rfl⟩⟩ + +@[to_additive] +theorem isUnit_iff_mulRight_bijective {a : M} : + IsUnit a ↔ Function.Bijective (· * a) := + ⟨fun h ↦ ⟨h.mul_left_injective, fun y ↦ ⟨y * h.unit⁻¹, by simp [mul_assoc]⟩⟩, + fun h ↦ ⟨⟨a, _, h.1 (by simpa [mul_assoc] using congr_arg (a * ·) (h.2 1).choose_spec), + (h.2 1).choose_spec⟩, rfl⟩⟩ + end Monoid -variable [DivisionMonoid M] {a : M} +section DivisionMonoid +variable [DivisionMonoid α] {a b c : α} @[to_additive (attr := simp)] protected theorem inv_mul_cancel : IsUnit a → a⁻¹ * a = 1 := by @@ -814,8 +889,261 @@ protected theorem mul_inv_cancel : IsUnit a → a * a⁻¹ = 1 := by #align is_unit.mul_inv_cancel IsUnit.mul_inv_cancel #align is_add_unit.add_neg_cancel IsAddUnit.add_neg_cancel +/-- The element of the group of units, corresponding to an element of a monoid which is a unit. As +opposed to `IsUnit.unit`, the inverse is computable and comes from the inversion on `α`. This is +useful to transfer properties of inversion in `Units α` to `α`. See also `toUnits`. -/ +@[to_additive (attr := simps val ) +"The element of the additive group of additive units, corresponding to an element of +an additive monoid which is an additive unit. As opposed to `IsAddUnit.addUnit`, the negation is +computable and comes from the negation on `α`. This is useful to transfer properties of negation +in `AddUnits α` to `α`. See also `toAddUnits`."] +def unit' (h : IsUnit a) : αˣ := ⟨a, a⁻¹, h.mul_inv_cancel, h.inv_mul_cancel⟩ +#align is_unit.unit' IsUnit.unit' +#align is_add_unit.add_unit' IsAddUnit.addUnit' +#align is_unit.coe_unit' IsUnit.val_unit' +#align is_add_unit.coe_add_unit' IsAddUnit.val_addUnit' + +-- Porting note: TODO: `simps val_inv` fails +@[to_additive] lemma val_inv_unit' (h : IsUnit a) : ↑(h.unit'⁻¹) = a⁻¹ := rfl +#align is_unit.coe_inv_unit' IsUnit.val_inv_unit' +#align is_add_unit.coe_neg_add_unit' IsAddUnit.val_neg_addUnit' + +@[to_additive (attr := simp)] +protected lemma mul_inv_cancel_left (h : IsUnit a) : ∀ b, a * (a⁻¹ * b) = b := + h.unit'.mul_inv_cancel_left +#align is_unit.mul_inv_cancel_left IsUnit.mul_inv_cancel_left +#align is_add_unit.add_neg_cancel_left IsAddUnit.add_neg_cancel_left + +@[to_additive (attr := simp)] +protected lemma inv_mul_cancel_left (h : IsUnit a) : ∀ b, a⁻¹ * (a * b) = b := + h.unit'.inv_mul_cancel_left +#align is_unit.inv_mul_cancel_left IsUnit.inv_mul_cancel_left +#align is_add_unit.neg_add_cancel_left IsAddUnit.neg_add_cancel_left + +@[to_additive (attr := simp)] +protected lemma mul_inv_cancel_right (h : IsUnit b) (a : α) : a * b * b⁻¹ = a := + h.unit'.mul_inv_cancel_right _ +#align is_unit.mul_inv_cancel_right IsUnit.mul_inv_cancel_right +#align is_add_unit.add_neg_cancel_right IsAddUnit.add_neg_cancel_right + +@[to_additive (attr := simp)] +protected lemma inv_mul_cancel_right (h : IsUnit b) (a : α) : a * b⁻¹ * b = a := + h.unit'.inv_mul_cancel_right _ +#align is_unit.inv_mul_cancel_right IsUnit.inv_mul_cancel_right +#align is_add_unit.neg_add_cancel_right IsAddUnit.neg_add_cancel_right + +@[to_additive] +protected lemma div_self (h : IsUnit a) : a / a = 1 := by rw [div_eq_mul_inv, h.mul_inv_cancel] +#align is_unit.div_self IsUnit.div_self +#align is_add_unit.sub_self IsAddUnit.sub_self + +@[to_additive] +protected lemma eq_mul_inv_iff_mul_eq (h : IsUnit c) : a = b * c⁻¹ ↔ a * c = b := + h.unit'.eq_mul_inv_iff_mul_eq +#align is_unit.eq_mul_inv_iff_mul_eq IsUnit.eq_mul_inv_iff_mul_eq +#align is_add_unit.eq_add_neg_iff_add_eq IsAddUnit.eq_add_neg_iff_add_eq + +@[to_additive] +protected lemma eq_inv_mul_iff_mul_eq (h : IsUnit b) : a = b⁻¹ * c ↔ b * a = c := + h.unit'.eq_inv_mul_iff_mul_eq +#align is_unit.eq_inv_mul_iff_mul_eq IsUnit.eq_inv_mul_iff_mul_eq +#align is_add_unit.eq_neg_add_iff_add_eq IsAddUnit.eq_neg_add_iff_add_eq + +@[to_additive] +protected lemma inv_mul_eq_iff_eq_mul (h : IsUnit a) : a⁻¹ * b = c ↔ b = a * c := + h.unit'.inv_mul_eq_iff_eq_mul +#align is_unit.inv_mul_eq_iff_eq_mul IsUnit.inv_mul_eq_iff_eq_mul +#align is_add_unit.neg_add_eq_iff_eq_add IsAddUnit.neg_add_eq_iff_eq_add + +@[to_additive] +protected lemma mul_inv_eq_iff_eq_mul (h : IsUnit b) : a * b⁻¹ = c ↔ a = c * b := + h.unit'.mul_inv_eq_iff_eq_mul +#align is_unit.mul_inv_eq_iff_eq_mul IsUnit.mul_inv_eq_iff_eq_mul +#align is_add_unit.add_neg_eq_iff_eq_add IsAddUnit.add_neg_eq_iff_eq_add + +@[to_additive] +protected lemma mul_inv_eq_one (h : IsUnit b) : a * b⁻¹ = 1 ↔ a = b := + @Units.mul_inv_eq_one _ _ h.unit' _ +#align is_unit.mul_inv_eq_one IsUnit.mul_inv_eq_one +#align is_add_unit.add_neg_eq_zero IsAddUnit.add_neg_eq_zero + +@[to_additive] +protected lemma inv_mul_eq_one (h : IsUnit a) : a⁻¹ * b = 1 ↔ a = b := + @Units.inv_mul_eq_one _ _ h.unit' _ +#align is_unit.inv_mul_eq_one IsUnit.inv_mul_eq_one +#align is_add_unit.neg_add_eq_zero IsAddUnit.neg_add_eq_zero + +@[to_additive] +protected lemma mul_eq_one_iff_eq_inv (h : IsUnit b) : a * b = 1 ↔ a = b⁻¹ := + @Units.mul_eq_one_iff_eq_inv _ _ h.unit' _ +#align is_unit.mul_eq_one_iff_eq_inv IsUnit.mul_eq_one_iff_eq_inv +#align is_add_unit.add_eq_zero_iff_eq_neg IsAddUnit.add_eq_zero_iff_eq_neg + +@[to_additive] +protected lemma mul_eq_one_iff_inv_eq (h : IsUnit a) : a * b = 1 ↔ a⁻¹ = b := + @Units.mul_eq_one_iff_inv_eq _ _ h.unit' _ +#align is_unit.mul_eq_one_iff_inv_eq IsUnit.mul_eq_one_iff_inv_eq +#align is_add_unit.add_eq_zero_iff_neg_eq IsAddUnit.add_eq_zero_iff_neg_eq + +@[to_additive (attr := simp)] +protected lemma div_mul_cancel (h : IsUnit b) (a : α) : a / b * b = a := by + rw [div_eq_mul_inv, h.inv_mul_cancel_right] +#align is_unit.div_mul_cancel IsUnit.div_mul_cancel +#align is_add_unit.sub_add_cancel IsAddUnit.sub_add_cancel + +@[to_additive (attr := simp)] +protected lemma mul_div_cancel (h : IsUnit b) (a : α) : a * b / b = a := by + rw [div_eq_mul_inv, h.mul_inv_cancel_right] +#align is_unit.mul_div_cancel IsUnit.mul_div_cancel +#align is_add_unit.add_sub_cancel IsAddUnit.add_sub_cancel + +@[to_additive] +protected lemma mul_one_div_cancel (h : IsUnit a) : a * (1 / a) = 1 := by simp [h] +#align is_unit.mul_one_div_cancel IsUnit.mul_one_div_cancel +#align is_add_unit.add_zero_sub_cancel IsAddUnit.add_zero_sub_cancel + +@[to_additive] +protected lemma one_div_mul_cancel (h : IsUnit a) : 1 / a * a = 1 := by simp [h] +#align is_unit.one_div_mul_cancel IsUnit.one_div_mul_cancel +#align is_add_unit.zero_sub_add_cancel IsAddUnit.zero_sub_add_cancel + +@[to_additive] +lemma inv (h : IsUnit a) : IsUnit a⁻¹ := by + obtain ⟨u, hu⟩ := h + rw [← hu, ← Units.val_inv_eq_inv_val] + exact Units.isUnit _ +#align is_unit.inv IsUnit.inv +#align is_add_unit.neg IsAddUnit.neg + +@[to_additive] lemma div (ha : IsUnit a) (hb : IsUnit b) : IsUnit (a / b) := by + rw [div_eq_mul_inv]; exact ha.mul hb.inv +#align is_unit.div IsUnit.div +#align is_add_unit.sub IsAddUnit.sub + +@[to_additive] +protected lemma div_left_inj (h : IsUnit c) : a / c = b / c ↔ a = b := by + simp only [div_eq_mul_inv] + exact Units.mul_left_inj h.inv.unit' +#align is_unit.div_left_inj IsUnit.div_left_inj +#align is_add_unit.sub_left_inj IsAddUnit.sub_left_inj + +@[to_additive] +protected lemma div_eq_iff (h : IsUnit b) : a / b = c ↔ a = c * b := by + rw [div_eq_mul_inv, h.mul_inv_eq_iff_eq_mul] +#align is_unit.div_eq_iff IsUnit.div_eq_iff +#align is_add_unit.sub_eq_iff IsAddUnit.sub_eq_iff + +@[to_additive] +protected lemma eq_div_iff (h : IsUnit c) : a = b / c ↔ a * c = b := by + rw [div_eq_mul_inv, h.eq_mul_inv_iff_mul_eq] +#align is_unit.eq_div_iff IsUnit.eq_div_iff +#align is_add_unit.eq_sub_iff IsAddUnit.eq_sub_iff + +@[to_additive] +protected lemma div_eq_of_eq_mul (h : IsUnit b) : a = c * b → a / b = c := + h.div_eq_iff.2 +#align is_unit.div_eq_of_eq_mul IsUnit.div_eq_of_eq_mul +#align is_add_unit.sub_eq_of_eq_add IsAddUnit.sub_eq_of_eq_add + +@[to_additive] +protected lemma eq_div_of_mul_eq (h : IsUnit c) : a * c = b → a = b / c := + h.eq_div_iff.2 +#align is_unit.eq_div_of_mul_eq IsUnit.eq_div_of_mul_eq +#align is_add_unit.eq_sub_of_add_eq IsAddUnit.eq_sub_of_add_eq + +@[to_additive] +protected lemma div_eq_one_iff_eq (h : IsUnit b) : a / b = 1 ↔ a = b := + ⟨eq_of_div_eq_one, fun hab => hab.symm ▸ h.div_self⟩ +#align is_unit.div_eq_one_iff_eq IsUnit.div_eq_one_iff_eq +#align is_add_unit.sub_eq_zero_iff_eq IsAddUnit.sub_eq_zero_iff_eq + +/-- The `Group` version of this lemma is `div_mul_cancel'''` -/ +@[to_additive "The `AddGroup` version of this lemma is `sub_add_cancel''`"] +protected lemma div_mul_left (h : IsUnit b) : b / (a * b) = 1 / a := by + rw [div_eq_mul_inv, mul_inv_rev, h.mul_inv_cancel_left, one_div] +#align is_unit.div_mul_left IsUnit.div_mul_left +#align is_add_unit.sub_add_left IsAddUnit.sub_add_left + +@[to_additive] +protected lemma mul_div_mul_right (h : IsUnit c) (a b : α) : a * c / (b * c) = a / b := by + simp only [div_eq_mul_inv, mul_inv_rev, mul_assoc, h.mul_inv_cancel_left] +#align is_unit.mul_div_mul_right IsUnit.mul_div_mul_right +#align is_add_unit.add_sub_add_right IsAddUnit.add_sub_add_right + +@[to_additive] +protected lemma mul_mul_div (a : α) (h : IsUnit b) : a * b * (1 / b) = a := by simp [h] +#align is_unit.mul_mul_div IsUnit.mul_mul_div +#align is_add_unit.add_add_sub IsAddUnit.add_add_sub + +end DivisionMonoid + +section DivisionCommMonoid +variable [DivisionCommMonoid α] {a b c d : α} + +@[to_additive] +protected lemma div_mul_right (h : IsUnit a) (b : α) : a / (a * b) = 1 / b := by + rw [mul_comm, h.div_mul_left] +#align is_unit.div_mul_right IsUnit.div_mul_right +#align is_add_unit.sub_add_right IsAddUnit.sub_add_right + +@[to_additive] +protected lemma mul_div_cancel_left (h : IsUnit a) (b : α) : a * b / a = b := by + rw [mul_comm, h.mul_div_cancel] +#align is_unit.mul_div_cancel_left IsUnit.mul_div_cancel_left +#align is_add_unit.add_sub_cancel_left IsAddUnit.add_sub_cancel_left + +@[to_additive] +protected lemma mul_div_cancel' (h : IsUnit a) (b : α) : a * (b / a) = b := by + rw [mul_comm, h.div_mul_cancel] +#align is_unit.mul_div_cancel' IsUnit.mul_div_cancel' +#align is_add_unit.add_sub_cancel' IsAddUnit.add_sub_cancel' + +@[to_additive] +protected lemma mul_div_mul_left (h : IsUnit c) (a b : α) : c * a / (c * b) = a / b := by + rw [mul_comm c, mul_comm c, h.mul_div_mul_right] +#align is_unit.mul_div_mul_left IsUnit.mul_div_mul_left +#align is_add_unit.add_sub_add_left IsAddUnit.add_sub_add_left + +@[to_additive] +protected lemma mul_eq_mul_of_div_eq_div (hb : IsUnit b) (hd : IsUnit d) + (a c : α) (h : a / b = c / d) : a * d = c * b := by + rw [← mul_one a, ← hb.div_self, ← mul_comm_div, h, div_mul_eq_mul_div, hd.div_mul_cancel] +#align is_unit.mul_eq_mul_of_div_eq_div IsUnit.mul_eq_mul_of_div_eq_div +#align is_add_unit.add_eq_add_of_sub_eq_sub IsAddUnit.add_eq_add_of_sub_eq_sub + +@[to_additive] +protected lemma div_eq_div_iff (hb : IsUnit b) (hd : IsUnit d) : + a / b = c / d ↔ a * d = c * b := by + rw [← (hb.mul hd).mul_left_inj, ← mul_assoc, hb.div_mul_cancel, ← mul_assoc, mul_right_comm, + hd.div_mul_cancel] +#align is_unit.div_eq_div_iff IsUnit.div_eq_div_iff +#align is_add_unit.sub_eq_sub_iff IsAddUnit.sub_eq_sub_iff + +@[to_additive] +protected lemma div_div_cancel (h : IsUnit a) : a / (a / b) = b := by + rw [div_div_eq_mul_div, h.mul_div_cancel_left] +#align is_unit.div_div_cancel IsUnit.div_div_cancel +#align is_add_unit.sub_sub_cancel IsAddUnit.sub_sub_cancel + +@[to_additive] +protected lemma div_div_cancel_left (h : IsUnit a) : a / b / a = b⁻¹ := by + rw [div_eq_mul_inv, div_eq_mul_inv, mul_right_comm, h.mul_inv_cancel, one_mul] +#align is_unit.div_div_cancel_left IsUnit.div_div_cancel_left +#align is_add_unit.sub_sub_cancel_left IsAddUnit.sub_sub_cancel_left + +end DivisionCommMonoid end IsUnit +@[field_simps] +lemma divp_eq_div [DivisionMonoid α] (a : α) (u : αˣ) : a /ₚ u = a / u := + by rw [div_eq_mul_inv, divp, u.val_inv_eq_inv_val] +#align divp_eq_div divp_eq_div + +@[to_additive] +lemma Group.isUnit [Group α] (a : α) : IsUnit a := ⟨⟨a, a⁻¹, mul_inv_self _, inv_mul_self _⟩, rfl⟩ +#align group.is_unit Group.isUnit +#align add_group.is_add_unit AddGroup.isAddUnit + -- namespace end IsUnit diff --git a/Mathlib/Algebra/Group/Units/Hom.lean b/Mathlib/Algebra/Group/Units/Hom.lean index c9ab629980894..db3a894abce4d 100644 --- a/Mathlib/Algebra/Group/Units/Hom.lean +++ b/Mathlib/Algebra/Group/Units/Hom.lean @@ -19,11 +19,6 @@ also contains unrelated results about `Units` that depend on `MonoidHom`. * `Units.map`: Turn a homomorphism from `α` to `β` monoids into a homomorphism from `αˣ` to `βˣ`. * `MonoidHom.toHomUnits`: Turn a homomorphism from a group `α` to `β` into a homomorphism from `α` to `βˣ`. - -## TODO - -The results that don't mention homomorphisms should be proved (earlier?) in a different file and be -used to golf the basic `Group` lemmas. -/ @@ -31,12 +26,6 @@ open Function universe u v w -@[to_additive] -theorem Group.isUnit {G} [Group G] (g : G) : IsUnit g := - ⟨⟨g, g⁻¹, mul_inv_self g, inv_mul_self g⟩, rfl⟩ -#align group.is_unit Group.isUnit -#align add_group.is_add_unit AddGroup.isAddUnit - section MonoidHomClass /-- If two homomorphisms from a division monoid to a monoid are equal at a unit `x`, then they are @@ -118,33 +107,16 @@ theorem coeHom_apply (x : Mˣ) : coeHom M x = ↑x := rfl #align units.coe_hom_apply Units.coeHom_apply #align add_units.coe_hom_apply AddUnits.coeHom_apply -@[to_additive (attr := simp, norm_cast)] -theorem val_pow_eq_pow_val (u : Mˣ) (n : ℕ) : ((u ^ n : Mˣ) : M) = (u : M) ^ n := - (Units.coeHom M).map_pow u n -#align units.coe_pow Units.val_pow_eq_pow_val -#align add_units.coe_nsmul AddUnits.val_nsmul_eq_nsmul_val - section DivisionMonoid variable [DivisionMonoid α] -@[to_additive (attr := simp, norm_cast)] -theorem val_div_eq_div_val : ∀ u₁ u₂ : αˣ, ↑(u₁ / u₂) = (u₁ / u₂ : α) := - (Units.coeHom α).map_div -#align units.coe_div Units.val_div_eq_div_val -#align add_units.coe_sub AddUnits.val_neg_eq_neg_val - @[to_additive (attr := simp, norm_cast)] theorem val_zpow_eq_zpow_val : ∀ (u : αˣ) (n : ℤ), ((u ^ n : αˣ) : α) = (u : α) ^ n := (Units.coeHom α).map_zpow #align units.coe_zpow Units.val_zpow_eq_zpow_val #align add_units.coe_zsmul AddUnits.val_zsmul_eq_zsmul_val -@[field_simps] -theorem _root_.divp_eq_div (a : α) (u : αˣ) : a /ₚ u = a / u := - by rw [div_eq_mul_inv, divp, u.val_inv_eq_inv_val] -#align divp_eq_div divp_eq_div - @[to_additive (attr := simp)] theorem _root_.map_units_inv {F : Type*} [MonoidHomClass F M α] (f : F) (u : Units M) : f ↑u⁻¹ = (f u)⁻¹ := ((f : M →* α).comp (Units.coeHom M)).map_inv u @@ -268,257 +240,4 @@ theorem liftRight_inv_mul (f : M →* N) (h : ∀ x, IsUnit (f x)) (x) : #align is_add_unit.lift_right_neg_add IsAddUnit.liftRight_neg_add end Monoid - -section DivisionMonoid - -variable [DivisionMonoid α] {a b c : α} - -/-- The element of the group of units, corresponding to an element of a monoid which is a unit. As -opposed to `IsUnit.unit`, the inverse is computable and comes from the inversion on `α`. This is -useful to transfer properties of inversion in `Units α` to `α`. See also `toUnits`. -/ -@[to_additive (attr := simps val) - "The element of the additive group of additive units, corresponding to an element of - an additive monoid which is an additive unit. As opposed to `IsAddUnit.addUnit`, the negation is - computable and comes from the negation on `α`. This is useful to transfer properties of negation - in `AddUnits α` to `α`. See also `toAddUnits`."] -def unit' (h : IsUnit a) : αˣ := - ⟨a, a⁻¹, h.mul_inv_cancel, h.inv_mul_cancel⟩ -#align is_unit.unit' IsUnit.unit' -#align is_add_unit.add_unit' IsAddUnit.addUnit' -#align is_unit.coe_unit' IsUnit.val_unit' -#align is_add_unit.coe_add_unit' IsAddUnit.val_addUnit' - --- Porting note: TODO: `simps val_inv` fails -@[to_additive] theorem val_inv_unit' (h : IsUnit a) : ↑(h.unit'⁻¹) = a⁻¹ := rfl -#align is_unit.coe_inv_unit' IsUnit.val_inv_unit' -#align is_add_unit.coe_neg_add_unit' IsAddUnit.val_neg_addUnit' - -@[to_additive (attr := simp)] -protected theorem mul_inv_cancel_left (h : IsUnit a) : ∀ b, a * (a⁻¹ * b) = b := - h.unit'.mul_inv_cancel_left -#align is_unit.mul_inv_cancel_left IsUnit.mul_inv_cancel_left -#align is_add_unit.add_neg_cancel_left IsAddUnit.add_neg_cancel_left - -@[to_additive (attr := simp)] -protected theorem inv_mul_cancel_left (h : IsUnit a) : ∀ b, a⁻¹ * (a * b) = b := - h.unit'.inv_mul_cancel_left -#align is_unit.inv_mul_cancel_left IsUnit.inv_mul_cancel_left -#align is_add_unit.neg_add_cancel_left IsAddUnit.neg_add_cancel_left - -@[to_additive (attr := simp)] -protected theorem mul_inv_cancel_right (h : IsUnit b) (a : α) : a * b * b⁻¹ = a := - h.unit'.mul_inv_cancel_right _ -#align is_unit.mul_inv_cancel_right IsUnit.mul_inv_cancel_right -#align is_add_unit.add_neg_cancel_right IsAddUnit.add_neg_cancel_right - -@[to_additive (attr := simp)] -protected theorem inv_mul_cancel_right (h : IsUnit b) (a : α) : a * b⁻¹ * b = a := - h.unit'.inv_mul_cancel_right _ -#align is_unit.inv_mul_cancel_right IsUnit.inv_mul_cancel_right -#align is_add_unit.neg_add_cancel_right IsAddUnit.neg_add_cancel_right - -@[to_additive] -protected theorem div_self (h : IsUnit a) : a / a = 1 := by rw [div_eq_mul_inv, h.mul_inv_cancel] -#align is_unit.div_self IsUnit.div_self -#align is_add_unit.sub_self IsAddUnit.sub_self - -@[to_additive] -protected theorem eq_mul_inv_iff_mul_eq (h : IsUnit c) : a = b * c⁻¹ ↔ a * c = b := - h.unit'.eq_mul_inv_iff_mul_eq -#align is_unit.eq_mul_inv_iff_mul_eq IsUnit.eq_mul_inv_iff_mul_eq -#align is_add_unit.eq_add_neg_iff_add_eq IsAddUnit.eq_add_neg_iff_add_eq - -@[to_additive] -protected theorem eq_inv_mul_iff_mul_eq (h : IsUnit b) : a = b⁻¹ * c ↔ b * a = c := - h.unit'.eq_inv_mul_iff_mul_eq -#align is_unit.eq_inv_mul_iff_mul_eq IsUnit.eq_inv_mul_iff_mul_eq -#align is_add_unit.eq_neg_add_iff_add_eq IsAddUnit.eq_neg_add_iff_add_eq - -@[to_additive] -protected theorem inv_mul_eq_iff_eq_mul (h : IsUnit a) : a⁻¹ * b = c ↔ b = a * c := - h.unit'.inv_mul_eq_iff_eq_mul -#align is_unit.inv_mul_eq_iff_eq_mul IsUnit.inv_mul_eq_iff_eq_mul -#align is_add_unit.neg_add_eq_iff_eq_add IsAddUnit.neg_add_eq_iff_eq_add - -@[to_additive] -protected theorem mul_inv_eq_iff_eq_mul (h : IsUnit b) : a * b⁻¹ = c ↔ a = c * b := - h.unit'.mul_inv_eq_iff_eq_mul -#align is_unit.mul_inv_eq_iff_eq_mul IsUnit.mul_inv_eq_iff_eq_mul -#align is_add_unit.add_neg_eq_iff_eq_add IsAddUnit.add_neg_eq_iff_eq_add - -@[to_additive] -protected theorem mul_inv_eq_one (h : IsUnit b) : a * b⁻¹ = 1 ↔ a = b := - @Units.mul_inv_eq_one _ _ h.unit' _ -#align is_unit.mul_inv_eq_one IsUnit.mul_inv_eq_one -#align is_add_unit.add_neg_eq_zero IsAddUnit.add_neg_eq_zero - -@[to_additive] -protected theorem inv_mul_eq_one (h : IsUnit a) : a⁻¹ * b = 1 ↔ a = b := - @Units.inv_mul_eq_one _ _ h.unit' _ -#align is_unit.inv_mul_eq_one IsUnit.inv_mul_eq_one -#align is_add_unit.neg_add_eq_zero IsAddUnit.neg_add_eq_zero - -@[to_additive] -protected theorem mul_eq_one_iff_eq_inv (h : IsUnit b) : a * b = 1 ↔ a = b⁻¹ := - @Units.mul_eq_one_iff_eq_inv _ _ h.unit' _ -#align is_unit.mul_eq_one_iff_eq_inv IsUnit.mul_eq_one_iff_eq_inv -#align is_add_unit.add_eq_zero_iff_eq_neg IsAddUnit.add_eq_zero_iff_eq_neg - -@[to_additive] -protected theorem mul_eq_one_iff_inv_eq (h : IsUnit a) : a * b = 1 ↔ a⁻¹ = b := - @Units.mul_eq_one_iff_inv_eq _ _ h.unit' _ -#align is_unit.mul_eq_one_iff_inv_eq IsUnit.mul_eq_one_iff_inv_eq -#align is_add_unit.add_eq_zero_iff_neg_eq IsAddUnit.add_eq_zero_iff_neg_eq - -@[to_additive (attr := simp)] -protected theorem div_mul_cancel (h : IsUnit b) (a : α) : a / b * b = a := by - rw [div_eq_mul_inv, h.inv_mul_cancel_right] -#align is_unit.div_mul_cancel IsUnit.div_mul_cancel -#align is_add_unit.sub_add_cancel IsAddUnit.sub_add_cancel - -@[to_additive (attr := simp)] -protected theorem mul_div_cancel (h : IsUnit b) (a : α) : a * b / b = a := by - rw [div_eq_mul_inv, h.mul_inv_cancel_right] -#align is_unit.mul_div_cancel IsUnit.mul_div_cancel -#align is_add_unit.add_sub_cancel IsAddUnit.add_sub_cancel - -@[to_additive] -protected theorem mul_one_div_cancel (h : IsUnit a) : a * (1 / a) = 1 := by simp [h] -#align is_unit.mul_one_div_cancel IsUnit.mul_one_div_cancel -#align is_add_unit.add_zero_sub_cancel IsAddUnit.add_zero_sub_cancel - -@[to_additive] -protected theorem one_div_mul_cancel (h : IsUnit a) : 1 / a * a = 1 := by simp [h] -#align is_unit.one_div_mul_cancel IsUnit.one_div_mul_cancel -#align is_add_unit.zero_sub_add_cancel IsAddUnit.zero_sub_add_cancel - -@[to_additive] -theorem inv (h : IsUnit a) : IsUnit a⁻¹ := by - rcases h with ⟨u, hu⟩ - rw [← hu, ← Units.val_inv_eq_inv_val] - exact Units.isUnit _ -#align is_unit.inv IsUnit.inv -#align is_add_unit.neg IsAddUnit.neg - -@[to_additive] -theorem div (ha : IsUnit a) (hb : IsUnit b) : IsUnit (a / b) := by - rw [div_eq_mul_inv] - exact ha.mul hb.inv -#align is_unit.div IsUnit.div -#align is_add_unit.sub IsAddUnit.sub - -@[to_additive] -protected theorem div_left_inj (h : IsUnit c) : a / c = b / c ↔ a = b := by - simp only [div_eq_mul_inv] - exact Units.mul_left_inj h.inv.unit' -#align is_unit.div_left_inj IsUnit.div_left_inj -#align is_add_unit.sub_left_inj IsAddUnit.sub_left_inj - -@[to_additive] -protected theorem div_eq_iff (h : IsUnit b) : a / b = c ↔ a = c * b := by - rw [div_eq_mul_inv, h.mul_inv_eq_iff_eq_mul] -#align is_unit.div_eq_iff IsUnit.div_eq_iff -#align is_add_unit.sub_eq_iff IsAddUnit.sub_eq_iff - -@[to_additive] -protected theorem eq_div_iff (h : IsUnit c) : a = b / c ↔ a * c = b := by - rw [div_eq_mul_inv, h.eq_mul_inv_iff_mul_eq] -#align is_unit.eq_div_iff IsUnit.eq_div_iff -#align is_add_unit.eq_sub_iff IsAddUnit.eq_sub_iff - -@[to_additive] -protected theorem div_eq_of_eq_mul (h : IsUnit b) : a = c * b → a / b = c := - h.div_eq_iff.2 -#align is_unit.div_eq_of_eq_mul IsUnit.div_eq_of_eq_mul -#align is_add_unit.sub_eq_of_eq_add IsAddUnit.sub_eq_of_eq_add - -@[to_additive] -protected theorem eq_div_of_mul_eq (h : IsUnit c) : a * c = b → a = b / c := - h.eq_div_iff.2 -#align is_unit.eq_div_of_mul_eq IsUnit.eq_div_of_mul_eq -#align is_add_unit.eq_sub_of_add_eq IsAddUnit.eq_sub_of_add_eq - -@[to_additive] -protected theorem div_eq_one_iff_eq (h : IsUnit b) : a / b = 1 ↔ a = b := - ⟨eq_of_div_eq_one, fun hab => hab.symm ▸ h.div_self⟩ -#align is_unit.div_eq_one_iff_eq IsUnit.div_eq_one_iff_eq -#align is_add_unit.sub_eq_zero_iff_eq IsAddUnit.sub_eq_zero_iff_eq - -/-- The `Group` version of this lemma is `div_mul_cancel'''` -/ -@[to_additive "The `AddGroup` version of this lemma is `sub_add_cancel''`"] -protected theorem div_mul_left (h : IsUnit b) : b / (a * b) = 1 / a := by - rw [div_eq_mul_inv, mul_inv_rev, h.mul_inv_cancel_left, one_div] -#align is_unit.div_mul_left IsUnit.div_mul_left -#align is_add_unit.sub_add_left IsAddUnit.sub_add_left - -@[to_additive] -protected theorem mul_div_mul_right (h : IsUnit c) (a b : α) : a * c / (b * c) = a / b := by - simp only [div_eq_mul_inv, mul_inv_rev, mul_assoc, h.mul_inv_cancel_left] -#align is_unit.mul_div_mul_right IsUnit.mul_div_mul_right -#align is_add_unit.add_sub_add_right IsAddUnit.add_sub_add_right - -@[to_additive] -protected theorem mul_mul_div (a : α) (h : IsUnit b) : a * b * (1 / b) = a := by simp [h] -#align is_unit.mul_mul_div IsUnit.mul_mul_div -#align is_add_unit.add_add_sub IsAddUnit.add_add_sub - -end DivisionMonoid - -section DivisionCommMonoid - -variable [DivisionCommMonoid α] {a b c d : α} - -@[to_additive] -protected theorem div_mul_right (h : IsUnit a) (b : α) : a / (a * b) = 1 / b := by - rw [mul_comm, h.div_mul_left] -#align is_unit.div_mul_right IsUnit.div_mul_right -#align is_add_unit.sub_add_right IsAddUnit.sub_add_right - -@[to_additive] -protected theorem mul_div_cancel_left (h : IsUnit a) (b : α) : a * b / a = b := by - rw [mul_comm, h.mul_div_cancel] -#align is_unit.mul_div_cancel_left IsUnit.mul_div_cancel_left -#align is_add_unit.add_sub_cancel_left IsAddUnit.add_sub_cancel_left - -@[to_additive] -protected theorem mul_div_cancel' (h : IsUnit a) (b : α) : a * (b / a) = b := by - rw [mul_comm, h.div_mul_cancel] -#align is_unit.mul_div_cancel' IsUnit.mul_div_cancel' -#align is_add_unit.add_sub_cancel' IsAddUnit.add_sub_cancel' - -@[to_additive] -protected theorem mul_div_mul_left (h : IsUnit c) (a b : α) : c * a / (c * b) = a / b := by - rw [mul_comm c, mul_comm c, h.mul_div_mul_right] -#align is_unit.mul_div_mul_left IsUnit.mul_div_mul_left -#align is_add_unit.add_sub_add_left IsAddUnit.add_sub_add_left - -@[to_additive] -protected theorem mul_eq_mul_of_div_eq_div (hb : IsUnit b) (hd : IsUnit d) - (a c : α) (h : a / b = c / d) : a * d = c * b := by - rw [← mul_one a, ← hb.div_self, ← mul_comm_div, h, div_mul_eq_mul_div, hd.div_mul_cancel] -#align is_unit.mul_eq_mul_of_div_eq_div IsUnit.mul_eq_mul_of_div_eq_div -#align is_add_unit.add_eq_add_of_sub_eq_sub IsAddUnit.add_eq_add_of_sub_eq_sub - -@[to_additive] -protected theorem div_eq_div_iff (hb : IsUnit b) (hd : IsUnit d) : - a / b = c / d ↔ a * d = c * b := by - rw [← (hb.mul hd).mul_left_inj, ← mul_assoc, hb.div_mul_cancel, ← mul_assoc, mul_right_comm, - hd.div_mul_cancel] -#align is_unit.div_eq_div_iff IsUnit.div_eq_div_iff -#align is_add_unit.sub_eq_sub_iff IsAddUnit.sub_eq_sub_iff - -@[to_additive] -protected theorem div_div_cancel (h : IsUnit a) : a / (a / b) = b := by - rw [div_div_eq_mul_div, h.mul_div_cancel_left] -#align is_unit.div_div_cancel IsUnit.div_div_cancel -#align is_add_unit.sub_sub_cancel IsAddUnit.sub_sub_cancel - -@[to_additive] -protected theorem div_div_cancel_left (h : IsUnit a) : a / b / a = b⁻¹ := by - rw [div_eq_mul_inv, div_eq_mul_inv, mul_right_comm, h.mul_inv_cancel, one_mul] -#align is_unit.div_div_cancel_left IsUnit.div_div_cancel_left -#align is_add_unit.sub_sub_cancel_left IsAddUnit.sub_sub_cancel_left - -end DivisionCommMonoid - end IsUnit diff --git a/Mathlib/Algebra/Group/WithOne/Defs.lean b/Mathlib/Algebra/Group/WithOne/Defs.lean index 41cc2435e9b3d..dcf263a377592 100644 --- a/Mathlib/Algebra/Group/WithOne/Defs.lean +++ b/Mathlib/Algebra/Group/WithOne/Defs.lean @@ -3,8 +3,8 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Johan Commelin -/ -import Mathlib.Order.WithBot import Mathlib.Algebra.Ring.Defs +import Mathlib.Order.WithBot #align_import algebra.group.with_one.defs from "leanprover-community/mathlib"@"995b47e555f1b6297c7cf16855f1023e355219fb" @@ -187,20 +187,28 @@ instance mulOneClass [Mul α] : MulOneClass (WithOne α) where one_mul := (Option.liftOrGet_isLeftId _).1 mul_one := (Option.liftOrGet_isRightId _).1 -@[to_additive] -instance monoid [Semigroup α] : Monoid (WithOne α) := - { WithOne.mulOneClass with mul_assoc := (Option.liftOrGet_isAssociative _).1 } - -@[to_additive] -instance commMonoid [CommSemigroup α] : CommMonoid (WithOne α) := - { WithOne.monoid with mul_comm := (Option.liftOrGet_isCommutative _).1 } - @[to_additive (attr := simp, norm_cast)] -theorem coe_mul [Mul α] (a b : α) : ((a * b : α) : WithOne α) = a * b := - rfl +lemma coe_mul [Mul α] (a b : α) : (↑(a * b) : WithOne α) = a * b := rfl #align with_one.coe_mul WithOne.coe_mul #align with_zero.coe_add WithZero.coe_add +@[to_additive] +instance monoid [Semigroup α] : Monoid (WithOne α) where + __ := mulOneClass + mul_assoc a b c := match a, b, c with + | 1, b, c => by simp + | (a : α), 1, c => by simp + | (a : α), (b : α), 1 => by simp + | (a : α), (b : α), (c : α) => by simp_rw [← coe_mul, mul_assoc] + +@[to_additive] +instance commMonoid [CommSemigroup α] : CommMonoid (WithOne α) where + mul_comm := fun a b => match a, b with + | (a : α), (b : α) => congr_arg some (mul_comm a b) + | (_ : α), 1 => rfl + | 1, (_ : α) => rfl + | 1, 1 => rfl + @[to_additive (attr := simp, norm_cast)] theorem coe_inv [Inv α] (a : α) : ((a⁻¹ : α) : WithOne α) = (a : WithOne α)⁻¹ := rfl @@ -392,3 +400,9 @@ instance semiring [Semiring α] : Semiring (WithZero α) := WithZero.monoidWithZero, WithZero.instDistrib with } end WithZero + +-- Check that we haven't needed to import all the basic lemmas about groups, +-- by asserting a random sample don't exist here: +assert_not_exists inv_involutive +assert_not_exists div_right_inj +assert_not_exists pow_ite diff --git a/Mathlib/Algebra/Group/WithOne/Units.lean b/Mathlib/Algebra/Group/WithOne/Units.lean index b7e73db87af88..53128543b40de 100644 --- a/Mathlib/Algebra/Group/WithOne/Units.lean +++ b/Mathlib/Algebra/Group/WithOne/Units.lean @@ -3,7 +3,8 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Johan Commelin -/ -import Mathlib.Algebra.Group.WithOne.Basic +import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.WithOne.Defs import Mathlib.Algebra.GroupWithZero.Units.Basic #align_import algebra.group.with_one.units from "leanprover-community/mathlib"@"4e87c8477c6c38b753f050bc9664b94ee859896c" diff --git a/Mathlib/Algebra/GroupPower/Basic.lean b/Mathlib/Algebra/GroupPower/Basic.lean index 71c1aff51bd68..6d70a57c6f22a 100644 --- a/Mathlib/Algebra/GroupPower/Basic.lean +++ b/Mathlib/Algebra/GroupPower/Basic.lean @@ -5,6 +5,7 @@ Authors: Jeremy Avigad, Robert Y. Lewis -/ import Mathlib.Algebra.Group.Commute.Basic import Mathlib.Algebra.GroupWithZero.Defs +import Mathlib.Data.Int.Defs import Mathlib.Tactic.Common #align_import algebra.group_power.basic from "leanprover-community/mathlib"@"9b2660e1b25419042c8da10bf411aa3c67f14383" @@ -17,7 +18,7 @@ We separate this from group, because it depends on `ℕ`, which in turn depends on other parts of algebra. This module contains lemmas about `a ^ n` and `n • a`, where `n : ℕ` or `n : ℤ`. -Further lemmas can be found in `Algebra.GroupPower.Lemmas`. +Further lemmas can be found in `Algebra.GroupPower.Ring`. The analogous results for groups with zero can be found in `Algebra.GroupWithZero.Power`. @@ -31,6 +32,8 @@ The analogous results for groups with zero can be found in `Algebra.GroupWithZer We adopt the convention that `0^0 = 1`. -/ +open Int + universe u v w x y z u₁ u₂ variable {α : Type*} {M : Type u} {N : Type v} {G : Type w} {H : Type x} {A : Type y} {B : Type z} @@ -43,24 +46,6 @@ First we prove some facts about `SemiconjBy` and `Commute`. They do not require `pow` and/or `nsmul` and will be useful later in this file. -/ - -section Pow - -variable [Pow M ℕ] - -@[to_additive (attr := simp) ite_nsmul] -theorem pow_ite (P : Prop) [Decidable P] (a : M) (b c : ℕ) : - (a ^ if P then b else c) = if P then a ^ b else a ^ c := by split_ifs <;> rfl -#align pow_ite pow_ite - -@[to_additive (attr := simp) nsmul_ite] -theorem ite_pow (P : Prop) [Decidable P] (a b : M) (c : ℕ) : - (if P then a else b) ^ c = if P then a ^ c else b ^ c := by split_ifs <;> rfl -#align ite_pow ite_pow - -end Pow - - /-! ### Monoids -/ @@ -351,6 +336,44 @@ protected theorem Commute.mul_zpow (h : Commute a b) : ∀ i : ℤ, (a * b) ^ i #align commute.mul_zpow Commute.mul_zpow #align add_commute.zsmul_add AddCommute.zsmul_add +-- Note that `mul_zsmul` and `zpow_mul` have the primes swapped +-- when additivised since their argument order, +-- and therefore the more "natural" choice of lemma, is reversed. +@[to_additive mul_zsmul'] lemma zpow_mul (a : α) : ∀ m n : ℤ, a ^ (m * n) = (a ^ m) ^ n + | (m : ℕ), (n : ℕ) => by + rw [zpow_ofNat, zpow_ofNat, ← pow_mul, ← zpow_ofNat] + rfl + | (m : ℕ), -[n+1] => by + rw [zpow_ofNat, zpow_negSucc, ← pow_mul, ofNat_mul_negSucc, zpow_neg, inv_inj, ← zpow_ofNat] + | -[m+1], (n : ℕ) => by + rw [zpow_ofNat, zpow_negSucc, ← inv_pow, ← pow_mul, negSucc_mul_ofNat, zpow_neg, inv_pow, + inv_inj, ← zpow_ofNat] + | -[m+1], -[n+1] => by + rw [zpow_negSucc, zpow_negSucc, negSucc_mul_negSucc, inv_pow, inv_inv, ← pow_mul, ← + zpow_ofNat] + rfl +#align zpow_mul zpow_mul +#align mul_zsmul' mul_zsmul' + +@[to_additive mul_zsmul] +lemma zpow_mul' (a : α) (m n : ℤ) : a ^ (m * n) = (a ^ n) ^ m := by rw [Int.mul_comm, zpow_mul] +#align zpow_mul' zpow_mul' +#align mul_zsmul mul_zsmul + +set_option linter.deprecated false + +@[to_additive bit0_zsmul] +lemma zpow_bit0 (a : α) (n : ℤ) : a ^ bit0 n = a ^ n * a ^ n := by + rw [bit0, ← Int.two_mul, zpow_mul', ← pow_two, ← zpow_coe_nat]; norm_cast +#align zpow_bit0 zpow_bit0 +#align bit0_zsmul bit0_zsmul + +@[to_additive bit0_zsmul'] +theorem zpow_bit0' (a : α) (n : ℤ) : a ^ bit0 n = (a * a) ^ n := + (zpow_bit0 a n).trans ((Commute.refl a).mul_zpow n).symm +#align zpow_bit0' zpow_bit0' +#align bit0_zsmul' bit0_zsmul' + end DivisionMonoid section DivisionCommMonoid @@ -399,6 +422,106 @@ theorem inv_pow_sub (a : G) {m n : ℕ} (h : n ≤ m) : a⁻¹ ^ (m - n) = (a ^ #align inv_pow_sub inv_pow_sub #align sub_nsmul_neg sub_nsmul_neg +@[to_additive add_one_zsmul] +lemma zpow_add_one (a : G) : ∀ n : ℤ, a ^ (n + 1) = a ^ n * a + | (n : ℕ) => by simp only [← Int.ofNat_succ, zpow_ofNat, pow_succ'] + | -[0+1] => by erw [zpow_zero, zpow_negSucc, pow_one, mul_left_inv] + | -[n + 1+1] => by + rw [zpow_negSucc, pow_succ, mul_inv_rev, inv_mul_cancel_right] + rw [Int.negSucc_eq, Int.neg_add, Int.neg_add_cancel_right] + exact zpow_negSucc _ _ +#align zpow_add_one zpow_add_one +#align add_one_zsmul add_one_zsmul + +@[to_additive sub_one_zsmul] +lemma zpow_sub_one (a : G) (n : ℤ) : a ^ (n - 1) = a ^ n * a⁻¹ := + calc + a ^ (n - 1) = a ^ (n - 1) * a * a⁻¹ := (mul_inv_cancel_right _ _).symm + _ = a ^ n * a⁻¹ := by rw [← zpow_add_one, Int.sub_add_cancel] +#align zpow_sub_one zpow_sub_one +#align sub_one_zsmul sub_one_zsmul + +@[to_additive add_zsmul] +lemma zpow_add (a : G) (m n : ℤ) : a ^ (m + n) = a ^ m * a ^ n := by + induction n using Int.induction_on with + | hz => simp + | hp n ihn => simp only [← Int.add_assoc, zpow_add_one, ihn, mul_assoc] + | hn n ihn => rw [zpow_sub_one, ← mul_assoc, ← ihn, ← zpow_sub_one, Int.add_sub_assoc] +#align zpow_add zpow_add +#align add_zsmul add_zsmul + +@[to_additive one_add_zsmul] +lemma zpow_one_add (a : G) (n : ℤ) : a ^ (1 + n) = a * a ^ n := by rw [zpow_add, zpow_one] +#align zpow_one_add zpow_one_add +#align one_add_zsmul one_add_zsmul + +@[to_additive add_zsmul_self] +lemma mul_self_zpow (a : G) (n : ℤ) : a * a ^ n = a ^ (n + 1) := by + rw [Int.add_comm, zpow_add, zpow_one] +#align mul_self_zpow mul_self_zpow +#align add_zsmul_self add_zsmul_self + +@[to_additive add_self_zsmul] +lemma mul_zpow_self (a : G) (n : ℤ) : a ^ n * a = a ^ (n + 1) := (zpow_add_one ..).symm +#align mul_zpow_self mul_zpow_self +#align add_self_zsmul add_self_zsmul + +@[to_additive sub_zsmul] lemma zpow_sub (a : G) (m n : ℤ) : a ^ (m - n) = a ^ m * (a ^ n)⁻¹ := by + rw [Int.sub_eq_add_neg, zpow_add, zpow_neg] +#align zpow_sub zpow_sub +#align sub_zsmul sub_zsmul + +@[to_additive] lemma zpow_mul_comm (a : G) (m n : ℤ) : a ^ m * a ^ n = a ^ n * a ^ m := by + rw [← zpow_add, Int.add_comm, zpow_add] +#align zpow_mul_comm zpow_mul_comm +#align zsmul_add_comm zsmul_add_comm + +section bit1 + +set_option linter.deprecated false + +@[to_additive bit1_zsmul] +lemma zpow_bit1 (a : G) (n : ℤ) : a ^ bit1 n = a ^ n * a ^ n * a := by + rw [bit1, zpow_add, zpow_bit0, zpow_one] +#align zpow_bit1 zpow_bit1 +#align bit1_zsmul bit1_zsmul + +end bit1 + +/-- To show a property of all powers of `g` it suffices to show it is closed under multiplication +by `g` and `g⁻¹` on the left. For subgroups generated by more than one element, see +`Subgroup.closure_induction_left`. -/ +@[to_additive "To show a property of all multiples of `g` it suffices to show it is closed under +addition by `g` and `-g` on the left. For additive subgroups generated by more than one element, see +`AddSubgroup.closure_induction_left`."] +lemma zpow_induction_left {g : G} {P : G → Prop} (h_one : P (1 : G)) + (h_mul : ∀ a, P a → P (g * a)) (h_inv : ∀ a, P a → P (g⁻¹ * a)) (n : ℤ) : P (g ^ n) := by + induction' n using Int.induction_on with n ih n ih + · rwa [zpow_zero] + · rw [Int.add_comm, zpow_add, zpow_one] + exact h_mul _ ih + · rw [Int.sub_eq_add_neg, Int.add_comm, zpow_add, zpow_neg_one] + exact h_inv _ ih +#align zpow_induction_left zpow_induction_left +#align zsmul_induction_left zsmul_induction_left + +/-- To show a property of all powers of `g` it suffices to show it is closed under multiplication +by `g` and `g⁻¹` on the right. For subgroups generated by more than one element, see +`Subgroup.closure_induction_right`. -/ +@[to_additive "To show a property of all multiples of `g` it suffices to show it is closed under +addition by `g` and `-g` on the right. For additive subgroups generated by more than one element, +see `AddSubgroup.closure_induction_right`."] +lemma zpow_induction_right {g : G} {P : G → Prop} (h_one : P (1 : G)) + (h_mul : ∀ a, P a → P (a * g)) (h_inv : ∀ a, P a → P (a * g⁻¹)) (n : ℤ) : P (g ^ n) := by + induction' n using Int.induction_on with n ih n ih + · rwa [zpow_zero] + · rw [zpow_add_one] + exact h_mul _ ih + · rw [zpow_sub_one] + exact h_inv _ ih +#align zpow_induction_right zpow_induction_right +#align zsmul_induction_right zsmul_induction_right + end Group @[to_additive (attr := simp)] diff --git a/Mathlib/Algebra/GroupPower/CovariantClass.lean b/Mathlib/Algebra/GroupPower/CovariantClass.lean index cb069580a1f15..418c3b742928f 100644 --- a/Mathlib/Algebra/GroupPower/CovariantClass.lean +++ b/Mathlib/Algebra/GroupPower/CovariantClass.lean @@ -5,7 +5,7 @@ Authors: Jeremy Avigad, Robert Y. Lewis, Yury G. Kudryashov -/ import Mathlib.Algebra.GroupPower.Basic import Mathlib.Algebra.Order.Monoid.OrderDual -import Mathlib.Data.Nat.Basic +import Mathlib.Data.Nat.Defs import Mathlib.Tactic.Monotonicity.Attr /-! @@ -167,6 +167,10 @@ theorem pow_left_strictMono (hn : n ≠ 0) : StrictMono (· ^ n : M → M) := st #align pow_strict_mono_right' pow_left_strictMono #align nsmul_strict_mono_left nsmul_right_strictMono +@[to_additive (attr := mono, gcongr) nsmul_lt_nsmul_right] +lemma pow_lt_pow_left' (hn : n ≠ 0) {a b : M} (hab : a < b) : a ^ n < b ^ n := + pow_left_strictMono hn hab + end CovariantLTSwap section CovariantLESwap @@ -222,6 +226,7 @@ section CovariantLE variable [CovariantClass M M (· * ·) (· ≤ ·)] +-- This generalises to lattices. See `pow_two_semiclosed` @[to_additive nsmul_nonneg_iff] theorem one_le_pow_iff {x : M} {n : ℕ} (hn : n ≠ 0) : 1 ≤ x ^ n ↔ 1 ≤ x := ⟨le_imp_le_of_lt_imp_lt fun h => pow_lt_one' h hn, fun h => one_le_pow_of_one_le' h n⟩ diff --git a/Mathlib/Algebra/GroupPower/IterateHom.lean b/Mathlib/Algebra/GroupPower/IterateHom.lean index a746ac44766c7..5a66bbc731e7e 100644 --- a/Mathlib/Algebra/GroupPower/IterateHom.lean +++ b/Mathlib/Algebra/GroupPower/IterateHom.lean @@ -3,7 +3,9 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Algebra.GroupPower.Lemmas +import Mathlib.Algebra.Ring.Hom.Defs +import Mathlib.Data.Int.Basic +import Mathlib.Data.Nat.Basic import Mathlib.GroupTheory.GroupAction.Opposite #align_import algebra.hom.iterate from "leanprover-community/mathlib"@"792a2a264169d64986541c6f8f7e3bbb6acb6295" diff --git a/Mathlib/Algebra/GroupPower/Lemmas.lean b/Mathlib/Algebra/GroupPower/Lemmas.lean index d70f19479e54c..5ff1c89a6feb8 100644 --- a/Mathlib/Algebra/GroupPower/Lemmas.lean +++ b/Mathlib/Algebra/GroupPower/Lemmas.lean @@ -3,14 +3,7 @@ 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 Mathlib.Algebra.Invertible.Basic -import Mathlib.Data.Nat.Cast.Basic -import Mathlib.Algebra.GroupPower.Ring -import Mathlib.Algebra.Order.Monoid.WithTop -import Mathlib.Data.Nat.Pow -import Mathlib.Data.Int.Cast.Lemmas -import Mathlib.Algebra.Group.Opposite -import Mathlib.GroupTheory.GroupAction.Ring +import Mathlib.Data.Nat.Order.Basic #align_import algebra.group_power.lemmas from "leanprover-community/mathlib"@"a07d750983b94c530ab69a726862c2ab6802b38c" @@ -28,602 +21,10 @@ universe u v w x y z u₁ u₂ variable {α : Type*} {M : Type u} {N : Type v} {G : Type w} {H : Type x} {A : Type y} {B : Type z} {R : Type u₁} {S : Type u₂} -/-! -### (Additive) monoid --/ - -section Monoid - -@[simp] -theorem nsmul_one [AddMonoidWithOne A] : ∀ n : ℕ, n • (1 : A) = n := by - let f : ℕ →+ A := - { toFun := fun n ↦ n • (1 : A), - map_zero' := by simp [zero_nsmul], - map_add' := by simp [add_nsmul] } - refine' eq_natCast' f _ - simp -#align nsmul_one nsmul_one - -variable [Monoid M] [Monoid N] [AddMonoid A] [AddMonoid B] - -instance invertiblePow (m : M) [Invertible m] (n : ℕ) : - Invertible (m ^ n) where - invOf := ⅟ m ^ n - invOf_mul_self := by rw [← (commute_invOf m).symm.mul_pow, invOf_mul_self, one_pow] - mul_invOf_self := by rw [← (commute_invOf m).mul_pow, mul_invOf_self, one_pow] -#align invertible_pow invertiblePow - -theorem invOf_pow (m : M) [Invertible m] (n : ℕ) [Invertible (m ^ n)] : ⅟ (m ^ n) = ⅟ m ^ n := - @invertible_unique M _ (m ^ n) (m ^ n) _ (invertiblePow m n) rfl -#align inv_of_pow invOf_pow - -@[to_additive] -theorem IsUnit.pow {m : M} (n : ℕ) : IsUnit m → IsUnit (m ^ n) := fun ⟨u, hu⟩ => - ⟨u ^ n, hu ▸ u.val_pow_eq_pow_val _⟩ -#align is_unit.pow IsUnit.pow -#align is_add_unit.nsmul IsAddUnit.nsmul - -/-- If a natural power of `x` is a unit, then `x` is a unit. -/ -@[to_additive "If a natural multiple of `x` is an additive unit, then `x` is an additive unit."] -def Units.ofPow (u : Mˣ) (x : M) {n : ℕ} (hn : n ≠ 0) (hu : x ^ n = u) : Mˣ := - u.leftOfMul x (x ^ (n - 1)) - (by rwa [← _root_.pow_succ, Nat.sub_add_cancel (Nat.succ_le_of_lt <| Nat.pos_of_ne_zero hn)]) - (Commute.self_pow _ _) -#align units.of_pow Units.ofPow -#align add_units.of_nsmul AddUnits.ofNSMul - -@[to_additive (attr := simp)] -theorem isUnit_pow_iff {a : M} {n : ℕ} (hn : n ≠ 0) : IsUnit (a ^ n) ↔ IsUnit a := - ⟨fun ⟨u, hu⟩ => (u.ofPow a hn hu.symm).isUnit, fun h => h.pow n⟩ -#align is_unit_pow_iff isUnit_pow_iff -#align is_add_unit_nsmul_iff isAddUnit_nsmul_iff - -@[to_additive] -theorem isUnit_pow_succ_iff {m : M} {n : ℕ} : IsUnit (m ^ (n + 1)) ↔ IsUnit m := - isUnit_pow_iff n.succ_ne_zero -#align is_unit_pow_succ_iff isUnit_pow_succ_iff -#align is_add_unit_nsmul_succ_iff isAddUnit_nsmul_succ_iff - -/-- If `x ^ n = 1`, `n ≠ 0`, then `x` is a unit. -/ -@[to_additive (attr := simps!) "If `n • x = 0`, `n ≠ 0`, then `x` is an additive unit."] -def Units.ofPowEqOne (x : M) (n : ℕ) (hx : x ^ n = 1) (hn : n ≠ 0) : Mˣ := - Units.ofPow 1 x hn hx -#align units.of_pow_eq_one Units.ofPowEqOne -#align add_units.of_nsmul_eq_zero AddUnits.ofNSMulEqZero - -@[to_additive (attr := simp)] -theorem Units.pow_ofPowEqOne {x : M} {n : ℕ} (hx : x ^ n = 1) (hn : n ≠ 0) : - Units.ofPowEqOne x n hx hn ^ n = 1 := - Units.ext <| by simp [hx] -#align units.pow_of_pow_eq_one Units.pow_ofPowEqOne -#align add_units.nsmul_of_nsmul_eq_zero AddUnits.nsmul_ofNSMulEqZero - -@[to_additive] -theorem isUnit_ofPowEqOne {x : M} {n : ℕ} (hx : x ^ n = 1) (hn : n ≠ 0) : IsUnit x := - (Units.ofPowEqOne x n hx hn).isUnit -#align is_unit_of_pow_eq_one isUnit_ofPowEqOne -#align is_add_unit_of_nsmul_eq_zero isAddUnit_ofNSMulEqZero - -/-- If `x ^ n = 1` then `x` has an inverse, `x^(n - 1)`. -/ -def invertibleOfPowEqOne (x : M) (n : ℕ) (hx : x ^ n = 1) (hn : n ≠ 0) : Invertible x := - (Units.ofPowEqOne x n hx hn).invertible -#align invertible_of_pow_eq_one invertibleOfPowEqOne - -theorem smul_pow [MulAction M N] [IsScalarTower M N N] [SMulCommClass M N N] (k : M) (x : N) - (p : ℕ) : (k • x) ^ p = k ^ p • x ^ p := by - induction' p with p IH - · simp - · rw [pow_succ', IH, smul_mul_smul, ← pow_succ', ← pow_succ'] -#align smul_pow smul_pow - -@[simp] -theorem smul_pow' [MulDistribMulAction M N] (x : M) (m : N) (n : ℕ) : x • m ^ n = (x • m) ^ n := by - induction' n with n ih - · rw [pow_zero, pow_zero] - exact smul_one x - · rw [pow_succ, pow_succ] - exact (smul_mul' x m (m ^ n)).trans (congr_arg _ ih) -#align smul_pow' smul_pow' - -end Monoid - -@[simp] -theorem zsmul_one [AddGroupWithOne A] (n : ℤ) : n • (1 : A) = n := by cases n <;> simp -#align zsmul_one zsmul_one - -section DivisionMonoid - -variable [DivisionMonoid α] - --- Note that `mul_zsmul` and `zpow_mul` have the primes swapped --- when additivised since their argument order, --- and therefore the more "natural" choice of lemma, is reversed. -@[to_additive mul_zsmul'] -theorem zpow_mul (a : α) : ∀ m n : ℤ, a ^ (m * n) = (a ^ m) ^ n - | (m : ℕ), (n : ℕ) => by - rw [zpow_ofNat, zpow_ofNat, ← pow_mul, ← zpow_ofNat] - rfl - | (m : ℕ), -[n+1] => by - rw [zpow_ofNat, zpow_negSucc, ← pow_mul, ofNat_mul_negSucc, zpow_neg, inv_inj, ← zpow_ofNat] - | -[m+1], (n : ℕ) => by - rw [zpow_ofNat, zpow_negSucc, ← inv_pow, ← pow_mul, negSucc_mul_ofNat, zpow_neg, inv_pow, - inv_inj, ← zpow_ofNat] - | -[m+1], -[n+1] => by - rw [zpow_negSucc, zpow_negSucc, negSucc_mul_negSucc, inv_pow, inv_inv, ← pow_mul, ← - zpow_ofNat] - rfl -#align zpow_mul zpow_mul -#align mul_zsmul' mul_zsmul' - -@[to_additive mul_zsmul] -theorem zpow_mul' (a : α) (m n : ℤ) : a ^ (m * n) = (a ^ n) ^ m := by rw [mul_comm, zpow_mul] -#align zpow_mul' zpow_mul' -#align mul_zsmul mul_zsmul - -section bit0 - -set_option linter.deprecated false - -@[to_additive bit0_zsmul] -theorem zpow_bit0 (a : α) : ∀ n : ℤ, a ^ bit0 n = a ^ n * a ^ n - | (n : ℕ) => by simp only [zpow_ofNat, ← Int.ofNat_bit0, pow_bit0] - | -[n+1] => by - simp only [zpow_negSucc, <-mul_inv_rev, <-pow_bit0] - rw [negSucc_eq, bit0_neg, zpow_neg] - norm_cast -#align zpow_bit0 zpow_bit0 -#align bit0_zsmul bit0_zsmul - -@[to_additive bit0_zsmul'] -theorem zpow_bit0' (a : α) (n : ℤ) : a ^ bit0 n = (a * a) ^ n := - (zpow_bit0 a n).trans ((Commute.refl a).mul_zpow n).symm -#align zpow_bit0' zpow_bit0' -#align bit0_zsmul' bit0_zsmul' - -@[simp] -theorem zpow_bit0_neg [HasDistribNeg α] (x : α) (n : ℤ) : (-x) ^ bit0 n = x ^ bit0 n := by - rw [zpow_bit0', zpow_bit0', neg_mul_neg] -#align zpow_bit0_neg zpow_bit0_neg - -end bit0 - -end DivisionMonoid - -section Group - -variable [Group G] - -@[to_additive add_one_zsmul] -theorem zpow_add_one (a : G) : ∀ n : ℤ, a ^ (n + 1) = a ^ n * a - | (n : ℕ) => by simp only [← Int.ofNat_succ, zpow_ofNat, pow_succ'] - | -[0+1] => by erw [zpow_zero, zpow_negSucc, pow_one, mul_left_inv] - | -[n + 1+1] => by - rw [zpow_negSucc, pow_succ, mul_inv_rev, inv_mul_cancel_right] - rw [Int.negSucc_eq, neg_add, add_assoc, neg_add_self, add_zero] - exact zpow_negSucc _ _ -#align zpow_add_one zpow_add_one -#align add_one_zsmul add_one_zsmul - -@[to_additive sub_one_zsmul] -theorem zpow_sub_one (a : G) (n : ℤ) : a ^ (n - 1) = a ^ n * a⁻¹ := - calc - a ^ (n - 1) = a ^ (n - 1) * a * a⁻¹ := (mul_inv_cancel_right _ _).symm - _ = a ^ n * a⁻¹ := by rw [← zpow_add_one, sub_add_cancel] -#align zpow_sub_one zpow_sub_one -#align sub_one_zsmul sub_one_zsmul - -@[to_additive add_zsmul] -theorem zpow_add (a : G) (m n : ℤ) : a ^ (m + n) = a ^ m * a ^ n := by - induction n using Int.induction_on with - | hz => simp - | hp n ihn => simp only [← add_assoc, zpow_add_one, ihn, mul_assoc] - | hn n ihn => rw [zpow_sub_one, ← mul_assoc, ← ihn, ← zpow_sub_one, add_sub_assoc] -#align zpow_add zpow_add -#align add_zsmul add_zsmul - -@[to_additive add_zsmul_self] -theorem mul_self_zpow (b : G) (m : ℤ) : b * b ^ m = b ^ (m + 1) := by - conv_lhs => - congr - rw [← zpow_one b] - rw [← zpow_add, add_comm] -#align mul_self_zpow mul_self_zpow -#align add_zsmul_self add_zsmul_self - -@[to_additive add_self_zsmul] -theorem mul_zpow_self (b : G) (m : ℤ) : b ^ m * b = b ^ (m + 1) := by - conv_lhs => - congr - · skip - rw [← zpow_one b] - rw [← zpow_add, add_comm] -#align mul_zpow_self mul_zpow_self -#align add_self_zsmul add_self_zsmul - -@[to_additive sub_zsmul] -theorem zpow_sub (a : G) (m n : ℤ) : a ^ (m - n) = a ^ m * (a ^ n)⁻¹ := by - rw [sub_eq_add_neg, zpow_add, zpow_neg] -#align zpow_sub zpow_sub -#align sub_zsmul sub_zsmul - -@[to_additive one_add_zsmul] -theorem zpow_one_add (a : G) (i : ℤ) : a ^ (1 + i) = a * a ^ i := by rw [zpow_add, zpow_one] -#align zpow_one_add zpow_one_add -#align one_add_zsmul one_add_zsmul - -@[to_additive] -theorem zpow_mul_comm (a : G) (i j : ℤ) : a ^ i * a ^ j = a ^ j * a ^ i := - (Commute.refl _).zpow_zpow _ _ -#align zpow_mul_comm zpow_mul_comm -#align zsmul_add_comm zsmul_add_comm - -section bit1 - -set_option linter.deprecated false - -@[to_additive bit1_zsmul] -theorem zpow_bit1 (a : G) (n : ℤ) : a ^ bit1 n = a ^ n * a ^ n * a := by - rw [bit1, zpow_add, zpow_bit0, zpow_one] -#align zpow_bit1 zpow_bit1 -#align bit1_zsmul bit1_zsmul - -end bit1 - -/-- To show a property of all powers of `g` it suffices to show it is closed under multiplication -by `g` and `g⁻¹` on the left. For subgroups generated by more than one element, see -`Subgroup.closure_induction_left`. -/ -@[to_additive "To show a property of all multiples of `g` it suffices to show it is closed under -addition by `g` and `-g` on the left. For additive subgroups generated by more than one element, see -`AddSubgroup.closure_induction_left`."] -theorem zpow_induction_left {g : G} {P : G → Prop} (h_one : P (1 : G)) - (h_mul : ∀ a, P a → P (g * a)) (h_inv : ∀ a, P a → P (g⁻¹ * a)) (n : ℤ) : P (g ^ n) := by - induction' n using Int.induction_on with n ih n ih - · rwa [zpow_zero] - · rw [add_comm, zpow_add, zpow_one] - exact h_mul _ ih - · rw [sub_eq_add_neg, add_comm, zpow_add, zpow_neg_one] - exact h_inv _ ih -#align zpow_induction_left zpow_induction_left -#align zsmul_induction_left zsmul_induction_left - -/-- To show a property of all powers of `g` it suffices to show it is closed under multiplication -by `g` and `g⁻¹` on the right. For subgroups generated by more than one element, see -`Subgroup.closure_induction_right`. -/ -@[to_additive "To show a property of all multiples of `g` it suffices to show it is closed under -addition by `g` and `-g` on the right. For additive subgroups generated by more than one element, -see `AddSubgroup.closure_induction_right`."] -theorem zpow_induction_right {g : G} {P : G → Prop} (h_one : P (1 : G)) - (h_mul : ∀ a, P a → P (a * g)) (h_inv : ∀ a, P a → P (a * g⁻¹)) (n : ℤ) : P (g ^ n) := by - induction' n using Int.induction_on with n ih n ih - · rwa [zpow_zero] - · rw [zpow_add_one] - exact h_mul _ ih - · rw [zpow_sub_one] - exact h_inv _ ih -#align zpow_induction_right zpow_induction_right -#align zsmul_induction_right zsmul_induction_right - -end Group - -/-! -### `zpow`/`zsmul` and an order - -Those lemmas are placed here -(rather than in `Mathlib.Algebra.GroupPower.Order` with their friends) -because they require facts from `Mathlib.Data.Int.Basic`. --/ - -section OrderedAddCommGroup - -variable [OrderedCommGroup α] {m n : ℤ} {a b : α} - -@[to_additive zsmul_pos] -theorem one_lt_zpow' (ha : 1 < a) {k : ℤ} (hk : (0 : ℤ) < k) : 1 < a ^ k := by - obtain ⟨n, hn⟩ := Int.eq_ofNat_of_zero_le hk.le - rw [hn, zpow_ofNat] - refine' one_lt_pow' ha (coe_nat_pos.mp _).ne' - rwa [← hn] -#align one_lt_zpow' one_lt_zpow' -#align zsmul_pos zsmul_pos - -@[to_additive zsmul_strictMono_left] -theorem zpow_right_strictMono (ha : 1 < a) : StrictMono fun n : ℤ => a ^ n := fun m n h => - calc - a ^ m = a ^ m * 1 := (mul_one _).symm - _ < a ^ m * a ^ (n - m) := mul_lt_mul_left' (one_lt_zpow' ha <| sub_pos_of_lt h) _ - _ = a ^ n := by rw [← zpow_add]; simp -#align zpow_strict_mono_right zpow_right_strictMono -#align zsmul_strict_mono_left zsmul_strictMono_left - -@[to_additive zsmul_mono_left] -theorem zpow_mono_right (ha : 1 ≤ a) : Monotone fun n : ℤ => a ^ n := fun m n h => - calc - a ^ m = a ^ m * 1 := (mul_one _).symm - _ ≤ a ^ m * a ^ (n - m) := mul_le_mul_left' (one_le_zpow ha <| sub_nonneg_of_le h) _ - _ = a ^ n := by rw [← zpow_add]; simp -#align zpow_mono_right zpow_mono_right -#align zsmul_mono_left zsmul_mono_left - -@[to_additive] -theorem zpow_le_zpow (ha : 1 ≤ a) (h : m ≤ n) : a ^ m ≤ a ^ n := - zpow_mono_right ha h -#align zpow_le_zpow zpow_le_zpow -#align zsmul_le_zsmul zsmul_le_zsmul - -@[to_additive] -theorem zpow_lt_zpow (ha : 1 < a) (h : m < n) : a ^ m < a ^ n := - zpow_right_strictMono ha h -#align zpow_lt_zpow zpow_lt_zpow -#align zsmul_lt_zsmul zsmul_lt_zsmul - -@[to_additive] -theorem zpow_le_zpow_iff (ha : 1 < a) : a ^ m ≤ a ^ n ↔ m ≤ n := - (zpow_right_strictMono ha).le_iff_le -#align zpow_le_zpow_iff zpow_le_zpow_iff -#align zsmul_le_zsmul_iff zsmul_le_zsmul_iff - -@[to_additive] -theorem zpow_lt_zpow_iff (ha : 1 < a) : a ^ m < a ^ n ↔ m < n := - (zpow_right_strictMono ha).lt_iff_lt -#align zpow_lt_zpow_iff zpow_lt_zpow_iff -#align zsmul_lt_zsmul_iff zsmul_lt_zsmul_iff - -variable (α) - -@[to_additive zsmul_strictMono_right] -theorem zpow_strictMono_left (hn : 0 < n) : StrictMono ((· ^ n) : α → α) := fun a b hab => by - rw [← one_lt_div', ← div_zpow] - exact one_lt_zpow' (one_lt_div'.2 hab) hn -#align zpow_strict_mono_left zpow_strictMono_left -#align zsmul_strict_mono_right zsmul_strictMono_right - -@[to_additive zsmul_mono_right] -theorem zpow_mono_left (hn : 0 ≤ n) : Monotone ((· ^ n) : α → α) := fun a b hab => by - rw [← one_le_div', ← div_zpow] - exact one_le_zpow (one_le_div'.2 hab) hn -#align zpow_mono_left zpow_mono_left -#align zsmul_mono_right zsmul_mono_right - -variable {α} - -@[to_additive] -theorem zpow_le_zpow' (hn : 0 ≤ n) (h : a ≤ b) : a ^ n ≤ b ^ n := - zpow_mono_left α hn h -#align zpow_le_zpow' zpow_le_zpow' -#align zsmul_le_zsmul' zsmul_le_zsmul' - -@[to_additive] -theorem zpow_lt_zpow' (hn : 0 < n) (h : a < b) : a ^ n < b ^ n := - zpow_strictMono_left α hn h -#align zpow_lt_zpow' zpow_lt_zpow' -#align zsmul_lt_zsmul' zsmul_lt_zsmul' - -end OrderedAddCommGroup - -section LinearOrderedCommGroup - -variable [LinearOrderedCommGroup α] {n : ℤ} {a b : α} - -@[to_additive] -theorem zpow_le_zpow_iff' (hn : 0 < n) {a b : α} : a ^ n ≤ b ^ n ↔ a ≤ b := - (zpow_strictMono_left α hn).le_iff_le -#align zpow_le_zpow_iff' zpow_le_zpow_iff' -#align zsmul_le_zsmul_iff' zsmul_le_zsmul_iff' - -@[to_additive] -theorem zpow_lt_zpow_iff' (hn : 0 < n) {a b : α} : a ^ n < b ^ n ↔ a < b := - (zpow_strictMono_left α hn).lt_iff_lt -#align zpow_lt_zpow_iff' zpow_lt_zpow_iff' -#align zsmul_lt_zsmul_iff' zsmul_lt_zsmul_iff' - -@[to_additive zsmul_right_injective - "See also `smul_right_injective`. TODO: provide a `NoZeroSMulDivisors` instance. We can't do - that here because importing that definition would create import cycles."] -theorem zpow_left_injective (hn : n ≠ 0) : Function.Injective ((· ^ n) : α → α) := by - rcases hn.symm.lt_or_lt with (h | h) - · exact (zpow_strictMono_left α h).injective - · refine' fun a b (hab : a ^ n = b ^ n) => (zpow_strictMono_left α (neg_pos.mpr h)).injective _ - rw [zpow_neg, zpow_neg, hab] -#align zpow_left_injective zpow_left_injective -#align zsmul_right_injective zsmul_right_injective - -@[to_additive zsmul_right_inj] -theorem zpow_left_inj (hn : n ≠ 0) : a ^ n = b ^ n ↔ a = b := - (zpow_left_injective hn).eq_iff -#align zpow_left_inj zpow_left_inj -#align zsmul_right_inj zsmul_right_inj - -/-- Alias of `zsmul_right_inj`, for ease of discovery alongside `zsmul_le_zsmul_iff'` and -`zsmul_lt_zsmul_iff'`. -/ -@[to_additive - "Alias of `zsmul_right_inj`, for ease of discovery alongside - `zsmul_le_zsmul_iff'` and `zsmul_lt_zsmul_iff'`."] -theorem zpow_eq_zpow_iff' (hn : n ≠ 0) : a ^ n = b ^ n ↔ a = b := - zpow_left_inj hn -#align zpow_eq_zpow_iff' zpow_eq_zpow_iff' -#align zsmul_eq_zsmul_iff' zsmul_eq_zsmul_iff' - -end LinearOrderedCommGroup - -section LinearOrderedAddCommGroup - -variable [LinearOrderedAddCommGroup α] {a b : α} - -theorem abs_nsmul (n : ℕ) (a : α) : |n • a| = n • |a| := by - rcases le_total a 0 with hneg | hpos - · rw [abs_of_nonpos hneg, ← abs_neg, ← neg_nsmul, abs_of_nonneg] - exact nsmul_nonneg (neg_nonneg.mpr hneg) n - · rw [abs_of_nonneg hpos, abs_of_nonneg] - exact nsmul_nonneg hpos n -#align abs_nsmul abs_nsmul - -theorem abs_zsmul (n : ℤ) (a : α) : |n • a| = |n| • |a| := by - obtain n0 | n0 := le_total 0 n - · obtain ⟨n, rfl⟩ := Int.eq_ofNat_of_zero_le n0 - simp only [abs_nsmul, coe_nat_zsmul, Nat.abs_cast] - · obtain ⟨m, h⟩ := Int.eq_ofNat_of_zero_le (neg_nonneg.2 n0) - rw [← abs_neg, ← neg_zsmul, ← abs_neg n, h, coe_nat_zsmul, Nat.abs_cast, coe_nat_zsmul] - exact abs_nsmul m _ -#align abs_zsmul abs_zsmul - -theorem abs_add_eq_add_abs_le (hle : a ≤ b) : - |a + b| = |a| + |b| ↔ 0 ≤ a ∧ 0 ≤ b ∨ a ≤ 0 ∧ b ≤ 0 := by - obtain a0 | a0 := le_or_lt 0 a <;> obtain b0 | b0 := le_or_lt 0 b - · simp [a0, b0, abs_of_nonneg, add_nonneg a0 b0] - · exact (lt_irrefl (0 : α) <| a0.trans_lt <| hle.trans_lt b0).elim - any_goals simp [a0.le, b0.le, abs_of_nonpos, add_nonpos, add_comm] - have : (|a + b| = -a + b ↔ b ≤ 0) ↔ (|a + b| = |a| + |b| ↔ 0 ≤ a ∧ 0 ≤ b ∨ a ≤ 0 ∧ b ≤ 0) := by - simp [a0, a0.le, a0.not_le, b0, abs_of_neg, abs_of_nonneg] - refine' this.mp ⟨fun h => _, fun h => by simp only [le_antisymm h b0, abs_of_neg a0, add_zero]⟩ - obtain ab | ab := le_or_lt (a + b) 0 - · refine' le_of_eq (eq_zero_of_neg_eq _) - rwa [abs_of_nonpos ab, neg_add_rev, add_comm, add_right_inj] at h - · refine' (lt_irrefl (0 : α) _).elim - rw [abs_of_pos ab, add_left_inj] at h - rwa [eq_zero_of_neg_eq h.symm] at a0 -#align abs_add_eq_add_abs_le abs_add_eq_add_abs_le - -theorem abs_add_eq_add_abs_iff (a b : α) : |a + b| = |a| + |b| ↔ 0 ≤ a ∧ 0 ≤ b ∨ a ≤ 0 ∧ b ≤ 0 := by - obtain ab | ab := le_total a b - · exact abs_add_eq_add_abs_le ab - · rw [add_comm a, add_comm (abs _), abs_add_eq_add_abs_le ab, and_comm, @and_comm (b ≤ 0)] -#align abs_add_eq_add_abs_iff abs_add_eq_add_abs_iff - -end LinearOrderedAddCommGroup - -@[simp] -theorem WithBot.coe_nsmul [AddMonoid A] (a : A) (n : ℕ) : ↑(n • a) = n • (a : WithBot A) := - AddMonoidHom.map_nsmul - { toFun := fun a : A => (a : WithBot A), - map_zero' := WithBot.coe_zero, - map_add' := WithBot.coe_add } - a n -#align with_bot.coe_nsmul WithBot.coe_nsmul - -theorem nsmul_eq_mul' [NonAssocSemiring R] (a : R) (n : ℕ) : n • a = a * n := by - induction' n with n ih <;> [rw [zero_nsmul, Nat.cast_zero, mul_zero]; - rw [succ_nsmul', ih, Nat.cast_succ, mul_add, mul_one]] -#align nsmul_eq_mul' nsmul_eq_mul'ₓ --- typeclasses do not match up exactly. - -@[simp] -theorem nsmul_eq_mul [NonAssocSemiring R] (n : ℕ) (a : R) : n • a = n * a := by - rw [nsmul_eq_mul', (n.cast_commute a).eq] -#align nsmul_eq_mul nsmul_eq_mulₓ --- typeclasses do not match up exactly. - -@[simp, norm_cast] -theorem Nat.cast_pow [Semiring R] (n m : ℕ) : (↑(n ^ m) : R) = (↑n : R) ^ m := by - induction' m with m ih - · simp - · rw [_root_.pow_succ', _root_.pow_succ', Nat.cast_mul, ih] -#align nat.cast_pow Nat.cast_pow - --- Porting note: `norm_cast` attribute removed. -/- Porting note `simp` attribute removed as suggested by linter: -simp can prove this: - by simp only [Nat.cast_pow] --/ --- -- @[simp] -theorem Int.coe_nat_pow (n m : ℕ) : ((n ^ m : ℕ) : ℤ) = (n : ℤ) ^ m := by - induction' m with m _ <;> simp -#align int.coe_nat_pow Int.coe_nat_pow - -theorem Int.natAbs_pow (n : ℤ) (k : ℕ) : Int.natAbs (n ^ k) = Int.natAbs n ^ k := by - induction' k with k ih <;> [rfl; rw [pow_succ', Int.natAbs_mul, pow_succ', ih]] -#align int.nat_abs_pow Int.natAbs_pow - -section bit0_bit1 - -set_option linter.deprecated false - --- The next four lemmas allow us to replace multiplication by a numeral with a `zsmul` expression. --- They are used by the `noncomm_ring` tactic, to normalise expressions before passing to `abel`. -theorem bit0_mul [NonUnitalNonAssocRing R] {n r : R} : bit0 n * r = (2 : ℤ) • (n * r) := by - dsimp [bit0] - rw [add_mul, ← one_add_one_eq_two, add_zsmul, one_zsmul] -#align bit0_mul bit0_mul - -theorem mul_bit0 [NonUnitalNonAssocRing R] {n r : R} : r * bit0 n = (2 : ℤ) • (r * n) := by - dsimp [bit0] - rw [mul_add, ← one_add_one_eq_two, add_zsmul, one_zsmul] -#align mul_bit0 mul_bit0 - -theorem bit1_mul [NonAssocRing R] {n r : R} : bit1 n * r = (2 : ℤ) • (n * r) + r := by - dsimp [bit1] - rw [add_mul, bit0_mul, one_mul] -#align bit1_mul bit1_mul - -theorem mul_bit1 [NonAssocRing R] {n r : R} : r * bit1 n = (2 : ℤ) • (r * n) + r := by - dsimp [bit1] - rw [mul_add, mul_bit0, mul_one] -#align mul_bit1 mul_bit1 - -end bit0_bit1 - -/-- Note this holds in marginally more generality than `Int.cast_mul` -/ -theorem Int.cast_mul_eq_zsmul_cast [AddCommGroupWithOne α] : - ∀ m n, ((m * n : ℤ) : α) = m • (n : α) := - fun m => - Int.inductionOn' m 0 (by simp) (fun k _ ih n => by simp [add_mul, add_zsmul, ih]) fun k _ ih n => - by simp [sub_mul, sub_zsmul, ih, ← sub_eq_add_neg] -#align int.cast_mul_eq_zsmul_cast Int.cast_mul_eq_zsmul_cast - -@[simp] -theorem zsmul_eq_mul [Ring R] (a : R) : ∀ n : ℤ, n • a = n * a - | (n : ℕ) => by rw [coe_nat_zsmul, nsmul_eq_mul, Int.cast_ofNat] - | -[n+1] => by simp [Nat.cast_succ, neg_add_rev, Int.cast_negSucc, add_mul] -#align zsmul_eq_mul zsmul_eq_mul - -theorem zsmul_eq_mul' [Ring R] (a : R) (n : ℤ) : n • a = a * n := by - rw [zsmul_eq_mul, (n.cast_commute a).eq] -#align zsmul_eq_mul' zsmul_eq_mul' - -theorem zsmul_int_int (a b : ℤ) : a • b = a * b := by simp -#align zsmul_int_int zsmul_int_int - -theorem zsmul_int_one (n : ℤ) : n • (1 : ℤ) = n := by simp -#align zsmul_int_one zsmul_int_one - -@[simp, norm_cast] -theorem Int.cast_pow [Ring R] (n : ℤ) (m : ℕ) : (↑(n ^ m) : R) = (↑n : R) ^ m := by - induction' m with m ih - · rw [pow_zero, pow_zero, Int.cast_one] - · rw [pow_succ, pow_succ, Int.cast_mul, ih] -#align int.cast_pow Int.cast_powₓ --- typeclasses do not align exactly - -theorem neg_one_pow_eq_pow_mod_two [Ring R] {n : ℕ} : (-1 : R) ^ n = (-1) ^ (n % 2) := by - rw [← Nat.mod_add_div n 2, pow_add, pow_mul]; simp [sq] -#align neg_one_pow_eq_pow_mod_two neg_one_pow_eq_pow_mod_two - section OrderedSemiring variable [OrderedSemiring R] {a : R} -/-- Bernoulli's inequality. This version works for semirings but requires -additional hypotheses `0 ≤ a * a` and `0 ≤ (1 + a) * (1 + a)`. -/ -theorem one_add_mul_le_pow' (Hsq : 0 ≤ a * a) (Hsq' : 0 ≤ (1 + a) * (1 + a)) (H : 0 ≤ 2 + a) : - ∀ n : ℕ, 1 + (n : R) * a ≤ (1 + a) ^ n - | 0 => by simp - | 1 => by simp - | n + 2 => - have : 0 ≤ (n : R) * (a * a * (2 + a)) + a * a := - add_nonneg (mul_nonneg n.cast_nonneg (mul_nonneg Hsq H)) Hsq - calc - 1 + (↑(n + 2) : R) * a ≤ 1 + ↑(n + 2) * a + (n * (a * a * (2 + a)) + a * a) := - le_add_of_nonneg_right this - _ = (1 + a) * (1 + a) * (1 + n * a) := by { - simp only [Nat.cast_add, add_mul, mul_add, one_mul, mul_one, ← one_add_one_eq_two, - Nat.cast_one, add_assoc, add_right_inj] - simp only [← add_assoc, add_comm _ (↑n * a)] - simp only [add_assoc, (n.cast_commute (_ : R)).left_comm] - simp only [add_comm, add_left_comm] } - _ ≤ (1 + a) * (1 + a) * (1 + a) ^ n := - mul_le_mul_of_nonneg_left (one_add_mul_le_pow' Hsq Hsq' H _) Hsq' - _ = (1 + a) ^ (n + 2) := by simp only [pow_succ, mul_assoc] -#align one_add_mul_le_pow' one_add_mul_le_pow' - theorem pow_le_pow_of_le_one_aux (h : 0 ≤ a) (ha : a ≤ 1) (i : ℕ) : ∀ k : ℕ, a ^ (i + k) ≤ a ^ i | 0 => by simp @@ -661,528 +62,3 @@ set_option linter.uppercaseLean3 false in #align sign_cases_of_C_mul_pow_nonneg sign_cases_of_C_mul_pow_nonneg end LinearOrderedSemiring - -section LinearOrderedRing - -variable [LinearOrderedRing R] {a : R} {n : ℕ} - -@[simp] -theorem abs_pow (a : R) (n : ℕ) : |a ^ n| = |a| ^ n := - (pow_abs a n).symm -#align abs_pow abs_pow - -section bit1 - -set_option linter.deprecated false - -@[simp] -theorem pow_bit1_neg_iff : a ^ bit1 n < 0 ↔ a < 0 := - ⟨fun h => not_le.1 fun h' => not_le.2 h <| pow_nonneg h' _, fun ha => pow_bit1_neg ha n⟩ -#align pow_bit1_neg_iff pow_bit1_neg_iff - -@[simp] -theorem pow_bit1_nonneg_iff : 0 ≤ a ^ bit1 n ↔ 0 ≤ a := - le_iff_le_iff_lt_iff_lt.2 pow_bit1_neg_iff -#align pow_bit1_nonneg_iff pow_bit1_nonneg_iff - -@[simp] -theorem pow_bit1_nonpos_iff : a ^ bit1 n ≤ 0 ↔ a ≤ 0 := by - simp only [le_iff_lt_or_eq, pow_bit1_neg_iff] - refine' ⟨_, _⟩ - · rintro (hpos | hz) - · left - exact hpos - · right - exact (pow_eq_zero_iff'.1 hz).1 - · rintro (hneg | hz) - · left - exact hneg - · right - simp [hz, bit1] -#align pow_bit1_nonpos_iff pow_bit1_nonpos_iff - -@[simp] -theorem pow_bit1_pos_iff : 0 < a ^ bit1 n ↔ 0 < a := - lt_iff_lt_of_le_iff_le pow_bit1_nonpos_iff -#align pow_bit1_pos_iff pow_bit1_pos_iff - -theorem strictMono_pow_bit1 (n : ℕ) : StrictMono fun a : R => a ^ bit1 n := by - intro a b hab - rcases le_total a 0 with ha | ha - · rcases le_or_lt b 0 with hb | hb - · rw [← neg_lt_neg_iff, ← neg_pow_bit1, ← neg_pow_bit1] - exact pow_lt_pow_left (neg_lt_neg hab) (neg_nonneg.2 hb) n.bit1_ne_zero - · exact (pow_bit1_nonpos_iff.2 ha).trans_lt (pow_bit1_pos_iff.2 hb) - · exact pow_lt_pow_left hab ha n.bit1_ne_zero -#align strict_mono_pow_bit1 strictMono_pow_bit1 - -end bit1 - -/-- Bernoulli's inequality for `n : ℕ`, `-2 ≤ a`. -/ -theorem one_add_mul_le_pow (H : -2 ≤ a) (n : ℕ) : 1 + (n : R) * a ≤ (1 + a) ^ n := - one_add_mul_le_pow' (mul_self_nonneg _) (mul_self_nonneg _) (neg_le_iff_add_nonneg'.1 H) _ -#align one_add_mul_le_pow one_add_mul_le_pow - -/-- Bernoulli's inequality reformulated to estimate `a^n`. -/ -theorem one_add_mul_sub_le_pow (H : -1 ≤ a) (n : ℕ) : 1 + (n : R) * (a - 1) ≤ a ^ n := by - have : -2 ≤ a - 1 := by - rwa [← one_add_one_eq_two, neg_add, ← sub_eq_add_neg, sub_le_sub_iff_right] - simpa only [add_sub_cancel'_right] using one_add_mul_le_pow this n -#align one_add_mul_sub_le_pow one_add_mul_sub_le_pow - -end LinearOrderedRing - -namespace Int - -lemma natAbs_sq (x : ℤ) : (x.natAbs : ℤ) ^ 2 = x ^ 2 := by rw [sq, Int.natAbs_mul_self', sq] -#align int.nat_abs_sq Int.natAbs_sq - -alias natAbs_pow_two := natAbs_sq -#align int.nat_abs_pow_two Int.natAbs_pow_two - -theorem natAbs_le_self_sq (a : ℤ) : (Int.natAbs a : ℤ) ≤ a ^ 2 := by - rw [← Int.natAbs_sq a, sq] - norm_cast - apply Nat.le_mul_self -#align int.abs_le_self_sq Int.natAbs_le_self_sq - -alias natAbs_le_self_pow_two := natAbs_le_self_sq - -theorem le_self_sq (b : ℤ) : b ≤ b ^ 2 := - le_trans le_natAbs (natAbs_le_self_sq _) -#align int.le_self_sq Int.le_self_sq - -alias le_self_pow_two := le_self_sq -#align int.le_self_pow_two Int.le_self_pow_two - -theorem pow_right_injective {x : ℤ} (h : 1 < x.natAbs) : - Function.Injective ((x ^ ·) : ℕ → ℤ) := by - suffices Function.Injective (natAbs ∘ (x ^ · : ℕ → ℤ)) by - exact Function.Injective.of_comp this - convert Nat.pow_right_injective h using 2 - rw [Function.comp_apply, natAbs_pow] -#align int.pow_right_injective Int.pow_right_injective - -end Int - -variable (M G A) - -/-- Additive homomorphisms from `ℕ` are defined by the image of `1`. -/ -def multiplesHom [AddMonoid A] : A ≃ (ℕ →+ A) where - toFun : A → ℕ →+ A := fun x => - { toFun := fun n => n • x - map_zero' := zero_nsmul x - map_add' := fun _ _ => add_nsmul _ _ _ } - invFun f := f 1 - left_inv := one_nsmul - right_inv f := AddMonoidHom.ext_nat <| one_nsmul (f 1) -#align multiples_hom multiplesHom - -/-- Additive homomorphisms from `ℤ` are defined by the image of `1`. -/ -def zmultiplesHom [AddGroup A] : - A ≃ (ℤ →+ A) where - toFun x := - { toFun := fun n => n • x - map_zero' := zero_zsmul x - map_add' := fun _ _ => add_zsmul _ _ _ } - invFun f := f 1 - left_inv := one_zsmul - right_inv f := AddMonoidHom.ext_int <| one_zsmul (f 1) -#align zmultiples_hom zmultiplesHom - -/-- Monoid homomorphisms from `Multiplicative ℕ` are defined by the image -of `Multiplicative.ofAdd 1`. -/ -def powersHom [Monoid M] : M ≃ (Multiplicative ℕ →* M) := - Additive.ofMul.trans <| (multiplesHom _).trans <| AddMonoidHom.toMultiplicative'' -#align powers_hom powersHom - -/-- Monoid homomorphisms from `Multiplicative ℤ` are defined by the image -of `Multiplicative.ofAdd 1`. -/ -def zpowersHom [Group G] : G ≃ (Multiplicative ℤ →* G) := - Additive.ofMul.trans <| (zmultiplesHom _).trans <| AddMonoidHom.toMultiplicative'' -#align zpowers_hom zpowersHom - -attribute [to_additive existing multiplesHom] powersHom - -attribute [to_additive existing zmultiplesHom] zpowersHom - -variable {M G A} - -theorem powersHom_apply [Monoid M] (x : M) (n : Multiplicative ℕ) : - powersHom M x n = x ^ (Multiplicative.toAdd n) := - rfl -#align powers_hom_apply powersHom_apply - -theorem powersHom_symm_apply [Monoid M] (f : Multiplicative ℕ →* M) : - (powersHom M).symm f = f (Multiplicative.ofAdd 1) := - rfl -#align powers_hom_symm_apply powersHom_symm_apply - -theorem zpowersHom_apply [Group G] (x : G) (n : Multiplicative ℤ) : - zpowersHom G x n = x ^ (Multiplicative.toAdd n) := - rfl -#align zpowers_hom_apply zpowersHom_apply - -theorem zpowersHom_symm_apply [Group G] (f : Multiplicative ℤ →* G) : - (zpowersHom G).symm f = f (Multiplicative.ofAdd 1) := - rfl -#align zpowers_hom_symm_apply zpowersHom_symm_apply - --- todo: can `to_additive` generate the following lemmas automatically? - -theorem multiplesHom_apply [AddMonoid A] (x : A) (n : ℕ) : multiplesHom A x n = n • x := - rfl -#align multiples_hom_apply multiplesHom_apply - -attribute [to_additive existing (attr := simp) multiplesHom_apply] powersHom_apply - -theorem multiplesHom_symm_apply [AddMonoid A] (f : ℕ →+ A) : (multiplesHom A).symm f = f 1 := - rfl -#align multiples_hom_symm_apply multiplesHom_symm_apply - -attribute [to_additive existing (attr := simp) multiplesHom_symm_apply] powersHom_symm_apply - -theorem zmultiplesHom_apply [AddGroup A] (x : A) (n : ℤ) : zmultiplesHom A x n = n • x := - rfl -#align zmultiples_hom_apply zmultiplesHom_apply - -attribute [to_additive existing (attr := simp) zmultiplesHom_apply] zpowersHom_apply - -theorem zmultiplesHom_symm_apply [AddGroup A] (f : ℤ →+ A) : (zmultiplesHom A).symm f = f 1 := - rfl -#align zmultiples_hom_symm_apply zmultiplesHom_symm_apply - -attribute [to_additive existing (attr := simp) zmultiplesHom_symm_apply] zpowersHom_symm_apply - --- TODO use to_additive in the rest of this file -theorem MonoidHom.apply_mnat [Monoid M] (f : Multiplicative ℕ →* M) (n : Multiplicative ℕ) : - f n = f (Multiplicative.ofAdd 1) ^ (Multiplicative.toAdd n) := by - rw [← powersHom_symm_apply, ← powersHom_apply, Equiv.apply_symm_apply] -#align monoid_hom.apply_mnat MonoidHom.apply_mnat - -@[ext] -theorem MonoidHom.ext_mnat [Monoid M] ⦃f g : Multiplicative ℕ →* M⦄ - (h : f (Multiplicative.ofAdd 1) = g (Multiplicative.ofAdd 1)) : f = g := - MonoidHom.ext fun n => by rw [f.apply_mnat, g.apply_mnat, h] -#align monoid_hom.ext_mnat MonoidHom.ext_mnat - -theorem MonoidHom.apply_mint [Group M] (f : Multiplicative ℤ →* M) (n : Multiplicative ℤ) : - f n = f (Multiplicative.ofAdd 1) ^ (Multiplicative.toAdd n) := by - rw [← zpowersHom_symm_apply, ← zpowersHom_apply, Equiv.apply_symm_apply] -#align monoid_hom.apply_mint MonoidHom.apply_mint - -/-! `MonoidHom.ext_mint` is defined in `Data.Int.Cast` -/ - -theorem AddMonoidHom.apply_nat [AddMonoid M] (f : ℕ →+ M) (n : ℕ) : f n = n • f 1 := by - rw [← multiplesHom_symm_apply, ← multiplesHom_apply, Equiv.apply_symm_apply] -#align add_monoid_hom.apply_nat AddMonoidHom.apply_nat - -/-! `AddMonoidHom.ext_nat` is defined in `Data.Nat.Cast` -/ - -theorem AddMonoidHom.apply_int [AddGroup M] (f : ℤ →+ M) (n : ℤ) : f n = n • f 1 := by - rw [← zmultiplesHom_symm_apply, ← zmultiplesHom_apply, Equiv.apply_symm_apply] -#align add_monoid_hom.apply_int AddMonoidHom.apply_int - -/-! `AddMonoidHom.ext_int` is defined in `Data.Int.Cast` -/ - -variable (M G A) -/-- If `M` is commutative, `powersHom` is a multiplicative equivalence. -/ -def powersMulHom [CommMonoid M] : M ≃* (Multiplicative ℕ →* M) := - { powersHom M with map_mul' := fun a b => MonoidHom.ext fun n => by simp [mul_pow] } -#align powers_mul_hom powersMulHom - -/-- If `M` is commutative, `zpowersHom` is a multiplicative equivalence. -/ -def zpowersMulHom [CommGroup G] : G ≃* (Multiplicative ℤ →* G) := - { zpowersHom G with map_mul' := fun a b => MonoidHom.ext fun n => by simp [mul_zpow] } -#align zpowers_mul_hom zpowersMulHom - -/-- If `M` is commutative, `multiplesHom` is an additive equivalence. -/ -def multiplesAddHom [AddCommMonoid A] : A ≃+ (ℕ →+ A) := - { multiplesHom A with map_add' := fun a b => AddMonoidHom.ext fun n => by simp [nsmul_add] } -#align multiples_add_hom multiplesAddHom - -/-- If `M` is commutative, `zmultiplesHom` is an additive equivalence. -/ -def zmultiplesAddHom [AddCommGroup A] : A ≃+ (ℤ →+ A) := - { zmultiplesHom A with map_add' := fun a b => AddMonoidHom.ext fun n => by simp [zsmul_add] } -#align zmultiples_add_hom zmultiplesAddHom - -variable {M G A} - -@[simp] -theorem powersMulHom_apply [CommMonoid M] (x : M) (n : Multiplicative ℕ) : - powersMulHom M x n = x ^ (Multiplicative.toAdd n) := - rfl -#align powers_mul_hom_apply powersMulHom_apply - -@[simp] -theorem powersMulHom_symm_apply [CommMonoid M] (f : Multiplicative ℕ →* M) : - (powersMulHom M).symm f = f (Multiplicative.ofAdd 1) := - rfl -#align powers_mul_hom_symm_apply powersMulHom_symm_apply - -@[simp] -theorem zpowersMulHom_apply [CommGroup G] (x : G) (n : Multiplicative ℤ) : - zpowersMulHom G x n = x ^ (Multiplicative.toAdd n) := - rfl -#align zpowers_mul_hom_apply zpowersMulHom_apply - -@[simp] -theorem zpowersMulHom_symm_apply [CommGroup G] (f : Multiplicative ℤ →* G) : - (zpowersMulHom G).symm f = f (Multiplicative.ofAdd 1) := - rfl -#align zpowers_mul_hom_symm_apply zpowersMulHom_symm_apply - -@[simp] -theorem multiplesAddHom_apply [AddCommMonoid A] (x : A) (n : ℕ) : multiplesAddHom A x n = n • x := - rfl -#align multiples_add_hom_apply multiplesAddHom_apply - -@[simp] -theorem multiplesAddHom_symm_apply [AddCommMonoid A] (f : ℕ →+ A) : - (multiplesAddHom A).symm f = f 1 := - rfl -#align multiples_add_hom_symm_apply multiplesAddHom_symm_apply - -@[simp] -theorem zmultiplesAddHom_apply [AddCommGroup A] (x : A) (n : ℤ) : - zmultiplesAddHom A x n = n • x := - rfl -#align zmultiples_add_hom_apply zmultiplesAddHom_apply - -@[simp] -theorem zmultiplesAddHom_symm_apply [AddCommGroup A] (f : ℤ →+ A) : - (zmultiplesAddHom A).symm f = f 1 := - rfl -#align zmultiples_add_hom_symm_apply zmultiplesAddHom_symm_apply - -/-! -### Commutativity (again) - -Facts about `SemiconjBy` and `Commute` that require `zpow` or `zsmul`, or the fact that integer -multiplication equals semiring multiplication. --/ - - -namespace SemiconjBy - -section - -variable [Semiring R] {a x y : R} - -@[simp] -theorem cast_nat_mul_right (h : SemiconjBy a x y) (n : ℕ) : SemiconjBy a ((n : R) * x) (n * y) := - SemiconjBy.mul_right (Nat.commute_cast _ _) h -#align semiconj_by.cast_nat_mul_right SemiconjBy.cast_nat_mul_right - -@[simp] -theorem cast_nat_mul_left (h : SemiconjBy a x y) (n : ℕ) : SemiconjBy ((n : R) * a) x y := - SemiconjBy.mul_left (Nat.cast_commute _ _) h -#align semiconj_by.cast_nat_mul_left SemiconjBy.cast_nat_mul_left - -@[simp] -theorem cast_nat_mul_cast_nat_mul (h : SemiconjBy a x y) (m n : ℕ) : - SemiconjBy ((m : R) * a) (n * x) (n * y) := - (h.cast_nat_mul_left m).cast_nat_mul_right n -#align semiconj_by.cast_nat_mul_cast_nat_mul SemiconjBy.cast_nat_mul_cast_nat_mul - -end - -variable [Monoid M] [Group G] [Ring R] - -@[to_additive (attr := simp)] -theorem units_zpow_right {a : M} {x y : Mˣ} (h : SemiconjBy a x y) : - ∀ m : ℤ, SemiconjBy a ↑(x ^ m) ↑(y ^ m) - | (n : ℕ) => by simp only [zpow_ofNat, Units.val_pow_eq_pow_val, h, pow_right] - | -[n+1] => by simp only [zpow_negSucc, Units.val_pow_eq_pow_val, units_inv_right, h, pow_right] -#align semiconj_by.units_zpow_right SemiconjBy.units_zpow_right -#align add_semiconj_by.add_units_zsmul_right AddSemiconjBy.addUnits_zsmul_right - -variable {a b x y x' y' : R} - -@[simp] -theorem cast_int_mul_right (h : SemiconjBy a x y) (m : ℤ) : SemiconjBy a ((m : ℤ) * x) (m * y) := - SemiconjBy.mul_right (Int.commute_cast _ _) h -#align semiconj_by.cast_int_mul_right SemiconjBy.cast_int_mul_right - -@[simp] -theorem cast_int_mul_left (h : SemiconjBy a x y) (m : ℤ) : SemiconjBy ((m : R) * a) x y := - SemiconjBy.mul_left (Int.cast_commute _ _) h -#align semiconj_by.cast_int_mul_left SemiconjBy.cast_int_mul_left - -@[simp] -theorem cast_int_mul_cast_int_mul (h : SemiconjBy a x y) (m n : ℤ) : - SemiconjBy ((m : R) * a) (n * x) (n * y) := - (h.cast_int_mul_left m).cast_int_mul_right n -#align semiconj_by.cast_int_mul_cast_int_mul SemiconjBy.cast_int_mul_cast_int_mul - -end SemiconjBy - -namespace Commute - -section - -variable [Semiring R] {a b : R} - -@[simp] -theorem cast_nat_mul_right (h : Commute a b) (n : ℕ) : Commute a ((n : R) * b) := - SemiconjBy.cast_nat_mul_right h n -#align commute.cast_nat_mul_right Commute.cast_nat_mul_right - -@[simp] -theorem cast_nat_mul_left (h : Commute a b) (n : ℕ) : Commute ((n : R) * a) b := - SemiconjBy.cast_nat_mul_left h n -#align commute.cast_nat_mul_left Commute.cast_nat_mul_left - -@[simp] -theorem cast_nat_mul_cast_nat_mul (h : Commute a b) - (m n : ℕ) : Commute (m * a : R) (n * b : R) := - SemiconjBy.cast_nat_mul_cast_nat_mul h m n -#align commute.cast_nat_mul_cast_nat_mul Commute.cast_nat_mul_cast_nat_mul - -variable (a) (m n : ℕ) - -/- Porting note: `simp` attribute removed as linter reports: -simp can prove this: - by simp only [Commute.refl, Commute.cast_nat_mul_right] --/ --- @[simp] -theorem self_cast_nat_mul : Commute a (n * a : R) := - (Commute.refl a).cast_nat_mul_right n -#align commute.self_cast_nat_mul Commute.self_cast_nat_mul - -/- Porting note: `simp` attribute removed as linter reports: -simp can prove this: - by simp only [Commute.refl, Commute.cast_nat_mul_left] --/ --- @[simp] -theorem cast_nat_mul_self : Commute ((n : R) * a) a := - (Commute.refl a).cast_nat_mul_left n -#align commute.cast_nat_mul_self Commute.cast_nat_mul_self - -/- Porting note: `simp` attribute removed as linter reports: -simp can prove this: - by simp only [Commute.refl, Commute.cast_nat_mul_left, Commute.cast_nat_mul_right] --/ --- @[simp] -theorem self_cast_nat_mul_cast_nat_mul : Commute (m * a : R) (n * a : R) := - (Commute.refl a).cast_nat_mul_cast_nat_mul m n -#align commute.self_cast_nat_mul_cast_nat_mul Commute.self_cast_nat_mul_cast_nat_mul - -end - -variable [Monoid M] [Group G] [Ring R] - -@[to_additive (attr := simp)] -theorem units_zpow_right {a : M} {u : Mˣ} (h : Commute a u) - (m : ℤ) : Commute a ↑(u ^ m) := - SemiconjBy.units_zpow_right h m -#align commute.units_zpow_right Commute.units_zpow_right -#align add_commute.add_units_zsmul_right AddCommute.addUnits_zsmul_right - -@[to_additive (attr := simp)] -theorem units_zpow_left {u : Mˣ} {a : M} (h : Commute (↑u) a) - (m : ℤ) : Commute (↑(u ^ m)) a := - (h.symm.units_zpow_right m).symm -#align commute.units_zpow_left Commute.units_zpow_left -#align add_commute.add_units_zsmul_left AddCommute.addUnits_zsmul_left - -variable {a b : R} - -@[simp] -theorem cast_int_mul_right (h : Commute a b) (m : ℤ) : Commute a (m * b : R) := - SemiconjBy.cast_int_mul_right h m -#align commute.cast_int_mul_right Commute.cast_int_mul_right - -@[simp] -theorem cast_int_mul_left (h : Commute a b) (m : ℤ) : - Commute ((m : R) * a) b := - SemiconjBy.cast_int_mul_left h m -#align commute.cast_int_mul_left Commute.cast_int_mul_left - -theorem cast_int_mul_cast_int_mul (h : Commute a b) - (m n : ℤ) : Commute (m * a : R) (n * b : R) := - SemiconjBy.cast_int_mul_cast_int_mul h m n -#align commute.cast_int_mul_cast_int_mul Commute.cast_int_mul_cast_int_mul - -variable (a) (m n : ℤ) - -@[simp] -theorem cast_int_left : Commute (m : R) a := Int.cast_commute _ _ -#align commute.cast_int_left Commute.cast_int_left - -@[simp] -theorem cast_int_right : Commute a m := Int.commute_cast _ _ -#align commute.cast_int_right Commute.cast_int_right - -/- Porting note: `simp` attribute removed as linter reports: -simp can prove this: - by simp only [Commute.cast_int_right, Commute.refl, Commute.mul_right] --/ --- @[simp] -theorem self_cast_int_mul : Commute a (n * a : R) := - (Commute.refl a).cast_int_mul_right n -#align commute.self_cast_int_mul Commute.self_cast_int_mul - -/- Porting note: `simp` attribute removed as linter reports: -simp can prove this: - by simp only [Commute.cast_int_left, Commute.refl, Commute.mul_left] --/ --- @[simp] -theorem cast_int_mul_self : Commute ((n : R) * a) a := - (Commute.refl a).cast_int_mul_left n -#align commute.cast_int_mul_self Commute.cast_int_mul_self - -theorem self_cast_int_mul_cast_int_mul : Commute (m * a : R) (n * a : R) := - (Commute.refl a).cast_int_mul_cast_int_mul m n -#align commute.self_cast_int_mul_cast_int_mul Commute.self_cast_int_mul_cast_int_mul - -end Commute - -section Multiplicative - -open Multiplicative - -theorem Nat.toAdd_pow (a : Multiplicative ℕ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b := - mul_comm _ _ -#align nat.to_add_pow Nat.toAdd_pow - -@[simp] -theorem Nat.ofAdd_mul (a b : ℕ) : ofAdd (a * b) = ofAdd a ^ b := - (Nat.toAdd_pow _ _).symm -#align nat.of_add_mul Nat.ofAdd_mul - -theorem Int.toAdd_pow (a : Multiplicative ℤ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b := - mul_comm _ _ -#align int.to_add_pow Int.toAdd_pow - -theorem Int.toAdd_zpow (a : Multiplicative ℤ) (b : ℤ) : toAdd (a ^ b) = toAdd a * b := - mul_comm _ _ -#align int.to_add_zpow Int.toAdd_zpow - -@[simp] -theorem Int.ofAdd_mul (a b : ℤ) : ofAdd (a * b) = ofAdd a ^ b := - (Int.toAdd_zpow _ _).symm -#align int.of_add_mul Int.ofAdd_mul - -end Multiplicative - -namespace Units - -variable [Monoid M] - -theorem conj_pow (u : Mˣ) (x : M) (n : ℕ) : - ((↑u : M) * x * (↑u⁻¹ : M)) ^ n = (u : M) * x ^ n * (↑u⁻¹ : M) := - (divp_eq_iff_mul_eq.2 - ((u.mk_semiconjBy x).pow_right n).eq.symm).symm -#align units.conj_pow Units.conj_pow - -theorem conj_pow' (u : Mˣ) (x : M) (n : ℕ) : - ((↑u⁻¹ : M) * x * (u : M)) ^ n = (↑u⁻¹ : M) * x ^ n * (u : M) := - u⁻¹.conj_pow x n -#align units.conj_pow' Units.conj_pow' - -end Units - --- Porting note: this was added in an ad hoc port for use in `Tactic/NormNum/Basic` - -@[simp] theorem pow_eq {m : ℤ} {n : ℕ} : m.pow n = m ^ n := rfl diff --git a/Mathlib/Algebra/GroupPower/Order.lean b/Mathlib/Algebra/GroupPower/Order.lean index d2c43828400a5..fa7f5d48b693b 100644 --- a/Mathlib/Algebra/GroupPower/Order.lean +++ b/Mathlib/Algebra/GroupPower/Order.lean @@ -3,12 +3,9 @@ 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 Mathlib.Algebra.Order.Ring.Abs -import Mathlib.Algebra.Order.WithZero import Mathlib.Algebra.GroupPower.CovariantClass import Mathlib.Algebra.GroupPower.Ring -import Mathlib.Data.Set.Intervals.Basic -import Mathlib.Data.Nat.Order.Basic +import Mathlib.Algebra.Order.WithZero #align_import algebra.group_power.order from "leanprover-community/mathlib"@"00f91228655eecdcd3ac97a7fd8dbcb139fe990a" @@ -19,9 +16,127 @@ Note that some lemmas are in `Algebra/GroupPower/Lemmas.lean` as they import fil depend on this file. -/ -open Function +open Function Int -variable {M R : Type*} +variable {α M R : Type*} + +section OrderedCommGroup +variable [OrderedCommGroup α] {m n : ℤ} {a b : α} + +@[to_additive zsmul_pos] lemma one_lt_zpow' (ha : 1 < a) (hn : 0 < n) : 1 < a ^ n := by + obtain ⟨n, rfl⟩ := Int.eq_ofNat_of_zero_le hn.le + rw [zpow_ofNat] + refine' one_lt_pow' ha ?_ + rintro rfl + simp at hn +#align one_lt_zpow' one_lt_zpow' +#align zsmul_pos zsmul_pos + +@[to_additive zsmul_strictMono_left] +lemma zpow_right_strictMono (ha : 1 < a) : StrictMono fun n : ℤ ↦ a ^ n := fun m n h ↦ + calc + a ^ m = a ^ m * 1 := (mul_one _).symm + _ < a ^ m * a ^ (n - m) := mul_lt_mul_left' (one_lt_zpow' ha <| Int.sub_pos_of_lt h) _ + _ = a ^ n := by simp [← zpow_add, m.add_comm] +#align zpow_strict_mono_right zpow_right_strictMono +#align zsmul_strict_mono_left zsmul_strictMono_left + +@[to_additive zsmul_mono_left] +lemma zpow_mono_right (ha : 1 ≤ a) : Monotone fun n : ℤ ↦ a ^ n := fun m n h ↦ + calc + a ^ m = a ^ m * 1 := (mul_one _).symm + _ ≤ a ^ m * a ^ (n - m) := mul_le_mul_left' (one_le_zpow ha <| Int.sub_nonneg_of_le h) _ + _ = a ^ n := by simp [← zpow_add, m.add_comm] +#align zpow_mono_right zpow_mono_right +#align zsmul_mono_left zsmul_mono_left + +@[to_additive] lemma zpow_le_zpow (ha : 1 ≤ a) (h : m ≤ n) : a ^ m ≤ a ^ n := zpow_mono_right ha h +#align zpow_le_zpow zpow_le_zpow +#align zsmul_le_zsmul zsmul_le_zsmul + +@[to_additive] +lemma zpow_lt_zpow (ha : 1 < a) (h : m < n) : a ^ m < a ^ n := zpow_right_strictMono ha h +#align zpow_lt_zpow zpow_lt_zpow +#align zsmul_lt_zsmul zsmul_lt_zsmul + +@[to_additive] +lemma zpow_le_zpow_iff (ha : 1 < a) : a ^ m ≤ a ^ n ↔ m ≤ n := (zpow_right_strictMono ha).le_iff_le +#align zpow_le_zpow_iff zpow_le_zpow_iff +#align zsmul_le_zsmul_iff zsmul_le_zsmul_iff + +@[to_additive] +lemma zpow_lt_zpow_iff (ha : 1 < a) : a ^ m < a ^ n ↔ m < n := (zpow_right_strictMono ha).lt_iff_lt +#align zpow_lt_zpow_iff zpow_lt_zpow_iff +#align zsmul_lt_zsmul_iff zsmul_lt_zsmul_iff + +variable (α) + +@[to_additive zsmul_strictMono_right] +lemma zpow_strictMono_left (hn : 0 < n) : StrictMono ((· ^ n) : α → α) := fun a b hab => by + rw [← one_lt_div', ← div_zpow]; exact one_lt_zpow' (one_lt_div'.2 hab) hn +#align zpow_strict_mono_left zpow_strictMono_left +#align zsmul_strict_mono_right zsmul_strictMono_right + +@[to_additive zsmul_mono_right] +lemma zpow_mono_left (hn : 0 ≤ n) : Monotone ((· ^ n) : α → α) := fun a b hab => by + rw [← one_le_div', ← div_zpow]; exact one_le_zpow (one_le_div'.2 hab) hn +#align zpow_mono_left zpow_mono_left +#align zsmul_mono_right zsmul_mono_right + +variable {α} + +@[to_additive] +lemma zpow_le_zpow' (hn : 0 ≤ n) (h : a ≤ b) : a ^ n ≤ b ^ n := zpow_mono_left α hn h +#align zpow_le_zpow' zpow_le_zpow' +#align zsmul_le_zsmul' zsmul_le_zsmul' + +@[to_additive] +lemma zpow_lt_zpow' (hn : 0 < n) (h : a < b) : a ^ n < b ^ n := zpow_strictMono_left α hn h +#align zpow_lt_zpow' zpow_lt_zpow' +#align zsmul_lt_zsmul' zsmul_lt_zsmul' + +end OrderedCommGroup + +section LinearOrderedCommGroup + +variable [LinearOrderedCommGroup α] {n : ℤ} {a b : α} + +@[to_additive] lemma zpow_le_zpow_iff' (hn : 0 < n) : a ^ n ≤ b ^ n ↔ a ≤ b := + (zpow_strictMono_left α hn).le_iff_le +#align zpow_le_zpow_iff' zpow_le_zpow_iff' +#align zsmul_le_zsmul_iff' zsmul_le_zsmul_iff' + +@[to_additive] lemma zpow_lt_zpow_iff' (hn : 0 < n) : a ^ n < b ^ n ↔ a < b := + (zpow_strictMono_left α hn).lt_iff_lt +#align zpow_lt_zpow_iff' zpow_lt_zpow_iff' +#align zsmul_lt_zsmul_iff' zsmul_lt_zsmul_iff' + +@[to_additive zsmul_right_injective +"See also `smul_right_injective`. TODO: provide a `NoZeroSMulDivisors` instance. We can't do +that here because importing that definition would create import cycles."] +lemma zpow_left_injective (hn : n ≠ 0) : Injective ((· ^ n) : α → α) := by + obtain hn | hn := hn.lt_or_lt + · refine fun a b (hab : a ^ n = b ^ n) ↦ + (zpow_strictMono_left _ $ Int.neg_pos_of_neg hn).injective ?_ + rw [zpow_neg, zpow_neg, hab] + · exact (zpow_strictMono_left _ hn).injective +#align zpow_left_injective zpow_left_injective +#align zsmul_right_injective zsmul_right_injective + +@[to_additive zsmul_right_inj] +lemma zpow_left_inj (hn : n ≠ 0) : a ^ n = b ^ n ↔ a = b := (zpow_left_injective hn).eq_iff +#align zpow_left_inj zpow_left_inj +#align zsmul_right_inj zsmul_right_inj + +/-- Alias of `zpow_left_inj`, for ease of discovery alongside `zsmul_le_zsmul_iff'` and +`zsmul_lt_zsmul_iff'`. -/ +@[to_additive "Alias of `zsmul_right_inj`, for ease of discovery alongside `zsmul_le_zsmul_iff'` and +`zsmul_lt_zsmul_iff'`."] +lemma zpow_eq_zpow_iff' (hn : n ≠ 0) : a ^ n = b ^ n ↔ a = b := zpow_left_inj hn +#align zpow_eq_zpow_iff' zpow_eq_zpow_iff' +#align zsmul_eq_zsmul_iff' zsmul_eq_zsmul_iff' + +end LinearOrderedCommGroup namespace CanonicallyOrderedCommSemiring @@ -35,7 +150,7 @@ end CanonicallyOrderedCommSemiring section OrderedSemiring -variable [OrderedSemiring R] {a x y : R} {n m : ℕ} +variable [OrderedSemiring R] {a b x y : R} {n m : ℕ} theorem zero_pow_le_one : ∀ n : ℕ, (0 : R) ^ n ≤ 1 | 0 => (pow_zero _).le @@ -113,6 +228,11 @@ theorem one_lt_pow (ha : 1 < a) : ∀ {n : ℕ} (_ : n ≠ 0), 1 < a ^ n exact one_lt_mul_of_lt_of_le ha (one_le_pow_of_one_le ha.le _) #align one_lt_pow one_lt_pow +lemma pow_add_pow_le' (ha : 0 ≤ a) (hb : 0 ≤ b) : a ^ n + b ^ n ≤ 2 * (a + b) ^ n := by + rw [two_mul] + exact add_le_add (pow_le_pow_left ha (le_add_of_nonneg_right hb) _) + (pow_le_pow_left hb (le_add_of_nonneg_left ha) _) + end OrderedSemiring section StrictOrderedSemiring @@ -127,7 +247,7 @@ theorem pow_lt_pow_left (h : x < y) (hx : 0 ≤ x) : ∀ {n : ℕ}, n ≠ 0 → #align pow_lt_pow_of_lt_left pow_lt_pow_left /-- See also `pow_left_strictMono` and `Nat.pow_left_strictMono`. -/ -lemma pow_left_strictMonoOn (hn : n ≠ 0) : StrictMonoOn (· ^ n : R → R) (Set.Ici 0) := +lemma pow_left_strictMonoOn (hn : n ≠ 0) : StrictMonoOn (· ^ n : R → R) {a | 0 ≤ a} := fun _a ha _b _ hab ↦ pow_lt_pow_left hab ha hn #align strict_mono_on_pow pow_left_strictMonoOn @@ -272,22 +392,9 @@ theorem lt_of_mul_self_lt_mul_self (hb : 0 ≤ b) : a * a < b * b → a < b := b end LinearOrderedSemiring section LinearOrderedRing +variable [LinearOrderedRing R] {a b : R} {n : ℕ} -variable [LinearOrderedRing R] - -theorem pow_abs (a : R) (n : ℕ) : |a| ^ n = |a ^ n| := - ((absHom.toMonoidHom : R →* R).map_pow a n).symm -#align pow_abs pow_abs - -theorem abs_neg_one_pow (n : ℕ) : |(-1 : R) ^ n| = 1 := by rw [← pow_abs, abs_neg, abs_one, one_pow] -#align abs_neg_one_pow abs_neg_one_pow - -theorem abs_pow_eq_one (a : R) {n : ℕ} (h : n ≠ 0) : |a ^ n| = 1 ↔ |a| = 1 := by - convert pow_left_inj (abs_nonneg a) zero_le_one h - exacts [(pow_abs _ _).symm, (one_pow _).symm] -#align abs_pow_eq_one abs_pow_eq_one - -section +section deprecated set_option linter.deprecated false theorem pow_bit0_nonneg (a : R) (n : ℕ) : 0 ≤ a ^ bit0 n := by @@ -316,82 +423,41 @@ theorem pow_bit0_pos_iff (a : R) {n : ℕ} (hn : n ≠ 0) : 0 < a ^ bit0 n ↔ a exact lt_irrefl _ h #align pow_bit0_pos_iff pow_bit0_pos_iff -end - -theorem sq_pos_iff (a : R) : 0 < a ^ 2 ↔ a ≠ 0 := - pow_bit0_pos_iff a one_ne_zero -#align sq_pos_iff sq_pos_iff - -variable {x y : R} - --- Porting note: added `simp` to replace `pow_bit0_abs` @[simp] -theorem sq_abs (x : R) : |x| ^ 2 = x ^ 2 := by simpa only [sq] using abs_mul_abs_self x -#align sq_abs sq_abs - -theorem abs_sq (x : R) : |x ^ 2| = x ^ 2 := by simpa only [sq] using abs_mul_self x -#align abs_sq abs_sq - -theorem sq_lt_sq : x ^ 2 < y ^ 2 ↔ |x| < |y| := by - simpa only [sq_abs] using - (pow_left_strictMonoOn two_ne_zero).lt_iff_lt (abs_nonneg x) (abs_nonneg y) -#align sq_lt_sq sq_lt_sq - -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 _)) -#align sq_lt_sq' sq_lt_sq' - -theorem sq_le_sq : x ^ 2 ≤ y ^ 2 ↔ |x| ≤ |y| := by - simpa only [sq_abs] using - (pow_left_strictMonoOn two_ne_zero).le_iff_le (abs_nonneg x) (abs_nonneg y) -#align sq_le_sq sq_le_sq - -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 _)) -#align sq_le_sq' sq_le_sq' - -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] -#align abs_lt_of_sq_lt_sq abs_lt_of_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 -#align abs_lt_of_sq_lt_sq' abs_lt_of_sq_lt_sq' - -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] -#align abs_le_of_sq_le_sq abs_le_of_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 -#align abs_le_of_sq_le_sq' abs_le_of_sq_le_sq' - -theorem 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] -#align sq_eq_sq_iff_abs_eq_abs sq_eq_sq_iff_abs_eq_abs +lemma pow_bit1_neg_iff : a ^ bit1 n < 0 ↔ a < 0 := + ⟨fun h ↦ not_le.1 fun h' => not_le.2 h <| pow_nonneg h' _, fun ha ↦ pow_bit1_neg ha n⟩ +#align pow_bit1_neg_iff pow_bit1_neg_iff @[simp] -theorem 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 -#align sq_le_one_iff_abs_le_one sq_le_one_iff_abs_le_one +lemma pow_bit1_nonneg_iff : 0 ≤ a ^ bit1 n ↔ 0 ≤ a := le_iff_le_iff_lt_iff_lt.2 pow_bit1_neg_iff +#align pow_bit1_nonneg_iff pow_bit1_nonneg_iff @[simp] -theorem 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 -#align sq_lt_one_iff_abs_lt_one sq_lt_one_iff_abs_lt_one +lemma pow_bit1_nonpos_iff : a ^ bit1 n ≤ 0 ↔ a ≤ 0 := by + simp only [le_iff_lt_or_eq, pow_bit1_neg_iff, pow_eq_zero_iff']; simp [bit1] +#align pow_bit1_nonpos_iff pow_bit1_nonpos_iff @[simp] -theorem 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 -#align one_le_sq_iff_one_le_abs one_le_sq_iff_one_le_abs - -@[simp] -theorem 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 -#align one_lt_sq_iff_one_lt_abs one_lt_sq_iff_one_lt_abs +lemma pow_bit1_pos_iff : 0 < a ^ bit1 n ↔ 0 < a := lt_iff_lt_of_le_iff_le pow_bit1_nonpos_iff +#align pow_bit1_pos_iff pow_bit1_pos_iff + +lemma strictMono_pow_bit1 (n : ℕ) : StrictMono (· ^ bit1 n : R → R) := by + intro a b hab + rcases le_total a 0 with ha | ha + · rcases le_or_lt b 0 with hb | hb + · rw [← neg_lt_neg_iff, ← neg_pow_bit1, ← neg_pow_bit1] + exact pow_lt_pow_left (neg_lt_neg hab) (neg_nonneg.2 hb) n.bit1_ne_zero + · exact (pow_bit1_nonpos_iff.2 ha).trans_lt (pow_bit1_pos_iff.2 hb) + · exact pow_lt_pow_left hab ha n.bit1_ne_zero +#align strict_mono_pow_bit1 strictMono_pow_bit1 + +end deprecated + +lemma sq_pos_iff (a : R) : 0 < a ^ 2 ↔ a ≠ 0 := pow_bit0_pos_iff a one_ne_zero +#align sq_pos_iff sq_pos_iff -theorem 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_left (sq_nonneg x) h 2 +lemma pow_four_le_pow_two_of_pow_two_le (h : a ^ 2 ≤ b) : a ^ 4 ≤ b ^ 2 := + (pow_mul a 2 2).symm ▸ pow_le_pow_left (sq_nonneg a) h 2 #align pow_four_le_pow_two_of_pow_two_le pow_four_le_pow_two_of_pow_two_le end LinearOrderedRing diff --git a/Mathlib/Algebra/GroupPower/Ring.lean b/Mathlib/Algebra/GroupPower/Ring.lean index df006e0e8f526..55ea9ad826efd 100644 --- a/Mathlib/Algebra/GroupPower/Ring.lean +++ b/Mathlib/Algebra/GroupPower/Ring.lean @@ -3,14 +3,11 @@ 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 Mathlib.Algebra.Group.Units.Hom import Mathlib.Algebra.GroupPower.Hom import Mathlib.Algebra.GroupWithZero.Commute import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.Ring.Commute import Mathlib.Algebra.Ring.Divisibility.Basic -import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Data.Nat.Order.Basic #align_import algebra.group_power.ring from "leanprover-community/mathlib"@"fc2ed6f838ce7c9b7c7171e58d78eaf7b438fb0e" @@ -19,8 +16,7 @@ import Mathlib.Data.Nat.Order.Basic # Power operations on monoids with zero, semirings, and rings This file provides additional lemmas about the natural power operator on rings and semirings. -Further lemmas about ordered semirings and rings can be found in `Algebra.GroupPower.Lemmas`. - +Further lemmas about ordered semirings and rings can be found in `Algebra.GroupPower.Order`. -/ variable {R S M : Type*} @@ -232,6 +228,16 @@ alias neg_one_pow_two := neg_one_sq end HasDistribNeg +section DivisionMonoid +variable [DivisionMonoid R] [HasDistribNeg R] + +set_option linter.deprecated false in +@[simp] lemma zpow_bit0_neg (a : R) (n : ℤ) : (-a) ^ bit0 n = a ^ bit0 n := by + rw [zpow_bit0', zpow_bit0', neg_mul_neg] +#align zpow_bit0_neg zpow_bit0_neg + +end DivisionMonoid + section Ring variable [Ring R] {a b : R} @@ -266,6 +272,10 @@ theorem sq_ne_one_iff : a ^ 2 ≠ 1 ↔ a ≠ 1 ∧ a ≠ -1 := sq_eq_one_iff.not.trans not_or #align sq_ne_one_iff sq_ne_one_iff +lemma neg_one_pow_eq_pow_mod_two (n : ℕ) : (-1 : R) ^ n = (-1) ^ (n % 2) := by + rw [← Nat.mod_add_div n 2, pow_add, pow_mul]; simp [sq] +#align neg_one_pow_eq_pow_mod_two neg_one_pow_eq_pow_mod_two + end Ring section CommRing diff --git a/Mathlib/Algebra/GroupRingAction/Basic.lean b/Mathlib/Algebra/GroupRingAction/Basic.lean index 3853de5e9d573..846d2024e27d2 100644 --- a/Mathlib/Algebra/GroupRingAction/Basic.lean +++ b/Mathlib/Algebra/GroupRingAction/Basic.lean @@ -3,8 +3,8 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ +import Mathlib.Algebra.GroupWithZero.Units.Lemmas import Mathlib.Algebra.Ring.Equiv -import Mathlib.Algebra.Field.Defs import Mathlib.GroupTheory.GroupAction.Group #align_import algebra.group_ring_action.basic from "leanprover-community/mathlib"@"207cfac9fcd06138865b5d04f7091e46d9320432" diff --git a/Mathlib/Algebra/GroupRingAction/Invariant.lean b/Mathlib/Algebra/GroupRingAction/Invariant.lean index 5345722af0806..b2a8b58d97802 100644 --- a/Mathlib/Algebra/GroupRingAction/Invariant.lean +++ b/Mathlib/Algebra/GroupRingAction/Invariant.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.GroupTheory.GroupAction.Hom -import Mathlib.RingTheory.Subring.Pointwise +import Mathlib.RingTheory.Subring.Basic #align_import algebra.group_ring_action.invariant from "leanprover-community/mathlib"@"e7bab9a85e92cf46c02cb4725a7be2f04691e3a7" diff --git a/Mathlib/Algebra/GroupWithZero/Defs.lean b/Mathlib/Algebra/GroupWithZero/Defs.lean index ce855a2e4e948..ab87a0d095187 100644 --- a/Mathlib/Algebra/GroupWithZero/Defs.lean +++ b/Mathlib/Algebra/GroupWithZero/Defs.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ import Mathlib.Algebra.Group.Defs +import Mathlib.Logic.Function.Basic import Mathlib.Logic.Nontrivial.Defs #align_import algebra.group_with_zero.defs from "leanprover-community/mathlib"@"2f3994e1b117b1e1da49bcfb67334f33460c3ce4" diff --git a/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean b/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean index 6298c0bc106f4..74b5cc530694e 100644 --- a/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean +++ b/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean @@ -5,7 +5,8 @@ Authors: Kenny Lau, Devon Tuma, Oliver Nash -/ import Mathlib.GroupTheory.Submonoid.Operations import Mathlib.GroupTheory.Submonoid.Membership -import Mathlib.GroupTheory.Subgroup.MulOpposite +import Mathlib.GroupTheory.Submonoid.MulOpposite +import Mathlib.GroupTheory.GroupAction.Opposite #align_import ring_theory.non_zero_divisors from "leanprover-community/mathlib"@"1126441d6bccf98c81214a0780c73d499f6721fe" @@ -155,8 +156,11 @@ theorem dvd_cancel_left_mem_nonZeroDivisors {x y r : R'} (hr : r ∈ R'⁰) : r theorem dvd_cancel_left_coe_nonZeroDivisors {x y : R'} {c : R'⁰} : c * x ∣ c * y ↔ x ∣ y := dvd_cancel_left_mem_nonZeroDivisors c.prop -theorem nonZeroDivisors.ne_zero [Nontrivial M] {x} (hx : x ∈ M⁰) : x ≠ 0 := fun h ↦ - one_ne_zero (hx _ <| (one_mul _).trans h) +theorem zero_not_mem_nonZeroDivisors [Nontrivial M] : 0 ∉ M⁰ := + fun h ↦ one_ne_zero <| h 1 <| mul_zero _ + +theorem nonZeroDivisors.ne_zero [Nontrivial M] {x} (hx : x ∈ M⁰) : x ≠ 0 := + ne_of_mem_of_not_mem hx zero_not_mem_nonZeroDivisors #align non_zero_divisors.ne_zero nonZeroDivisors.ne_zero theorem nonZeroDivisors.coe_ne_zero [Nontrivial M] (x : M⁰) : (x : M) ≠ 0 := diff --git a/Mathlib/Algebra/GroupWithZero/Power.lean b/Mathlib/Algebra/GroupWithZero/Power.lean index cdcdae65df8f8..1782d98e8a532 100644 --- a/Mathlib/Algebra/GroupWithZero/Power.lean +++ b/Mathlib/Algebra/GroupWithZero/Power.lean @@ -3,8 +3,9 @@ Copyright (c) 2020 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.Algebra.GroupPower.Lemmas -import Mathlib.Util.AssertExists +import Mathlib.Algebra.GroupPower.Ring +import Mathlib.Algebra.GroupWithZero.Units.Lemmas +import Mathlib.Data.Int.Order.Basic #align_import algebra.group_with_zero.power from "leanprover-community/mathlib"@"46a64b5b4268c594af770c44d9e502afc6a515cb" @@ -187,3 +188,5 @@ end -- Guard against import creep regression. assert_not_exists Int.bitwise_or +assert_not_exists Set.range +assert_not_exists Nat.gcdA diff --git a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean index 88f5f4b33658c..ccabe79e3032f 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean @@ -5,7 +5,6 @@ Authors: Johan Commelin -/ import Mathlib.Algebra.GroupWithZero.Basic import Mathlib.Algebra.Group.Units -import Mathlib.Logic.Nontrivial.Basic import Mathlib.Tactic.Nontriviality import Mathlib.Util.AssertExists import Mathlib.Tactic.Contrapose diff --git a/Mathlib/Algebra/GroupWithZero/Units/Lemmas.lean b/Mathlib/Algebra/GroupWithZero/Units/Lemmas.lean index 8d55661eeadcb..e4b934971710d 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Lemmas.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Lemmas.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ +import Mathlib.Algebra.Group.Commute.Units import Mathlib.Algebra.Group.Hom.Basic import Mathlib.Algebra.Group.Units.Hom import Mathlib.Algebra.GroupWithZero.Commute @@ -23,7 +24,7 @@ variable [MonoidWithZero M₀] section GroupWithZero -variable [GroupWithZero G₀] {a b c : G₀} +variable [GroupWithZero G₀] {a b c d : G₀} @[simp] theorem div_self (h : a ≠ 0) : a / a = 1 := @@ -147,6 +148,12 @@ theorem divp_mk0 (a : G₀) {b : G₀} (hb : b ≠ 0) : a /ₚ Units.mk0 b hb = divp_eq_div _ _ #align divp_mk0 divp_mk0 +namespace Commute + +protected lemma div_eq_div_iff (hbd : Commute b d) (hb : b ≠ 0) (hd : d ≠ 0) : + a / b = c / d ↔ a * d = c * b := hbd.div_eq_div_iff_of_isUnit hb.isUnit hd.isUnit + +end Commute end GroupWithZero section CommGroupWithZero diff --git a/Mathlib/Algebra/HierarchyDesign.lean b/Mathlib/Algebra/HierarchyDesign.lean index 1b6703f2fcdd2..f2c0ee5072ba6 100644 --- a/Mathlib/Algebra/HierarchyDesign.lean +++ b/Mathlib/Algebra/HierarchyDesign.lean @@ -69,7 +69,7 @@ when applicable: * Instances transferred elementwise to pi types, like `Pi.Monoid`. See `Mathlib.Algebra.Group.Pi` for more examples. ``` - instance Pi.Z [∀ i, Z $ f i] : Z (Π i : I, f i) := ... + instance Pi.Z [∀ i, Z <| f i] : Z (Π i : I, f i) := ... ``` * Instances transferred to `MulOpposite M`, like `MulOpposite.Monoid`. See `Mathlib.Algebra.Opposites` for more examples. diff --git a/Mathlib/Algebra/Homology/ComplexShape.lean b/Mathlib/Algebra/Homology/ComplexShape.lean index af12d94e53a03..dab8c049e86ec 100644 --- a/Mathlib/Algebra/Homology/ComplexShape.lean +++ b/Mathlib/Algebra/Homology/ComplexShape.lean @@ -41,10 +41,10 @@ so `d : X i ⟶ X j` is nonzero only when `i = j + 1`. `HomologicalComplex` with one of these shapes baked in.) -/ -open Classical - noncomputable section +open Classical + /-- A `c : ComplexShape ι` describes the shape of a chain complex, with chain groups indexed by `ι`. Typically `ι` will be `ℕ`, `ℤ`, or `Fin n`. @@ -212,3 +212,25 @@ theorem down_mk {α : Type*} [AddRightCancelSemigroup α] [One α] (i j : α) (h #align complex_shape.down_mk ComplexShape.down_mk end ComplexShape + +end + +namespace ComplexShape + +variable (α : Type*) [AddRightCancelSemigroup α] [DecidableEq α] + +instance (a : α) : DecidableRel (ComplexShape.up' a).Rel := + fun _ _ => by dsimp; infer_instance + +instance (a : α) : DecidableRel (ComplexShape.down' a).Rel := + fun _ _ => by dsimp; infer_instance + +variable [One α] + +instance : DecidableRel (ComplexShape.up α).Rel := by + dsimp [ComplexShape.up]; infer_instance + +instance : DecidableRel (ComplexShape.down α).Rel := by + dsimp [ComplexShape.down]; infer_instance + +end ComplexShape diff --git a/Mathlib/Algebra/Homology/ExactSequence.lean b/Mathlib/Algebra/Homology/ExactSequence.lean index e650d84e71005..3f6ce07fb5b62 100644 --- a/Mathlib/Algebra/Homology/ExactSequence.lean +++ b/Mathlib/Algebra/Homology/ExactSequence.lean @@ -44,7 +44,7 @@ variable {n : ℕ} (S : ComposableArrows C n) two consecutive arrows are zero. -/ structure IsComplex : Prop where /-- the composition of two consecutive arrows is zero -/ - zero (i : ℕ) (hi : i + 2 ≤ n := by linarith) : + zero (i : ℕ) (hi : i + 2 ≤ n := by omega) : S.map' i (i + 1) ≫ S.map' (i + 1) (i + 2) = 0 attribute [reassoc] IsComplex.zero @@ -52,8 +52,8 @@ attribute [reassoc] IsComplex.zero variable {S} @[reassoc] -lemma IsComplex.zero' (hS : S.IsComplex) (i j k : ℕ) (hij : i + 1 = j := by linarith) - (hjk : j + 1 = k := by linarith) (hk : k ≤ n := by linarith) : +lemma IsComplex.zero' (hS : S.IsComplex) (i j k : ℕ) (hij : i + 1 = j := by omega) + (hjk : j + 1 = k := by omega) (hk : k ≤ n := by omega) : S.map' i j ≫ S.map' j k = 0 := by subst hij hjk exact hS.zero i hk @@ -75,33 +75,33 @@ lemma isComplex₀ (S : ComposableArrows C 0) : S.IsComplex where zero i hi := by simp (config := {decide := true}) at hi lemma isComplex₁ (S : ComposableArrows C 1) : S.IsComplex where - zero i hi := by exfalso; linarith + zero i hi := by exfalso; omega variable (S) /-- The short complex consisting of maps `S.map' i j` and `S.map' j k` when we know that `S : ComposableArrows C n` satisfies `S.IsComplex`. -/ @[reducible] -def sc' (hS : S.IsComplex) (i j k : ℕ) (hij : i + 1 = j := by linarith) - (hjk : j + 1 = k := by linarith) (hk : k ≤ n := by linarith) : +def sc' (hS : S.IsComplex) (i j k : ℕ) (hij : i + 1 = j := by omega) + (hjk : j + 1 = k := by omega) (hk : k ≤ n := by omega) : ShortComplex C := ShortComplex.mk (S.map' i j) (S.map' j k) (hS.zero' i j k) /-- The short complex consisting of maps `S.map' i (i + 1)` and `S.map' (i + 1) (i + 2)` when we know that `S : ComposableArrows C n` satisfies `S.IsComplex`. -/ -abbrev sc (hS : S.IsComplex) (i : ℕ) (hi : i + 2 ≤ n := by linarith) : +abbrev sc (hS : S.IsComplex) (i : ℕ) (hi : i + 2 ≤ n := by omega) : ShortComplex C := S.sc' hS i (i + 1) (i + 2) /-- `F : ComposableArrows C n` is exact if it is a complex and that all short complexes consisting of two consecutive arrows are exact. -/ structure Exact extends S.IsComplex : Prop where - exact (i : ℕ) (hi : i + 2 ≤ n := by linarith) : (S.sc toIsComplex i).Exact + exact (i : ℕ) (hi : i + 2 ≤ n := by omega) : (S.sc toIsComplex i).Exact variable {S} -lemma Exact.exact' (hS : S.Exact) (i j k : ℕ) (hij : i + 1 = j := by linarith) - (hjk : j + 1 = k := by linarith) (hk : k ≤ n := by linarith) : +lemma Exact.exact' (hS : S.Exact) (i j k : ℕ) (hij : i + 1 = j := by omega) + (hjk : j + 1 = k := by omega) (hk : k ≤ n := by omega) : (S.sc' hS.toIsComplex i j k).Exact := by subst hij hjk exact hS.exact i hk @@ -109,8 +109,8 @@ lemma Exact.exact' (hS : S.Exact) (i j k : ℕ) (hij : i + 1 = j := by linarith) /-- Functoriality maps for `ComposableArrows.sc'`. -/ @[simps] def sc'Map {S₁ S₂ : ComposableArrows C n} (φ : S₁ ⟶ S₂) (h₁ : S₁.IsComplex) (h₂ : S₂.IsComplex) - (i j k : ℕ) (hij : i + 1 = j := by linarith) - (hjk : j + 1 = k := by linarith) (hk : k ≤ n := by linarith) : + (i j k : ℕ) (hij : i + 1 = j := by omega) + (hjk : j + 1 = k := by omega) (hk : k ≤ n := by omega) : S₁.sc' h₁ i j k ⟶ S₂.sc' h₂ i j k where τ₁ := φ.app _ τ₂ := φ.app _ @@ -119,7 +119,7 @@ def sc'Map {S₁ S₂ : ComposableArrows C n} (φ : S₁ ⟶ S₂) (h₁ : S₁. /-- Functoriality maps for `ComposableArrows.sc`. -/ @[simps!] def scMap {S₁ S₂ : ComposableArrows C n} (φ : S₁ ⟶ S₂) (h₁ : S₁.IsComplex) (h₂ : S₂.IsComplex) - (i : ℕ) (hi : i + 2 ≤ n := by linarith) : + (i : ℕ) (hi : i + 2 ≤ n := by omega) : S₁.sc h₁ i ⟶ S₂.sc h₂ i := sc'Map φ h₁ h₂ i (i + 1) (i + 2) @@ -127,8 +127,8 @@ def scMap {S₁ S₂ : ComposableArrows C n} (φ : S₁ ⟶ S₂) (h₁ : S₁.I in `ComposableArrows C n`. -/ @[simps] def sc'MapIso {S₁ S₂ : ComposableArrows C n} (e : S₁ ≅ S₂) - (h₁ : S₁.IsComplex) (h₂ : S₂.IsComplex) (i j k : ℕ) (hij : i + 1 = j := by linarith) - (hjk : j + 1 = k := by linarith) (hk : k ≤ n := by linarith) : + (h₁ : S₁.IsComplex) (h₂ : S₂.IsComplex) (i j k : ℕ) (hij : i + 1 = j := by omega) + (hjk : j + 1 = k := by omega) (hk : k ≤ n := by omega) : S₁.sc' h₁ i j k ≅ S₂.sc' h₂ i j k where hom := sc'Map e.hom h₁ h₂ i j k inv := sc'Map e.inv h₂ h₁ i j k @@ -140,7 +140,7 @@ in `ComposableArrows C n`. -/ @[simps] def scMapIso {S₁ S₂ : ComposableArrows C n} (e : S₁ ≅ S₂) (h₁ : S₁.IsComplex) (h₂ : S₂.IsComplex) - (i : ℕ) (hi : i + 2 ≤ n := by linarith) : + (i : ℕ) (hi : i + 2 ≤ n := by omega) : S₁.sc h₁ i ≅ S₂.sc h₂ i where hom := scMap e.hom h₁ h₂ i inv := scMap e.inv h₂ h₁ i @@ -164,16 +164,16 @@ lemma exact₀ (S : ComposableArrows C 0) : S.Exact where lemma exact₁ (S : ComposableArrows C 1) : S.Exact where toIsComplex := S.isComplex₁ - exact i hi := by exfalso; linarith + exact i hi := by exfalso; omega lemma isComplex₂_iff (S : ComposableArrows C 2) : S.IsComplex ↔ S.map' 0 1 ≫ S.map' 1 2 = 0 := by constructor · intro h - exact h.zero 0 (by linarith) + exact h.zero 0 (by omega) · intro h refine' IsComplex.mk (fun i hi => _) - obtain rfl : i = 0 := by linarith + obtain rfl : i = 0 := by omega exact h lemma isComplex₂_mk (S : ComposableArrows C 2) (w : S.map' 0 1 ≫ S.map' 1 2 = 0) : @@ -188,10 +188,10 @@ lemma exact₂_iff (S : ComposableArrows C 2) (hS : S.IsComplex) : S.Exact ↔ (S.sc' hS 0 1 2).Exact := by constructor · intro h - exact h.exact 0 (by linarith) + exact h.exact 0 (by omega) · intro h refine' Exact.mk hS (fun i hi => _) - obtain rfl : i = 0 := by linarith + obtain rfl : i = 0 := by omega exact h lemma exact₂_mk (S : ComposableArrows C 2) (w : S.map' 0 1 ≫ S.map' 1 2 = 0) @@ -216,7 +216,7 @@ lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) : · rw [exact₂_iff]; swap · rw [isComplex₂_iff] exact h.toIsComplex.zero 0 - exact h.exact 0 (by linarith) + exact h.exact 0 (by omega) · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1))) (fun i hi => h.exact (i + 1)) · rintro ⟨h, h₀⟩ @@ -247,13 +247,13 @@ lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) : · rw [exact₂_iff]; swap · rw [isComplex₂_iff] exact h.toIsComplex.zero n - exact h.exact n (by linarith) + exact h.exact n (by omega) · rintro ⟨h, h'⟩ refine' Exact.mk (IsComplex.mk (fun i hi => _)) (fun i hi => _) - · obtain hi | rfl := LE.le.lt_or_eq (show i ≤ n by linarith) + · obtain hi | rfl := LE.le.lt_or_eq (show i ≤ n by omega) · exact h.toIsComplex.zero i · exact h'.toIsComplex.zero 0 - · obtain hi | rfl := LE.le.lt_or_eq (show i ≤ n by linarith) + · obtain hi | rfl := LE.le.lt_or_eq (show i ≤ n by omega) · exact h.exact i · exact h'.exact 0 diff --git a/Mathlib/Algebra/Homology/HomologicalComplex.lean b/Mathlib/Algebra/Homology/HomologicalComplex.lean index 6ca2a073cd072..f279c38826528 100644 --- a/Mathlib/Algebra/Homology/HomologicalComplex.lean +++ b/Mathlib/Algebra/Homology/HomologicalComplex.lean @@ -6,6 +6,7 @@ Authors: Johan Commelin, Scott Morrison import Mathlib.Algebra.Homology.ComplexShape import Mathlib.CategoryTheory.Subobject.Limits import Mathlib.CategoryTheory.GradedObject +import Mathlib.Algebra.Homology.ShortComplex.Basic #align_import algebra.homology.homological_complex from "leanprover-community/mathlib"@"88bca0ce5d22ebfd9e73e682e51d60ea13b48347" @@ -732,37 +733,16 @@ end OfHom section Mk --- porting note: removed @[nolint has_nonempty_instance] -/-- Auxiliary structure for setting up the recursion in `mk`. -This is purely an implementation detail: for some reason just using the dependent 6-tuple directly -results in `mk_aux` taking much longer (well over the `-T100000` limit) to elaborate. --/ -structure MkStruct where - (X₀ X₁ X₂ : V) - d₀ : X₁ ⟶ X₀ - d₁ : X₂ ⟶ X₁ - s : d₁ ≫ d₀ = 0 -#align chain_complex.mk_struct ChainComplex.MkStruct - variable {V} -/-- Flatten to a tuple. -/ -def MkStruct.flat (t : MkStruct V) : - Σ' (X₀ X₁ X₂ : V) (d₀ : X₁ ⟶ X₀) (d₁ : X₂ ⟶ X₁), d₁ ≫ d₀ = 0 := - ⟨t.X₀, t.X₁, t.X₂, t.d₀, t.d₁, t.s⟩ -#align chain_complex.mk_struct.flat ChainComplex.MkStruct.flat variable (X₀ X₁ X₂ : V) (d₀ : X₁ ⟶ X₀) (d₁ : X₂ ⟶ X₁) (s : d₁ ≫ d₀ = 0) - (succ : - ∀ t : Σ' (X₀ X₁ X₂ : V) (d₀ : X₁ ⟶ X₀) (d₁ : X₂ ⟶ X₁), d₁ ≫ d₀ = 0, - Σ' (X₃ : V) (d₂ : X₃ ⟶ t.2.2.1), d₂ ≫ t.2.2.2.2.1 = 0) + (succ : ∀ (S : ShortComplex V), Σ' (X₃ : V) (d₂ : X₃ ⟶ S.X₁), d₂ ≫ S.f = 0) /-- Auxiliary definition for `mk`. -/ -def mkAux : ∀ _ : ℕ, MkStruct V - | 0 => ⟨X₀, X₁, X₂, d₀, d₁, s⟩ - | n + 1 => - let p := mkAux n - ⟨p.X₁, p.X₂, (succ p.flat).1, p.d₁, (succ p.flat).2.1, (succ p.flat).2.2⟩ +def mkAux : ℕ → ShortComplex V + | 0 => ShortComplex.mk _ _ s + | n + 1 => ShortComplex.mk _ _ (succ (mkAux n)).2.2 #align chain_complex.mk_aux ChainComplex.mkAux /-- An inductive constructor for `ℕ`-indexed chain complexes. @@ -774,8 +754,8 @@ and returns the next object, its differential, and the fact it composes appropri See also `mk'`, which only sees the previous differential in the inductive step. -/ def mk : ChainComplex V ℕ := - of (fun n => (mkAux X₀ X₁ X₂ d₀ d₁ s succ n).X₀) (fun n => (mkAux X₀ X₁ X₂ d₀ d₁ s succ n).d₀) - fun n => (mkAux X₀ X₁ X₂ d₀ d₁ s succ n).s + of (fun n => (mkAux X₀ X₁ X₂ d₀ d₁ s succ n).X₃) (fun n => (mkAux X₀ X₁ X₂ d₀ d₁ s succ n).g) + fun n => (mkAux X₀ X₁ X₂ d₀ d₁ s succ n).zero #align chain_complex.mk ChainComplex.mk @[simp] @@ -816,13 +796,12 @@ then a function which takes a differential, and returns the next object, its differential, and the fact it composes appropriately to zero. -/ def mk' (X₀ X₁ : V) (d : X₁ ⟶ X₀) - (succ' : ∀ t : ΣX₀ X₁ : V, X₁ ⟶ X₀, Σ' (X₂ : V) (d : X₂ ⟶ t.2.1), d ≫ t.2.2 = 0) : + (succ' : ∀ {X₀ X₁ : V} (f : X₁ ⟶ X₀), Σ' (X₂ : V) (d : X₂ ⟶ X₁), d ≫ f = 0) : ChainComplex V ℕ := - mk X₀ X₁ (succ' ⟨X₀, X₁, d⟩).1 d (succ' ⟨X₀, X₁, d⟩).2.1 (succ' ⟨X₀, X₁, d⟩).2.2 fun t => - succ' ⟨t.2.1, t.2.2.1, t.2.2.2.2.1⟩ + mk _ _ _ _ _ (succ' d).2.2 (fun S => succ' S.f) #align chain_complex.mk' ChainComplex.mk' -variable (succ' : ∀ t : ΣX₀ X₁ : V, X₁ ⟶ X₀, Σ' (X₂ : V) (d : X₂ ⟶ t.2.1), d ≫ t.2.2 = 0) +variable (succ' : ∀ {X₀ X₁ : V} (f : X₁ ⟶ X₀), Σ' (X₂ : V) (d : X₂ ⟶ X₁), d ≫ f = 0) @[simp] theorem mk'_X_0 : (mk' X₀ X₁ d₀ succ').X 0 = X₀ := @@ -1030,7 +1009,7 @@ variable (X₀ X₁ X₂ : V) (d₀ : X₀ ⟶ X₁) (d₁ : X₁ ⟶ X₂) (s : Σ' (X₃ : V) (d₂ : t.2.2.1 ⟶ X₃), t.2.2.2.2.1 ≫ d₂ = 0) /-- Auxiliary definition for `mk`. -/ -def mkAux : ∀ _ : ℕ, MkStruct V +def mkAux : ℕ → MkStruct V | 0 => ⟨X₀, X₁, X₂, d₀, d₁, s⟩ | n + 1 => let p := mkAux n diff --git a/Mathlib/Algebra/Homology/HomotopyCategory.lean b/Mathlib/Algebra/Homology/HomotopyCategory.lean index 8baf39506dd33..65409ca66e334 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory.lean @@ -77,10 +77,13 @@ instance : (quotient V c).Additive where open ZeroObject --- TODO upgrade this to `HasZeroObject`, presumably for any `quotient`. instance [HasZeroObject V] : Inhabited (HomotopyCategory V c) := ⟨(quotient V c).obj 0⟩ +instance [HasZeroObject V] : HasZeroObject (HomotopyCategory V c) := + ⟨(quotient V c).obj 0, by + rw [IsZero.iff_id_eq_zero, ← (quotient V c).map_id, id_zero, Functor.map_zero]⟩ + variable {V c} -- porting note: removed @[simp] attribute because it hinders the automatic application of the @@ -151,6 +154,15 @@ def homotopyEquivOfIso {C D : HomologicalComplex V c} (by rw [quotient_map_out_comp_out, i.inv_hom_id, (quotient V c).map_id]) #align homotopy_category.homotopy_equiv_of_iso HomotopyCategory.homotopyEquivOfIso +lemma isZero_quotient_obj_iff (C : HomologicalComplex V c) : + IsZero ((quotient _ _).obj C) ↔ Nonempty (Homotopy (𝟙 C) 0) := by + rw [IsZero.iff_id_eq_zero] + constructor + · intro h + exact ⟨(homotopyOfEq _ _ (by simp [h]))⟩ + · rintro ⟨h⟩ + simpa using (eq_of_homotopy _ _ h) + variable (V c) section diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean index 9a7416646a0f6..788721c3cc570 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean @@ -5,7 +5,7 @@ Authors: Joël Riou -/ import Mathlib.Algebra.Homology.Homotopy import Mathlib.Algebra.GroupPower.NegOnePow -import Mathlib.Algebra.Category.GroupCat.Limits +import Mathlib.Algebra.Category.GroupCat.Preadditive import Mathlib.Tactic.Linarith import Mathlib.CategoryTheory.Linear.LinearFunctor @@ -329,6 +329,11 @@ protected lemma smul_comp {n₁ n₂ n₁₂ : ℤ} (k : R) (z₁ : Cochain F G ext p q hpq simp only [comp_v _ _ h p _ q rfl (by linarith), smul_v, Linear.smul_comp] +@[simp] +lemma units_smul_comp {n₁ n₂ n₁₂ : ℤ} (k : Rˣ) (z₁ : Cochain F G n₁) (z₂ : Cochain G K n₂) + (h : n₁ + n₂ = n₁₂) : (k • z₁).comp z₂ h = k • (z₁.comp z₂ h) := by + apply Cochain.smul_comp + @[simp] protected lemma id_comp {n : ℤ} (z₂ : Cochain F G n) : (Cochain.ofHom (𝟙 F)).comp z₂ (zero_add n) = z₂ := by @@ -365,6 +370,11 @@ protected lemma comp_smul {n₁ n₂ n₁₂ : ℤ} (z₁ : Cochain F G n₁) (k ext p q hpq simp only [comp_v _ _ h p _ q rfl (by linarith), smul_v, Linear.comp_smul] +@[simp] +lemma comp_units_smul {n₁ n₂ n₁₂ : ℤ} (z₁ : Cochain F G n₁) (k : Rˣ) (z₂ : Cochain G K n₂) + (h : n₁ + n₂ = n₁₂ ) : z₁.comp (k • z₂) h = k • (z₁.comp z₂ h) := by + apply Cochain.comp_smul + @[simp] protected lemma comp_id {n : ℤ} (z₁ : Cochain F G n) : z₁.comp (Cochain.ofHom (𝟙 G)) (add_zero n) = z₁ := by @@ -457,6 +467,9 @@ variable {F G R} @[simp] lemma δ_smul (k : R) (z : Cochain F G n) : δ n m (k • z) = k • δ n m z := (δ_hom R F G n m).map_smul k z +@[simp] lemma δ_units_smul (k : Rˣ) (z : Cochain F G n) : δ n m (k • z) = k • δ n m z := + δ_smul .. + lemma δ_δ (n₀ n₁ n₂ : ℤ) (z : Cochain F G n₀) : δ n₁ n₂ (δ n₀ n₁ z) = 0 := by by_cases h₁₂ : n₁ + 1 = n₂; swap; rw [δ_shape _ _ h₁₂] by_cases h₀₁ : n₀ + 1 = n₁; swap; rw [δ_shape _ _ h₀₁, δ_zero] @@ -543,6 +556,7 @@ lemma δ_neg_one_cochain (z : Cochain F G (-1)) : rw [Homotopy.nullHomotopicMap'_f (show (ComplexShape.up ℤ).Rel (p-1) p by simp) (show (ComplexShape.up ℤ).Rel p (p+1) by simp)] abel + end HomComplex variable (F G) @@ -615,6 +629,10 @@ lemma coe_neg (z : Cocycle F G n) : lemma coe_smul (z : Cocycle F G n) (x : R) : (↑(x • z) : Cochain F G n) = x • (z : Cochain F G n) := rfl +@[simp] +lemma coe_units_smul (z : Cocycle F G n) (x : Rˣ) : + (↑(x • z) : Cochain F G n) = x • (z : Cochain F G n) := rfl + @[simp] lemma coe_sub (z₁ z₂ : Cocycle F G n) : (↑(z₁ - z₂) : Cochain F G n) = (z₁ : Cochain F G n) - (z₂ : Cochain F G n) := rfl @@ -690,10 +708,39 @@ def diff : Cocycle K K 1 := end Cocycle -namespace Cochain - variable {F G} +@[simp] +lemma δ_comp_zero_cocycle {n : ℤ} (z₁ : Cochain F G n) (z₂ : Cocycle G K 0) (m : ℤ) : + δ n m (z₁.comp z₂.1 (add_zero n)) = + (δ n m z₁).comp z₂.1 (add_zero m) := by + by_cases hnm : n + 1 = m + · simp [δ_comp_zero_cochain _ _ _ hnm] + · simp [δ_shape _ _ hnm] + +@[simp] +lemma δ_comp_ofHom {n : ℤ} (z₁ : Cochain F G n) (f : G ⟶ K) (m : ℤ) : + δ n m (z₁.comp (Cochain.ofHom f) (add_zero n)) = + (δ n m z₁).comp (Cochain.ofHom f) (add_zero m) := by + rw [← Cocycle.ofHom_coe, δ_comp_zero_cocycle] + + +@[simp] +lemma δ_zero_cocycle_comp {n : ℤ} (z₁ : Cocycle F G 0) (z₂ : Cochain G K n) (m : ℤ) : + δ n m (z₁.1.comp z₂ (zero_add n)) = + z₁.1.comp (δ n m z₂) (zero_add m) := by + by_cases hnm : n + 1 = m + · simp [δ_zero_cochain_comp _ _ _ hnm] + · simp [δ_shape _ _ hnm] + +@[simp] +lemma δ_ofHom_comp {n : ℤ} (f : F ⟶ G) (z : Cochain G K n) (m : ℤ) : + δ n m ((Cochain.ofHom f).comp z (zero_add n)) = + (Cochain.ofHom f).comp (δ n m z) (zero_add m) := by + rw [← Cocycle.ofHom_coe, δ_zero_cocycle_comp] + +namespace Cochain + /-- Given two morphisms of complexes `φ₁ φ₂ : F ⟶ G`, the datum of an homotopy between `φ₁` and `φ₂` is equivalent to the datum of a `1`-cochain `z` such that `δ (-1) 0 z` is the difference of the zero cochains associated to `φ₂` and `φ₁`. -/ diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplexShift.lean b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplexShift.lean index d0103b2dbd1c4..9828d433230c6 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplexShift.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplexShift.lean @@ -400,7 +400,7 @@ lemma δ_rightShift (a n' m' : ℤ) (hn' : n' + a = n) (m : ℤ) (hm' : m' + a = add_comp, HomologicalComplex.d_comp_XIsoOfEq_inv, Linear.units_smul_comp, smul_add, add_right_inj, smul_smul] congr 1 - rw [← hm', add_comm m', Int.negOnePow_add, ← mul_assoc, + simp only [← hm', add_comm m', Int.negOnePow_add, ← mul_assoc, Int.units_mul_self, one_mul] · have hnm' : ¬ n' + 1 = m' := fun _ => hnm (by linarith) rw [δ_shape _ _ hnm', δ_shape _ _ hnm, rightShift_zero, smul_zero] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean new file mode 100644 index 0000000000000..04df842fc2ef3 --- /dev/null +++ b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean @@ -0,0 +1,537 @@ +/- +Copyright (c) 2023 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.Algebra.Homology.HomotopyCategory.HomComplex +import Mathlib.Algebra.Homology.HomotopyCofiber + +/-! # The mapping cone of a morphism of cochain complexes + +In this file, we study the homotopy cofiber `HomologicalComplex.homotopyCofiber` +of a morphism `φ : F ⟶ G` of cochain complexes indexed by `ℤ`. In this case, +we redefine it as `CochainComplex.mappingCone φ`. The API involves definitions +- `mappingCone.inl φ : Cochain F (mappingCone φ) (-1)`, +- `mappingCone.inr φ : G ⟶ mappingCone φ`, +- `mappingCone.fst φ : Cocycle (mappingCone φ) F 1` and +- `mappingCone.snd φ : Cochain (mappingCone φ) G 0`. + +-/ + +open CategoryTheory Limits + +variable {C : Type*} [Category C] [Preadditive C] + +namespace CochainComplex + +open HomologicalComplex + +section + +variable {ι : Type*} [AddRightCancelSemigroup ι] [One ι] + {F G : CochainComplex C ι} (φ : F ⟶ G) + +instance [∀ p, HasBinaryBiproduct (F.X (p + 1)) (G.X p)] : + HasHomotopyCofiber φ where + hasBinaryBiproduct := by + rintro i _ rfl + infer_instance + +end + +variable {F G : CochainComplex C ℤ} (φ : F ⟶ G) + +variable [HasHomotopyCofiber φ] + +/-- The mapping cone of a morphism of cochain complexes indexed by `ℤ`. -/ +noncomputable def mappingCone := homotopyCofiber φ + +namespace mappingCone + +open HomComplex + +/-- The left inclusion in the mapping cone, as a cochain of degree `-1`. -/ +noncomputable def inl : Cochain F (mappingCone φ) (-1) := + Cochain.mk (fun p q hpq => homotopyCofiber.inlX φ p q (by dsimp; linarith)) + +/-- The right inclusion in the mapping cone. -/ +noncomputable def inr : G ⟶ mappingCone φ := homotopyCofiber.inr φ + +/-- The first projection from the mapping cone, as a cocyle of degree `1`. -/ +noncomputable def fst : Cocycle (mappingCone φ) F 1 := + Cocycle.mk (Cochain.mk (fun p q hpq => homotopyCofiber.fstX φ p q hpq)) 2 (by linarith) (by + ext p _ rfl + simp [δ_v 1 2 (by linarith) _ p (p + 2) (by linarith) (p + 1) (p + 1) (by linarith) rfl, + homotopyCofiber.d_fstX φ p (p + 1) (p + 2) rfl, mappingCone, + show Int.negOnePow 2 = 1 by rfl]) + +/-- The second projection from the mapping cone, as a cochain of degree `0`. -/ +noncomputable def snd : Cochain (mappingCone φ) G 0 := + Cochain.ofHoms (homotopyCofiber.sndX φ) + +@[reassoc (attr := simp)] +lemma inl_v_fst_v (p q : ℤ) (hpq : q + 1 = p) : + (inl φ).v p q (by rw [← hpq, add_neg_cancel_right]) ≫ + (fst φ : Cochain (mappingCone φ) F 1).v q p hpq = 𝟙 _ := by + simp [inl, fst] + +@[reassoc (attr := simp)] +lemma inl_v_snd_v (p q : ℤ) (hpq : p + (-1) = q) : + (inl φ).v p q hpq ≫ (snd φ).v q q (add_zero q) = 0 := by + simp [inl, snd] + +@[reassoc (attr := simp)] +lemma inr_f_fst_v (p q : ℤ) (hpq : p + 1 = q) : + (inr φ).f p ≫ (fst φ).1.v p q hpq = 0 := by + simp [inr, fst] + +@[reassoc (attr := simp)] +lemma inr_f_snd_v (p : ℤ) : + (inr φ).f p ≫ (snd φ).v p p (add_zero p) = 𝟙 _ := by + simp [inr, snd] + +@[simp] +lemma inl_fst : + (inl φ).comp (fst φ).1 (neg_add_self 1) = Cochain.ofHom (𝟙 F) := by + ext p + simp [Cochain.comp_v _ _ (neg_add_self 1) p (p-1) p rfl (by linarith)] + +@[simp] +lemma inl_snd : + (inl φ).comp (snd φ) (add_zero (-1)) = 0 := by + ext p q hpq + simp [Cochain.comp_v _ _ (add_zero (-1)) p q q (by linarith) (by linarith)] + +@[simp] +lemma inr_fst : + (Cochain.ofHom (inr φ)).comp (fst φ).1 (zero_add 1) = 0 := by + ext p q hpq + simp [Cochain.comp_v _ _ (zero_add 1) p p q (by linarith) (by linarith)] + +@[simp] +lemma inr_snd : + (Cochain.ofHom (inr φ)).comp (snd φ) (zero_add 0) = Cochain.ofHom (𝟙 G) := by aesop_cat + +/-! In order to obtain identities of cochains involving `inl`, `inr`, `fst` and `snd`, +it is often convenient to use an `ext` lemma, and use simp lemmas like `inl_v_f_fst_v`, +but it is sometimes possible to get identities of cochains by using rewrites of +identities of cochains like `inl_fst`. Then, similarly as in category theory, +if we associate the compositions of cochains to the right as much as possible, +it is also interesting to have `reassoc` variants of lemmas, like `inl_fst_assoc`. -/ + +@[simp] +lemma inl_fst_assoc {K : CochainComplex C ℤ} {d e : ℤ} (γ : Cochain F K d) (he : 1 + d = e) : + (inl φ).comp ((fst φ).1.comp γ he) (by rw [← he, neg_add_cancel_left]) = γ := by + rw [← Cochain.comp_assoc _ _ _ (neg_add_self 1) (by linarith) (by linarith), inl_fst, + Cochain.id_comp] + +@[simp] +lemma inl_snd_assoc {K : CochainComplex C ℤ} {d e f : ℤ} (γ : Cochain G K d) + (he : 0 + d = e) (hf : -1 + e = f) : + (inl φ).comp ((snd φ).comp γ he) hf = 0 := by + obtain rfl : e = d := by linarith + rw [← Cochain.comp_assoc_of_second_is_zero_cochain, inl_snd, Cochain.zero_comp] + +@[simp] +lemma inr_fst_assoc {K : CochainComplex C ℤ} {d e f : ℤ} (γ : Cochain F K d) + (he : 1 + d = e) (hf : 0 + e = f) : + (Cochain.ofHom (inr φ)).comp ((fst φ).1.comp γ he) hf = 0 := by + obtain rfl : e = f := by linarith + rw [← Cochain.comp_assoc_of_first_is_zero_cochain, inr_fst, Cochain.zero_comp] + +@[simp] +lemma inr_snd_assoc {K : CochainComplex C ℤ} {d e : ℤ} (γ : Cochain G K d) (he : 0 + d = e) : + (Cochain.ofHom (inr φ)).comp ((snd φ).comp γ he) (by simp only [← he, zero_add]) = γ := by + obtain rfl : d = e := by linarith + rw [← Cochain.comp_assoc_of_first_is_zero_cochain, inr_snd, Cochain.id_comp] + +lemma ext_to (i j : ℤ) (hij : i + 1 = j) {A : C} {f g : A ⟶ (mappingCone φ).X i} + (h₁ : f ≫ (fst φ).1.v i j hij = g ≫ (fst φ).1.v i j hij) + (h₂ : f ≫ (snd φ).v i i (add_zero i) = g ≫ (snd φ).v i i (add_zero i)) : + f = g := + homotopyCofiber.ext_to_X φ i j hij h₁ (by simpa [snd] using h₂) + +lemma ext_to_iff (i j : ℤ) (hij : i + 1 = j) {A : C} (f g : A ⟶ (mappingCone φ).X i) : + f = g ↔ f ≫ (fst φ).1.v i j hij = g ≫ (fst φ).1.v i j hij ∧ + f ≫ (snd φ).v i i (add_zero i) = g ≫ (snd φ).v i i (add_zero i) := by + constructor + · rintro rfl + tauto + · rintro ⟨h₁, h₂⟩ + exact ext_to φ i j hij h₁ h₂ + +lemma ext_from (i j : ℤ) (hij : j + 1 = i) {A : C} {f g : (mappingCone φ).X j ⟶ A} + (h₁ : (inl φ).v i j (by linarith) ≫ f = (inl φ).v i j (by linarith) ≫ g) + (h₂ : (inr φ).f j ≫ f = (inr φ).f j ≫ g) : + f = g := + homotopyCofiber.ext_from_X φ i j hij h₁ h₂ + +lemma ext_from_iff (i j : ℤ) (hij : j + 1 = i) {A : C} (f g : (mappingCone φ).X j ⟶ A) : + f = g ↔ (inl φ).v i j (by linarith) ≫ f = (inl φ).v i j (by linarith) ≫ g ∧ + (inr φ).f j ≫ f = (inr φ).f j ≫ g := by + constructor + · rintro rfl + tauto + · rintro ⟨h₁, h₂⟩ + exact ext_from φ i j hij h₁ h₂ + +lemma ext_cochain_to_iff (i j : ℤ) (hij : i + 1 = j) + {K : CochainComplex C ℤ} {γ₁ γ₂ : Cochain K (mappingCone φ) i} : + γ₁ = γ₂ ↔ γ₁.comp (fst φ).1 hij = γ₂.comp (fst φ).1 hij ∧ + γ₁.comp (snd φ) (add_zero i) = γ₂.comp (snd φ) (add_zero i) := by + constructor + · rintro rfl + tauto + · rintro ⟨h₁, h₂⟩ + ext p q hpq + rw [ext_to_iff φ q (q + 1) rfl] + replace h₁ := Cochain.congr_v h₁ p (q + 1) (by linarith) + replace h₂ := Cochain.congr_v h₂ p q hpq + simp only [Cochain.comp_v _ _ _ p q (q + 1) hpq rfl] at h₁ + simp only [Cochain.comp_zero_cochain_v] at h₂ + exact ⟨h₁, h₂⟩ + +lemma ext_cochain_from_iff (i j : ℤ) (hij : i + 1 = j) + {K : CochainComplex C ℤ} {γ₁ γ₂ : Cochain (mappingCone φ) K j} : + γ₁ = γ₂ ↔ + (inl φ).comp γ₁ (show _ = i by linarith) = (inl φ).comp γ₂ (by linarith) ∧ + (Cochain.ofHom (inr φ)).comp γ₁ (zero_add j) = + (Cochain.ofHom (inr φ)).comp γ₂ (zero_add j) := by + constructor + · rintro rfl + tauto + · rintro ⟨h₁, h₂⟩ + ext p q hpq + rw [ext_from_iff φ (p + 1) p rfl] + replace h₁ := Cochain.congr_v h₁ (p + 1) q (by linarith) + replace h₂ := Cochain.congr_v h₂ p q (by linarith) + simp only [Cochain.comp_v (inl φ) _ _ (p + 1) p q (by linarith) hpq] at h₁ + simp only [Cochain.zero_cochain_comp_v, Cochain.ofHom_v] at h₂ + refine' ⟨h₁, h₂⟩ + +lemma id : + (fst φ).1.comp (inl φ) (add_neg_self 1) + + (snd φ).comp (Cochain.ofHom (inr φ)) (add_zero 0) = Cochain.ofHom (𝟙 _) := by + simp [ext_cochain_from_iff φ (-1) 0 (neg_add_self 1)] + +lemma id_X (p q : ℤ) (hpq : p + 1 = q) : + (fst φ).1.v p q hpq ≫ (inl φ).v q p (by linarith) + + (snd φ).v p p (add_zero p) ≫ (inr φ).f p = 𝟙 ((mappingCone φ).X p) := by + simpa only [Cochain.add_v, Cochain.comp_zero_cochain_v, Cochain.ofHom_v, id_f, + Cochain.comp_v _ _ (add_neg_self 1) p q p hpq (by linarith)] + using Cochain.congr_v (id φ) p p (add_zero p) + +@[reassoc] +lemma inl_v_d (i j k : ℤ) (hij : i + (-1) = j) (hik : k + (-1) = i) : + (inl φ).v i j hij ≫ (mappingCone φ).d j i = + φ.f i ≫ (inr φ).f i - F.d i k ≫ (inl φ).v _ _ hik := by + dsimp [mappingCone, inl, inr] + rw [homotopyCofiber.inlX_d φ j i k (by dsimp; linarith) (by dsimp; linarith)] + abel + +@[reassoc (attr := simp 1100)] +lemma inr_f_d (n₁ n₂ : ℤ) : + (inr φ).f n₁ ≫ (mappingCone φ).d n₁ n₂ = G.d n₁ n₂ ≫ (inr φ).f n₂ := by + apply Hom.comm + +@[reassoc] +lemma d_fst_v (i j k : ℤ) (hij : i + 1 = j) (hjk : j + 1 = k) : + (mappingCone φ).d i j ≫ (fst φ).1.v j k hjk = + -(fst φ).1.v i j hij ≫ F.d j k := by + apply homotopyCofiber.d_fstX + +@[reassoc (attr := simp)] +lemma d_fst_v' (i j : ℤ) (hij : i + 1 = j) : + (mappingCone φ).d (i - 1) i ≫ (fst φ).1.v i j hij = + -(fst φ).1.v (i - 1) i (by linarith) ≫ F.d i j := + d_fst_v φ (i - 1) i j (by linarith) hij + +@[reassoc] +lemma d_snd_v (i j : ℤ) (hij : i + 1 = j) : + (mappingCone φ).d i j ≫ (snd φ).v j j (add_zero _) = + (fst φ).1.v i j hij ≫ φ.f j + (snd φ).v i i (add_zero i) ≫ G.d i j := by + dsimp [mappingCone, snd, fst] + simp only [Cochain.ofHoms_v] + apply homotopyCofiber.d_sndX + +@[reassoc (attr := simp)] +lemma d_snd_v' (n : ℤ) : + (mappingCone φ).d (n - 1) n ≫ (snd φ).v n n (add_zero n) = + (fst φ : Cochain (mappingCone φ) F 1).v (n - 1) n (by linarith) ≫ φ.f n + + (snd φ).v (n - 1) (n - 1) (add_zero _) ≫ G.d (n - 1) n := by + apply d_snd_v + +@[simp] +lemma δ_inl : + δ (-1) 0 (inl φ) = Cochain.ofHom (φ ≫ inr φ) := by + ext p + simp [δ_v (-1) 0 (neg_add_self 1) (inl φ) p p (add_zero p) _ _ rfl rfl, + inl_v_d φ p (p - 1) (p + 1) (by linarith) (by linarith)] + +@[simp] +lemma δ_snd : + δ 0 1 (snd φ) = -(fst φ).1.comp (Cochain.ofHom φ) (add_zero 1) := by + ext p q hpq + simp [d_snd_v φ p q hpq] + +section + +variable {K : CochainComplex C ℤ} {n m : ℤ} (α : Cochain F K m) + (β : Cochain G K n) (h : m + 1 = n) + +/-- Given `φ : F ⟶ G`, this is the cochain in `Cochain (mappingCone φ) K n` that is +constructed from two cochains `α : Cochain F K m` (with `m + 1 = n`) and `β : Cochain F K n`. -/ +noncomputable def descCochain : Cochain (mappingCone φ) K n := + (fst φ).1.comp α (by rw [← h, add_comm]) + (snd φ).comp β (zero_add n) + +@[simp] +lemma inl_descCochain : + (inl φ).comp (descCochain φ α β h) (by linarith) = α := by + simp [descCochain] + +@[simp] +lemma inr_descCochain : + (Cochain.ofHom (inr φ)).comp (descCochain φ α β h) (zero_add n) = β := by + simp [descCochain] + +@[reassoc (attr := simp)] +lemma inl_v_descCochain_v (p₁ p₂ p₃ : ℤ) (h₁₂ : p₁ + (-1) = p₂) (h₂₃ : p₂ + n = p₃) : + (inl φ).v p₁ p₂ h₁₂ ≫ (descCochain φ α β h).v p₂ p₃ h₂₃ = + α.v p₁ p₃ (by rw [← h₂₃, ← h₁₂, ← h, add_comm m, add_assoc, neg_add_cancel_left]) := by + simpa only [Cochain.comp_v _ _ (show -1 + n = m by linarith) p₁ p₂ p₃ + (by linarith) (by linarith)] using + Cochain.congr_v (inl_descCochain φ α β h) p₁ p₃ (by linarith) + +@[reassoc (attr := simp)] +lemma inr_f_descCochain_v (p₁ p₂ : ℤ) (h₁₂ : p₁ + n = p₂) : + (inr φ).f p₁ ≫ (descCochain φ α β h).v p₁ p₂ h₁₂ = β.v p₁ p₂ h₁₂ := by + simpa only [Cochain.comp_v _ _ (zero_add n) p₁ p₁ p₂ (add_zero p₁) h₁₂, Cochain.ofHom_v] + using Cochain.congr_v (inr_descCochain φ α β h) p₁ p₂ (by linarith) + +lemma δ_descCochain (n' : ℤ) (hn' : n + 1 = n') : + δ n n' (descCochain φ α β h) = + (fst φ).1.comp (δ m n α + + n'.negOnePow • (Cochain.ofHom φ).comp β (zero_add n)) (by linarith) + + (snd φ).comp (δ n n' β) (zero_add n') := by + dsimp only [descCochain] + simp only [δ_add, Cochain.comp_add, δ_comp (fst φ).1 α _ 2 n n' hn' (by linarith) (by linarith), + Cocycle.δ_eq_zero, Cochain.zero_comp, smul_zero, add_zero, + δ_comp (snd φ) β (zero_add n) 1 n' n' hn' (zero_add 1) hn', δ_snd, Cochain.neg_comp, + smul_neg, Cochain.comp_assoc_of_second_is_zero_cochain, Cochain.comp_units_smul, ← hn', + Int.negOnePow_succ, Units.neg_smul, Cochain.comp_neg] + abel + +end + +/-- Given `φ : F ⟶ G`, this is the cocycle in `Cocycle (mappingCone φ) K n` that is +constructed from `α : Cochain F K m` (with `m + 1 = n`) and `β : Cocycle F K n`, +when a suitable cocycle relation is satisfied. -/ +@[simps!] +noncomputable def descCocycle {K : CochainComplex C ℤ} {n m : ℤ} + (α : Cochain F K m) (β : Cocycle G K n) + (h : m + 1 = n) (eq : δ m n α = n.negOnePow • (Cochain.ofHom φ).comp β.1 (zero_add n)) : + Cocycle (mappingCone φ) K n := + Cocycle.mk (descCochain φ α β.1 h) (n + 1) rfl + (by simp [δ_descCochain _ _ _ _ _ rfl, eq, Int.negOnePow_succ]) + +section + +variable {K : CochainComplex C ℤ} (α : Cochain F K (-1)) (β : G ⟶ K) + (eq : δ (-1) 0 α = Cochain.ofHom (φ ≫ β)) + +/-- Given `φ : F ⟶ G`, this is the morphism `mappingCone φ ⟶ K` that is constructed +from a cochain `α : Cochain F K (-1)` and a morphism `β : G ⟶ K` such that +`δ (-1) 0 α = Cochain.ofHom (φ ≫ β)`. -/ +noncomputable def desc : mappingCone φ ⟶ K := + Cocycle.homOf (descCocycle φ α (Cocycle.ofHom β) (neg_add_self 1) (by simp [eq])) + +@[simp] +lemma ofHom_desc : + Cochain.ofHom (desc φ α β eq) = descCochain φ α (Cochain.ofHom β) (neg_add_self 1) := by + simp [desc] + +@[reassoc (attr := simp)] +lemma inl_v_desc_f (p q : ℤ) (h : p + (-1) = q) : + (inl φ).v p q h ≫ (desc φ α β eq).f q = α.v p q h := by + simp [desc] + +lemma inl_desc : + (inl φ).comp (Cochain.ofHom (desc φ α β eq)) (add_zero _) = α := by + simp + +@[reassoc (attr := simp)] +lemma inr_f_desc_f (p : ℤ) : + (inr φ).f p ≫ (desc φ α β eq).f p = β.f p := by + simp [desc] + +@[reassoc (attr := simp)] +lemma inr_desc : inr φ ≫ desc φ α β eq = β := by aesop_cat + +lemma desc_f (p q : ℤ) (hpq : p + 1 = q) : + (desc φ α β eq).f p = (fst φ).1.v p q hpq ≫ α.v q p (by linarith) + + (snd φ).v p p (add_zero p) ≫ β.f p := by + simp [ext_from_iff _ _ _ hpq] + +end + +/-- Constructor for homotopies between morphisms from a mapping cone. -/ +noncomputable def descHomotopy {K : CochainComplex C ℤ} (f₁ f₂ : mappingCone φ ⟶ K) + (γ₁ : Cochain F K (-2)) (γ₂ : Cochain G K (-1)) + (h₁ : (inl φ).comp (Cochain.ofHom f₁) (add_zero (-1)) = + δ (-2) (-1) γ₁ + (Cochain.ofHom φ).comp γ₂ (zero_add (-1)) + + (inl φ).comp (Cochain.ofHom f₂) (add_zero (-1))) + (h₂ : Cochain.ofHom (inr φ ≫ f₁) = δ (-1) 0 γ₂ + Cochain.ofHom (inr φ ≫ f₂)) : + Homotopy f₁ f₂ := + (Cochain.equivHomotopy f₁ f₂).symm ⟨descCochain φ γ₁ γ₂ (by linarith), by + simp only [Cochain.ofHom_comp] at h₂ + simp [ext_cochain_from_iff _ _ _ (neg_add_self 1), + δ_descCochain _ _ _ _ _ (neg_add_self 1), h₁, h₂]⟩ + +section + +variable {K : CochainComplex C ℤ} {n m : ℤ} + (α : Cochain K F m) (β : Cochain K G n) (h : n + 1 = m) + +/-- Given `φ : F ⟶ G`, this is the cochain in `Cochain (mappingCone φ) K n` that is +constructed from two cochains `α : Cochain F K m` (with `m + 1 = n`) and `β : Cochain F K n`. -/ +noncomputable def liftCochain : Cochain K (mappingCone φ) n := + α.comp (inl φ) (by linarith) + β.comp (Cochain.ofHom (inr φ)) (add_zero n) + +@[simp] +lemma liftCochain_fst : + (liftCochain φ α β h).comp (fst φ).1 h = α := by + simp [liftCochain] + +@[simp] +lemma liftCochain_snd : + (liftCochain φ α β h).comp (snd φ) (add_zero n) = β := by + simp [liftCochain] + +@[reassoc (attr := simp)] +lemma liftCochain_v_fst_v (p₁ p₂ p₃ : ℤ) (h₁₂ : p₁ + n = p₂) (h₂₃ : p₂ + 1 = p₃) : + (liftCochain φ α β h).v p₁ p₂ h₁₂ ≫ (fst φ).1.v p₂ p₃ h₂₃ = α.v p₁ p₃ (by linarith) := by + simpa only [Cochain.comp_v _ _ h p₁ p₂ p₃ h₁₂ h₂₃] + using Cochain.congr_v (liftCochain_fst φ α β h) p₁ p₃ (by linarith) + + +@[reassoc (attr := simp)] +lemma liftCochain_v_snd_v (p₁ p₂ : ℤ) (h₁₂ : p₁ + n = p₂) : + (liftCochain φ α β h).v p₁ p₂ h₁₂ ≫ (snd φ).v p₂ p₂ (add_zero p₂) = β.v p₁ p₂ h₁₂ := by + simpa only [Cochain.comp_v _ _ (add_zero n) p₁ p₂ p₂ h₁₂ (add_zero p₂)] + using Cochain.congr_v (liftCochain_snd φ α β h) p₁ p₂ (by linarith) + +lemma δ_liftCochain (m' : ℤ) (hm' : m + 1 = m') : + δ n m (liftCochain φ α β h) = -(δ m m' α).comp (inl φ) (by linarith) + + (δ n m β + α.comp (Cochain.ofHom φ) (add_zero m)).comp + (Cochain.ofHom (inr φ)) (add_zero m) := by + dsimp only [liftCochain] + simp only [δ_add, δ_comp α (inl φ) _ m' _ _ h hm' (neg_add_self 1), + δ_comp_zero_cochain _ _ _ h, δ_inl, Cochain.ofHom_comp, + Int.negOnePow_neg, Int.negOnePow_one, Units.neg_smul, one_smul, + δ_ofHom, Cochain.comp_zero, zero_add, Cochain.add_comp, + Cochain.comp_assoc_of_second_is_zero_cochain] + abel + +end + +/-- Given `φ : F ⟶ G`, this is the cocycle in `Cocycle K (mappingCone φ) n` that is +constructed from `α : Cochain K F m` (with `n + 1 = m`) and `β : Cocycle K G n`, +when a suitable cocycle relation is satisfied. -/ +@[simps!] +noncomputable def liftCocycle {K : CochainComplex C ℤ} {n m : ℤ} + (α : Cocycle K F m) (β : Cochain K G n) (h : n + 1 = m) + (eq : δ n m β + α.1.comp (Cochain.ofHom φ) (add_zero m) = 0) : + Cocycle K (mappingCone φ) n := + Cocycle.mk (liftCochain φ α β h) m h (by + simp only [δ_liftCochain φ α β h (m+1) rfl, eq, + Cocycle.δ_eq_zero, Cochain.zero_comp, neg_zero, add_zero]) + +section + +variable {K : CochainComplex C ℤ} (α : Cocycle K F 1) (β : Cochain K G 0) + (eq : δ 0 1 β + α.1.comp (Cochain.ofHom φ) (add_zero 1) = 0) + +/-- Given `φ : F ⟶ G`, this is the morphism `K ⟶ mappingCone φ` that is constructed +from a cocycle `α : Cochain K F 1` and a cochain `β : Cochain K G 0` +when a suitable cocycle relation is satisfied. -/ +noncomputable def lift : + K ⟶ mappingCone φ := + Cocycle.homOf (liftCocycle φ α β (zero_add 1) eq) + +@[simp] +lemma ofHom_lift : + Cochain.ofHom (lift φ α β eq) = liftCochain φ α β (zero_add 1) := by + simp only [lift, Cocycle.cochain_ofHom_homOf_eq_coe, liftCocycle_coe] + +@[reassoc (attr := simp)] +lemma lift_f_fst_v (p q : ℤ) (hpq : p + 1 = q) : + (lift φ α β eq).f p ≫ (fst φ).1.v p q hpq = α.1.v p q hpq := by + simp [lift] + +lemma lift_fst : + (Cochain.ofHom (lift φ α β eq)).comp (fst φ).1 (zero_add 1) = α.1 := by simp + +@[reassoc (attr := simp)] +lemma lift_f_snd_v (p q : ℤ) (hpq : p + 0 = q) : + (lift φ α β eq).f p ≫ (snd φ).v p q hpq = β.v p q hpq := by + obtain rfl : q = p := by linarith + simp [lift] + +lemma lift_snd : + (Cochain.ofHom (lift φ α β eq)).comp (snd φ) (zero_add 0) = β := by simp + +lemma lift_f (p q : ℤ) (hpq : p + 1 = q) : + (lift φ α β eq).f p = α.1.v p q hpq ≫ + (inl φ).v q p (by linarith) + β.v p p (add_zero p) ≫ (inr φ).f p := by + simp [ext_to_iff _ _ _ hpq] + +end + +/-- Constructor for homotopies between morphisms to a mapping cone. -/ +noncomputable def liftHomotopy {K : CochainComplex C ℤ} (f₁ f₂ : K ⟶ mappingCone φ) + (α : Cochain K F 0) (β : Cochain K G (-1)) + (h₁ : (Cochain.ofHom f₁).comp (fst φ).1 (zero_add 1) = + -δ 0 1 α + (Cochain.ofHom f₂).comp (fst φ).1 (zero_add 1)) + (h₂ : (Cochain.ofHom f₁).comp (snd φ) (zero_add 0) = + δ (-1) 0 β + α.comp (Cochain.ofHom φ) (zero_add 0) + + (Cochain.ofHom f₂).comp (snd φ) (zero_add 0)) : + Homotopy f₁ f₂ := + (Cochain.equivHomotopy f₁ f₂).symm ⟨liftCochain φ α β (neg_add_self 1), by + simp [δ_liftCochain _ _ _ _ _ (zero_add 1), ext_cochain_to_iff _ _ _ (zero_add 1), h₁, h₂]⟩ + +section + +variable {K L : CochainComplex C ℤ} {n m : ℤ} + (α : Cochain K F m) (β : Cochain K G n) {n' m' : ℤ} (α' : Cochain F L m') (β' : Cochain G L n') + (h : n + 1 = m) (h' : m' + 1 = n') (p : ℤ) (hp : n + n' = p) + +@[simp] +lemma liftCochain_descCochain : + (liftCochain φ α β h).comp (descCochain φ α' β' h') hp = + α.comp α' (by linarith) + β.comp β' (by linarith) := by + simp [liftCochain, descCochain, + Cochain.comp_assoc α (inl φ) _ _ (show -1 + n' = m' by linarith) (by linarith)] + +lemma liftCochain_v_descCochain_v (p₁ p₂ p₃ : ℤ) (h₁₂ : p₁ + n = p₂) (h₂₃ : p₂ + n' = p₃) + (q : ℤ) (hq : p₁ + m = q) : + (liftCochain φ α β h).v p₁ p₂ h₁₂ ≫ (descCochain φ α' β' h').v p₂ p₃ h₂₃ = + α.v p₁ q hq ≫ α'.v q p₃ (by linarith) + β.v p₁ p₂ h₁₂ ≫ β'.v p₂ p₃ h₂₃ := by + have eq := Cochain.congr_v (liftCochain_descCochain φ α β α' β' h h' p hp) p₁ p₃ (by linarith) + simpa only [Cochain.comp_v _ _ hp p₁ p₂ p₃ h₁₂ h₂₃, Cochain.add_v, + Cochain.comp_v _ _ _ _ _ _ hq (show q + m' = p₃ by linarith)] using eq + +end + +lemma lift_desc_f {K L : CochainComplex C ℤ} (α : Cocycle K F 1) (β : Cochain K G 0) + (eq : δ 0 1 β + α.1.comp (Cochain.ofHom φ) (add_zero 1) = 0) + (α' : Cochain F L (-1)) (β' : G ⟶ L) + (eq' : δ (-1) 0 α' = Cochain.ofHom (φ ≫ β')) (n n' : ℤ) (hnn' : n + 1 = n') : + (lift φ α β eq).f n ≫ (desc φ α' β' eq').f n = + α.1.v n n' hnn' ≫ α'.v n' n (by linarith) + β.v n n (add_zero n) ≫ β'.f n := by + simp only [lift, desc, Cocycle.homOf_f, liftCocycle_coe, descCocycle_coe, Cocycle.ofHom_coe, + liftCochain_v_descCochain_v φ α.1 β α' (Cochain.ofHom β') (zero_add 1) (neg_add_self 1) 0 + (add_zero 0) n n n (add_zero n) (add_zero n) n' hnn', Cochain.ofHom_v] + +end mappingCone + +end CochainComplex diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean b/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean index 8728fcb936bc2..8f2441b963537 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean @@ -105,9 +105,13 @@ instance (n : ℤ) : variable {C} +@[simp] +lemma shiftFunctor_obj_X' (K : CochainComplex C ℤ) (n p : ℤ) : + ((CategoryTheory.shiftFunctor (CochainComplex C ℤ) n).obj K).X p = K.X (p + n) := rfl + @[simp] lemma shiftFunctor_map_f' {K L : CochainComplex C ℤ} (φ : K ⟶ L) (n p : ℤ) : - ((CategoryTheory.shiftFunctor (CochainComplex C ℤ) n).map φ).f p = φ.f (p+n) := rfl + ((CategoryTheory.shiftFunctor (CochainComplex C ℤ) n).map φ).f p = φ.f (p + n) := rfl @[simp] lemma shiftFunctor_obj_d' (K : CochainComplex C ℤ) (n i j : ℤ) : @@ -283,4 +287,9 @@ noncomputable instance commShiftQuotient : (HomotopyCategory.quotient C (ComplexShape.up ℤ)).CommShift ℤ := Quotient.functor_commShift (homotopic C (ComplexShape.up ℤ)) ℤ +instance (n : ℤ) : (shiftFunctor (HomotopyCategory C (ComplexShape.up ℤ)) n).Additive := by + have : ((quotient C (ComplexShape.up ℤ) ⋙ shiftFunctor _ n)).Additive := + Functor.additive_of_iso ((quotient C (ComplexShape.up ℤ)).commShiftIso n) + apply Functor.additive_of_full_essSurj_comp (quotient _ _ ) + end HomotopyCategory diff --git a/Mathlib/Algebra/Homology/HomotopyCofiber.lean b/Mathlib/Algebra/Homology/HomotopyCofiber.lean index c40dcc9bdef3f..bb3c1d2bf08ad 100644 --- a/Mathlib/Algebra/Homology/HomotopyCofiber.lean +++ b/Mathlib/Algebra/Homology/HomotopyCofiber.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ +import Mathlib.Algebra.Homology.HomologicalComplexBiprod import Mathlib.Algebra.Homology.Homotopy /-! The homotopy cofiber of a morphism of homological complexes @@ -12,7 +13,7 @@ between homological complexes in `HomologicalComplex C c`. In degree `i`, it is isomorphic to `(F.X j) ⊞ (G.X i)` if there is a `j` such that `c.Rel i j`, and `G.X i` otherwise. (This is also known as the mapping cone of `φ`. Under the name `CochainComplex.mappingCone`, a specific API shall be developed -for the case of cochain complexes indexed by `ℤ` (TODO).) +for the case of cochain complexes indexed by `ℤ`.) When we assume `hc : ∀ j, ∃ i, c.Rel i j` (which holds in the case of chain complexes, or cochain complexes indexed by `ℤ`), then for any homological complex `K`, @@ -28,7 +29,7 @@ see `cylinder.desc`. There is also a homotopy equivalence `cylinder.homotopyEquiv K : HomotopyEquiv K.cylinder K`. From the construction of the cylinder, we deduce the lemma `Homotopy.map_eq_of_inverts_homotopyEquivalences` which assert that if a functor inverts homotopy equivalences, then the image of -two homotopic maps are equal (TODO). +two homotopic maps are equal. -/ @@ -229,7 +230,6 @@ noncomputable def homotopyCofiber : HomologicalComplex C c where · simp [homotopyCofiber.inlX_d' φ j k hjk hk] · simp - namespace homotopyCofiber /-- The right inclusion `G ⟶ homotopyCofiber φ`. -/ @@ -367,4 +367,190 @@ noncomputable def descEquiv (K : HomologicalComplex C c) (hc : ∀ j, ∃ i, c.R end homotopyCofiber +section + +variable (K) +variable [∀ i, HasBinaryBiproduct (K.X i) (K.X i)] + [HasHomotopyCofiber (biprod.lift (𝟙 K) (-𝟙 K))] + +/-- The cylinder object of a homological complex `K` is the homotopy cofiber +of the morphism `biprod.lift (𝟙 K) (-𝟙 K) : K ⟶ K ⊞ K`. -/ +noncomputable abbrev cylinder := homotopyCofiber (biprod.lift (𝟙 K) (-𝟙 K)) + +namespace cylinder + +/-- The left inclusion `K ⟶ K.cylinder`. -/ +noncomputable def ι₀ : K ⟶ K.cylinder := biprod.inl ≫ homotopyCofiber.inr _ + +/-- The right inclusion `K ⟶ K.cylinder`. -/ +noncomputable def ι₁ : K ⟶ K.cylinder := biprod.inr ≫ homotopyCofiber.inr _ + +variable {K} + +section + +variable (φ₀ φ₁ : K ⟶ F) (h : Homotopy φ₀ φ₁) + +/-- The morphism `K.cylinder ⟶ F` that is induced by two morphisms `φ₀ φ₁ : K ⟶ F` +and a homotopy `h : Homotopy φ₀ φ₁`. -/ +noncomputable def desc : K.cylinder ⟶ F := + homotopyCofiber.desc _ (biprod.desc φ₀ φ₁) + (Homotopy.trans (Homotopy.ofEq (by + simp only [biprod.lift_desc, id_comp, neg_comp, sub_eq_add_neg])) + ((Homotopy.equivSubZero h))) + +@[reassoc (attr := simp)] +lemma ι₀_desc : ι₀ K ≫ desc φ₀ φ₁ h = φ₀ := by simp [ι₀, desc] + +@[reassoc (attr := simp)] +lemma ι₁_desc : ι₁ K ≫ desc φ₀ φ₁ h = φ₁ := by simp [ι₁, desc] + +end + +variable (K) + +/-- The projection `π : K.cylinder ⟶ K`. -/ +noncomputable def π : K.cylinder ⟶ K := desc (𝟙 K) (𝟙 K) (Homotopy.refl _) + +@[reassoc (attr := simp)] +lemma ι₀_π : ι₀ K ≫ π K = 𝟙 K := by simp [π] + +@[reassoc (attr := simp)] +lemma ι₁_π : ι₁ K ≫ π K = 𝟙 K := by simp [π] + +/-- The left inclusion `K.X i ⟶ K.cylinder.X j` when `c.Rel j i`. -/ +noncomputable abbrev inlX (i j : ι) (hij : c.Rel j i) : K.X i ⟶ K.cylinder.X j := + homotopyCofiber.inlX (biprod.lift (𝟙 K) (-𝟙 K)) i j hij + +/-- The right inclusion `(K ⊞ K).X i ⟶ K.cylinder.X i`. -/ +noncomputable abbrev inrX (i : ι) : (K ⊞ K).X i ⟶ K.cylinder.X i := + homotopyCofiber.inrX (biprod.lift (𝟙 K) (-𝟙 K)) i + +@[reassoc (attr := simp)] +lemma inlX_π (i j : ι) (hij : c.Rel j i) : + inlX K i j hij ≫ (π K).f j = 0 := by + erw [homotopyCofiber.inlX_desc_f] + simp [Homotopy.equivSubZero] + +@[reassoc (attr := simp)] +lemma inrX_π (i : ι) : + inrX K i ≫ (π K).f i = (biprod.desc (𝟙 _) (𝟙 K)).f i := + homotopyCofiber.inrX_desc_f _ _ _ _ + +section + +variable (hc : ∀ j, ∃ i, c.Rel i j) + +namespace πCompι₀Homotopy + +/-- A null homotopic map `K.cylinder ⟶ K.cylinder` which identifies to +`π K ≫ ι₀ K - 𝟙 _`, see `nullHomotopicMap_eq`. -/ +noncomputable def nullHomotopicMap : K.cylinder ⟶ K.cylinder := + Homotopy.nullHomotopicMap' + (fun i j hij => homotopyCofiber.sndX (biprod.lift (𝟙 K) (-𝟙 K)) i ≫ + (biprod.snd : K ⊞ K ⟶ K).f i ≫ inlX K i j hij) + +/-- The obvious homotopy from `nullHomotopicMap K` to zero. -/ +noncomputable def nullHomotopy : Homotopy (nullHomotopicMap K) 0 := + Homotopy.nullHomotopy' _ + +lemma inlX_nullHomotopy_f (i j : ι) (hij : c.Rel j i) : + inlX K i j hij ≫ (nullHomotopicMap K).f j = + inlX K i j hij ≫ (π K ≫ ι₀ K - 𝟙 _).f j := by + dsimp [nullHomotopicMap] + by_cases hj : ∃ (k : ι), c.Rel k j + · obtain ⟨k, hjk⟩ := hj + simp only [assoc, Homotopy.nullHomotopicMap'_f hjk hij, homotopyCofiber_X, homotopyCofiber_d, + homotopyCofiber.d_sndX_assoc _ _ _ hij, add_comp, comp_add, homotopyCofiber.inlX_fstX_assoc, + homotopyCofiber.inlX_sndX_assoc, zero_comp, add_zero, comp_sub, inlX_π_assoc, comp_id, + zero_sub, ← HomologicalComplex.comp_f_assoc, biprod.lift_snd, neg_f_apply, id_f, + neg_comp, id_comp] + · simp only [not_exists] at hj + simp only [Homotopy.nullHomotopicMap'_f_of_not_rel_right hij hj, + homotopyCofiber_X, homotopyCofiber_d, assoc, comp_sub, comp_id, + homotopyCofiber.d_sndX_assoc _ _ _ hij, add_comp, comp_add, zero_comp, add_zero, + homotopyCofiber.inlX_fstX_assoc, homotopyCofiber.inlX_sndX_assoc, + ← HomologicalComplex.comp_f_assoc, biprod.lift_snd, neg_f_apply, id_f, neg_comp, + id_comp, inlX_π_assoc, zero_sub] + +lemma biprod_lift_id_sub_id : biprod.lift (𝟙 K) (-𝟙 K) = biprod.inl - biprod.inr := + biprod.hom_ext _ _ (by simp) (by simp) + +lemma inrX_nullHomotopy_f (j : ι) : + inrX K j ≫ (nullHomotopicMap K).f j = inrX K j ≫ (π K ≫ ι₀ K - 𝟙 _).f j := by + obtain ⟨i, hij⟩ := hc j + dsimp [nullHomotopicMap] + by_cases hj : ∃ (k : ι), c.Rel j k + · obtain ⟨k, hjk⟩ := hj + simp only [Homotopy.nullHomotopicMap'_f hij hjk, + homotopyCofiber_X, homotopyCofiber_d, assoc, comp_add, + homotopyCofiber.inrX_d_assoc, homotopyCofiber.inrX_sndX_assoc, comp_sub, + inrX_π_assoc, comp_id, ← Hom.comm_assoc, homotopyCofiber.inlX_d _ _ _ _ _ hjk, + comp_neg, add_neg_cancel_left] + rw [← cancel_epi (biprodXIso K K j).inv] + ext + · simp [ι₀] + · dsimp + simp only [inr_biprodXIso_inv_assoc, biprod_inr_snd_f_assoc, comp_sub, + biprod_inr_desc_f_assoc, id_f, id_comp, ι₀, comp_f, biprod_lift_id_sub_id, + sub_f_apply, sub_comp, homotopyCofiber_X, homotopyCofiber.inr_f] + · simp only [not_exists] at hj + simp only [assoc, Homotopy.nullHomotopicMap'_f_of_not_rel_left hij hj, homotopyCofiber_X, + homotopyCofiber_d, homotopyCofiber.inlX_d' _ _ _ _ (hj _), homotopyCofiber.inrX_sndX_assoc, + comp_sub, inrX_π_assoc, comp_id, ι₀, comp_f, homotopyCofiber.inr_f] + rw [← cancel_epi (biprodXIso K K j).inv] + ext + · simp + · simp [biprod_lift_id_sub_id] + +lemma nullHomotopicMap_eq : nullHomotopicMap K = π K ≫ ι₀ K - 𝟙 _ := by + ext i + by_cases hi : c.Rel i (c.next i) + · exact homotopyCofiber.ext_from_X (biprod.lift (𝟙 K) (-𝟙 K)) (c.next i) i hi + (inlX_nullHomotopy_f _ _ _ _) (inrX_nullHomotopy_f _ hc _) + · exact homotopyCofiber.ext_from_X' (biprod.lift (𝟙 K) (-𝟙 K)) _ hi (inrX_nullHomotopy_f _ hc _) + +end πCompι₀Homotopy + +/-- The homotopy between `π K ≫ ι₀ K` and `𝟙 K.cylinder`. -/ +noncomputable def πCompι₀Homotopy : Homotopy (π K ≫ ι₀ K) (𝟙 K.cylinder) := + Homotopy.equivSubZero.symm + ((Homotopy.ofEq (πCompι₀Homotopy.nullHomotopicMap_eq K hc).symm).trans + (πCompι₀Homotopy.nullHomotopy K)) + +/-- The homotopy equivalence between `K.cylinder` and `K`. -/ +noncomputable def homotopyEquiv : HomotopyEquiv K.cylinder K where + hom := π K + inv := ι₀ K + homotopyHomInvId := πCompι₀Homotopy K hc + homotopyInvHomId := Homotopy.ofEq (by simp) + +/-- The homotopy between `cylinder.ι₀ K` and `cylinder.ι₁ K`. -/ +noncomputable def homotopy₀₁ : Homotopy (ι₀ K) (ι₁ K) := + (Homotopy.ofEq (by simp)).trans (((πCompι₀Homotopy K hc).compLeft (ι₁ K)).trans + (Homotopy.ofEq (by simp))) + +lemma map_ι₀_eq_map_ι₁ {D : Type*} [Category D] (H : HomologicalComplex C c ⥤ D) + (hH : (homotopyEquivalences C c).IsInvertedBy H) : + H.map (ι₀ K) = H.map (ι₁ K) := by + have : IsIso (H.map (cylinder.π K)) := hH _ ⟨homotopyEquiv K hc, rfl⟩ + simp only [← cancel_mono (H.map (cylinder.π K)), ← H.map_comp, ι₀_π, H.map_id, ι₁_π] + +end + +end cylinder + +/-- If a functor inverts homotopy equivalences, it sends homotopic maps to the same map. -/ +lemma _root_.Homotopy.map_eq_of_inverts_homotopyEquivalences + {φ₀ φ₁ : F ⟶ G} (h : Homotopy φ₀ φ₁) (hc : ∀ j, ∃ i, c.Rel i j) + [∀ i, HasBinaryBiproduct (F.X i) (F.X i)] + [HasHomotopyCofiber (biprod.lift (𝟙 F) (-𝟙 F))] + {D : Type*} [Category D] (H : HomologicalComplex C c ⥤ D) + (hH : (homotopyEquivalences C c).IsInvertedBy H) : + H.map φ₀ = H.map φ₁ := by + simp only [← cylinder.ι₀_desc _ _ h, ← cylinder.ι₁_desc _ _ h, H.map_comp, + cylinder.map_ι₀_eq_map_ι₁ _ hc _ hH] + +end + end HomologicalComplex diff --git a/Mathlib/Algebra/Homology/ImageToKernel.lean b/Mathlib/Algebra/Homology/ImageToKernel.lean index 6d38e1591b0f2..ae4be6c5f18ae 100644 --- a/Mathlib/Algebra/Homology/ImageToKernel.lean +++ b/Mathlib/Algebra/Homology/ImageToKernel.lean @@ -64,7 +64,7 @@ theorem subobject_ofLE_as_imageToKernel (w : f ≫ g = 0) (h) : rfl #align subobject_of_le_as_image_to_kernel subobject_ofLE_as_imageToKernel -attribute [local instance] ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.instFunLike -- porting note: removed elementwise attribute which does not seem to be helpful here -- a more suitable lemma is added below @@ -303,7 +303,7 @@ theorem homology'.π_map (p : α.right = β.left) : section -attribute [local instance] ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.instFunLike @[simp] lemma homology'.π_map_apply [ConcreteCategory.{w} V] (p : α.right = β.left) diff --git a/Mathlib/Algebra/Homology/Localization.lean b/Mathlib/Algebra/Homology/Localization.lean index 3d5912e76ba04..8505e58d6d5e4 100644 --- a/Mathlib/Algebra/Homology/Localization.lean +++ b/Mathlib/Algebra/Homology/Localization.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.Algebra.Homology.HomotopyCategory import Mathlib.Algebra.Homology.QuasiIso import Mathlib.CategoryTheory.Localization.HasLocalization diff --git a/Mathlib/Algebra/Homology/ShortComplex/Abelian.lean b/Mathlib/Algebra/Homology/ShortComplex/Abelian.lean index 1dffc9bed40a0..1002f6f1a3be3 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Abelian.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Abelian.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.Algebra.Homology.Homology +import Mathlib.Algebra.Homology.ImageToKernel import Mathlib.Algebra.Homology.ShortComplex.Homology import Mathlib.CategoryTheory.Abelian.Basic diff --git a/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean b/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean index 1d9489809dc7c..f06fd1a126356 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean @@ -121,7 +121,7 @@ section abelian variable {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] [HasForget₂ C Ab] [Abelian C] [(forget₂ C Ab).Additive] [(forget₂ C Ab).PreservesHomology] -attribute [local instance] ConcreteCategory.funLike ConcreteCategory.hasCoeToSort +attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort namespace ShortComplex @@ -142,7 +142,7 @@ lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁) (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂ have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂ - dsimp [FunLike.coe] at eq₁ eq₂ + dsimp [DFunLike.coe] at eq₁ eq₂ rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq rw [eq₂] at eq refine' eq.trans (congr_arg ((forget C).map D.v₂₃.τ₁) _) diff --git a/Mathlib/Algebra/Homology/ShortComplex/Limits.lean b/Mathlib/Algebra/Homology/ShortComplex/Limits.lean index 688e829900d6b..ed25fe4044e88 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Limits.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Limits.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.Algebra.Homology.ShortComplex.FunctorEquivalence +import Mathlib.Algebra.Homology.ShortComplex.Basic import Mathlib.CategoryTheory.Limits.Constructions.EpiMono import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits import Mathlib.CategoryTheory.Limits.Preserves.Finite diff --git a/Mathlib/Algebra/Invertible/Basic.lean b/Mathlib/Algebra/Invertible/Basic.lean index 8302fbf223df8..ab4ab18a1d678 100644 --- a/Mathlib/Algebra/Invertible/Basic.lean +++ b/Mathlib/Algebra/Invertible/Basic.lean @@ -5,6 +5,7 @@ Authors: Anne Baanen -/ import Mathlib.Algebra.Invertible.GroupWithZero import Mathlib.Algebra.Group.Units +import Mathlib.Algebra.GroupPower.Basic import Mathlib.Algebra.GroupWithZero.Units.Lemmas import Mathlib.Algebra.Ring.Defs @@ -159,6 +160,21 @@ def Invertible.mulRight (a : α) {b : α} (_ : Invertible b) : Invertible a ≃ #align invertible.mul_right_apply Invertible.mulRight_apply #align invertible.mul_right_symm_apply Invertible.mulRight_symm_apply +instance invertiblePow (m : α) [Invertible m] (n : ℕ) : Invertible (m ^ n) where + invOf := ⅟ m ^ n + invOf_mul_self := by rw [← (commute_invOf m).symm.mul_pow, invOf_mul_self, one_pow] + mul_invOf_self := by rw [← (commute_invOf m).mul_pow, mul_invOf_self, one_pow] +#align invertible_pow invertiblePow + +lemma invOf_pow (m : α) [Invertible m] (n : ℕ) [Invertible (m ^ n)] : ⅟ (m ^ n) = ⅟ m ^ n := + @invertible_unique _ _ _ _ _ (invertiblePow m n) rfl +#align inv_of_pow invOf_pow + +/-- If `x ^ n = 1` then `x` has an inverse, `x^(n - 1)`. -/ +def invertibleOfPowEqOne (x : α) (n : ℕ) (hx : x ^ n = 1) (hn : n ≠ 0) : Invertible x := + (Units.ofPowEqOne x n hx hn).invertible +#align invertible_of_pow_eq_one invertibleOfPowEqOne + end Monoid section MonoidWithZero diff --git a/Mathlib/Algebra/Lie/Basic.lean b/Mathlib/Algebra/Lie/Basic.lean index f5ba1c8037f32..6efc83f255c8a 100644 --- a/Mathlib/Algebra/Lie/Basic.lean +++ b/Mathlib/Algebra/Lie/Basic.lean @@ -307,7 +307,7 @@ attribute [coe] LieHom.toLinearMap instance : Coe (L₁ →ₗ⁅R⁆ L₂) (L₁ →ₗ[R] L₂) := ⟨LieHom.toLinearMap⟩ -instance : FunLike (L₁ →ₗ⁅R⁆ L₂) L₁ (fun _ => L₂) := +instance : FunLike (L₁ →ₗ⁅R⁆ L₂) L₁ L₂ := { coe := fun f => f.toFun, coe_injective' := fun x y h => by cases x; cases y; simp at h; simp [h] } @@ -736,7 +736,7 @@ attribute [coe] LieModuleHom.toLinearMap instance : CoeOut (M →ₗ⁅R,L⁆ N) (M →ₗ[R] N) := ⟨LieModuleHom.toLinearMap⟩ -instance : FunLike (M →ₗ⁅R, L⁆ N) M (fun _ => N) := +instance : FunLike (M →ₗ⁅R, L⁆ N) M N := { coe := fun f => f.toFun, coe_injective' := fun x y h => by cases x; cases y; simp at h; simp [h] } diff --git a/Mathlib/Algebra/Lie/DirectSum.lean b/Mathlib/Algebra/Lie/DirectSum.lean index 38e6851c3cf94..8782092b5e646 100644 --- a/Mathlib/Algebra/Lie/DirectSum.lean +++ b/Mathlib/Algebra/Lie/DirectSum.lean @@ -170,7 +170,7 @@ def lieAlgebraOf [DecidableEq ι] (j : ι) : L j →ₗ⁅R⁆ ⨁ i, L i := -- with `simp [of, singleAddHom]` simp only [of, singleAddHom, bracket_apply] erw [AddHom.coe_mk, single_apply, single_apply] - simp? [h] says simp only [h, dite_eq_ite, ite_true, single_apply] + simp? [h] says simp only [h, ↓reduceDite, single_apply] intros erw [single_add] · -- This used to be the end of the proof before leanprover/lean4#2644 diff --git a/Mathlib/Algebra/Lie/Engel.lean b/Mathlib/Algebra/Lie/Engel.lean index d6f31f2eea26d..6e56816151418 100644 --- a/Mathlib/Algebra/Lie/Engel.lean +++ b/Mathlib/Algebra/Lie/Engel.lean @@ -158,10 +158,8 @@ be nilpotent is that the image of the map `L → End(M)` consists of nilpotent e Engel's theorem `LieAlgebra.isEngelian_of_isNoetherian` states that any Noetherian Lie algebra is Engelian. -/ def LieAlgebra.IsEngelian : Prop := - ∀ (M : Type u₄) [AddCommGroup M], - ∀ [Module R M] [LieRingModule L M], - ∀ [LieModule R L M], - ∀ _ : ∀ x : L, _root_.IsNilpotent (toEndomorphism R L M x), LieModule.IsNilpotent R L M + ∀ (M : Type u₄) [AddCommGroup M] [Module R M] [LieRingModule L M] [LieModule R L M], + (∀ x : L, _root_.IsNilpotent (toEndomorphism R L M x)) → LieModule.IsNilpotent R L M #align lie_algebra.is_engelian LieAlgebra.IsEngelian variable {R L} diff --git a/Mathlib/Algebra/Lie/Killing.lean b/Mathlib/Algebra/Lie/Killing.lean index e1fbb04f34613..c44cae53d080e 100644 --- a/Mathlib/Algebra/Lie/Killing.lean +++ b/Mathlib/Algebra/Lie/Killing.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ import Mathlib.Algebra.DirectSum.LinearMap +import Mathlib.Algebra.GroupWithZero.NonZeroDivisors import Mathlib.Algebra.Lie.Nilpotent import Mathlib.Algebra.Lie.Semisimple import Mathlib.Algebra.Lie.Weights.Cartan @@ -54,8 +55,6 @@ variable (R K L M : Type*) [CommRing R] [LieRing L] [LieAlgebra R L] [Module.Free R M] [Module.Finite R M] [Field K] [LieAlgebra K L] [Module K M] [LieModule K L M] [FiniteDimensional K M] -attribute [local instance] Module.free_of_finite_type_torsion_free' - local notation "φ" => LieModule.toEndomorphism R L M open LinearMap (trace) @@ -387,7 +386,7 @@ variable [IsDomain R] [IsPrincipalIdealRing R] lemma killingForm_eq : killingForm R I = I.restrictBilinear (killingForm R L) := - LieSubmodule.traceForm_eq_of_le_idealizer I I $ by simp + LieSubmodule.traceForm_eq_of_le_idealizer I I <| by simp lemma restrictBilinear_killingForm : I.restrictBilinear (killingForm R L) = LieModule.traceForm R I L := @@ -407,7 +406,7 @@ namespace LieAlgebra /-- We say a Lie algebra is Killing if its Killing form is non-singular. -NB: The is not standard terminology (the literature does not seem to name Lie algebras with this +NB: This is not standard terminology (the literature does not seem to name Lie algebras with this property). -/ class IsKilling : Prop := /-- We say a Lie algebra is Killing if its Killing form is non-singular. -/ diff --git a/Mathlib/Algebra/Lie/Subalgebra.lean b/Mathlib/Algebra/Lie/Subalgebra.lean index ef30f165203c1..c69b97673e615 100644 --- a/Mathlib/Algebra/Lie/Subalgebra.lean +++ b/Mathlib/Algebra/Lie/Subalgebra.lean @@ -762,7 +762,7 @@ variable [CommRing R] [LieRing L₁] [LieRing L₂] [LieAlgebra R L₁] [LieAlge /-- An injective Lie algebra morphism is an equivalence onto its range. -/ noncomputable def ofInjective (f : L₁ →ₗ⁅R⁆ L₂) (h : Function.Injective f) : L₁ ≃ₗ⁅R⁆ f.range := { LinearEquiv.ofInjective (f : L₁ →ₗ[R] L₂) <| by rwa [LieHom.coe_toLinearMap] with - map_lie' := @fun x y ↦ SetCoe.ext $ f.map_lie x y } + map_lie' := @fun x y ↦ SetCoe.ext <| f.map_lie x y } #align lie_equiv.of_injective LieEquiv.ofInjective @[simp] diff --git a/Mathlib/Algebra/Lie/Weights/Linear.lean b/Mathlib/Algebra/Lie/Weights/Linear.lean index e2967a3e5c4ed..c58ebda93b918 100644 --- a/Mathlib/Algebra/Lie/Weights/Linear.lean +++ b/Mathlib/Algebra/Lie/Weights/Linear.lean @@ -41,8 +41,6 @@ or `R` has characteristic zero. open Set -attribute [local instance] Module.free_of_finite_type_torsion_free' - variable (R L M : Type*) [CommRing R] [LieRing L] [LieAlgebra R L] [AddCommGroup M] [Module R M] [LieRingModule L M] [LieModule R L M] diff --git a/Mathlib/Algebra/ModEq.lean b/Mathlib/Algebra/ModEq.lean index d1ca0405ba739..c34af46c6663a 100644 --- a/Mathlib/Algebra/ModEq.lean +++ b/Mathlib/Algebra/ModEq.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ +import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Data.Int.ModEq import Mathlib.GroupTheory.QuotientGroup @@ -15,7 +16,7 @@ This file defines equality modulo an element in a commutative group. ## Main definitions -* `a ≡ b [PMOD p]`: `a` and `b` are congruent modulo a`p`. +* `a ≡ b [PMOD p]`: `a` and `b` are congruent modulo `p`. ## See also diff --git a/Mathlib/Algebra/Module/Basic.lean b/Mathlib/Algebra/Module/Basic.lean index acb21a25cd433..d9d3cc9da73b5 100644 --- a/Mathlib/Algebra/Module/Basic.lean +++ b/Mathlib/Algebra/Module/Basic.lean @@ -6,11 +6,9 @@ Authors: Nathaniel Thomas, Jeremy Avigad, Johannes Hölzl, Mario Carneiro import Mathlib.Algebra.Field.Defs import Mathlib.Algebra.Function.Indicator import Mathlib.Algebra.SMulWithZero -import Mathlib.Data.Int.Units -import Mathlib.Data.Rat.Defs -import Mathlib.Data.Rat.Basic import Mathlib.GroupTheory.GroupAction.Group import Mathlib.GroupTheory.GroupAction.Pi +import Mathlib.Logic.Basic import Mathlib.Tactic.Abel #align_import algebra.module.basic from "leanprover-community/mathlib"@"30413fc89f202a090a54d78e540963ed3de0056e" @@ -334,7 +332,7 @@ def RingHom.toModule [Semiring R] [Semiring S] (f : R →+* S) : Module R S := #align ring_hom.to_module RingHom.toModule /-- If the module action of `R` on `S` is compatible with multiplication on `S`, then -`fun x => x • 1` is a ring homomorphism from `R` to `S`. +`fun x ↦ x • 1` is a ring homomorphism from `R` to `S`. This is the `RingHom` version of `MonoidHom.smulOneHom`. @@ -345,6 +343,15 @@ When `R` is commutative, usually `algebraMap` should be preferred. -/ map_zero' := zero_smul R 1 map_add' := (add_smul · · 1) +/-- A homomorphism between semirings R and S can be equivalently specified by a R-module +structure on S such that S/S/R is a scalar tower. -/ +def ringHomEquivModuleIsScalarTower [Semiring R] [Semiring S] : + (R →+* S) ≃ {_inst : Module R S // IsScalarTower R S S} where + toFun f := ⟨Module.compHom S f, SMul.comp.isScalarTower _⟩ + invFun := fun ⟨_, _⟩ ↦ RingHom.smulOneHom + left_inv f := RingHom.ext fun r ↦ mul_one (f r) + right_inv := fun ⟨_, _⟩ ↦ Subtype.ext <| Module.ext _ _ <| funext₂ <| smul_one_smul S + section AddCommMonoid variable [Semiring R] [AddCommMonoid M] [Module R M] @@ -397,7 +404,7 @@ theorem zsmul_eq_smul_cast (n : ℤ) (b : M) : n • b = (n : R) • b := have : (smulAddHom ℤ M).flip b = ((smulAddHom R M).flip b).comp (Int.castAddHom R) := by apply AddMonoidHom.ext_int simp - FunLike.congr_fun this n + DFunLike.congr_fun this n #align zsmul_eq_smul_cast zsmul_eq_smul_cast end @@ -586,6 +593,13 @@ theorem smul_eq_zero : c • x = 0 ↔ c = 0 ∨ x = 0 := theorem smul_ne_zero_iff : c • x ≠ 0 ↔ c ≠ 0 ∧ x ≠ 0 := by rw [Ne.def, smul_eq_zero, not_or] #align smul_ne_zero_iff smul_ne_zero_iff +lemma smul_eq_zero_iff_left (hx : x ≠ 0) : c • x = 0 ↔ c = 0 := by simp [hx] +lemma smul_eq_zero_iff_right (hc : c ≠ 0) : c • x = 0 ↔ x = 0 := by simp [hc] +#align smul_eq_zero_iff_eq' smul_eq_zero_iff_right +lemma smul_ne_zero_iff_left (hx : x ≠ 0) : c • x ≠ 0 ↔ c ≠ 0 := by simp [hx] +lemma smul_ne_zero_iff_right (hc : c ≠ 0) : c • x ≠ 0 ↔ x ≠ 0 := by simp [hc] +#align smul_ne_zero_iff_ne' smul_ne_zero_iff_right + end SMulWithZero section Module @@ -720,7 +734,7 @@ variable [GroupWithZero R] [AddMonoid M] [DistribMulAction R M] -- see note [lower instance priority] /-- This instance applies to `DivisionSemiring`s, in particular `NNReal` and `NNRat`. -/ instance (priority := 100) GroupWithZero.toNoZeroSMulDivisors : NoZeroSMulDivisors R M := - ⟨fun {_ _} h => or_iff_not_imp_left.2 fun hc => (smul_eq_zero_iff_eq' hc).1 h⟩ + ⟨fun {a _} h ↦ or_iff_not_imp_left.2 fun ha ↦ (smul_eq_zero_iff_eq <| Units.mk0 a ha).1 h⟩ #align group_with_zero.to_no_zero_smul_divisors GroupWithZero.toNoZeroSMulDivisors end GroupWithZero @@ -751,7 +765,7 @@ theorem Int.smul_one_eq_coe {R : Type*} [Ring R] (m : ℤ) : m • (1 : R) = ↑ namespace Function lemma support_smul_subset_left [Zero R] [Zero M] [SMulWithZero R M] (f : α → R) (g : α → M) : - support (f • g) ⊆ support f := fun x hfg hf ↦ hfg $ by rw [Pi.smul_apply', hf, zero_smul] + support (f • g) ⊆ support f := fun x hfg hf ↦ hfg <| by rw [Pi.smul_apply', hf, zero_smul] #align function.support_smul_subset_left Function.support_smul_subset_left lemma support_const_smul_of_ne_zero [Zero R] [Zero M] [SMulWithZero R M] [NoZeroSMulDivisors R M] @@ -784,7 +798,7 @@ lemma indicator_smul_apply (s : Set α) (r : α → R) (f : α → M) (a : α) : lemma indicator_smul (s : Set α) (r : α → R) (f : α → M) : indicator s (fun a ↦ r a • f a) = fun a ↦ r a • indicator s f a := - funext $ indicator_smul_apply s r f + funext <| indicator_smul_apply s r f #align set.indicator_smul Set.indicator_smul lemma indicator_const_smul_apply (s : Set α) (r : R) (f : α → M) (a : α) : @@ -794,7 +808,7 @@ lemma indicator_const_smul_apply (s : Set α) (r : R) (f : α → M) (a : α) : lemma indicator_const_smul (s : Set α) (r : R) (f : α → M) : indicator s (r • f ·) = (r • indicator s f ·) := - funext $ indicator_const_smul_apply s r f + funext <| indicator_const_smul_apply s r f #align set.indicator_const_smul Set.indicator_const_smul end SMulZeroClass @@ -810,14 +824,14 @@ lemma indicator_smul_apply_left (s : Set α) (r : α → R) (f : α → M) (a : lemma indicator_smul_left (s : Set α) (r : α → R) (f : α → M) : indicator s (fun a ↦ r a • f a) = fun a ↦ indicator s r a • f a := - funext $ indicator_smul_apply_left _ _ _ + funext <| indicator_smul_apply_left _ _ _ lemma indicator_smul_const_apply (s : Set α) (r : α → R) (m : M) (a : α) : indicator s (r · • m) a = indicator s r a • m := indicator_smul_apply_left _ _ _ _ lemma indicator_smul_const (s : Set α) (r : α → R) (m : M) : indicator s (r · • m) = (indicator s r · • m) := - funext $ indicator_smul_const_apply _ _ _ + funext <| indicator_smul_const_apply _ _ _ end SMulWithZero end Set diff --git a/Mathlib/Algebra/Module/DirectLimitAndTensorProduct.lean b/Mathlib/Algebra/Module/DirectLimitAndTensorProduct.lean index 18dffd407253d..39c08157b6c37 100644 --- a/Mathlib/Algebra/Module/DirectLimitAndTensorProduct.lean +++ b/Mathlib/Algebra/Module/DirectLimitAndTensorProduct.lean @@ -61,7 +61,7 @@ noncomputable def toDirectLimit : DirectLimit G f ⊗[R] M →ₗ[R] DirectLimit TensorProduct.lift <| DirectLimit.lift _ _ _ _ (fun i ↦ (TensorProduct.mk R _ _).compr₂ (of R ι _ (fun _i _j h ↦ (f _ _ h).rTensor M) i)) - fun _ _ _ g ↦ FunLike.ext _ _ (of_f (G := (G · ⊗[R] M)) (x := g ⊗ₜ ·)) + fun _ _ _ g ↦ DFunLike.ext _ _ (of_f (G := (G · ⊗[R] M)) (x := g ⊗ₜ ·)) variable {M} in @[simp] lemma toDirectLimit_tmul_of @@ -80,9 +80,9 @@ noncomputable def directLimitLeft : refine LinearEquiv.ofLinear (toDirectLimit f M) (fromDirectLimit f M) ?_ ?_ <;> cases isEmpty_or_nonempty ι · ext; apply Subsingleton.elim - · refine FunLike.ext _ _ fun x ↦ x.induction_on fun i g ↦ g.induction_on ?_ ?_ ?_ <;> aesop + · refine DFunLike.ext _ _ fun x ↦ x.induction_on fun i g ↦ g.induction_on ?_ ?_ ?_ <;> aesop · ext; apply Subsingleton.elim - · exact ext (FunLike.ext _ _ fun g ↦ FunLike.ext _ _ fun _ ↦ g.induction_on <| by aesop) + · exact ext (DFunLike.ext _ _ fun g ↦ DFunLike.ext _ _ fun _ ↦ g.induction_on <| by aesop) @[simp] lemma directLimitLeft_tmul_of {i : ι} (g : G i) (m : M) : directLimitLeft f M (of _ _ _ _ _ g ⊗ₜ m) = of _ _ _ (f ▷ M) _ (g ⊗ₜ m) := @@ -99,7 +99,7 @@ noncomputable def directLimitRight : M ⊗[R] DirectLimit G f ≃ₗ[R] DirectLimit (M ⊗[R] G ·) (M ◁ f) := TensorProduct.comm _ _ _ ≪≫ₗ directLimitLeft f M ≪≫ₗ Module.DirectLimit.congr (fun i ↦ TensorProduct.comm _ _ _) - (fun i j h ↦ TensorProduct.ext <| FunLike.ext _ _ <| by aesop) + (fun i j h ↦ TensorProduct.ext <| DFunLike.ext _ _ <| by aesop) @[simp] lemma directLimitRight_tmul_of {i : ι} (m : M) (g : G i): directLimitRight f M (m ⊗ₜ of _ _ _ _ _ g) = of _ _ _ _ i (m ⊗ₜ g) := by diff --git a/Mathlib/Algebra/Module/Equiv.lean b/Mathlib/Algebra/Module/Equiv.lean index 988bc8f5ced38..58a9d52ed8090 100644 --- a/Mathlib/Algebra/Module/Equiv.lean +++ b/Mathlib/Algebra/Module/Equiv.lean @@ -123,7 +123,7 @@ instance (priority := 100) [RingHomInvPair σ σ'] [RingHomInvPair σ' σ] [s : SemilinearEquivClass F σ M M₂] : SemilinearMapClass F σ M M₂ := { s with coe := (s.coe : F → M → M₂) - coe_injective' := @FunLike.coe_injective F _ _ _ } + coe_injective' := @DFunLike.coe_injective F _ _ _ } end SemilinearEquivClass @@ -173,7 +173,7 @@ theorem toLinearMap_inj {e₁ e₂ : M ≃ₛₗ[σ] M₂} : (↑e₁ : M →ₛ instance : SemilinearEquivClass (M ≃ₛₗ[σ] M₂) σ M M₂ where inv := LinearEquiv.invFun - coe_injective' _ _ h _ := toLinearMap_injective (FunLike.coe_injective h) + coe_injective' _ _ h _ := toLinearMap_injective (DFunLike.coe_injective h) left_inv := LinearEquiv.left_inv right_inv := LinearEquiv.right_inv map_add := (·.map_add') --map_add' Porting note: TODO why did I need to change this? @@ -186,7 +186,7 @@ theorem coe_mk {to_fun inv_fun map_add map_smul left_inv right_inv} : #align linear_equiv.coe_mk LinearEquiv.coe_mk theorem coe_injective : @Injective (M ≃ₛₗ[σ] M₂) (M → M₂) CoeFun.coe := - FunLike.coe_injective + DFunLike.coe_injective #align linear_equiv.coe_injective LinearEquiv.coe_injective end @@ -232,19 +232,19 @@ variable {e e'} @[ext] theorem ext (h : ∀ x, e x = e' x) : e = e' := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align linear_equiv.ext LinearEquiv.ext theorem ext_iff : e = e' ↔ ∀ x, e x = e' x := - FunLike.ext_iff + DFunLike.ext_iff #align linear_equiv.ext_iff LinearEquiv.ext_iff protected theorem congr_arg {x x'} : x = x' → e x = e x' := - FunLike.congr_arg e + DFunLike.congr_arg e #align linear_equiv.congr_arg LinearEquiv.congr_arg protected theorem congr_fun (h : e = e') (x : M) : e x = e' x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align linear_equiv.congr_fun LinearEquiv.congr_fun end @@ -837,7 +837,7 @@ theorem toNatLinearEquiv_toAddEquiv : ↑e.toNatLinearEquiv = e := by @[simp] theorem _root_.LinearEquiv.toAddEquiv_toNatLinearEquiv (e : M ≃ₗ[ℕ] M₂) : AddEquiv.toNatLinearEquiv ↑e = e := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align linear_equiv.to_add_equiv_to_nat_linear_equiv LinearEquiv.toAddEquiv_toNatLinearEquiv @[simp] @@ -884,7 +884,7 @@ theorem toIntLinearEquiv_toAddEquiv : ↑e.toIntLinearEquiv = e := by @[simp] theorem _root_.LinearEquiv.toAddEquiv_toIntLinearEquiv (e : M ≃ₗ[ℤ] M₂) : AddEquiv.toIntLinearEquiv (e : M ≃+ M₂) = e := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align linear_equiv.to_add_equiv_to_int_linear_equiv LinearEquiv.toAddEquiv_toIntLinearEquiv @[simp] diff --git a/Mathlib/Algebra/Module/GradedModule.lean b/Mathlib/Algebra/Module/GradedModule.lean index 2a96ae3200f8b..64b425822a732 100644 --- a/Mathlib/Algebra/Module/GradedModule.lean +++ b/Mathlib/Algebra/Module/GradedModule.lean @@ -116,7 +116,7 @@ open AddMonoidHom private theorem one_smul' [DecidableEq ιA] [DecidableEq ιB] [GMonoid A] [Gmodule A M] (x : ⨁ i, M i) : (1 : ⨁ i, A i) • x = x := by - suffices smulAddMonoidHom A M 1 = AddMonoidHom.id (⨁ i, M i) from FunLike.congr_fun this x + suffices smulAddMonoidHom A M 1 = AddMonoidHom.id (⨁ i, M i) from DFunLike.congr_fun this x apply DirectSum.addHom_ext; intro i xi rw [show (1 : DirectSum ιA fun i => A i) = (of A 0) GOne.one by rfl] rw [smulAddMonoidHom_apply_of_of] @@ -135,7 +135,7 @@ private theorem mul_smul' [DecidableEq ιA] [DecidableEq ιB] [GSemiring A] [Gmo (AddMonoidHom.compHom AddMonoidHom.flipHom <| (smulAddMonoidHom A M).flip.compHom.comp <| smulAddMonoidHom A M).flip from-- `fun a b c ↦ a • (b • c)` as a bundled hom - FunLike.congr_fun (FunLike.congr_fun (FunLike.congr_fun this a) b) c + DFunLike.congr_fun (DFunLike.congr_fun (DFunLike.congr_fun this a) b) c ext ai ax bi bx ci cx : 6 dsimp only [coe_comp, Function.comp_apply, compHom_apply_apply, flip_apply, flipHom_apply] rw [smulAddMonoidHom_apply_of_of, smulAddMonoidHom_apply_of_of, DirectSum.mulHom_of_of, diff --git a/Mathlib/Algebra/Module/Hom.lean b/Mathlib/Algebra/Module/Hom.lean index ba091bb791c20..fa7735a70f57a 100644 --- a/Mathlib/Algebra/Module/Hom.lean +++ b/Mathlib/Algebra/Module/Hom.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.Module.Pi +import Mathlib.Algebra.Module.Basic import Mathlib.Algebra.Group.Hom.Instances #align_import algebra.module.hom from "leanprover-community/mathlib"@"134625f523e737f650a6ea7f0c82a6177e45e622" diff --git a/Mathlib/Algebra/Module/LinearMap.lean b/Mathlib/Algebra/Module/LinearMap.lean index e543896ee0add..6ebe521a7f4d6 100644 --- a/Mathlib/Algebra/Module/LinearMap.lean +++ b/Mathlib/Algebra/Module/LinearMap.lean @@ -209,18 +209,18 @@ instance semilinearMapClass : SemilinearMapClass (M →ₛₗ[σ] M₃) σ M M cases f cases g congr - apply FunLike.coe_injective' + apply DFunLike.coe_injective' exact h map_add f := f.map_add' map_smulₛₗ := LinearMap.map_smul' #align linear_map.semilinear_map_class LinearMap.semilinearMapClass --- Porting note: we don't port specialized `CoeFun` instances if there is `FunLike` instead +-- Porting note: we don't port specialized `CoeFun` instances if there is `DFunLike` instead #noalign LinearMap.has_coe_to_fun -- Porting note: adding this instance prevents a timeout in `ext_ring_op` -instance instFunLike {σ : R →+* S} : FunLike (M →ₛₗ[σ] M₃) M (λ _ ↦ M₃) := - { AddHomClass.toFunLike with } +instance instFunLike {σ : R →+* S} : FunLike (M →ₛₗ[σ] M₃) M M₃ := + { AddHomClass.toDFunLike with } /-- The `DistribMulActionHom` underlying a `LinearMap`. -/ def toDistribMulActionHom (f : M →ₗ[R] M₂) : DistribMulActionHom R M M₂ := @@ -236,7 +236,7 @@ theorem toFun_eq_coe {f : M →ₛₗ[σ] M₃} : f.toFun = (f : M → M₃) := @[ext] theorem ext {f g : M →ₛₗ[σ] M₃} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align linear_map.ext LinearMap.ext /-- Copy of a `LinearMap` with a new `toFun` equal to the old one. Useful to fix definitional @@ -253,7 +253,7 @@ theorem coe_copy (f : M →ₛₗ[σ] M₃) (f' : M → M₃) (h : f' = ⇑f) : #align linear_map.coe_copy LinearMap.coe_copy theorem copy_eq (f : M →ₛₗ[σ] M₃) (f' : M → M₃) (h : f' = ⇑f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align linear_map.copy_eq LinearMap.copy_eq initialize_simps_projections LinearMap (toFun → apply) @@ -319,21 +319,21 @@ theorem isLinear : IsLinearMap R fₗ := variable {fₗ gₗ f g σ} -theorem coe_injective : Injective (FunLike.coe : (M →ₛₗ[σ] M₃) → _) := - FunLike.coe_injective +theorem coe_injective : Injective (DFunLike.coe : (M →ₛₗ[σ] M₃) → _) := + DFunLike.coe_injective #align linear_map.coe_injective LinearMap.coe_injective protected theorem congr_arg {x x' : M} : x = x' → f x = f x' := - FunLike.congr_arg f + DFunLike.congr_arg f #align linear_map.congr_arg LinearMap.congr_arg /-- If two linear maps are equal, they are equal at each point. -/ protected theorem congr_fun (h : f = g) (x : M) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align linear_map.congr_fun LinearMap.congr_fun theorem ext_iff : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align linear_map.ext_iff LinearMap.ext_iff @[simp] @@ -429,19 +429,39 @@ class CompatibleSMul (R S : Type*) [Semiring S] [SMul R M] [Module S M] [SMul R variable {M M₂} -instance (priority := 100) IsScalarTower.compatibleSMul {R S : Type*} [Semiring S] [SMul R S] - [SMul R M] [Module S M] [IsScalarTower R S M] [SMul R M₂] [Module S M₂] [IsScalarTower R S M₂] : +section + +variable {R S : Type*} [Semiring S] [SMul R M] [Module S M] [SMul R M₂] [Module S M₂] + +instance (priority := 100) IsScalarTower.compatibleSMul [SMul R S] + [IsScalarTower R S M] [IsScalarTower R S M₂] : CompatibleSMul M M₂ R S := ⟨fun fₗ c x ↦ by rw [← smul_one_smul S c x, ← smul_one_smul S c (fₗ x), map_smul]⟩ #align linear_map.is_scalar_tower.compatible_smul LinearMap.IsScalarTower.compatibleSMul +instance IsScalarTower.compatibleSMul' [SMul R S] [IsScalarTower R S M] : + CompatibleSMul S M R S where + __ := IsScalarTower.smulHomClass R S M (S →ₗ[S] M) + @[simp] -theorem map_smul_of_tower {R S : Type*} [Semiring S] [SMul R M] [Module S M] [SMul R M₂] - [Module S M₂] [CompatibleSMul M M₂ R S] (fₗ : M →ₗ[S] M₂) (c : R) (x : M) : +theorem map_smul_of_tower [CompatibleSMul M M₂ R S] (fₗ : M →ₗ[S] M₂) (c : R) (x : M) : fₗ (c • x) = c • fₗ x := CompatibleSMul.map_smul fₗ c x #align linear_map.map_smul_of_tower LinearMap.map_smul_of_tower +variable (R R) in +theorem isScalarTower_of_injective [SMul R S] [CompatibleSMul M M₂ R S] [IsScalarTower R S M₂] + (f : M →ₗ[S] M₂) (hf : Function.Injective f) : IsScalarTower R S M where + smul_assoc r s _ := hf <| by rw [f.map_smul_of_tower r, map_smul, map_smul, smul_assoc] + +end + +variable (R) in +theorem isLinearMap_of_compatibleSMul [Module S M] [Module S M₂] [CompatibleSMul M M₂ R S] + (f : M →ₗ[S] M₂) : IsLinearMap R f where + map_add := map_add f + map_smul := map_smul_of_tower f + /-- convert a linear map to an additive map -/ def toAddMonoidHom : M →+ M₃ where toFun := f @@ -499,7 +519,7 @@ end RestrictScalars theorem toAddMonoidHom_injective : Function.Injective (toAddMonoidHom : (M →ₛₗ[σ] M₃) → M →+ M₃) := fun fₗ gₗ h ↦ - ext <| (FunLike.congr_fun h : ∀ x, fₗ.toAddMonoidHom x = gₗ.toAddMonoidHom x) + ext <| (DFunLike.congr_fun h : ∀ x, fₗ.toAddMonoidHom x = gₗ.toAddMonoidHom x) #align linear_map.to_add_monoid_hom_injective LinearMap.toAddMonoidHom_injective /-- If two `σ`-linear maps from `R` are equal on `1`, then they are equal. -/ @@ -935,7 +955,7 @@ theorem comp_add (f g : M →ₛₗ[σ₁₂] M₂) (h : M₂ →ₛₗ[σ₂₃ /-- The type of linear maps is an additive monoid. -/ instance addCommMonoid : AddCommMonoid (M →ₛₗ[σ₁₂] M₂) := - FunLike.coe_injective.addCommMonoid _ rfl (fun _ _ ↦ rfl) fun _ _ ↦ rfl + DFunLike.coe_injective.addCommMonoid _ rfl (fun _ _ ↦ rfl) fun _ _ ↦ rfl /-- The negation of a linear map is linear. -/ instance : Neg (M →ₛₗ[σ₁₂] N₂) := @@ -983,7 +1003,7 @@ theorem comp_sub (f g : M →ₛₗ[σ₁₂] N₂) (h : N₂ →ₛₗ[σ₂₃ /-- The type of linear maps is an additive group. -/ instance addCommGroup : AddCommGroup (M →ₛₗ[σ₁₂] N₂) := - FunLike.coe_injective.addCommGroup _ rfl (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) + DFunLike.coe_injective.addCommGroup _ rfl (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) fun _ _ ↦ rfl end Arithmetic diff --git a/Mathlib/Algebra/Module/LocalizedModule.lean b/Mathlib/Algebra/Module/LocalizedModule.lean index 1f0c6c62a8573..c2a2f20119261 100644 --- a/Mathlib/Algebra/Module/LocalizedModule.lean +++ b/Mathlib/Algebra/Module/LocalizedModule.lean @@ -3,15 +3,15 @@ Copyright (c) 2022 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang, Jujian Zhang -/ -import Mathlib.RingTheory.IsTensorProduct -import Mathlib.RingTheory.Localization.Module +import Mathlib.Algebra.Algebra.Bilinear +import Mathlib.RingTheory.Localization.Basic #align_import algebra.module.localized_module from "leanprover-community/mathlib"@"831c494092374cfe9f50591ed0ac81a25efc5b86" /-! # Localized Module -Given a commutative ring `R`, a multiplicative subset `S ⊆ R` and an `R`-module `M`, we can +Given a commutative semiring `R`, a multiplicative subset `S ⊆ R` and an `R`-module `M`, we can localize `M` by `S`. This gives us a `Localization S`-module. ## Main definitions @@ -30,7 +30,6 @@ localize `M` by `S`. This gives us a `Localization S`-module. we have `mk r s • mk m t = mk (r • m) (s * t)` where `mk r s : Localization S` is localized ring by `S`. * `LocalizedModule.isModule` : `LocalizedModule M S` is a `Localization S`-module. -* `IsLocalizedModule.IsBaseChange` : A localization of modules is a base change. ## Future work @@ -508,35 +507,27 @@ def divBy (s : S) : LocalizedModule S M →ₗ[R] LocalizedModule S M where simp_rw [mk_add_mk, LocalizedModule.liftOn_mk, mk_add_mk, mul_smul, mul_comm _ s, mul_assoc, smul_comm _ s, ← smul_add, mul_left_comm s t₁ t₂, mk_cancel_common_left s] map_smul' r x := by - refine x.inductionOn (fun _ ↦ ?_) + refine x.induction_on (fun _ _ ↦ ?_) dsimp only change liftOn (mk _ _) _ _ = r • (liftOn (mk _ _) _ _) simp_rw [RingHom.toMonoidHom_eq_coe, OneHom.toFun_eq_coe, MonoidHom.toOneHom_coe, - MonoidHom.coe_coe, ZeroHom.coe_mk, liftOn_mk, mul_assoc, ← smul_def] - rfl + MonoidHom.coe_coe, ZeroHom.coe_mk, liftOn_mk, mul_assoc, ← smul_def, algebraMap_smul] #align localized_module.div_by LocalizedModule.divBy theorem divBy_mul_by (s : S) (p : LocalizedModule S M) : divBy s (algebraMap R (Module.End R (LocalizedModule S M)) s p) = p := - p.inductionOn - (by - intro ⟨m, t⟩ - rw [Module.algebraMap_end_apply, divBy_apply] - erw [LocalizedModule.liftOn_mk] - rw [mul_assoc, ← smul_def, ZeroHom.coe_mk, RingHom.toFun_eq_coe, algebraMap_smul, smul'_mk, - ← Submonoid.smul_def, mk_cancel_common_right _ s] - rfl) + p.induction_on fun m t => by + rw [Module.algebraMap_end_apply, divBy_apply] + erw [smul_def] + rw [LocalizedModule.liftOn_mk, mul_assoc, ← smul_def, ZeroHom.coe_mk, RingHom.toFun_eq_coe, + algebraMap_smul, smul'_mk, ← Submonoid.smul_def, mk_cancel_common_right _ s] #align localized_module.div_by_mul_by LocalizedModule.divBy_mul_by theorem mul_by_divBy (s : S) (p : LocalizedModule S M) : algebraMap R (Module.End R (LocalizedModule S M)) s (divBy s p) = p := - p.inductionOn - (by - intro ⟨m, t⟩ - rw [divBy_apply, Module.algebraMap_end_apply] - erw [LocalizedModule.liftOn_mk, smul'_mk] - rw [← Submonoid.smul_def, mk_cancel_common_right _ s] - rfl) + p.induction_on fun m t => by + rw [divBy_apply, Module.algebraMap_end_apply, LocalizedModule.liftOn_mk, smul'_mk, + ← Submonoid.smul_def, mk_cancel_common_right _ s] #align localized_module.mul_by_div_by LocalizedModule.mul_by_divBy end @@ -547,17 +538,21 @@ section IsLocalizedModule universe u v -variable {R : Type*} [CommRing R] (S : Submonoid R) +variable {R : Type*} [CommSemiring R] (S : Submonoid R) variable {M M' M'' : Type*} [AddCommMonoid M] [AddCommMonoid M'] [AddCommMonoid M''] -variable [Module R M] [Module R M'] [Module R M''] (f : M →ₗ[R] M') (g : M →ₗ[R] M'') +variable {A : Type*} [CommSemiring A] [Algebra R A] [Module A M'] [IsLocalization S A] + +variable [Module R M] [Module R M'] [Module R M''] [IsScalarTower R A M'] + +variable (f : M →ₗ[R] M') (g : M →ₗ[R] M'') /-- The characteristic predicate for localized module. `IsLocalizedModule S f` describes that `f : M ⟶ M'` is the localization map identifying `M'` as `LocalizedModule S M`. -/ -class IsLocalizedModule : Prop where +@[mk_iff] class IsLocalizedModule : Prop where map_units : ∀ x : S, IsUnit (algebraMap R (Module.End R M') x) surj' : ∀ y : M', ∃ x : M × S, x.2 • y = f x.1 exists_of_eq : ∀ {x₁ x₂}, f x₁ = f x₂ → ∃ c : S, c • x₁ = c • x₂ @@ -577,6 +572,55 @@ lemma IsLocalizedModule.eq_iff_exists [IsLocalizedModule S f] {x₁ x₂} : apply_fun f at h simp_rw [f.map_smul_of_tower, Submonoid.smul_def, ← Module.algebraMap_end_apply R R] at h exact ((Module.End_isUnit_iff _).mp <| map_units f c).1 h + +theorem IsLocalizedModule.of_linearEquiv (e : M' ≃ₗ[R] M'') [hf : IsLocalizedModule S f] : + IsLocalizedModule S (e ∘ₗ f : M →ₗ[R] M'') where + map_units s := by + rw [show algebraMap R (Module.End R M'') s = e ∘ₗ (algebraMap R (Module.End R M') s) ∘ₗ e.symm + by ext; simp, Module.End_isUnit_iff, LinearMap.coe_comp, LinearMap.coe_comp, + LinearEquiv.coe_coe, LinearEquiv.coe_coe, EquivLike.comp_bijective, EquivLike.bijective_comp] + exact (Module.End_isUnit_iff _).mp <| hf.map_units s + surj' x := by + obtain ⟨p, h⟩ := hf.surj' (e.symm x) + exact ⟨p, by rw [LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply, ← e.congr_arg h, + Submonoid.smul_def, Submonoid.smul_def, LinearEquiv.map_smul, LinearEquiv.apply_symm_apply]⟩ + exists_of_eq h := by + simp_rw [LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply, + EmbeddingLike.apply_eq_iff_eq] at h + exact hf.exists_of_eq h + +variable (M) in +lemma isLocalizedModule_id (R') [CommSemiring R'] [Algebra R R'] [IsLocalization S R'] [Module R' M] + [IsScalarTower R R' M] : IsLocalizedModule S (.id : M →ₗ[R] M) where + map_units s := by + rw [← (Algebra.lsmul R (A := R') R M).commutes]; exact (IsLocalization.map_units R' s).map _ + surj' m := ⟨(m, 1), one_smul _ _⟩ + exists_of_eq h := ⟨1, congr_arg _ h⟩ + +variable {S} in +theorem isLocalizedModule_iff_isLocalization {A Aₛ} [CommSemiring A] [Algebra R A] [CommSemiring Aₛ] + [Algebra A Aₛ] [Algebra R Aₛ] [IsScalarTower R A Aₛ] : + IsLocalizedModule S (IsScalarTower.toAlgHom R A Aₛ).toLinearMap ↔ + IsLocalization (Algebra.algebraMapSubmonoid A S) Aₛ := by + rw [isLocalizedModule_iff, isLocalization_iff] + refine and_congr ?_ (and_congr (forall_congr' fun _ ↦ ?_) (forall₂_congr fun _ _ ↦ ?_)) + · simp_rw [← (Algebra.lmul R Aₛ).commutes, Algebra.lmul_isUnit_iff, Subtype.forall, + Algebra.algebraMapSubmonoid, ← SetLike.mem_coe, Submonoid.coe_map, + Set.ball_image_iff, ← IsScalarTower.algebraMap_apply] + · simp_rw [Prod.exists, Subtype.exists, Algebra.algebraMapSubmonoid] + simp [← IsScalarTower.algebraMap_apply, Submonoid.mk_smul, Algebra.smul_def, mul_comm] + · congr!; simp_rw [Subtype.exists, Algebra.algebraMapSubmonoid]; simp [Algebra.smul_def] + +instance {A Aₛ} [CommSemiring A] [Algebra R A][CommSemiring Aₛ] [Algebra A Aₛ] [Algebra R Aₛ] + [IsScalarTower R A Aₛ] [h : IsLocalization (Algebra.algebraMapSubmonoid A S) Aₛ] : + IsLocalizedModule S (IsScalarTower.toAlgHom R A Aₛ).toLinearMap := + isLocalizedModule_iff_isLocalization.mpr h + +lemma isLocalizedModule_iff_isLocalization' (R') [CommSemiring R'] [Algebra R R'] : + IsLocalizedModule S (Algebra.ofId R R').toLinearMap ↔ IsLocalization S R' := by + convert isLocalizedModule_iff_isLocalization (S := S) (A := R) (Aₛ := R') + exact (Submonoid.map_id S).symm + namespace LocalizedModule /-- @@ -636,12 +680,10 @@ theorem lift'_add (g : M →ₗ[R] M'') (h : ∀ x : S, IsUnit ((algebraMap R (M theorem lift'_smul (g : M →ₗ[R] M'') (h : ∀ x : S, IsUnit ((algebraMap R (Module.End R M'')) x)) (r : R) (m) : r • LocalizedModule.lift' S g h m = LocalizedModule.lift' S g h (r • m) := - m.inductionOn - (by - intro ⟨a, b⟩ - erw [LocalizedModule.lift'_mk, LocalizedModule.smul'_mk, LocalizedModule.lift'_mk] - -- Porting note: We remove `generalize_proofs h1 h2`. This does nothing here. - erw [← map_smul, ← g.map_smul]) + m.induction_on fun a b => by + rw [LocalizedModule.lift'_mk, LocalizedModule.smul'_mk, LocalizedModule.lift'_mk] + -- Porting note: We remove `generalize_proofs h1 h2`. This does nothing here. + rw [← map_smul, ← g.map_smul] #align localized_module.lift'_smul LocalizedModule.lift'_smul /-- @@ -698,19 +740,17 @@ instance localizedModuleIsLocalizedModule : IsLocalizedModule S (LocalizedModule where map_units s := ⟨⟨algebraMap R (Module.End R (LocalizedModule S M)) s, LocalizedModule.divBy s, - FunLike.ext _ _ <| LocalizedModule.mul_by_divBy s, - FunLike.ext _ _ <| LocalizedModule.divBy_mul_by s⟩, - FunLike.ext _ _ fun p => - p.inductionOn <| by + DFunLike.ext _ _ <| LocalizedModule.mul_by_divBy s, + DFunLike.ext _ _ <| LocalizedModule.divBy_mul_by s⟩, + DFunLike.ext _ _ fun p => + p.induction_on <| by intros rfl⟩ surj' p := - p.inductionOn - (by - intro ⟨m, t⟩ - refine' ⟨⟨m, t⟩, _⟩ - erw [LocalizedModule.smul'_mk, LocalizedModule.mkLinearMap_apply, Submonoid.coe_subtype, - LocalizedModule.mk_cancel t]) + p.induction_on fun m t => by + refine' ⟨⟨m, t⟩, _⟩ + erw [LocalizedModule.smul'_mk, LocalizedModule.mkLinearMap_apply, Submonoid.coe_subtype, + LocalizedModule.mk_cancel t] exists_of_eq eq1 := by simpa only [eq_comm, one_smul] using LocalizedModule.mk_eq.mp eq1 #align localized_module_is_localized_module localizedModuleIsLocalizedModule @@ -727,7 +767,7 @@ noncomputable def fromLocalizedModule' : LocalizedModule S M → M' := fun p => rintro ⟨a, b⟩ ⟨a', b'⟩ ⟨c, eq1⟩ dsimp -- Porting note: We remove `generalize_proofs h1 h2`. - erw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, ← map_smul, ← map_smul, + rw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, ← map_smul, ← map_smul, Module.End_algebraMap_isUnit_inv_apply_eq_iff', ← map_smul] exact (IsLocalizedModule.eq_iff_exists S f).mpr ⟨c, eq1.symm⟩) #align is_localized_module.from_localized_module' IsLocalizedModule.fromLocalizedModule' @@ -746,14 +786,12 @@ theorem fromLocalizedModule'_add (x y : LocalizedModule S M) : intro a a' b b' simp only [LocalizedModule.mk_add_mk, fromLocalizedModule'_mk] -- Porting note: We remove `generalize_proofs h1 h2 h3`. - erw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, smul_add, ← map_smul, ← map_smul, + rw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, smul_add, ← map_smul, ← map_smul, ← map_smul, map_add] congr 1 all_goals rw [Module.End_algebraMap_isUnit_inv_apply_eq_iff'] - · erw [mul_smul, f.map_smul] - rfl - · erw [mul_comm, f.map_smul, mul_smul] - rfl) + · simp [mul_smul, Submonoid.smul_def] + · rw [Submonoid.coe_mul, LinearMap.map_smul_of_tower, mul_comm, mul_smul, Submonoid.smul_def]) x y #align is_localized_module.from_localized_module'_add IsLocalizedModule.fromLocalizedModule'_add @@ -790,9 +828,8 @@ theorem fromLocalizedModule.inj : Function.Injective <| fromLocalizedModule S f -- Porting note: We remove `generalize_proofs h1 h2`. rw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, ← LinearMap.map_smul, Module.End_algebraMap_isUnit_inv_apply_eq_iff'] at eq1 - erw [LocalizedModule.mk_eq, ← IsLocalizedModule.eq_iff_exists S f, - f.map_smul, f.map_smul, eq1] - rw [Submonoid.coe_subtype] + rw [LocalizedModule.mk_eq, ← IsLocalizedModule.eq_iff_exists S f, Submonoid.smul_def, + Submonoid.smul_def, f.map_smul, f.map_smul, eq1] #align is_localized_module.from_localized_module.inj IsLocalizedModule.fromLocalizedModule.inj theorem fromLocalizedModule.surj : Function.Surjective <| fromLocalizedModule S f := fun x => @@ -838,13 +875,15 @@ theorem iso_symm_apply' (m : M') (a : M) (b : S) (eq1 : b • m = f a) : (iso_symm_apply_aux S f m).trans <| LocalizedModule.mk_eq.mpr <| by -- Porting note: We remove `generalize_proofs h1`. - erw [← IsLocalizedModule.eq_iff_exists S f, f.map_smul, f.map_smul, ← (surj' _).choose_spec, - ← mul_smul, mul_comm, mul_smul, eq1] + rw [← IsLocalizedModule.eq_iff_exists S f, Submonoid.smul_def, Submonoid.smul_def, f.map_smul, + f.map_smul, ← (surj' _).choose_spec, ← Submonoid.smul_def, ← Submonoid.smul_def, ← mul_smul, + mul_comm, mul_smul, eq1] #align is_localized_module.iso_symm_apply' IsLocalizedModule.iso_symm_apply' theorem iso_symm_comp : (iso S f).symm.toLinearMap.comp f = LocalizedModule.mkLinearMap S M := by - ext m; rw [LinearMap.comp_apply, LocalizedModule.mkLinearMap_apply] - change (iso S f).symm _ = _; rw [iso_symm_apply']; exact one_smul _ _ + ext m + rw [LinearMap.comp_apply, LocalizedModule.mkLinearMap_apply, LinearEquiv.coe_coe, iso_symm_apply'] + exact one_smul _ _ #align is_localized_module.iso_symm_comp IsLocalizedModule.iso_symm_comp /-- @@ -866,15 +905,14 @@ theorem lift_unique (g : M →ₗ[R] M'') (h : ∀ x : S, IsUnit ((algebraMap R (l : M' →ₗ[R] M'') (hl : l.comp f = g) : lift S f g h = l := by dsimp only [IsLocalizedModule.lift] rw [LocalizedModule.lift_unique S g h (l.comp (iso S f).toLinearMap), LinearMap.comp_assoc, - show (iso S f).toLinearMap.comp (iso S f).symm.toLinearMap = LinearMap.id from _, + LinearEquiv.comp_coe, LinearEquiv.symm_trans_self, LinearEquiv.refl_toLinearMap, LinearMap.comp_id] - · rw [LinearEquiv.comp_toLinearMap_symm_eq, LinearMap.id_comp] - · rw [LinearMap.comp_assoc, ← hl] - congr 1 - ext x - rw [LinearMap.comp_apply, LocalizedModule.mkLinearMap_apply, LinearEquiv.coe_coe, iso_apply, - fromLocalizedModule'_mk, Module.End_algebraMap_isUnit_inv_apply_eq_iff, OneMemClass.coe_one, - one_smul] + rw [LinearMap.comp_assoc, ← hl] + congr 1 + ext x + rw [LinearMap.comp_apply, LocalizedModule.mkLinearMap_apply, LinearEquiv.coe_coe, iso_apply, + fromLocalizedModule'_mk, Module.End_algebraMap_isUnit_inv_apply_eq_iff, OneMemClass.coe_one, + one_smul] #align is_localized_module.lift_unique IsLocalizedModule.lift_unique /-- Universal property from localized module: @@ -1045,6 +1083,14 @@ theorem mk_eq_mk' (s : S) (m : M) : LocalizedModule.mk_cancel, LocalizedModule.mkLinearMap_apply] #align is_localized_module.mk_eq_mk' IsLocalizedModule.mk_eq_mk' +variable (A) in +lemma mk'_smul_mk' (x : R) (m : M) (s t : S) : + IsLocalization.mk' A x s • mk' f m t = mk' f (x • m) (s * t) := by + apply smul_injective f (s * t) + conv_lhs => simp only [smul_assoc, mul_smul, smul_comm t] + simp only [mk'_cancel', map_smul, Submonoid.smul_def s] + rw [← smul_assoc, IsLocalization.smul_mk'_self, algebraMap_smul] + variable (S) theorem eq_zero_iff {m : M} : f m = 0 ↔ ∃ s' : S, s' • m = 0 := @@ -1077,8 +1123,7 @@ theorem mkOfAlgebra {R S S' : Type*} [CommRing R] [CommRing S] [CommRing S'] [Al exact (h₁ x x.2).mul_left_cancel e · intro a refine' ⟨((h₁ x x.2).unit⁻¹ : _) * a, _⟩ - change (x : R) • (_ * a) = _ - rw [Algebra.smul_def, ← mul_assoc, IsUnit.mul_val_inv, one_mul] + rw [Module.algebraMap_end_apply, Algebra.smul_def, ← mul_assoc, IsUnit.mul_val_inv, one_mul] · exact h₂ · intros x y dsimp only [AlgHom.toLinearMap_apply] @@ -1089,32 +1134,4 @@ theorem mkOfAlgebra {R S S' : Type*} [CommRing R] [CommRing S] [CommRing S'] [Al end Algebra -variable {A : Type*} - [CommRing A] [Algebra R A] [Module A M'] [IsScalarTower R A M'] [IsLocalization S A] - - -/-- If `(f : M →ₗ[R] M')` is a localization of modules, then the map -`(localization S) × M → N, (s, m) ↦ s • f m` is the tensor product (insomuch as it is the universal -bilinear map). -In particular, there is an isomorphism between `LocalizedModule S M` and `(Localization S) ⊗[R] M` -given by `m/s ↦ (1/s) ⊗ₜ m`. --/ -theorem isBaseChange : IsBaseChange A f := by - refine' IsBaseChange.of_lift_unique _ (fun Q _ _ _ _ g ↦ _) - have := IsLocalizedModule.is_universal S f g <| by - intro s - simp_rw [Module.End_isUnit_iff, Function.bijective_iff_existsUnique, - Module.algebraMap_end_apply] - intro q - refine' ⟨(IsLocalization.mk' _ 1 s : A) • q, _, _⟩ - · simp only [← smul_assoc, IsLocalization.smul_mk'_self, map_one, one_smul] - · rintro q rfl - simp only [smul_comm _ (s : R), ← smul_assoc, IsLocalization.smul_mk'_self, map_one, one_smul] - rcases this with ⟨ℓ, rfl, h₂⟩ - refine' ⟨ℓ.extendScalarsOfIsLocalization S A, by simp, fun g'' h ↦ _⟩ - ext x - simp [← h₂ (LinearMap.restrictScalars R g'') h] - -end IsLocalizedModule - end IsLocalizedModule diff --git a/Mathlib/Algebra/Module/Projective.lean b/Mathlib/Algebra/Module/Projective.lean index d22165fbe00ed..77cdfa3f4fa02 100644 --- a/Mathlib/Algebra/Module/Projective.lean +++ b/Mathlib/Algebra/Module/Projective.lean @@ -90,7 +90,7 @@ theorem projective_def : theorem projective_def' : Projective R P ↔ ∃ s : P →ₗ[R] P →₀ R, Finsupp.total P P R id ∘ₗ s = .id := - by simp_rw [projective_def, FunLike.ext_iff, Function.LeftInverse, comp_apply, id_apply] + by simp_rw [projective_def, DFunLike.ext_iff, Function.LeftInverse, comp_apply, id_apply] #align module.projective_def' Module.projective_def' /-- A projective R-module has the property that maps from it lift along surjections. -/ @@ -140,7 +140,7 @@ instance [h : ∀ i : ι, Projective R (A i)] : Projective R (Π₀ i, A i) := .of_lifting_property'' fun f hf ↦ by classical choose g hg using fun i ↦ projective_lifting_property f (DFinsupp.lsingle i) hf - replace hg : ∀ i x, f (g i x) = DFinsupp.single i x := fun i ↦ FunLike.congr_fun (hg i) + replace hg : ∀ i x, f (g i x) = DFinsupp.single i x := fun i ↦ DFunLike.congr_fun (hg i) refine ⟨DFinsupp.coprodMap g, ?_⟩ ext i x j simp only [comp_apply, id_apply, DFinsupp.lsingle_apply, DFinsupp.coprodMap_apply_single, hg] diff --git a/Mathlib/Algebra/Module/Submodule/Basic.lean b/Mathlib/Algebra/Module/Submodule/Basic.lean index 268a0cda51cdf..f266313cd6edb 100644 --- a/Mathlib/Algebra/Module/Submodule/Basic.lean +++ b/Mathlib/Algebra/Module/Submodule/Basic.lean @@ -382,70 +382,6 @@ theorem vadd_def [VAdd M α] (g : p) (m : α) : g +ᵥ m = (g : M) +ᵥ m := end AddAction -section RestrictScalars - -variable (S) [Semiring S] [Module S M] [Module R M] [SMul S R] [IsScalarTower S R M] - -/-- `V.restrict_scalars S` is the `S`-submodule of the `S`-module given by restriction of scalars, -corresponding to `V`, an `R`-submodule of the original `R`-module. --/ -def restrictScalars (V : Submodule R M) : Submodule S M where - carrier := V - zero_mem' := V.zero_mem - smul_mem' c _ h := V.smul_of_tower_mem c h - add_mem' hx hy := V.add_mem hx hy -#align submodule.restrict_scalars Submodule.restrictScalars - -@[simp] -theorem coe_restrictScalars (V : Submodule R M) : (V.restrictScalars S : Set M) = V := - rfl -#align submodule.coe_restrict_scalars Submodule.coe_restrictScalars - -@[simp] -theorem restrictScalars_mem (V : Submodule R M) (m : M) : m ∈ V.restrictScalars S ↔ m ∈ V := - Iff.refl _ -#align submodule.restrict_scalars_mem Submodule.restrictScalars_mem - -@[simp] -theorem restrictScalars_self (V : Submodule R M) : V.restrictScalars R = V := - SetLike.coe_injective rfl -#align submodule.restrict_scalars_self Submodule.restrictScalars_self - -variable (R M) - -theorem restrictScalars_injective : - Function.Injective (restrictScalars S : Submodule R M → Submodule S M) := fun _ _ h => - ext <| Set.ext_iff.1 (SetLike.ext'_iff.1 h : _) -#align submodule.restrict_scalars_injective Submodule.restrictScalars_injective - -@[simp] -theorem restrictScalars_inj {V₁ V₂ : Submodule R M} : - restrictScalars S V₁ = restrictScalars S V₂ ↔ V₁ = V₂ := - (restrictScalars_injective S _ _).eq_iff -#align submodule.restrict_scalars_inj Submodule.restrictScalars_inj - -/-- Even though `p.restrictScalars S` has type `Submodule S M`, it is still an `R`-module. -/ -instance restrictScalars.origModule (p : Submodule R M) : Module R (p.restrictScalars S) := - (by infer_instance : Module R p) -#align submodule.restrict_scalars.orig_module Submodule.restrictScalars.origModule - -instance restrictScalars.isScalarTower (p : Submodule R M) : - IsScalarTower S R (p.restrictScalars S) where - smul_assoc r s x := Subtype.ext <| smul_assoc r s (x : M) -#align submodule.restrict_scalars.is_scalar_tower Submodule.restrictScalars.isScalarTower - -/-- `restrictScalars S` is an embedding of the lattice of `R`-submodules into -the lattice of `S`-submodules. -/ -@[simps] -def restrictScalarsEmbedding : Submodule R M ↪o Submodule S M where - toFun := restrictScalars S - inj' := restrictScalars_injective S R M - map_rel_iff' := by simp [SetLike.le_def] -#align submodule.restrict_scalars_embedding Submodule.restrictScalarsEmbedding -#align submodule.restrict_scalars_embedding_apply Submodule.restrictScalarsEmbedding_apply - -end RestrictScalars - end AddCommMonoid section AddCommGroup @@ -521,7 +457,7 @@ protected theorem add_mem_iff_right : x ∈ p → (x + y ∈ p ↔ y ∈ p) := #align submodule.add_mem_iff_right Submodule.add_mem_iff_right protected theorem coe_neg (x : p) : ((-x : p) : M) = -x := - AddSubgroupClass.coe_neg _ + NegMemClass.coe_neg _ #align submodule.coe_neg Submodule.coe_neg protected theorem coe_sub (x y : p) : (↑(x - y) : M) = ↑x - ↑y := diff --git a/Mathlib/Algebra/Module/Submodule/Lattice.lean b/Mathlib/Algebra/Module/Submodule/Lattice.lean index aa9d30f411965..0ffc60f5138ed 100644 --- a/Mathlib/Algebra/Module/Submodule/Lattice.lean +++ b/Mathlib/Algebra/Module/Submodule/Lattice.lean @@ -3,7 +3,8 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov -/ -import Mathlib.Algebra.Module.Submodule.LinearMap +import Mathlib.Algebra.Module.Equiv +import Mathlib.Algebra.Module.Submodule.Basic import Mathlib.Algebra.PUnitInstances #align_import algebra.module.submodule.lattice from "leanprover-community/mathlib"@"f7fc89d5d5ff1db2d1242c7bb0e9062ce47ef47c" @@ -63,27 +64,16 @@ theorem bot_toAddSubmonoid : (⊥ : Submodule R M).toAddSubmonoid = ⊥ := rfl #align submodule.bot_to_add_submonoid Submodule.bot_toAddSubmonoid -section - -variable (R) - @[simp] -theorem restrictScalars_bot : restrictScalars S (⊥ : Submodule R M) = ⊥ := - rfl -#align submodule.restrict_scalars_bot Submodule.restrictScalars_bot +lemma bot_toAddSubgroup {R M} [Ring R] [AddCommGroup M] [Module R M] : + (⊥ : Submodule R M).toAddSubgroup = ⊥ := rfl +variable (R) in @[simp] theorem mem_bot {x : M} : x ∈ (⊥ : Submodule R M) ↔ x = 0 := Set.mem_singleton_iff #align submodule.mem_bot Submodule.mem_bot -end - -@[simp] -theorem restrictScalars_eq_bot_iff {p : Submodule R M} : restrictScalars S p = ⊥ ↔ p = ⊥ := by - simp [SetLike.ext_iff] -#align submodule.restrict_scalars_eq_bot_iff Submodule.restrictScalars_eq_bot_iff - instance uniqueBot : Unique (⊥ : Submodule R M) := ⟨inferInstance, fun x ↦ Subtype.ext <| (mem_bot R).1 x.mem⟩ #align submodule.unique_bot Submodule.uniqueBot @@ -162,27 +152,15 @@ theorem top_toAddSubmonoid : (⊤ : Submodule R M).toAddSubmonoid = ⊤ := rfl #align submodule.top_to_add_submonoid Submodule.top_toAddSubmonoid +@[simp] +lemma top_toAddSubgroup {R M} [Ring R] [AddCommGroup M] [Module R M] : + (⊤ : Submodule R M).toAddSubgroup = ⊤ := rfl + @[simp] theorem mem_top {x : M} : x ∈ (⊤ : Submodule R M) := trivial #align submodule.mem_top Submodule.mem_top -section - -variable (R) - -@[simp] -theorem restrictScalars_top : restrictScalars S (⊤ : Submodule R M) = ⊤ := - rfl -#align submodule.restrict_scalars_top Submodule.restrictScalars_top - -end - -@[simp] -theorem restrictScalars_eq_top_iff {p : Submodule R M} : restrictScalars S p = ⊤ ↔ p = ⊤ := by - simp [SetLike.ext_iff] -#align submodule.restrict_scalars_eq_top_iff Submodule.restrictScalars_eq_top_iff - instance : OrderTop (Submodule R M) where top := ⊤ le_top _ _ _ := trivial @@ -340,6 +318,28 @@ theorem mem_sSup_of_mem {S : Set (Submodule R M)} {s : Submodule R M} (hs : s exact this #align submodule.mem_Sup_of_mem Submodule.mem_sSup_of_mem +@[simp] +theorem toAddSubmonoid_sSup (s : Set (Submodule R M)) : + (sSup s).toAddSubmonoid = sSup (toAddSubmonoid '' s) := by + let p : Submodule R M := + { toAddSubmonoid := sSup (toAddSubmonoid '' s) + smul_mem' := fun t {m} h ↦ by + simp_rw [AddSubsemigroup.mem_carrier, AddSubmonoid.mem_toSubsemigroup, sSup_eq_iSup'] at h ⊢ + refine AddSubmonoid.iSup_induction' + (C := fun x _ ↦ t • x ∈ ⨆ p : toAddSubmonoid '' s, (p : AddSubmonoid M)) ?_ ?_ + (fun x y _ _ ↦ ?_) h + · rintro ⟨-, ⟨p : Submodule R M, hp : p ∈ s, rfl⟩⟩ x (hx : x ∈ p) + suffices p.toAddSubmonoid ≤ ⨆ q : toAddSubmonoid '' s, (q : AddSubmonoid M) by + exact this (smul_mem p t hx) + apply le_sSup + rw [Subtype.range_coe_subtype] + exact ⟨p, hp, rfl⟩ + · simpa only [smul_zero] using zero_mem _ + · simp_rw [smul_add]; exact add_mem } + refine le_antisymm (?_ : sSup s ≤ p) ?_ + · exact sSup_le fun q hq ↦ le_sSup <| Set.mem_image_of_mem toAddSubmonoid hq + · exact sSup_le fun _ ⟨q, hq, hq'⟩ ↦ hq'.symm ▸ le_sSup hq + variable (R) @[simp] diff --git a/Mathlib/Algebra/Module/Submodule/LinearMap.lean b/Mathlib/Algebra/Module/Submodule/LinearMap.lean index a0084077ab8ad..2df774051997e 100644 --- a/Mathlib/Algebra/Module/Submodule/LinearMap.lean +++ b/Mathlib/Algebra/Module/Submodule/LinearMap.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Module.Equiv +import Mathlib.Algebra.Module.LinearMap import Mathlib.Algebra.Module.Submodule.Basic #align_import algebra.module.submodule.basic from "leanprover-community/mathlib"@"8130e5155d637db35907c272de9aec9dc851c03a" @@ -105,22 +105,6 @@ instance [AddAction M α] : AddAction p α := end AddAction -section RestrictScalars - -variable (S) [Semiring S] [Module S M] [Module R M] [SMul S R] [IsScalarTower S R M] -variable (R M) - -/-- Turning `p : Submodule R M` into an `S`-submodule gives the same module structure -as turning it into a type and adding a module structure. -/ -@[simps (config := { simpRhs := true })] -def restrictScalarsEquiv (p : Submodule R M) : p.restrictScalars S ≃ₗ[R] p := - { AddEquiv.refl p with - map_smul' := fun _ _ => rfl } -#align submodule.restrict_scalars_equiv Submodule.restrictScalarsEquiv -#align submodule.restrict_scalars_equiv_symm_apply Submodule.restrictScalarsEquiv_symm_apply - -end RestrictScalars - end AddCommMonoid end Submodule @@ -269,7 +253,7 @@ theorem coeFn_sum {ι : Type*} (t : Finset ι) (f : ι → M →ₛₗ[σ₁₂] ⇑(∑ i in t, f i) = ∑ i in t, (f i : M → M₂) := _root_.map_sum (show AddMonoidHom (M →ₛₗ[σ₁₂] M₂) (M → M₂) - from { toFun := FunLike.coe, + from { toFun := DFunLike.coe, map_zero' := rfl map_add' := fun _ _ => rfl }) _ _ #align linear_map.coe_fn_sum LinearMap.coeFn_sum diff --git a/Mathlib/Algebra/Module/Submodule/Localization.lean b/Mathlib/Algebra/Module/Submodule/Localization.lean new file mode 100644 index 0000000000000..338116da4bbda --- /dev/null +++ b/Mathlib/Algebra/Module/Submodule/Localization.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.Algebra.Module.LocalizedModule +import Mathlib.LinearAlgebra.Quotient + +/-! +# Localization of Submodules + +Results about localizations of submodules and quotient modules are provided in this file. + +## Main result +- `Submodule.localized`: + The localization of an `R`-submodule of `M` at `p` viewed as an `Rₚ`-submodule of `Mₚ`. +- `Submodule.toLocalized`: + The localization map of a submodule `M' →ₗ[R] M'.localized p`. +- `Submodule.toLocalizedQuotient`: + The localization map of a quotient module `M ⧸ M' →ₗ[R] LocalizedModule p M ⧸ M'.localized p`. + +## TODO +- Statements regarding the exactness of localization. +- Connection with flatness. + +-/ + +open nonZeroDivisors + +universe u u' v v' + +variable {R : Type u} (S : Type u') {M : Type v} {N : Type v'} +variable [CommRing R] [CommRing S] [AddCommGroup M] [AddCommGroup N] [Module R M] +variable [Module R M] [Module R N] [Algebra R S] [Module S N] [IsScalarTower R S N] +variable (p : Submonoid R) [IsLocalization p S] (f : M →ₗ[R] N) [IsLocalizedModule p f] +variable (hp : p ≤ R⁰) + +variable (M' : Submodule R M) + +/-- Let `S` be the localization of `R` at `p` and `N` be the localization of `M` at `p`. +This is the localization of an `R`-submodule of `M` viewed as an `S`-submodule of `N`. -/ +def Submodule.localized' : Submodule S N where + carrier := { x | ∃ m ∈ M', ∃ s : p, IsLocalizedModule.mk' f m s = x } + add_mem' := fun {x} {y} ⟨m, hm, s, hx⟩ ⟨n, hn, t, hy⟩ ↦ ⟨t • m + s • n, add_mem (M'.smul_mem t hm) + (M'.smul_mem s hn), s * t, by rw [← hx, ← hy, IsLocalizedModule.mk'_add_mk']⟩ + zero_mem' := ⟨0, zero_mem _, 1, by simp⟩ + smul_mem' := fun r x h ↦ by + have ⟨m, hm, s, hx⟩ := h + have ⟨y, t, hyt⟩ := IsLocalization.mk'_surjective p r + exact ⟨y • m, M'.smul_mem y hm, t * s, by simp [← hyt, ← hx, IsLocalizedModule.mk'_smul_mk']⟩ + +/-- The localization of an `R`-submodule of `M` at `p` viewed as an `Rₚ`-submodule of `Mₚ`. -/ +abbrev Submodule.localized : Submodule (Localization p) (LocalizedModule p M) := + M'.localized' (Localization p) p (LocalizedModule.mkLinearMap p M) + +/-- The localization map of a submodule. -/ +@[simps!] +def Submodule.toLocalized' : M' →ₗ[R] M'.localized' S p f := + f.restrict (q := (M'.localized' S p f).restrictScalars R) (fun x hx ↦ ⟨x, hx, 1, by simp⟩) + +/-- The localization map of a submodule. -/ +abbrev Submodule.toLocalized : M' →ₗ[R] M'.localized p := + M'.toLocalized' (Localization p) p (LocalizedModule.mkLinearMap p M) + +instance Submodule.isLocalizedModule : IsLocalizedModule p (M'.toLocalized' S p f) where + map_units x := by + simp_rw [Module.End_isUnit_iff] + constructor + · exact fun _ _ e ↦ Subtype.ext + (IsLocalizedModule.smul_injective f x (congr_arg Subtype.val e)) + · rintro m + use (IsLocalization.mk' S 1 x) • m + rw [Module.algebraMap_end_apply, ← smul_assoc, IsLocalization.smul_mk'_one, + IsLocalization.mk'_self', one_smul] + surj' := by + rintro ⟨y, x, hx, s, rfl⟩ + exact ⟨⟨⟨x, hx⟩, s⟩, by ext; simp⟩ + exists_of_eq e := by simpa [Subtype.ext_iff] using + IsLocalizedModule.exists_of_eq (S := p) (f := f) (congr_arg Subtype.val e) + +/-- The localization map of a quotient module. -/ +def Submodule.toLocalizedQuotient' : M ⧸ M' →ₗ[R] N ⧸ M'.localized' S p f := + Submodule.mapQ M' ((M'.localized' S p f).restrictScalars R) f (fun x hx ↦ ⟨x, hx, 1, by simp⟩) + +/-- The localization map of a quotient module. -/ +abbrev Submodule.toLocalizedQuotient : M ⧸ M' →ₗ[R] LocalizedModule p M ⧸ M'.localized p := + M'.toLocalizedQuotient' (Localization p) p (LocalizedModule.mkLinearMap p M) + +@[simp] +lemma Submodule.toLocalizedQuotient'_mk (x : M) : + M'.toLocalizedQuotient' S p f (Submodule.Quotient.mk x) = Submodule.Quotient.mk (f x) := rfl + +open Submodule Submodule.Quotient IsLocalization in +instance IsLocalizedModule.toLocalizedQuotient' (M' : Submodule R M) : + IsLocalizedModule p (M'.toLocalizedQuotient' S p f) where + map_units x := by + refine (Module.End_isUnit_iff _).mpr ⟨fun m n e ↦ ?_, fun m ↦ ⟨(IsLocalization.mk' S 1 x) • m, + by rw [Module.algebraMap_end_apply, ← smul_assoc, smul_mk'_one, mk'_self', one_smul]⟩⟩ + obtain ⟨⟨m, rfl⟩, n, rfl⟩ := PProd.mk (mk_surjective _ m) (mk_surjective _ n) + simp only [Module.algebraMap_end_apply, ← mk_smul, Submodule.Quotient.eq, ← smul_sub] at e + replace e := Submodule.smul_mem _ (IsLocalization.mk' S 1 x) e + rwa [smul_comm, ← smul_assoc, smul_mk'_one, mk'_self', one_smul, ← Submodule.Quotient.eq] at e + surj' y := by + obtain ⟨y, rfl⟩ := mk_surjective _ y + obtain ⟨⟨y, s⟩, rfl⟩ := IsLocalizedModule.mk'_surjective p f y + exact ⟨⟨Submodule.Quotient.mk y, s⟩, + by simp only [Function.uncurry_apply_pair, toLocalizedQuotient'_mk, ← mk_smul, mk'_cancel']⟩ + exists_of_eq {m n} e := by + obtain ⟨⟨m, rfl⟩, n, rfl⟩ := PProd.mk (mk_surjective _ m) (mk_surjective _ n) + obtain ⟨x, hx, s, hs⟩ : f (m - n) ∈ _ := by simpa [Submodule.Quotient.eq] using e + obtain ⟨c, hc⟩ := exists_of_eq (S := p) (show f (s • (m - n)) = f x by simp [-map_sub, ← hs]) + exact ⟨c * s, by simpa only [← Quotient.mk_smul, Submodule.Quotient.eq, + ← smul_sub, mul_smul, hc] using M'.smul_mem c hx⟩ + +instance (M' : Submodule R M) : IsLocalizedModule p (M'.toLocalizedQuotient p) := + IsLocalizedModule.toLocalizedQuotient' _ _ _ _ diff --git a/Mathlib/Algebra/Module/Submodule/Map.lean b/Mathlib/Algebra/Module/Submodule/Map.lean index e49158181b800..99e4a373fdff3 100644 --- a/Mathlib/Algebra/Module/Submodule/Map.lean +++ b/Mathlib/Algebra/Module/Submodule/Map.lean @@ -6,6 +6,7 @@ Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Fréd -/ import Mathlib.Algebra.Module.Submodule.Lattice +import Mathlib.Algebra.Module.Submodule.LinearMap /-! # `map` and `comap` for `Submodule`s @@ -166,6 +167,12 @@ theorem coe_equivMapOfInjective_apply (f : F) (i : Injective f) (p : Submodule R rfl #align submodule.coe_equiv_map_of_injective_apply Submodule.coe_equivMapOfInjective_apply +@[simp] +theorem map_equivMapOfInjective_symm_apply (f : F) (i : Injective f) (p : Submodule R M) + (x : p.map f) : f ((equivMapOfInjective f i p).symm x) = x := by + rw [← LinearEquiv.apply_symm_apply (equivMapOfInjective f i p) x, coe_equivMapOfInjective_apply, + i.eq_iff, LinearEquiv.apply_symm_apply] + /-- The pullback of a submodule `p ⊆ M₂` along `f : M → M₂` -/ def comap (f : F) (p : Submodule R₂ M₂) : Submodule R M := { p.toAddSubmonoid.comap f with diff --git a/Mathlib/Algebra/Module/Submodule/RestrictScalars.lean b/Mathlib/Algebra/Module/Submodule/RestrictScalars.lean new file mode 100644 index 0000000000000..4d695134ccf88 --- /dev/null +++ b/Mathlib/Algebra/Module/Submodule/RestrictScalars.lean @@ -0,0 +1,127 @@ +/- +Copyright (c) 2024 Oliver Nash. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Nathaniel Thomas, Jeremy Avigad, Johannes Hölzl, Mario Carneiro, Andrew Yang, + Johannes Hölzl, Kevin Buzzard, Yury Kudryashov +-/ +import Mathlib.Algebra.Module.Submodule.Lattice +import Mathlib.Order.Hom.CompleteLattice + +/-! + +# Restriction of scalars for submodules + +If semiring `S` acts on a semiring `R` and `M` is a module over both (compatibly with this action) +then we can turn an `R`-submodule into an `S`-submodule by forgetting the action of `R`. We call +this restriction of scalars for submodules. + +## Main definitions: + * `Submodule.restrictScalars`: regard an `R`-submodule as an `S`-submodule if `S` acts on `R` + +-/ + +namespace Submodule + +variable (S : Type*) {R M : Type*} [Semiring R] [AddCommMonoid M] [Semiring S] + [Module S M] [Module R M] [SMul S R] [IsScalarTower S R M] + +/-- `V.restrict_scalars S` is the `S`-submodule of the `S`-module given by restriction of scalars, +corresponding to `V`, an `R`-submodule of the original `R`-module. +-/ +def restrictScalars (V : Submodule R M) : Submodule S M where + carrier := V + zero_mem' := V.zero_mem + smul_mem' c _ h := V.smul_of_tower_mem c h + add_mem' hx hy := V.add_mem hx hy +#align submodule.restrict_scalars Submodule.restrictScalars + +@[simp] +theorem coe_restrictScalars (V : Submodule R M) : (V.restrictScalars S : Set M) = V := + rfl +#align submodule.coe_restrict_scalars Submodule.coe_restrictScalars + +@[simp] +theorem toAddSubmonoid_restrictScalars (V : Submodule R M) : + (V.restrictScalars S).toAddSubmonoid = V.toAddSubmonoid := + rfl + +@[simp] +theorem restrictScalars_mem (V : Submodule R M) (m : M) : m ∈ V.restrictScalars S ↔ m ∈ V := + Iff.refl _ +#align submodule.restrict_scalars_mem Submodule.restrictScalars_mem + +@[simp] +theorem restrictScalars_self (V : Submodule R M) : V.restrictScalars R = V := + SetLike.coe_injective rfl +#align submodule.restrict_scalars_self Submodule.restrictScalars_self + +variable (R M) + +theorem restrictScalars_injective : + Function.Injective (restrictScalars S : Submodule R M → Submodule S M) := fun _ _ h => + ext <| Set.ext_iff.1 (SetLike.ext'_iff.1 h : _) +#align submodule.restrict_scalars_injective Submodule.restrictScalars_injective + +@[simp] +theorem restrictScalars_inj {V₁ V₂ : Submodule R M} : + restrictScalars S V₁ = restrictScalars S V₂ ↔ V₁ = V₂ := + (restrictScalars_injective S _ _).eq_iff +#align submodule.restrict_scalars_inj Submodule.restrictScalars_inj + +/-- Even though `p.restrictScalars S` has type `Submodule S M`, it is still an `R`-module. -/ +instance restrictScalars.origModule (p : Submodule R M) : Module R (p.restrictScalars S) := + (by infer_instance : Module R p) +#align submodule.restrict_scalars.orig_module Submodule.restrictScalars.origModule + +instance restrictScalars.isScalarTower (p : Submodule R M) : + IsScalarTower S R (p.restrictScalars S) where + smul_assoc r s x := Subtype.ext <| smul_assoc r s (x : M) +#align submodule.restrict_scalars.is_scalar_tower Submodule.restrictScalars.isScalarTower + +/-- `restrictScalars S` is an embedding of the lattice of `R`-submodules into +the lattice of `S`-submodules. -/ +@[simps] +def restrictScalarsEmbedding : Submodule R M ↪o Submodule S M where + toFun := restrictScalars S + inj' := restrictScalars_injective S R M + map_rel_iff' := by simp [SetLike.le_def] +#align submodule.restrict_scalars_embedding Submodule.restrictScalarsEmbedding +#align submodule.restrict_scalars_embedding_apply Submodule.restrictScalarsEmbedding_apply + +/-- Turning `p : Submodule R M` into an `S`-submodule gives the same module structure +as turning it into a type and adding a module structure. -/ +@[simps (config := { simpRhs := true })] +def restrictScalarsEquiv (p : Submodule R M) : p.restrictScalars S ≃ₗ[R] p := + { AddEquiv.refl p with + map_smul' := fun _ _ => rfl } +#align submodule.restrict_scalars_equiv Submodule.restrictScalarsEquiv +#align submodule.restrict_scalars_equiv_symm_apply Submodule.restrictScalarsEquiv_symm_apply + +@[simp] +theorem restrictScalars_bot : restrictScalars S (⊥ : Submodule R M) = ⊥ := + rfl +#align submodule.restrict_scalars_bot Submodule.restrictScalars_bot + +@[simp] +theorem restrictScalars_eq_bot_iff {p : Submodule R M} : restrictScalars S p = ⊥ ↔ p = ⊥ := by + simp [SetLike.ext_iff] +#align submodule.restrict_scalars_eq_bot_iff Submodule.restrictScalars_eq_bot_iff + +@[simp] +theorem restrictScalars_top : restrictScalars S (⊤ : Submodule R M) = ⊤ := + rfl +#align submodule.restrict_scalars_top Submodule.restrictScalars_top + +@[simp] +theorem restrictScalars_eq_top_iff {p : Submodule R M} : restrictScalars S p = ⊤ ↔ p = ⊤ := by + simp [SetLike.ext_iff] +#align submodule.restrict_scalars_eq_top_iff Submodule.restrictScalars_eq_top_iff + +/-- If ring `S` acts on a ring `R` and `M` is a module over both (compatibly with this action) then +we can turn an `R`-submodule into an `S`-submodule by forgetting the action of `R`. -/ +def restrictScalarsLatticeHom : CompleteLatticeHom (Submodule R M) (Submodule S M) where + toFun := restrictScalars S + map_sInf' s := by ext; simp + map_sSup' s := by rw [← toAddSubmonoid_eq, toAddSubmonoid_sSup, ← Set.image_comp]; simp + +end Submodule diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index e9982ba7de835..175b3b3361f61 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -720,6 +720,19 @@ theorem noZeroSMulDivisors_iff_torsion_eq_bot : NoZeroSMulDivisors R M ↔ torsi exact ⟨⟨a, mem_nonZeroDivisors_of_ne_zero ha⟩, hax⟩ } #align submodule.no_zero_smul_divisors_iff_torsion_eq_bot Submodule.noZeroSMulDivisors_iff_torsion_eq_bot +lemma torsion_int {G} [AddCommGroup G] : + (torsion ℤ G).toAddSubgroup = AddCommGroup.torsion G := by + ext x + refine ((isOfFinAddOrder_iff_zsmul_eq_zero (x := x)).trans ?_).symm + simp [mem_nonZeroDivisors_iff_ne_zero] + +lemma AddMonoid.IsTorsionFree_iff_noZeroSMulDivisors {G : Type*} [AddCommGroup G] : + AddMonoid.IsTorsionFree G ↔ NoZeroSMulDivisors ℤ G := by + rw [Submodule.noZeroSMulDivisors_iff_torsion_eq_bot, + AddMonoid.isTorsionFree_iff_torsion_eq_bot, + ← Submodule.toAddSubgroup_injective.eq_iff, + Submodule.torsion_int, Submodule.bot_toAddSubgroup] + end Torsion namespace QuotientTorsion diff --git a/Mathlib/Algebra/Module/Zlattice.lean b/Mathlib/Algebra/Module/Zlattice.lean index 78231025e212e..392cd9916fb30 100644 --- a/Mathlib/Algebra/Module/Zlattice.lean +++ b/Mathlib/Algebra/Module/Zlattice.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Xavier Roblot -/ import Mathlib.LinearAlgebra.FreeModule.PID +import Mathlib.LinearAlgebra.FreeModule.Finite.Basic import Mathlib.MeasureTheory.Group.FundamentalDomain import Mathlib.MeasureTheory.Measure.Lebesgue.EqHaar import Mathlib.RingTheory.Localization.Module @@ -244,7 +245,7 @@ theorem fundamentalDomain_isBounded [Finite ι] [HasSolidNorm K] : theorem vadd_mem_fundamentalDomain [Fintype ι] (y : span ℤ (Set.range b)) (x : E) : y +ᵥ x ∈ fundamentalDomain b ↔ y = -floor b x := by - rw [Subtype.ext_iff, ← add_right_inj x, AddSubgroupClass.coe_neg, ← sub_eq_add_neg, ← fract_apply, + rw [Subtype.ext_iff, ← add_right_inj x, NegMemClass.coe_neg, ← sub_eq_add_neg, ← fract_apply, ← fract_zspan_add b _ (Subtype.mem y), add_comm, ← vadd_eq_add, ← vadd_def, eq_comm, ← fract_eq_self] #align zspan.vadd_mem_fundamental_domain Zspan.vadd_mem_fundamentalDomain @@ -418,7 +419,7 @@ theorem Zlattice.module_free : Module.Free ℤ L := by have : NoZeroSMulDivisors ℤ L := by change NoZeroSMulDivisors ℤ (AddSubgroup.toIntSubmodule L) exact noZeroSMulDivisors _ - exact Module.free_of_finite_type_torsion_free' + infer_instance open FiniteDimensional @@ -464,7 +465,7 @@ theorem Zlattice.rank : finrank ℤ L = finrank K E := by Finset.sdiff_eq_empty_iff_subset] at h replace h := Finset.card_le_card h rwa [not_lt, h_card, ← topEquiv.finrank_eq, ← h_spanE, ← ht_span, - finrank_span_set_eq_card _ ht_lin] + finrank_span_set_eq_card ht_lin] -- Assume that `e ∪ {v}` is not `ℤ`-linear independent then we get the contradiction suffices ¬ LinearIndependent ℤ (fun x : ↥(insert v (Set.range e)) => (x : E)) by contrapose! this @@ -500,6 +501,6 @@ theorem Zlattice.rank : finrank ℤ L = finrank K E := by · -- To prove that `finrank K E ≤ finrank ℤ L`, we use the fact `b` generates `E` over `K` -- and thus `finrank K E ≤ card b = finrank ℤ L` rw [← topEquiv.finrank_eq, ← h_spanE] - convert finrank_span_le_card (K := K) (Set.range b) + convert finrank_span_le_card (R := K) (Set.range b) end Zlattice diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index 8788d413f6369..0414c168ef1cb 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -459,7 +459,7 @@ theorem single_commute_single [Mul G] {a₁ a₂ : G} {b₁ b₂ : k} theorem single_commute [Mul G] {a : G} {b : k} (ha : ∀ a', Commute a a') (hb : ∀ b', Commute b b') : ∀ f : MonoidAlgebra k G, Commute (single a b) f := suffices AddMonoidHom.mulLeft (single a b) = AddMonoidHom.mulRight (single a b) from - FunLike.congr_fun this + DFunLike.congr_fun this addHom_ext' fun a' => AddMonoidHom.ext fun b' => single_commute_single (ha a') (hb b') @[simp] @@ -612,7 +612,7 @@ theorem liftNC_smul [MulOneClass G] {R : Type*} [Semiring R] (f : k →+* R) (g suffices : (liftNC (↑f) g).comp (smulAddHom k (MonoidAlgebra k G) c) = (AddMonoidHom.mulLeft (f c)).comp (liftNC (↑f) g) - exact FunLike.congr_fun this φ + exact DFunLike.congr_fun this φ -- Porting note: `ext` couldn't a find appropriate theorem. refine addHom_ext' fun a => AddMonoidHom.ext fun b => ?_ -- Porting note: `reducible` cannot be `local` so the proof gets more complex. @@ -685,7 +685,7 @@ theorem nonUnitalAlgHom_ext [DistribMulAction k A] {φ₁ φ₂ : MonoidAlgebra @[ext high] theorem nonUnitalAlgHom_ext' [DistribMulAction k A] {φ₁ φ₂ : MonoidAlgebra k G →ₙₐ[k] A} (h : φ₁.toMulHom.comp (ofMagma k G) = φ₂.toMulHom.comp (ofMagma k G)) : φ₁ = φ₂ := - nonUnitalAlgHom_ext k <| FunLike.congr_fun h + nonUnitalAlgHom_ext k <| DFunLike.congr_fun h #align monoid_algebra.non_unital_alg_hom_ext' MonoidAlgebra.nonUnitalAlgHom_ext' /-- The functor `G ↦ MonoidAlgebra k G`, from the category of magmas to the category of non-unital, @@ -792,7 +792,7 @@ theorem ringHom_ext' {R} [Semiring k] [MulOneClass G] [Semiring R] {f g : Monoid (h_of : (f : MonoidAlgebra k G →* R).comp (of k G) = (g : MonoidAlgebra k G →* R).comp (of k G)) : f = g := - ringHom_ext (RingHom.congr_fun h₁) (FunLike.congr_fun h_of) + ringHom_ext (RingHom.congr_fun h₁) (DFunLike.congr_fun h_of) #align monoid_algebra.ring_hom_ext' MonoidAlgebra.ringHom_ext' /-- The instance `Algebra k (MonoidAlgebra A G)` whenever we have `Algebra k A`. @@ -879,7 +879,7 @@ theorem algHom_ext' ⦃φ₁ φ₂ : MonoidAlgebra k G →ₐ[k] A⦄ (h : (φ₁ : MonoidAlgebra k G →* A).comp (of k G) = (φ₂ : MonoidAlgebra k G →* A).comp (of k G)) : φ₁ = φ₂ := - algHom_ext <| FunLike.congr_fun h + algHom_ext <| DFunLike.congr_fun h #align monoid_algebra.alg_hom_ext' MonoidAlgebra.algHom_ext' variable (k G A) @@ -1875,7 +1875,7 @@ theorem ringHom_ext' {R} [Semiring k] [AddMonoid G] [Semiring R] {f g : k[G] → (h₁ : f.comp singleZeroRingHom = g.comp singleZeroRingHom) (h_of : (f : k[G] →* R).comp (of k G) = (g : k[G] →* R).comp (of k G)) : f = g := - ringHom_ext (RingHom.congr_fun h₁) (FunLike.congr_fun h_of) + ringHom_ext (RingHom.congr_fun h₁) (DFunLike.congr_fun h_of) #align add_monoid_algebra.ring_hom_ext' AddMonoidAlgebra.ringHom_ext' section Opposite @@ -1987,7 +1987,7 @@ theorem algHom_ext ⦃φ₁ φ₂ : k[G] →ₐ[k] A⦄ theorem algHom_ext' ⦃φ₁ φ₂ : k[G] →ₐ[k] A⦄ (h : (φ₁ : k[G] →* A).comp (of k G) = (φ₂ : k[G] →* A).comp (of k G)) : φ₁ = φ₂ := - algHom_ext <| FunLike.congr_fun h + algHom_ext <| DFunLike.congr_fun h #align add_monoid_algebra.alg_hom_ext' AddMonoidAlgebra.algHom_ext' variable (k G A) diff --git a/Mathlib/Algebra/MonoidAlgebra/Degree.lean b/Mathlib/Algebra/MonoidAlgebra/Degree.lean index 1503775afe947..3e5043ad13f6b 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Degree.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Degree.lean @@ -102,19 +102,15 @@ variable [Add A] [Add B] [Add T] [CovariantClass B B (· + ·) (· ≤ ·)] theorem sup_support_mul_le {degb : A → B} (degbm : ∀ {a b}, degb (a + b) ≤ degb a + degb b) (f g : R[A]) : - (f * g).support.sup degb ≤ f.support.sup degb + g.support.sup degb := by - refine' (Finset.sup_mono <| support_mul _ _).trans _ - simp_rw [Finset.sup_biUnion, Finset.sup_singleton] - refine' Finset.sup_le fun fd fds => Finset.sup_le fun gd gds => degbm.trans <| add_le_add _ _ <;> - exact Finset.le_sup ‹_› + (f * g).support.sup degb ≤ f.support.sup degb + g.support.sup degb := + (Finset.sup_mono <| support_mul _ _).trans <| Finset.sup_add_le.2 fun _fd fds _gd gds ↦ + degbm.trans <| add_le_add (Finset.le_sup fds) (Finset.le_sup gds) #align add_monoid_algebra.sup_support_mul_le AddMonoidAlgebra.sup_support_mul_le theorem le_inf_support_mul {degt : A → T} (degtm : ∀ {a b}, degt a + degt b ≤ degt (a + b)) (f g : R[A]) : - f.support.inf degt + g.support.inf degt ≤ (f * g).support.inf degt := by - refine' OrderDual.ofDual_le_ofDual.mpr <| sup_support_mul_le _ f g - intros a b - exact OrderDual.ofDual_le_ofDual.mp degtm + f.support.inf degt + g.support.inf degt ≤ (f * g).support.inf degt := + sup_support_mul_le (B := Tᵒᵈ) degtm f g #align add_monoid_algebra.le_inf_support_mul AddMonoidAlgebra.le_inf_support_mul end AddOnly diff --git a/Mathlib/Algebra/MonoidAlgebra/Division.lean b/Mathlib/Algebra/MonoidAlgebra/Division.lean index 93e831282febc..6b12e0599bb8e 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Division.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Division.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.Algebra.MonoidAlgebra.Basic -import Mathlib.Data.Finsupp.Order #align_import algebra.monoid_algebra.division from "leanprover-community/mathlib"@"72c366d0475675f1309d3027d3d7d47ee4423951" diff --git a/Mathlib/Algebra/MonoidAlgebra/Grading.lean b/Mathlib/Algebra/MonoidAlgebra/Grading.lean index f5c16d37fc29e..2c27e0a171d4e 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Grading.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Grading.lean @@ -100,17 +100,12 @@ instance gradeBy.gradedMonoid [AddMonoid M] [AddMonoid ι] [CommSemiring R] (f : SetLike.GradedMonoid (gradeBy R f : ι → Submodule R R[M]) where one_mem m h := by rw [one_def] at h - by_cases H : (1 : R) = (0 : R) - · rw [H, single, Finsupp.single_zero] at h - cases h - · rw [Finsupp.support_single_ne_zero _ H, Finset.mem_singleton] at h - rw [h, AddMonoidHom.map_zero] + obtain rfl : m = 0 := Finset.mem_singleton.1 <| Finsupp.support_single_subset h + apply map_zero mul_mem i j a b ha hb c hc := by - set h := support_mul a b hc - simp only [Finset.mem_biUnion] at h - rcases h with ⟨ma, ⟨hma, ⟨mb, ⟨hmb, hmc⟩⟩⟩⟩ - rw [← ha ma hma, ← hb mb hmb, Finset.mem_singleton.mp hmc] - apply AddMonoidHom.map_add + obtain ⟨ma, hma, mb, hmb, rfl⟩ : ∃ y ∈ a.support, ∃ z ∈ b.support, y + z = c := + Finset.mem_add.1 <| support_mul a b hc + rw [map_add, ha ma hma, hb mb hmb] #align add_monoid_algebra.grade_by.graded_monoid AddMonoidAlgebra.gradeBy.gradedMonoid instance grade.gradedMonoid [AddMonoid M] [CommSemiring R] : diff --git a/Mathlib/Algebra/MonoidAlgebra/Ideal.lean b/Mathlib/Algebra/MonoidAlgebra/Ideal.lean index 3bbe854b730d6..1b9981715cba3 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Ideal.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Ideal.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.MonoidAlgebra.Division +import Mathlib.Algebra.MonoidAlgebra.Basic import Mathlib.RingTheory.Ideal.Basic #align_import algebra.monoid_algebra.ideal from "leanprover-community/mathlib"@"72c366d0475675f1309d3027d3d7d47ee4423951" diff --git a/Mathlib/Algebra/MonoidAlgebra/NoZeroDivisors.lean b/Mathlib/Algebra/MonoidAlgebra/NoZeroDivisors.lean index 226b04d52247f..92a8748c06f1e 100644 --- a/Mathlib/Algebra/MonoidAlgebra/NoZeroDivisors.lean +++ b/Mathlib/Algebra/MonoidAlgebra/NoZeroDivisors.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.Algebra.MonoidAlgebra.Support +import Mathlib.Algebra.MonoidAlgebra.Basic import Mathlib.Algebra.Group.UniqueProds #align_import algebra.monoid_algebra.no_zero_divisors from "leanprover-community/mathlib"@"3e067975886cf5801e597925328c335609511b1a" diff --git a/Mathlib/Algebra/MonoidAlgebra/Support.lean b/Mathlib/Algebra/MonoidAlgebra/Support.lean index b56b9d6eda8ef..b4964b5c57347 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Support.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Support.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ import Mathlib.Algebra.MonoidAlgebra.Basic +import Mathlib.Data.Finset.Pointwise #align_import algebra.monoid_algebra.support from "leanprover-community/mathlib"@"16749fc4661828cba18cd0f4e3c5eb66a8e80598" @@ -11,6 +12,7 @@ import Mathlib.Algebra.MonoidAlgebra.Basic # Lemmas about the support of a finitely supported function -/ +open scoped Pointwise universe u₁ u₂ u₃ @@ -20,36 +22,23 @@ open Finset Finsupp variable {k : Type u₁} {G : Type u₂} [Semiring k] +theorem support_mul [Mul G] [DecidableEq G] (a b : MonoidAlgebra k G) : + (a * b).support ⊆ a.support * b.support := + support_sum.trans <| biUnion_subset.2 fun _x hx ↦ + support_sum.trans <| biUnion_subset.2 fun _y hy ↦ + support_single_subset.trans <| singleton_subset_iff.2 <| mem_image₂_of_mem hx hy +#align monoid_algebra.support_mul MonoidAlgebra.support_mul + theorem support_single_mul_subset [DecidableEq G] [Mul G] (f : MonoidAlgebra k G) (r : k) (a : G) : - (single a r * f : MonoidAlgebra k G).support ⊆ Finset.image (a * ·) f.support := by - intro x hx - contrapose hx - have : ∀ y, a * y = x → f y = 0 := by - simpa only [not_and', mem_image, mem_support_iff, exists_prop, not_exists, - Classical.not_not] using hx - simp only [mem_support_iff, mul_apply, sum_single_index, zero_mul, ite_self, sum_zero, - Classical.not_not] - exact - Finset.sum_eq_zero - (by - simp (config := { contextual := true }) only [this, mem_support_iff, mul_zero, Ne.def, - ite_eq_right_iff, eq_self_iff_true, imp_true_iff]) + (single a r * f : MonoidAlgebra k G).support ⊆ Finset.image (a * ·) f.support := + (support_mul _ _).trans <| (Finset.image₂_subset_right support_single_subset).trans <| by + rw [Finset.image₂_singleton_left] #align monoid_algebra.support_single_mul_subset MonoidAlgebra.support_single_mul_subset theorem support_mul_single_subset [DecidableEq G] [Mul G] (f : MonoidAlgebra k G) (r : k) (a : G) : - (f * single a r).support ⊆ Finset.image (· * a) f.support := by - intro x hx - contrapose hx - have : ∀ y, y * a = x → f y = 0 := by - simpa only [not_and', mem_image, mem_support_iff, exists_prop, not_exists, - Classical.not_not] using hx - simp only [mem_support_iff, mul_apply, sum_single_index, zero_mul, ite_self, sum_zero, - Classical.not_not] - exact - Finset.sum_eq_zero - (by - simp (config := { contextual := true }) only [this, sum_single_index, ite_eq_right_iff, - eq_self_iff_true, imp_true_iff, zero_mul]) + (f * single a r).support ⊆ Finset.image (· * a) f.support := + (support_mul _ _).trans <| (Finset.image₂_subset_left support_single_subset).trans <| by + rw [Finset.image₂_singleton_right] #align monoid_algebra.support_mul_single_subset MonoidAlgebra.support_mul_single_subset theorem support_single_mul_eq_image [DecidableEq G] [Mul G] (f : MonoidAlgebra k G) {r : k} @@ -72,13 +61,6 @@ theorem support_mul_single_eq_image [DecidableEq G] [Mul G] (f : MonoidAlgebra k Finsupp.sum_ite_eq', Ne.def, not_false_iff, if_true, mul_zero, ite_self, sum_zero, rx.eq_iff] #align monoid_algebra.support_mul_single_eq_image MonoidAlgebra.support_mul_single_eq_image -theorem support_mul [Mul G] [DecidableEq G] (a b : MonoidAlgebra k G) : - (a * b).support ⊆ a.support.biUnion fun a₁ => b.support.biUnion fun a₂ => {a₁ * a₂} := - Subset.trans support_sum <| - biUnion_mono fun _ _ => - Subset.trans support_sum <| biUnion_mono fun _a₂ _ => support_single_subset -#align monoid_algebra.support_mul MonoidAlgebra.support_mul - theorem support_mul_single [Mul G] [IsRightCancelMul G] (f : MonoidAlgebra k G) (r : k) (hr : ∀ y, y * r = 0 ↔ y = 0) (x : G) : (f * single x r).support = f.support.map (mulRightEmbedding x) := by @@ -97,6 +79,13 @@ theorem support_single_mul [Mul G] [IsLeftCancelMul G] (f : MonoidAlgebra k G) ( mem_map, mulLeftEmbedding_apply] #align monoid_algebra.support_single_mul MonoidAlgebra.support_single_mul +lemma support_one_subset [One G] : (1 : MonoidAlgebra k G).support ⊆ 1 := + Finsupp.support_single_subset + +@[simp] +lemma support_one [One G] [NeZero (1 : k)] : (1 : MonoidAlgebra k G).support = 1 := + Finsupp.support_single_ne_zero _ one_ne_zero + section Span variable [MulOneClass G] @@ -118,7 +107,7 @@ open Finset Finsupp MulOpposite variable {k : Type u₁} {G : Type u₂} [Semiring k] theorem support_mul [DecidableEq G] [Add G] (a b : k[G]) : - (a * b).support ⊆ a.support.biUnion fun a₁ => b.support.biUnion fun a₂ => {a₁ + a₂} := + (a * b).support ⊆ a.support + b.support := @MonoidAlgebra.support_mul k (Multiplicative G) _ _ _ _ _ #align add_monoid_algebra.support_mul AddMonoidAlgebra.support_mul @@ -134,6 +123,12 @@ theorem support_single_mul [Add G] [IsLeftCancelAdd G] (f : k[G]) (r : k) MonoidAlgebra.support_single_mul (G := Multiplicative G) _ _ hr _ #align add_monoid_algebra.support_single_mul AddMonoidAlgebra.support_single_mul +lemma support_one_subset [Zero G] : (1 : k[G]).support ⊆ 0 := Finsupp.support_single_subset + +@[simp] +lemma support_one [Zero G] [NeZero (1 : k)] : (1 : k[G]).support = 0 := + Finsupp.support_single_ne_zero _ one_ne_zero + section Span /-- An element of `k[G]` is in the submodule generated by its support. -/ diff --git a/Mathlib/Algebra/Opposites.lean b/Mathlib/Algebra/Opposites.lean index 20757a0240041..18df91311400d 100644 --- a/Mathlib/Algebra/Opposites.lean +++ b/Mathlib/Algebra/Opposites.lean @@ -120,7 +120,7 @@ theorem unop_comp_op : (unop : αᵐᵒᵖ → α) ∘ op = id := /-- A recursor for `MulOpposite`. Use as `induction x using MulOpposite.rec'`. -/ @[to_additive (attr := simp, elab_as_elim) "A recursor for `AddOpposite`. Use as `induction x using AddOpposite.rec'`."] -protected def rec' {F : ∀ _ : αᵐᵒᵖ, Sort v} (h : ∀ X, F (op X)) : ∀ X, F X := fun X => h (unop X) +protected def rec' {F : αᵐᵒᵖ → Sort v} (h : ∀ X, F (op X)) : ∀ X, F X := fun X => h (unop X) #align mul_opposite.rec MulOpposite.rec' #align add_opposite.rec AddOpposite.rec' @@ -171,7 +171,7 @@ theorem unop_surjective : Surjective (unop : αᵐᵒᵖ → α) := #align add_opposite.unop_surjective AddOpposite.unop_surjective @[to_additive (attr := simp)] -theorem op_inj {x y : α} : op x = op y ↔ x = y := iff_of_eq $ PreOpposite.op'.injEq _ _ +theorem op_inj {x y : α} : op x = op y ↔ x = y := iff_of_eq <| PreOpposite.op'.injEq _ _ #align mul_opposite.op_inj MulOpposite.op_inj #align add_opposite.op_inj AddOpposite.op_inj @@ -217,20 +217,20 @@ instance add [Add α] : Add αᵐᵒᵖ where add x y := op (unop x + unop y) instance sub [Sub α] : Sub αᵐᵒᵖ where sub x y := op (unop x - unop y) -instance neg [Neg α] : Neg αᵐᵒᵖ where neg x := op $ -unop x +instance neg [Neg α] : Neg αᵐᵒᵖ where neg x := op <| -unop x instance involutiveNeg [InvolutiveNeg α] : InvolutiveNeg αᵐᵒᵖ := - { MulOpposite.neg α with neg_neg := fun _ => unop_injective $ neg_neg _ } + { MulOpposite.neg α with neg_neg := fun _ => unop_injective <| neg_neg _ } @[to_additive] instance mul [Mul α] : Mul αᵐᵒᵖ where mul x y := op (unop y * unop x) @[to_additive] -instance inv [Inv α] : Inv αᵐᵒᵖ where inv x := op $ (unop x)⁻¹ +instance inv [Inv α] : Inv αᵐᵒᵖ where inv x := op <| (unop x)⁻¹ @[to_additive] instance involutiveInv [InvolutiveInv α] : InvolutiveInv αᵐᵒᵖ := - { MulOpposite.inv α with inv_inv := fun _ => unop_injective $ inv_inv _ } + { MulOpposite.inv α with inv_inv := fun _ => unop_injective <| inv_inv _ } @[to_additive] instance smul (R : Type*) [SMul R α] : SMul R αᵐᵒᵖ where smul c x := op (c • unop x) @@ -342,11 +342,11 @@ theorem op_eq_zero_iff [Zero α] (a : α) : op a = (0 : αᵐᵒᵖ) ↔ a = (0 #align mul_opposite.op_eq_zero_iff MulOpposite.op_eq_zero_iff theorem unop_ne_zero_iff [Zero α] (a : αᵐᵒᵖ) : a.unop ≠ (0 : α) ↔ a ≠ (0 : αᵐᵒᵖ) := - not_congr $ unop_eq_zero_iff a + not_congr <| unop_eq_zero_iff a #align mul_opposite.unop_ne_zero_iff MulOpposite.unop_ne_zero_iff theorem op_ne_zero_iff [Zero α] (a : α) : op a ≠ (0 : αᵐᵒᵖ) ↔ a ≠ (0 : α) := - not_congr $ op_eq_zero_iff a + not_congr <| op_eq_zero_iff a #align mul_opposite.op_ne_zero_iff MulOpposite.op_ne_zero_iff @[to_additive (attr := simp, nolint simpComm)] @@ -406,7 +406,7 @@ theorem unop_mul [Mul α] (a b : αᵃᵒᵖ) : unop (a * b) = unop a * unop b : instance inv [Inv α] : Inv αᵃᵒᵖ where inv a := op (unop a)⁻¹ instance involutiveInv [InvolutiveInv α] : InvolutiveInv αᵃᵒᵖ := - { AddOpposite.inv with inv_inv := fun _ => unop_injective $ inv_inv _ } + { AddOpposite.inv with inv_inv := fun _ => unop_injective <| inv_inv _ } @[simp] theorem op_inv [Inv α] (a : α) : op a⁻¹ = (op a)⁻¹ := diff --git a/Mathlib/Algebra/Order/AbsoluteValue.lean b/Mathlib/Algebra/Order/AbsoluteValue.lean index 34226cc5fcb0b..a20907054974b 100644 --- a/Mathlib/Algebra/Order/AbsoluteValue.lean +++ b/Mathlib/Algebra/Order/AbsoluteValue.lean @@ -74,7 +74,7 @@ theorem coe_mk (f : R →ₙ* S) {h₁ h₂ h₃} : (AbsoluteValue.mk f h₁ h @[ext] theorem ext ⦃f g : AbsoluteValue R S⦄ : (∀ x, f x = g x) → f = g := - FunLike.ext _ _ + DFunLike.ext _ _ #align absolute_value.ext AbsoluteValue.ext /-- See Note [custom simps projection]. -/ @@ -84,10 +84,10 @@ def Simps.apply (f : AbsoluteValue R S) : R → S := initialize_simps_projections AbsoluteValue (toMulHom_toFun → apply) -/-- Helper instance for when there's too many metavariables to apply `FunLike.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.has_coe_to_fun` directly. -/ instance : CoeFun (AbsoluteValue R S) fun _ => R → S := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[simp] theorem coe_toMulHom : ⇑abv.toMulHom = abv := diff --git a/Mathlib/Algebra/Order/Archimedean.lean b/Mathlib/Algebra/Order/Archimedean.lean index 002d784a47374..d6dfd3195037b 100644 --- a/Mathlib/Algebra/Order/Archimedean.lean +++ b/Mathlib/Algebra/Order/Archimedean.lean @@ -5,7 +5,6 @@ Authors: Mario Carneiro -/ import Mathlib.Data.Int.LeastGreatest import Mathlib.Data.Rat.Floor -import Mathlib.Algebra.Order.Field.Power #align_import algebra.order.archimedean from "leanprover-community/mathlib"@"6f413f3f7330b94c92a5a27488fdc74e6d483a78" @@ -51,7 +50,8 @@ instance OrderDual.archimedean [OrderedAddCommGroup α] [Archimedean α] : Archi theorem exists_lt_nsmul [OrderedAddCommMonoid M] [Archimedean M] [CovariantClass M M (· + ·) (· < ·)] {a : M} (ha : 0 < a) (b : M) : ∃ n : ℕ, b < n • a := - let ⟨k, hk⟩ := Archimedean.arch b ha; ⟨k + 1, hk.trans_lt $ nsmul_lt_nsmul_left ha k.lt_succ_self⟩ + let ⟨k, hk⟩ := Archimedean.arch b ha + ⟨k + 1, hk.trans_lt <| nsmul_lt_nsmul_left ha k.lt_succ_self⟩ section LinearOrderedAddCommGroup diff --git a/Mathlib/Algebra/Order/Field/Basic.lean b/Mathlib/Algebra/Order/Field/Basic.lean index 13d56dcdd2c8d..b61deefbd42c0 100644 --- a/Mathlib/Algebra/Order/Field/Basic.lean +++ b/Mathlib/Algebra/Order/Field/Basic.lean @@ -3,11 +3,10 @@ Copyright (c) 2014 Robert Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Lewis, Leonardo de Moura, Mario Carneiro, Floris van Doorn -/ -import Mathlib.Order.Bounds.OrderIso import Mathlib.Algebra.Field.Basic import Mathlib.Algebra.Order.Field.Defs -import Mathlib.Algebra.GroupPower.Order -import Mathlib.Data.Int.Cast.Basic +import Mathlib.Algebra.Order.Ring.Abs +import Mathlib.Order.Bounds.OrderIso #align_import algebra.order.field.basic from "leanprover-community/mathlib"@"84771a9f5f0bd5e5d6218811556508ddf476dcbd" diff --git a/Mathlib/Algebra/Order/Field/Pi.lean b/Mathlib/Algebra/Order/Field/Pi.lean index b72795a6edaaa..ae51ebf39547f 100644 --- a/Mathlib/Algebra/Order/Field/Pi.lean +++ b/Mathlib/Algebra/Order/Field/Pi.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Order.Field.Basic -import Mathlib.Data.Fintype.Lattice +import Mathlib.Data.Finset.Lattice +import Mathlib.Data.Fintype.Card #align_import algebra.order.field.pi from "leanprover-community/mathlib"@"509de852e1de55e1efa8eacfa11df0823f26f226" diff --git a/Mathlib/Algebra/Order/Field/Power.lean b/Mathlib/Algebra/Order/Field/Power.lean index bb5d8eac43933..5e95fdc7abf9e 100644 --- a/Mathlib/Algebra/Order/Field/Power.lean +++ b/Mathlib/Algebra/Order/Field/Power.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Parity import Mathlib.Algebra.CharZero.Lemmas import Mathlib.Algebra.GroupWithZero.Power import Mathlib.Algebra.Order.Field.Basic +import Mathlib.Algebra.Order.Ring.Pow import Mathlib.Data.Int.Bitwise #align_import algebra.order.field.power from "leanprover-community/mathlib"@"acb3d204d4ee883eb686f45d486a2a6811a01329" @@ -219,8 +220,7 @@ theorem zpow_bit0_abs (a : α) (p : ℤ) : |a| ^ bit0 p = a ^ bit0 p := (even_bit0 _).zpow_abs _ #align zpow_bit0_abs zpow_bit0_abs -/-! ### Miscellaneous lemmmas -/ - +/-! ### Bernoulli's inequality -/ /-- Bernoulli's inequality reformulated to estimate `(n : α)`. -/ theorem Nat.cast_le_pow_sub_div_sub (H : 1 < a) (n : ℕ) : (n : α) ≤ (a ^ n - 1) / (a - 1) := diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index 97f604bb717cd..b460e02b2ffa8 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -8,7 +8,7 @@ import Mathlib.Data.Int.Lemmas import Mathlib.Data.Int.CharZero import Mathlib.Data.Set.Intervals.Group import Mathlib.Data.Set.Lattice -import Mathlib.Init.Meta.WellFoundedTactics +import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Tactic.Abel import Mathlib.Tactic.Linarith import Mathlib.Tactic.Positivity @@ -965,7 +965,7 @@ theorem fract_nonneg (a : α) : 0 ≤ fract a := /-- The fractional part of `a` is positive if and only if `a ≠ ⌊a⌋`. -/ lemma fract_pos : 0 < fract a ↔ a ≠ ⌊a⌋ := - (fract_nonneg a).lt_iff_ne.trans $ ne_comm.trans sub_ne_zero + (fract_nonneg a).lt_iff_ne.trans <| ne_comm.trans sub_ne_zero #align int.fract_pos Int.fract_pos theorem fract_lt_one (a : α) : fract a < 1 := diff --git a/Mathlib/Algebra/Order/Floor/Div.lean b/Mathlib/Algebra/Order/Floor/Div.lean new file mode 100644 index 0000000000000..087f0c6729abc --- /dev/null +++ b/Mathlib/Algebra/Order/Floor/Div.lean @@ -0,0 +1,269 @@ +/- +Copyright (c) 2023 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies +-/ +import Mathlib.Algebra.Order.Module.Defs +import Mathlib.Algebra.Order.Pi +import Mathlib.Data.Finsupp.Order +import Mathlib.Data.Nat.Order.Basic +import Mathlib.Order.GaloisConnection + +/-! +# Flooring, ceiling division + +This file defines division rounded up and down. + +The setup is an ordered monoid `α` acting on an ordered monoid `β`. If `a : α`, `b : β`, we would +like to be able to "divide" `b` by `a`, namely find `c : β` such that `a • c = b`. +This is of course not always possible, but in some cases at least there is a least `c` such that +`b ≤ a • c` and a greatest `c` such that `a • c ≤ b`. We call the first one the "ceiling division +of `b` by `a`" and the second one the "flooring division of `b` by `a`" + +If `α` and `β` are both `ℕ`, then one can check that our flooring and ceiling divisions really are +the floor and ceil of the exact division. +If `α` is `ℕ` and `β` is the functions `ι → ℕ`, then the flooring and ceiling divisions are taken +pointwise. + +In order theory terms, those operations are respectively the right and left adjoints to the map +`b ↦ a • b`. + +## Main declarations + +* `FloorDiv`: Typeclass for the existence of a flooring division, denoted `b ⌊/⌋ a`. +* `CeilDiv`: Typeclass for the existence of a ceiling division, denoted `b ⌈/⌉ a`. + +Note in both cases we only allow dividing by positive inputs. We enforce the following junk values: +* `b ⌊/⌋ a = b ⌈/⌉ a = 0` if `a ≤ 0` +* `0 ⌊/⌋ a = 0 ⌈/⌉ a = 0` + +## Notation + +* `b ⌊/⌋ a` for the flooring division of `b` by `a` +* `b ⌈/⌉ a` for the ceiling division of `b` by `a` + +## TODO + +* `norm_num` extension +* Prove `⌈a / b⌉ = a ⌈/⌉ b` when `a, b : ℕ` +-/ + +variable {ι α β : Type*} + +section OrderedAddCommMonoid +variable (α β) [OrderedAddCommMonoid α] [OrderedAddCommMonoid β] [SMulZeroClass α β] + +/-- Typeclass for division rounded down. For each `a > 0`, this asserts the existence of a right +adjoint to the map `b ↦ a • b : β → β`. -/ +class FloorDiv where + /-- Flooring division. If `a > 0`, then `b ⌊/⌋ a` is the greatest `c` such that `a • c ≤ b`. -/ + floorDiv : β → α → β + /-- Do not use this. Use `gc_floorDiv_smul` or `gc_floorDiv_mul` instead. -/ + protected floorDiv_gc ⦃a⦄ : 0 < a → GaloisConnection (a • ·) (floorDiv · a) + /-- Do not use this. Use `floorDiv_nonpos` instead. -/ + protected floorDiv_nonpos ⦃a⦄ : a ≤ 0 → ∀ b, floorDiv b a = 0 + /-- Do not use this. Use `zero_floorDiv` instead. -/ + protected zero_floorDiv (a) : floorDiv 0 a = 0 + +/-- Typeclass for division rounded up. For each `a > 0`, this asserts the existence of a left +adjoint to the map `b ↦ a • b : β → β`. -/ +class CeilDiv where + /-- Ceiling division. If `a > 0`, then `b ⌈/⌉ a` is the least `c` such that `b ≤ a • c`. -/ + ceilDiv : β → α → β + /-- Do not use this. Use `gc_smul_ceilDiv` or `gc_mul_ceilDiv` instead. -/ + protected ceilDiv_gc ⦃a⦄ : 0 < a → GaloisConnection (ceilDiv · a) (a • ·) + /-- Do not use this. Use `ceilDiv_nonpos` instead. -/ + protected ceilDiv_nonpos ⦃a⦄ : a ≤ 0 → ∀ b, ceilDiv b a = 0 + /-- Do not use this. Use `zero_ceilDiv` instead. -/ + protected zero_ceilDiv (a) : ceilDiv 0 a = 0 + +@[inherit_doc] infixl:70 " ⌊/⌋ " => FloorDiv.floorDiv +@[inherit_doc] infixl:70 " ⌈/⌉ " => CeilDiv.ceilDiv + +variable {α β} + +section FloorDiv +variable [FloorDiv α β] {a : α} {b c : β} + +lemma gc_floorDiv_smul (ha : 0 < a) : GaloisConnection (a • · : β → β) (· ⌊/⌋ a) := + FloorDiv.floorDiv_gc ha + +@[simp] lemma le_floorDiv_iff_smul_le (ha : 0 < a) : c ≤ b ⌊/⌋ a ↔ a • c ≤ b := + (gc_floorDiv_smul ha _ _).symm + +@[simp] lemma floorDiv_of_nonpos (ha : a ≤ 0) (b : β) : b ⌊/⌋ a = 0 := FloorDiv.floorDiv_nonpos ha _ +lemma floorDiv_zero (b : β) : b ⌊/⌋ (0 : α) = 0 := by simp +@[simp] lemma zero_floorDiv (a : α) : (0 : β) ⌊/⌋ a = 0 := FloorDiv.zero_floorDiv _ + +lemma smul_floorDiv_le (ha : 0 < a) : a • (b ⌊/⌋ a) ≤ b := (le_floorDiv_iff_smul_le ha).1 le_rfl + +end FloorDiv + +section CeilDiv +variable [CeilDiv α β] {a : α} {b c : β} + +lemma gc_smul_ceilDiv (ha : 0 < a) : GaloisConnection (· ⌈/⌉ a) (a • · : β → β) := + CeilDiv.ceilDiv_gc ha + +@[simp] +lemma ceilDiv_le_iff_le_smul (ha : 0 < a) : b ⌈/⌉ a ≤ c ↔ b ≤ a • c := gc_smul_ceilDiv ha _ _ + +@[simp] lemma ceilDiv_of_nonpos (ha : a ≤ 0) (b : β) : b ⌈/⌉ a = 0 := CeilDiv.ceilDiv_nonpos ha _ +lemma ceilDiv_zero (b : β) : b ⌈/⌉ (0 : α) = 0 := by simp +@[simp] lemma zero_ceilDiv (a : α) : (0 : β) ⌈/⌉ a = 0 := CeilDiv.zero_ceilDiv _ + +lemma le_smul_ceilDiv (ha : 0 < a) : b ≤ a • (b ⌈/⌉ a) := (ceilDiv_le_iff_le_smul ha).1 le_rfl + +end CeilDiv +end OrderedAddCommMonoid + +section LinearOrderedAddCommMonoid +variable [LinearOrderedAddCommMonoid α] [OrderedAddCommMonoid β] [SMulZeroClass α β] + [PosSMulReflectLE α β] [FloorDiv α β] [CeilDiv α β] {a : α} {b c : β} + +lemma floorDiv_le_ceilDiv : b ⌊/⌋ a ≤ b ⌈/⌉ a := by + obtain ha | ha := le_or_lt a 0 + · simp [ha] + · exact le_of_smul_le_smul_left ((smul_floorDiv_le ha).trans $ le_smul_ceilDiv ha) ha + +end LinearOrderedAddCommMonoid + +section OrderedSemiring +variable [OrderedSemiring α] [OrderedAddCommMonoid β] [MulActionWithZero α β] + +section FloorDiv +variable [FloorDiv α β] {a : α} + +@[simp] lemma floorDiv_one [Nontrivial α] (b : β) : b ⌊/⌋ (1 : α) = b := + eq_of_forall_le_iff $ fun c ↦ by simp [zero_lt_one' α] + +@[simp] lemma smul_floorDiv [PosSMulMono α β] [PosSMulReflectLE α β] (ha : 0 < a) (b : β) : + a • b ⌊/⌋ a = b := + eq_of_forall_le_iff $ by simp [smul_le_smul_iff_of_pos_left, ha] + +end FloorDiv + +section CeilDiv +variable [CeilDiv α β] {a : α} + +@[simp] lemma ceilDiv_one [Nontrivial α] (b : β) : b ⌈/⌉ (1 : α) = b := + eq_of_forall_ge_iff $ fun c ↦ by simp [zero_lt_one' α] + +@[simp] lemma smul_ceilDiv [PosSMulMono α β] [PosSMulReflectLE α β] (ha : 0 < a) (b : β) : + a • b ⌈/⌉ a = b := + eq_of_forall_ge_iff $ by simp [smul_le_smul_iff_of_pos_left, ha] + +end CeilDiv + +section FloorDiv +variable [FloorDiv α α] {a b c : α} + +lemma gc_floorDiv_mul (ha : 0 < a) : GaloisConnection (a * ·) (· ⌊/⌋ a) := gc_floorDiv_smul ha +lemma le_floorDiv_iff_mul_le (ha : 0 < a) : c ≤ b ⌊/⌋ a ↔ a • c ≤ b := le_floorDiv_iff_smul_le ha + +end FloorDiv + +section CeilDiv +variable [CeilDiv α α] {a b c : α} + +lemma gc_mul_ceilDiv (ha : 0 < a) : GaloisConnection (· ⌈/⌉ a) (a * ·) := gc_smul_ceilDiv ha +lemma ceilDiv_le_iff_le_mul (ha : 0 < a) : b ⌈/⌉ a ≤ c ↔ b ≤ a * c := ceilDiv_le_iff_le_smul ha + +end CeilDiv +end OrderedSemiring + +namespace Nat + +instance instFloorDiv : FloorDiv ℕ ℕ where + floorDiv := HDiv.hDiv + floorDiv_gc a ha := by simpa [mul_comm] using Nat.galoisConnection_mul_div ha + floorDiv_nonpos a ha b := by rw [ha.antisymm $ zero_le _, Nat.div_zero] + zero_floorDiv := Nat.zero_div + +instance instCeilDiv : CeilDiv ℕ ℕ where + ceilDiv a b := (a + b - 1) / b + ceilDiv_gc a ha b c := by + simp [div_le_iff_le_mul_add_pred ha, add_assoc, tsub_add_cancel_of_le $ succ_le_iff.2 ha] + ceilDiv_nonpos a ha b := by simp_rw [ha.antisymm $ zero_le _, Nat.div_zero] + zero_ceilDiv a := by cases a <;> simp [Nat.div_eq_zero_iff] + +@[simp] lemma floorDiv_eq_div (a b : ℕ) : a ⌊/⌋ b = a / b := rfl +lemma ceilDiv_eq_add_pred_div (a b : ℕ) : a ⌈/⌉ b = (a + b - 1) / b := rfl + +end Nat + +namespace Pi +variable {π : ι → Type*} [OrderedAddCommMonoid α] [∀ i, OrderedAddCommMonoid (π i)] + [∀ i, SMulZeroClass α (π i)] + +section FloorDiv +variable [∀ i, FloorDiv α (π i)] + +instance instFloorDiv : FloorDiv α (∀ i, π i) where + floorDiv f a i := f i ⌊/⌋ a + floorDiv_gc _a ha _f _g := forall_congr' fun _i ↦ gc_floorDiv_smul ha _ _ + floorDiv_nonpos a ha f := by ext i; exact floorDiv_of_nonpos ha _ + zero_floorDiv a := by ext i; exact zero_floorDiv a + +lemma floorDiv_def (f : ∀ i, π i) (a : α) : f ⌊/⌋ a = fun i ↦ f i ⌊/⌋ a := rfl +@[simp] lemma floorDiv_apply (f : ∀ i, π i) (a : α) (i : ι) : (f ⌊/⌋ a) i = f i ⌊/⌋ a := rfl + +end FloorDiv + +section CeilDiv +variable [∀ i, CeilDiv α (π i)] + +instance instCeilDiv : CeilDiv α (∀ i, π i) where + ceilDiv f a i := f i ⌈/⌉ a + ceilDiv_gc _a ha _f _g := forall_congr' fun _i ↦ gc_smul_ceilDiv ha _ _ + ceilDiv_nonpos a ha f := by ext i; exact ceilDiv_of_nonpos ha _ + zero_ceilDiv a := by ext; exact zero_ceilDiv _ + +lemma ceilDiv_def (f : ∀ i, π i) (a : α) : f ⌈/⌉ a = fun i ↦ f i ⌈/⌉ a := rfl +@[simp] lemma ceilDiv_apply (f : ∀ i, π i) (a : α) (i : ι) : (f ⌈/⌉ a) i = f i ⌈/⌉ a := rfl + +end CeilDiv +end Pi + +namespace Finsupp +variable [OrderedAddCommMonoid α] [OrderedAddCommMonoid β] [SMulZeroClass α β] + +section FloorDiv +variable [FloorDiv α β] {f : ι →₀ β} {a : α} + +noncomputable instance instFloorDiv : FloorDiv α (ι →₀ β) where + floorDiv f a := f.mapRange (· ⌊/⌋ a) <| zero_floorDiv _ + floorDiv_gc _a ha f _g := forall_congr' fun i ↦ by + simpa only [coe_smul, Pi.smul_apply, mapRange_apply] using gc_floorDiv_smul ha (f i) _ + floorDiv_nonpos a ha f := by ext i; exact floorDiv_of_nonpos ha _ + zero_floorDiv a := by ext; exact zero_floorDiv _ + +lemma floorDiv_def (f : ι →₀ β) (a : α) : f ⌊/⌋ a = fun i ↦ f i ⌊/⌋ a := rfl +@[simp] lemma floorDiv_apply (f : ι →₀ β) (a : α) (i : ι) : (f ⌊/⌋ a) i = f i ⌊/⌋ a := rfl + +lemma support_floorDiv_subset : (f ⌊/⌋ a).support ⊆ f.support := by + simp (config := { contextual := true}) [Finset.subset_iff, not_imp_not] + +end FloorDiv + +section CeilDiv +variable [CeilDiv α β] {f : ι →₀ β} {a : α} + +noncomputable instance instCeilDiv : CeilDiv α (ι →₀ β) where + ceilDiv f a := f.mapRange (· ⌈/⌉ a) <| by simp + ceilDiv_gc _a ha f _g := forall_congr' fun i ↦ by + simpa only [coe_smul, Pi.smul_apply, mapRange_apply] using gc_smul_ceilDiv ha (f i) _ + ceilDiv_nonpos a ha f := by ext i; exact ceilDiv_of_nonpos ha _ + zero_ceilDiv a := by ext; exact zero_ceilDiv _ + +lemma ceilDiv_def (f : ι →₀ β) (a : α) : f ⌈/⌉ a = fun i ↦ f i ⌈/⌉ a := rfl +@[simp] lemma ceilDiv_apply (f : ι →₀ β) (a : α) (i : ι) : (f ⌈/⌉ a) i = f i ⌈/⌉ a := rfl + +lemma support_ceilDiv_subset : (f ⌈/⌉ a).support ⊆ f.support := by + simp (config := { contextual := true}) [Finset.subset_iff, not_imp_not] + +end CeilDiv +end Finsupp + +/-- This is the motivating example.-/ +noncomputable example : FloorDiv ℕ (ℕ →₀ ℕ) := inferInstance diff --git a/Mathlib/Algebra/Order/Group/Abs.lean b/Mathlib/Algebra/Order/Group/Abs.lean index c8ba880a1665f..4125dd4357503 100644 --- a/Mathlib/Algebra/Order/Group/Abs.lean +++ b/Mathlib/Algebra/Order/Group/Abs.lean @@ -3,225 +3,366 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ -import Mathlib.Algebra.Abs -import Mathlib.Algebra.Order.Group.OrderIso -import Mathlib.Order.MinMax +import Mathlib.Algebra.GroupPower.CovariantClass +import Mathlib.Algebra.Order.Group.Lattice #align_import algebra.order.group.abs from "leanprover-community/mathlib"@"2196ab363eb097c008d4497125e0dde23fb36db2" /-! -# Absolute values in ordered groups. --/ +# Absolute values in ordered groups +The absolute value of an element in a group which is also a lattice is its supremum with its +negation. This generalizes the usual absolute value on real numbers (`|x| = max x (-x)`). -variable {α : Type*} +## Notations + +- `|a|`: The *absolute value* of an element `a` of an additive lattice ordered group +- `|a|ₘ`: The *absolute value* of an element `a` of a multiplicative lattice ordered group +-/ open Function -section CovariantAddLe +variable {α : Type*} -section Neg +section Lattice +variable [Lattice α] + +section Group +variable [Group α] {a b : α} + +#noalign has_inv.to_has_abs +#noalign has_neg.to_has_abs + +/-- `mabs a` is the absolute value of `a`. -/ +@[to_additive "`abs a` is the absolute value of `a`"] def mabs (a : α) : α := a ⊔ a⁻¹ +#align has_abs.abs abs + +#align abs_eq_sup_inv mabs +#align abs_eq_sup_neg abs + +@[inherit_doc mabs] +macro:max atomic("|" noWs) a:term noWs "|ₘ" : term => `(mabs $a) + +@[inherit_doc abs] +macro:max atomic("|" noWs) a:term noWs "|" : term => `(abs $a) + +/-- Unexpander for the notation `|a|ₘ` for `mabs a`. +Tries to add discretionary parentheses in unparseable cases. -/ +@[app_unexpander abs] +def mabs.unexpander : Lean.PrettyPrinter.Unexpander + | `($_ $a) => + match a with + | `(|$_|ₘ) | `(-$_) => `(|($a)|ₘ) + | _ => `(|$a|ₘ) + | _ => throw () + +/-- Unexpander for the notation `|a|` for `abs a`. +Tries to add discretionary parentheses in unparseable cases. -/ +@[app_unexpander abs] +def abs.unexpander : Lean.PrettyPrinter.Unexpander + | `($_ $a) => + match a with + | `(|$_|) | `(-$_) => `(|($a)|) + | _ => `(|$a|) + | _ => throw () + +@[to_additive] lemma mabs_le' : |a|ₘ ≤ b ↔ a ≤ b ∧ a⁻¹ ≤ b := sup_le_iff +#align abs_le' abs_le' --- see Note [lower instance priority] -/-- `abs a` is the absolute value of `a`. -/ -@[to_additive "`abs a` is the absolute value of `a`"] -instance (priority := 100) Inv.toHasAbs [Inv α] [Sup α] : Abs α := - ⟨fun a => a ⊔ a⁻¹⟩ -#align has_inv.to_has_abs Inv.toHasAbs -#align has_neg.to_has_abs Neg.toHasAbs +@[to_additive] lemma le_mabs_self (a : α) : a ≤ |a|ₘ := le_sup_left +#align le_abs_self le_abs_self +#align lattice_ordered_comm_group.le_mabs le_mabs_self +#align lattice_ordered_comm_group.le_abs le_abs_self -@[to_additive] -theorem abs_eq_sup_inv [Inv α] [Sup α] (a : α) : |a| = a ⊔ a⁻¹ := - rfl -#align abs_eq_sup_inv abs_eq_sup_inv -#align abs_eq_sup_neg abs_eq_sup_neg +@[to_additive] lemma inv_le_mabs (a : α) : a⁻¹ ≤ |a|ₘ := le_sup_right +#align neg_le_abs_self neg_le_abs +#align lattice_ordered_comm_group.inv_le_abs inv_le_mabs +#align lattice_ordered_comm_group.neg_le_abs neg_le_abs -variable [Neg α] [LinearOrder α] {a b : α} +@[to_additive] lemma mabs_le_mabs (h₀ : a ≤ b) (h₁ : a⁻¹ ≤ b) : |a|ₘ ≤ |b|ₘ := + (mabs_le'.2 ⟨h₀, h₁⟩).trans (le_mabs_self b) +#align abs_le_abs abs_le_abs -theorem abs_eq_max_neg : abs a = max a (-a) := - rfl -#align abs_eq_max_neg abs_eq_max_neg +@[to_additive (attr := simp)] lemma mabs_inv (a : α) : |a⁻¹|ₘ = |a|ₘ := by simp [mabs, sup_comm] +#align abs_neg abs_neg -theorem abs_choice (x : α) : |x| = x ∨ |x| = -x := - max_choice _ _ -#align abs_choice abs_choice +@[to_additive] lemma mabs_div_comm (a b : α) : |a / b|ₘ = |b / a|ₘ := by rw [← mabs_inv, inv_div] +#align abs_sub_comm abs_sub_comm -theorem abs_le' : |a| ≤ b ↔ a ≤ b ∧ -a ≤ b := - max_le_iff -#align abs_le' abs_le' +variable [CovariantClass α α (· * ·) (· ≤ ·)] -theorem le_abs : a ≤ |b| ↔ a ≤ b ∨ a ≤ -b := - le_max_iff -#align le_abs le_abs +@[to_additive] lemma mabs_of_one_le (h : 1 ≤ a) : |a|ₘ = a := + sup_eq_left.2 <| (inv_le_one'.2 h).trans h +#align abs_of_nonneg abs_of_nonneg +#align lattice_ordered_comm_group.mabs_of_one_le mabs_of_one_le +#align lattice_ordered_comm_group.abs_of_nonneg abs_of_nonneg -theorem le_abs_self (a : α) : a ≤ |a| := - le_max_left _ _ -#align le_abs_self le_abs_self +@[to_additive] lemma mabs_of_one_lt (h : 1 < a) : |a|ₘ = a := mabs_of_one_le h.le +#align abs_of_pos abs_of_pos -theorem neg_le_abs_self (a : α) : -a ≤ |a| := - le_max_right _ _ -#align neg_le_abs_self neg_le_abs_self +@[to_additive] lemma mabs_of_le_one (h : a ≤ 1) : |a|ₘ = a⁻¹ := + sup_eq_right.2 <| h.trans (one_le_inv'.2 h) +#align abs_of_nonpos abs_of_nonpos -theorem lt_abs : a < |b| ↔ a < b ∨ a < -b := - lt_max_iff -#align lt_abs lt_abs +@[to_additive] lemma mabs_of_lt_one (h : a < 1) : |a|ₘ = a⁻¹ := mabs_of_le_one h.le +#align abs_of_neg abs_of_neg -theorem abs_le_abs (h₀ : a ≤ b) (h₁ : -a ≤ b) : |a| ≤ |b| := - (abs_le'.2 ⟨h₀, h₁⟩).trans (le_abs_self b) -#align abs_le_abs abs_le_abs +@[to_additive] lemma mabs_le_mabs_of_one_le (ha : 1 ≤ a) (hab : a ≤ b) : |a|ₘ ≤ |b|ₘ := by + rwa [mabs_of_one_le ha, mabs_of_one_le (ha.trans hab)] +#align abs_le_abs_of_nonneg abs_le_abs_of_nonneg -theorem abs_by_cases (P : α → Prop) {a : α} (h1 : P a) (h2 : P (-a)) : P |a| := - sup_ind _ _ h1 h2 -#align abs_by_cases abs_by_cases +attribute [gcongr] abs_le_abs_of_nonneg -end Neg +@[to_additive (attr := simp)] lemma mabs_one : |(1 : α)|ₘ = 1 := mabs_of_one_le le_rfl +#align abs_zero abs_zero -section AddGroup +variable [CovariantClass α α (swap (· * ·)) (· ≤ ·)] -variable [AddGroup α] [LinearOrder α] +@[to_additive (attr := simp) abs_nonneg] lemma one_le_mabs (a : α) : 1 ≤ |a|ₘ := by + apply pow_two_semiclosed _ + rw [mabs, pow_two, mul_sup, sup_mul, ← pow_two, mul_left_inv, sup_comm, ← sup_assoc] + apply le_sup_right +#align abs_nonneg abs_nonneg -@[simp] -theorem abs_neg (a : α) : |(-a)| = |a| := by rw [abs_eq_max_neg, max_comm, neg_neg, abs_eq_max_neg] -#align abs_neg abs_neg +@[to_additive (attr := simp)] lemma mabs_mabs (a : α) : |(|a|ₘ)|ₘ = |a|ₘ := + mabs_of_one_le <| one_le_mabs a +#align abs_abs abs_abs +#align lattice_ordered_comm_group.mabs_mabs mabs_mabs +#align lattice_ordered_comm_group.abs_abs abs_abs -theorem eq_or_eq_neg_of_abs_eq {a b : α} (h : |a| = b) : a = b ∨ a = -b := by - simpa only [← h, eq_comm (a := |a|), neg_eq_iff_eq_neg] using abs_choice a -#align eq_or_eq_neg_of_abs_eq eq_or_eq_neg_of_abs_eq +end Group -theorem abs_eq_abs {a b : α} : |a| = |b| ↔ a = b ∨ a = -b := by - refine' ⟨fun h => _, fun h => _⟩ - · obtain rfl | rfl := eq_or_eq_neg_of_abs_eq h <;> - simpa only [neg_eq_iff_eq_neg (a := |b|), neg_inj, or_comm] using abs_choice b - · cases' h with h h <;> - simp [h, abs_neg] -#align abs_eq_abs abs_eq_abs +section CommGroup +variable [CommGroup α] [CovariantClass α α (· * ·) (· ≤ ·)] {a b : α} -theorem abs_sub_comm (a b : α) : |a - b| = |b - a| := +-- Banasiak Proposition 2.12, Zaanen 2nd lecture +/-- The absolute value satisfies the triangle inequality. -/ +@[to_additive "The absolute value satisfies the triangle inequality."] +lemma mabs_mul_le (a b : α) : |a * b|ₘ ≤ |a|ₘ * |b|ₘ := by + apply sup_le + · exact mul_le_mul' (le_mabs_self a) (le_mabs_self b) + · rw [mul_inv] + exact mul_le_mul' (inv_le_mabs _) (inv_le_mabs _) +#align lattice_ordered_comm_group.mabs_mul_le mabs_mul_le +#align lattice_ordered_comm_group.abs_add_le abs_add_le + +@[to_additive] +lemma mabs_mabs_div_mabs_le (a b : α) : |(|a|ₘ / |b|ₘ)|ₘ ≤ |a / b|ₘ := by + rw [mabs, sup_le_iff] + constructor + · apply div_le_iff_le_mul.2 + convert mabs_mul_le (a / b) b + rw [div_mul_cancel'] + · rw [div_eq_mul_inv, mul_inv_rev, inv_inv, mul_inv_le_iff_le_mul, mabs_div_comm] + convert mabs_mul_le (b / a) a + · rw [div_mul_cancel'] +#align lattice_ordered_comm_group.abs_abs_div_abs_le mabs_mabs_div_mabs_le +#align lattice_ordered_comm_group.abs_abs_sub_abs_le abs_abs_sub_abs_le + +@[to_additive] lemma sup_div_inf_eq_mabs_div (a b : α) : (a ⊔ b) / (a ⊓ b) = |b / a|ₘ := by + simp_rw [sup_div, div_inf, div_self', sup_comm, sup_sup_sup_comm, sup_idem] + rw [← inv_div, sup_comm (b := _ / _), ← mabs, sup_eq_left] + exact one_le_mabs _ +#align lattice_ordered_comm_group.sup_div_inf_eq_abs_div sup_div_inf_eq_mabs_div +#align lattice_ordered_comm_group.sup_sub_inf_eq_abs_sub sup_sub_inf_eq_abs_sub + +@[to_additive two_nsmul_sup_eq_add_add_abs_sub] +lemma sup_sq_eq_mul_mul_mabs_div (a b : α) : (a ⊔ b) ^ 2 = a * b * |b / a|ₘ := by + rw [← inf_mul_sup a b, ← sup_div_inf_eq_mabs_div, div_eq_mul_inv, ← mul_assoc, mul_comm, + mul_assoc, ← pow_two, inv_mul_cancel_left] +#align lattice_ordered_comm_group.sup_sq_eq_mul_mul_abs_div sup_sq_eq_mul_mul_mabs_div +#align lattice_ordered_comm_group.two_sup_eq_add_add_abs_sub two_nsmul_sup_eq_add_add_abs_sub + +@[to_additive two_nsmul_inf_eq_add_sub_abs_sub] +lemma inf_sq_eq_mul_div_mabs_div (a b : α) : (a ⊓ b) ^ 2 = a * b / |b / a|ₘ := by + rw [← inf_mul_sup a b, ← sup_div_inf_eq_mabs_div, div_eq_mul_inv, div_eq_mul_inv, mul_inv_rev, + inv_inv, mul_assoc, mul_inv_cancel_comm_assoc, ← pow_two] +#align lattice_ordered_comm_group.inf_sq_eq_mul_div_abs_div inf_sq_eq_mul_div_mabs_div +#align lattice_ordered_comm_group.two_inf_eq_add_sub_abs_sub two_nsmul_inf_eq_add_sub_abs_sub + +-- See, e.g. Zaanen, Lectures on Riesz Spaces +-- 3rd lecture +@[to_additive] +lemma mabs_div_sup_mul_mabs_div_inf [CovariantClass α α (· * ·) (· ≤ ·)] (a b c : α) : + |(a ⊔ c) / (b ⊔ c)|ₘ * |(a ⊓ c) / (b ⊓ c)|ₘ = |a / b|ₘ := by + letI : DistribLattice α := CommGroup.toDistribLattice α calc - |a - b| = |(-(b - a))| := congr_arg _ (neg_sub b a).symm - _ = |b - a| := abs_neg (b - a) -#align abs_sub_comm abs_sub_comm + |(a ⊔ c) / (b ⊔ c)|ₘ * |(a ⊓ c) / (b ⊓ c)|ₘ = + (b ⊔ c ⊔ (a ⊔ c)) / ((b ⊔ c) ⊓ (a ⊔ c)) * |(a ⊓ c) / (b ⊓ c)|ₘ := by + rw [sup_div_inf_eq_mabs_div] + _ = (b ⊔ c ⊔ (a ⊔ c)) / ((b ⊔ c) ⊓ (a ⊔ c)) * ((b ⊓ c ⊔ a ⊓ c) / (b ⊓ c ⊓ (a ⊓ c))) := by + rw [sup_div_inf_eq_mabs_div (b ⊓ c) (a ⊓ c)] + _ = (b ⊔ a ⊔ c) / (b ⊓ a ⊔ c) * (((b ⊔ a) ⊓ c) / (b ⊓ a ⊓ c)) := by + rw [← sup_inf_right, ← inf_sup_right, sup_assoc, @sup_comm _ _ c (a ⊔ c), sup_right_idem, + sup_assoc, inf_assoc, @inf_comm _ _ c (a ⊓ c), inf_right_idem, inf_assoc] + _ = (b ⊔ a ⊔ c) * ((b ⊔ a) ⊓ c) / ((b ⊓ a ⊔ c) * (b ⊓ a ⊓ c)) := by rw [div_mul_div_comm] + _ = (b ⊔ a) * c / ((b ⊓ a) * c) := by + rw [mul_comm, inf_mul_sup, mul_comm (b ⊓ a ⊔ c), inf_mul_sup] + _ = (b ⊔ a) / (b ⊓ a) := by + rw [div_eq_mul_inv, mul_inv_rev, mul_assoc, mul_inv_cancel_left, ← div_eq_mul_inv] + _ = |a / b|ₘ := by rw [sup_div_inf_eq_mabs_div] +#align lattice_ordered_comm_group.abs_div_sup_mul_abs_div_inf mabs_div_sup_mul_mabs_div_inf +#align lattice_ordered_comm_group.abs_sub_sup_add_abs_sub_inf abs_sub_sup_add_abs_sub_inf + +@[to_additive] lemma mabs_sup_div_sup_le_mabs (a b c : α) : |(a ⊔ c) / (b ⊔ c)|ₘ ≤ |a / b|ₘ := by + apply le_of_mul_le_of_one_le_left _ (one_le_mabs _); rw [mabs_div_sup_mul_mabs_div_inf] +#align lattice_ordered_comm_group.mabs_sup_div_sup_le_mabs mabs_sup_div_sup_le_mabs +#align lattice_ordered_comm_group.abs_sup_sub_sup_le_abs abs_sup_sub_sup_le_abs + +@[to_additive] lemma mabs_inf_div_inf_le_mabs (a b c : α) : |(a ⊓ c) / (b ⊓ c)|ₘ ≤ |a / b|ₘ := by + apply le_of_mul_le_of_one_le_right _ (one_le_mabs _); rw [mabs_div_sup_mul_mabs_div_inf] +#align lattice_ordered_comm_group.mabs_inf_div_inf_le_mabs mabs_inf_div_inf_le_mabs +#align lattice_ordered_comm_group.abs_inf_sub_inf_le_abs abs_inf_sub_inf_le_abs + +-- Commutative case, Zaanen, 3rd lecture +-- For the non-commutative case, see Birkhoff Theorem 19 (27) +@[to_additive Birkhoff_inequalities] +lemma m_Birkhoff_inequalities (a b c : α) : + |(a ⊔ c) / (b ⊔ c)|ₘ ⊔ |(a ⊓ c) / (b ⊓ c)|ₘ ≤ |a / b|ₘ := + sup_le (mabs_sup_div_sup_le_mabs a b c) (mabs_inf_div_inf_le_mabs a b c) +set_option linter.uppercaseLean3 false in +#align lattice_ordered_comm_group.m_Birkhoff_inequalities m_Birkhoff_inequalities +set_option linter.uppercaseLean3 false in +#align lattice_ordered_comm_group.Birkhoff_inequalities Birkhoff_inequalities + +end CommGroup +end Lattice + +section LinearOrder +variable [Group α] [LinearOrder α] {a b : α} + +@[to_additive] lemma mabs_choice (x : α) : |x|ₘ = x ∨ |x|ₘ = x⁻¹ := max_choice _ _ +#align abs_choice abs_choice -variable [CovariantClass α α (· + ·) (· ≤ ·)] {a b c : α} +@[to_additive] lemma le_mabs : a ≤ |b|ₘ ↔ a ≤ b ∨ a ≤ b⁻¹ := le_max_iff +#align le_abs le_abs -theorem abs_of_nonneg (h : 0 ≤ a) : |a| = a := - max_eq_left <| (neg_nonpos.2 h).trans h -#align abs_of_nonneg abs_of_nonneg +@[to_additive] lemma mabs_eq_max_inv : |a|ₘ = max a a⁻¹ := rfl +#align abs_eq_max_neg abs_eq_max_neg -theorem abs_of_pos (h : 0 < a) : |a| = a := - abs_of_nonneg h.le -#align abs_of_pos abs_of_pos +@[to_additive] lemma lt_mabs : a < |b|ₘ ↔ a < b ∨ a < b⁻¹ := lt_max_iff +#align lt_abs lt_abs -theorem abs_of_nonpos (h : a ≤ 0) : |a| = -a := - max_eq_right <| h.trans (neg_nonneg.2 h) -#align abs_of_nonpos abs_of_nonpos +@[to_additive] lemma mabs_by_cases (P : α → Prop) (h1 : P a) (h2 : P a⁻¹) : P |a|ₘ := + sup_ind _ _ h1 h2 +#align abs_by_cases abs_by_cases -theorem abs_of_neg (h : a < 0) : |a| = -a := - abs_of_nonpos h.le -#align abs_of_neg abs_of_neg +@[to_additive] lemma eq_or_eq_inv_of_mabs_eq (h : |a|ₘ = b) : a = b ∨ a = b⁻¹ := by + simpa only [← h, eq_comm (a := |a|ₘ), inv_eq_iff_eq_inv] using mabs_choice a +#align eq_or_eq_neg_of_abs_eq eq_or_eq_neg_of_abs_eq -@[gcongr] -theorem abs_le_abs_of_nonneg (ha : 0 ≤ a) (hab : a ≤ b) : |a| ≤ |b| := by - rwa [abs_of_nonneg ha, abs_of_nonneg (ha.trans hab)] -#align abs_le_abs_of_nonneg abs_le_abs_of_nonneg +@[to_additive] lemma mabs_eq_mabs : |a|ₘ = |b|ₘ ↔ a = b ∨ a = b⁻¹ := by + refine' ⟨fun h ↦ ?_, by rintro (h | h) <;> simp [h, abs_neg]⟩ + obtain rfl | rfl := eq_or_eq_inv_of_mabs_eq h <;> + simpa only [inv_eq_iff_eq_inv (a := |b|ₘ), inv_inj, or_comm] using mabs_choice b +#align abs_eq_abs abs_eq_abs -@[simp] -theorem abs_zero : |0| = (0 : α) := - abs_of_nonneg le_rfl -#align abs_zero abs_zero +variable [CovariantClass α α (· * ·) (· ≤ ·)] {a b c : α} -@[simp] -theorem abs_pos : 0 < |a| ↔ a ≠ 0 := by - rcases lt_trichotomy a 0 with (ha | rfl | ha) - · simp [abs_of_neg ha, neg_pos, ha.ne, ha] +@[to_additive (attr := simp) abs_pos] lemma one_lt_mabs : 1 < |a|ₘ ↔ a ≠ 1 := by + obtain ha | rfl | ha := lt_trichotomy a 1 + · simp [mabs_of_lt_one ha, neg_pos, ha.ne, ha] · simp - · simp [abs_of_pos ha, ha, ha.ne.symm] + · simp [mabs_of_one_lt ha, ha, ha.ne'] #align abs_pos abs_pos -theorem abs_pos_of_pos (h : 0 < a) : 0 < |a| := - abs_pos.2 h.ne.symm +@[to_additive abs_pos_of_pos] lemma one_lt_mabs_pos_of_one_lt (h : 1 < a) : 1 < |a|ₘ := + one_lt_mabs.2 h.ne' #align abs_pos_of_pos abs_pos_of_pos -theorem abs_pos_of_neg (h : a < 0) : 0 < |a| := - abs_pos.2 h.ne +@[to_additive abs_pos_of_neg] lemma one_lt_mabs_of_lt_one (h : a < 1) : 1 < |a|ₘ := + one_lt_mabs.2 h.ne #align abs_pos_of_neg abs_pos_of_neg -theorem neg_abs_le_self (a : α) : -|a| ≤ a := by - rcases le_total 0 a with h | h - · calc - -|a| = -a := congr_arg Neg.neg (abs_of_nonneg h) - _ ≤ 0 := neg_nonpos.mpr h - _ ≤ a := h - · calc - -|a| = - -a := congr_arg Neg.neg (abs_of_nonpos h) - _ ≤ a := (neg_neg a).le -#align neg_abs_le_self neg_abs_le_self - -theorem add_abs_nonneg (a : α) : 0 ≤ a + |a| := by - rw [← add_right_neg a] - apply add_le_add_left - exact neg_le_abs_self a +@[to_additive] lemma inv_mabs_le (a : α) : |a|ₘ⁻¹ ≤ a := by + obtain h | h := le_total 1 a + · simpa [mabs_of_one_le h] using (inv_le_one'.2 h).trans h + · simp [mabs_of_le_one h] +#align neg_abs_le_self neg_abs_le + +@[to_additive add_abs_nonneg] lemma one_le_mul_mabs (a : α) : 1 ≤ a * |a|ₘ := by + rw [← mul_right_inv a]; exact mul_le_mul_left' (inv_le_mabs a) _ #align add_abs_nonneg add_abs_nonneg -theorem neg_abs_le_neg (a : α) : -|a| ≤ -a := by simpa using neg_abs_le_self (-a) +@[to_additive] lemma inv_mabs_le_inv (a : α) : |a|ₘ⁻¹ ≤ a⁻¹ := by simpa using inv_mabs_le a⁻¹ #align neg_abs_le_neg neg_abs_le_neg -@[simp] -theorem abs_nonneg (a : α) : 0 ≤ |a| := - (le_total 0 a).elim (fun h => h.trans (le_abs_self a)) fun h => - (neg_nonneg.2 h).trans <| neg_le_abs_self a -#align abs_nonneg abs_nonneg +variable [CovariantClass α α (swap (· * ·)) (· ≤ ·)] -@[simp] -theorem abs_abs (a : α) : |(|a|)| = |a| := - abs_of_nonneg <| abs_nonneg a -#align abs_abs abs_abs +@[to_additive] lemma mabs_ne_one : |a|ₘ ≠ 1 ↔ a ≠ 1 := + (one_le_mabs a).gt_iff_ne.symm.trans one_lt_mabs -@[simp] -theorem abs_eq_zero : |a| = 0 ↔ a = 0 := - Decidable.not_iff_not.1 <| ne_comm.trans <| (abs_nonneg a).lt_iff_ne.symm.trans abs_pos +@[to_additive (attr := simp)] lemma mabs_eq_one : |a|ₘ = 1 ↔ a = 1 := not_iff_not.1 mabs_ne_one #align abs_eq_zero abs_eq_zero -@[simp] -theorem abs_nonpos_iff {a : α} : |a| ≤ 0 ↔ a = 0 := - (abs_nonneg a).le_iff_eq.trans abs_eq_zero +@[to_additive (attr := simp) abs_nonpos_iff] lemma mabs_le_one : |a|ₘ ≤ 1 ↔ a = 1 := + (one_le_mabs a).le_iff_eq.trans mabs_eq_one #align abs_nonpos_iff abs_nonpos_iff -variable [CovariantClass α α (swap (· + ·)) (· ≤ ·)] - -theorem abs_le_abs_of_nonpos (ha : a ≤ 0) (hab : b ≤ a) : |a| ≤ |b| := by - rw [abs_of_nonpos ha, abs_of_nonpos (hab.trans ha)] - exact neg_le_neg_iff.mpr hab +@[to_additive] lemma mabs_le_mabs_of_le_one (ha : a ≤ 1) (hab : b ≤ a) : |a|ₘ ≤ |b|ₘ := by + rw [mabs_of_le_one ha, mabs_of_le_one (hab.trans ha)]; exact inv_le_inv_iff.mpr hab #align abs_le_abs_of_nonpos abs_le_abs_of_nonpos -theorem abs_lt : |a| < b ↔ -b < a ∧ a < b := - max_lt_iff.trans <| and_comm.trans <| by rw [neg_lt] +@[to_additive] lemma mabs_lt : |a|ₘ < b ↔ b⁻¹ < a ∧ a < b := + max_lt_iff.trans <| and_comm.trans <| by rw [inv_lt'] #align abs_lt abs_lt -theorem neg_lt_of_abs_lt (h : |a| < b) : -b < a := - (abs_lt.mp h).1 +@[to_additive] lemma inv_lt_of_mabs_lt (h : |a|ₘ < b) : b⁻¹ < a := (mabs_lt.mp h).1 #align neg_lt_of_abs_lt neg_lt_of_abs_lt -theorem lt_of_abs_lt (h : |a| < b) : a < b := - (abs_lt.mp h).2 +@[to_additive] lemma lt_of_mabs_lt : |a|ₘ < b → a < b := (le_mabs_self _).trans_lt #align lt_of_abs_lt lt_of_abs_lt -theorem max_sub_min_eq_abs' (a b : α) : max a b - min a b = |a - b| := by +@[to_additive] lemma max_div_min_eq_mabs' (a b : α) : max a b / min a b = |a / b|ₘ := by rcases le_total a b with ab | ba - · rw [max_eq_right ab, min_eq_left ab, abs_of_nonpos, neg_sub] - rwa [sub_nonpos] - · rw [max_eq_left ba, min_eq_right ba, abs_of_nonneg] - rwa [sub_nonneg] + · rw [max_eq_right ab, min_eq_left ab, mabs_of_le_one, inv_div] + rwa [div_le_one'] + · rw [max_eq_left ba, min_eq_right ba, mabs_of_one_le] + rwa [one_le_div'] #align max_sub_min_eq_abs' max_sub_min_eq_abs' -theorem max_sub_min_eq_abs (a b : α) : max a b - min a b = |b - a| := by - rw [abs_sub_comm] - exact max_sub_min_eq_abs' _ _ +@[to_additive] lemma max_div_min_eq_mabs (a b : α) : max a b / min a b = |b / a|ₘ := by + rw [mabs_div_comm, max_div_min_eq_mabs'] #align max_sub_min_eq_abs max_sub_min_eq_abs -end AddGroup - -end CovariantAddLe +end LinearOrder + +section LinearOrderedCommGroup +variable [LinearOrderedCommGroup α] {a b : α} + +@[to_additive] lemma mabs_pow (n : ℕ) (a : α) : |a ^ n|ₘ = |a|ₘ ^ n := by + obtain ha | ha := le_total a 1 + · rw [mabs_of_le_one ha, ← mabs_inv, ← inv_pow, mabs_of_one_le] + exact one_le_pow_of_one_le' (one_le_inv'.2 ha) n + · rw [mabs_of_one_le ha, mabs_of_one_le (one_le_pow_of_one_le' ha n)] +#align abs_nsmul abs_nsmul + +@[to_additive] private lemma mabs_mul_eq_mul_mabs_le (hab : a ≤ b) : + |a * b|ₘ = |a|ₘ * |b|ₘ ↔ 1 ≤ a ∧ 1 ≤ b ∨ a ≤ 1 ∧ b ≤ 1 := by + obtain ha | ha := le_or_lt 1 a <;> obtain hb | hb := le_or_lt 1 b + · simp [ha, hb, mabs_of_one_le, one_le_mul ha hb] + · exact (lt_irrefl (1 : α) <| ha.trans_lt <| hab.trans_lt hb).elim + any_goals simp [ha.le, hb.le, mabs_of_le_one, mul_le_one', mul_comm] + have : (|a * b|ₘ = a⁻¹ * b ↔ b ≤ 1) ↔ + (|a * b|ₘ = |a|ₘ * |b|ₘ ↔ 1 ≤ a ∧ 1 ≤ b ∨ a ≤ 1 ∧ b ≤ 1) := by + simp [ha.le, ha.not_le, hb, mabs_of_le_one, mabs_of_one_le] + refine this.mp ⟨fun h ↦ ?_, fun h ↦ by simp only [h.antisymm hb, mabs_of_lt_one ha, mul_one]⟩ + obtain ab | ab := le_or_lt (a * b) 1 + · refine (eq_one_of_inv_eq' ?_).le + rwa [mabs_of_le_one ab, mul_inv_rev, mul_comm, mul_right_inj] at h + · rw [mabs_of_one_lt ab, mul_left_inj] at h + rw [eq_one_of_inv_eq' h.symm] at ha + cases ha.false +#noalign abs_add_eq_add_abs_le + +@[to_additive] lemma mabs_mul_eq_mul_mabs_iff (a b : α) : + |a * b|ₘ = |a|ₘ * |b|ₘ ↔ 1 ≤ a ∧ 1 ≤ b ∨ a ≤ 1 ∧ b ≤ 1 := by + obtain ab | ab := le_total a b + · exact mabs_mul_eq_mul_mabs_le ab + · simpa only [mul_comm, and_comm] using mabs_mul_eq_mul_mabs_le ab +#align abs_add_eq_add_abs_iff abs_add_eq_add_abs_iff + +end LinearOrderedCommGroup section LinearOrderedAddCommGroup @@ -267,7 +408,7 @@ theorem apply_abs_le_mul_of_one_le {β : Type*} [MulOneClass β] [Preorder β] theorem abs_add (a b : α) : |a + b| ≤ |a| + |b| := abs_le.2 ⟨(neg_add |a| |b|).symm ▸ - add_le_add ((@neg_le α ..).2 <| neg_le_abs_self _) ((@neg_le α ..).2 <| neg_le_abs_self _), + add_le_add ((@neg_le α ..).2 <| neg_le_abs _) ((@neg_le α ..).2 <| neg_le_abs _), add_le_add (le_abs_self _) (le_abs_self _)⟩ #align abs_add abs_add @@ -323,7 +464,7 @@ theorem abs_eq (hb : 0 ≤ b) : |a| = b ↔ a = b ∨ a = -b := by theorem abs_le_max_abs_abs (hab : a ≤ b) (hbc : b ≤ c) : |b| ≤ max |a| |c| := abs_le'.2 ⟨by simp [hbc.trans (le_abs_self c)], by - simp [((@neg_le_neg_iff α ..).mpr hab).trans (neg_le_abs_self a)]⟩ + simp [((@neg_le_neg_iff α ..).mpr hab).trans (neg_le_abs a)]⟩ #align abs_le_max_abs_abs abs_le_max_abs_abs theorem min_abs_abs_le_abs_max : min |a| |b| ≤ |max a b| := @@ -347,7 +488,7 @@ theorem abs_min_le_max_abs_abs : |min a b| ≤ max |a| |b| := #align abs_min_le_max_abs_abs abs_min_le_max_abs_abs theorem eq_of_abs_sub_eq_zero {a b : α} (h : |a - b| = 0) : a = b := - sub_eq_zero.1 <| abs_eq_zero.1 h + sub_eq_zero.1 <| (abs_eq_zero (α := α)).1 h #align eq_of_abs_sub_eq_zero eq_of_abs_sub_eq_zero theorem abs_sub_le (a b c : α) : |a - c| ≤ |a - b| + |b - c| := @@ -398,3 +539,28 @@ theorem max_zero_add_max_neg_zero_eq_abs_self (a : α) : max a 0 + max (-a) 0 = #align max_zero_add_max_neg_zero_eq_abs_self max_zero_add_max_neg_zero_eq_abs_self end LinearOrderedAddCommGroup + +namespace LatticeOrderedAddCommGroup +variable [Lattice α] [AddCommGroup α] {s t : Set α} + +/-- A set `s` in a lattice ordered group is *solid* if for all `x ∈ s` and all `y ∈ α` such that +`|y| ≤ |x|`, then `y ∈ s`. -/ +def IsSolid (s : Set α) : Prop := ∀ ⦃x⦄, x ∈ s → ∀ ⦃y⦄, |y| ≤ |x| → y ∈ s +#align lattice_ordered_add_comm_group.is_solid LatticeOrderedAddCommGroup.IsSolid + +/-- The solid closure of a subset `s` is the smallest superset of `s` that is solid. -/ +def solidClosure (s : Set α) : Set α := {y | ∃ x ∈ s, |y| ≤ |x|} +#align lattice_ordered_add_comm_group.solid_closure LatticeOrderedAddCommGroup.solidClosure + +lemma isSolid_solidClosure (s : Set α) : IsSolid (solidClosure s) := + fun _ ⟨y, hy, hxy⟩ _ hzx ↦ ⟨y, hy, hzx.trans hxy⟩ +#align lattice_ordered_add_comm_group.is_solid_solid_closure LatticeOrderedAddCommGroup.isSolid_solidClosure + +lemma solidClosure_min (hst : s ⊆ t) (ht : IsSolid t) : solidClosure s ⊆ t := + fun _ ⟨_, hy, hxy⟩ ↦ ht (hst hy) hxy +#align lattice_ordered_add_comm_group.solid_closure_min LatticeOrderedAddCommGroup.solidClosure_min + +end LatticeOrderedAddCommGroup + +@[deprecated] alias neg_le_abs_self := neg_le_abs +@[deprecated] alias neg_abs_le_self := neg_abs_le diff --git a/Mathlib/Algebra/Order/Group/Defs.lean b/Mathlib/Algebra/Order/Group/Defs.lean index 573400b9a22ec..2f3415fe52982 100644 --- a/Mathlib/Algebra/Order/Group/Defs.lean +++ b/Mathlib/Algebra/Order/Group/Defs.lean @@ -5,7 +5,7 @@ Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ import Mathlib.Algebra.Order.Monoid.Defs import Mathlib.Algebra.Order.Sub.Defs -import Mathlib.Order.Hom.Basic +import Mathlib.Util.AssertExists #align_import algebra.order.group.defs from "leanprover-community/mathlib"@"b599f4e4e5cf1fbcb4194503671d3d9e569c1fce" diff --git a/Mathlib/Algebra/Order/Group/InjSurj.lean b/Mathlib/Algebra/Order/Group/InjSurj.lean index 068aad9e85468..1e62f7a16e825 100644 --- a/Mathlib/Algebra/Order/Group/InjSurj.lean +++ b/Mathlib/Algebra/Order/Group/InjSurj.lean @@ -5,7 +5,6 @@ Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Monoid.Basic -import Mathlib.Algebra.Order.Group.Instances #align_import algebra.order.group.inj_surj from "leanprover-community/mathlib"@"655994e298904d7e5bbd1e18c95defd7b543eb94" diff --git a/Mathlib/Algebra/Order/Group/Lattice.lean b/Mathlib/Algebra/Order/Group/Lattice.lean new file mode 100644 index 0000000000000..12a0d2f3fdb4c --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Lattice.lean @@ -0,0 +1,134 @@ +/- +Copyright (c) 2021 Christopher Hoskin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christopher Hoskin, Yaël Dillies +-/ +import Mathlib.Algebra.GroupPower.Basic +import Mathlib.Algebra.Order.Group.OrderIso + +#align_import algebra.order.lattice_group from "leanprover-community/mathlib"@"5dc275ec639221ca4d5f56938eb966f6ad9bc89f" + +/-! +# Lattice ordered groups + +Lattice ordered groups were introduced by [Birkhoff][birkhoff1942]. They form the algebraic +underpinnings of vector lattices, Banach lattices, AL-space, AM-space etc. + +A lattice ordered group is a type `α` satisfying: +* `Lattice α` +* `CommGroup α` +* `CovariantClass α α (· * ·) (· ≤ ·)` +* `CovariantClass α α (swap (· * ·)) (· ≤ ·)` + +This file establishes basic properties of lattice ordered groups. It is shown that when the group is +commutative, the lattice is distributive. This also holds in the non-commutative case +([Birkhoff][birkhoff1942],[Fuchs][fuchs1963]) but we do not yet have the machinery to establish this +in mathlib. + +## References + +* [Birkhoff, Lattice-ordered Groups][birkhoff1942] +* [Bourbaki, Algebra II][bourbaki1981] +* [Fuchs, Partially Ordered Algebraic Systems][fuchs1963] +* [Zaanen, Lectures on "Riesz Spaces"][zaanen1966] +* [Banasiak, Banach Lattices in Applications][banasiak] + +## Tags + +lattice, order, group +-/ + +open Function + +variable {α β : Type*} + +section Group +variable [Lattice α] [Group α] [CovariantClass α α (· * ·) (· ≤ ·)] + [CovariantClass α α (swap (· * ·)) (· ≤ ·)] + +-- Special case of Bourbaki A.VI.9 (1) +@[to_additive] +lemma mul_sup (a b c : α) : c * (a ⊔ b) = c * a ⊔ c * b := (OrderIso.mulLeft _).map_sup _ _ +#align mul_sup mul_sup +#align add_sup add_sup + +@[to_additive] +lemma sup_mul (a b c : α) : (a ⊔ b) * c = a * c ⊔ b * c := (OrderIso.mulRight _).map_sup _ _ +#align sup_mul sup_mul +#align sup_add sup_add + +@[to_additive] +lemma mul_inf (a b c : α) : c * (a ⊓ b) = c * a ⊓ c * b := (OrderIso.mulLeft _).map_inf _ _ +#align mul_inf mul_inf +#align add_inf add_inf +#align lattice_ordered_comm_group.mul_inf_eq_mul_inf_mul mul_inf +#align lattice_ordered_comm_group.add_inf_eq_add_inf_add add_inf + +@[to_additive] +lemma inf_mul (a b c : α) : (a ⊓ b) * c = a * c ⊓ b * c := (OrderIso.mulRight _).map_inf _ _ +#align inf_mul inf_mul +#align inf_add inf_add + +-- Special case of Bourbaki A.VI.9 (2) +@[to_additive] lemma inv_sup (a b : α) : (a ⊔ b)⁻¹ = a⁻¹ ⊓ b⁻¹ := (OrderIso.inv α).map_sup _ _ +#align inv_sup_eq_inv_inf_inv inv_sup +#align neg_sup_eq_neg_inf_neg neg_sup + +@[to_additive] lemma inv_inf (a b : α) : (a ⊓ b)⁻¹ = a⁻¹ ⊔ b⁻¹ := (OrderIso.inv α).map_inf _ _ +#align inv_inf_eq_sup_inv inv_inf +#align neg_inf_eq_sup_neg neg_inf + +@[to_additive] +lemma div_sup (a b c : α) : c / (a ⊔ b) = c / a ⊓ c / b := (OrderIso.divLeft c).map_sup _ _ + +@[to_additive] +lemma sup_div (a b c : α) : (a ⊔ b) / c = a / c ⊔ b / c := (OrderIso.divRight _).map_sup _ _ + +@[to_additive] +lemma div_inf (a b c : α) : c / (a ⊓ b) = c / a ⊔ c / b := (OrderIso.divLeft c).map_inf _ _ + +@[to_additive] +lemma inf_div (a b c : α) : (a ⊓ b) / c = a / c ⊓ b / c := (OrderIso.divRight _).map_inf _ _ + +-- In fact 0 ≤ n•a implies 0 ≤ a, see L. Fuchs, "Partially ordered algebraic systems" +-- Chapter V, 1.E +-- See also `one_le_pow_iff` for the existing version in linear orders +@[to_additive] +lemma pow_two_semiclosed [CovariantClass α α (· * ·) (· ≤ ·)] + [CovariantClass α α (swap (· * ·)) (· ≤ ·)] {a : α} (ha : 1 ≤ a ^ 2) : 1 ≤ a := by + suffices this : (a ⊓ 1) * (a ⊓ 1) = a ⊓ 1 by + rwa [← inf_eq_right, ← mul_right_eq_self] + rw [mul_inf, inf_mul, ← pow_two, mul_one, one_mul, inf_assoc, inf_left_idem, inf_comm, + inf_assoc, inf_of_le_left ha] + +end Group + +variable [Lattice α] [CommGroup α] + +-- Fuchs p67 +-- Bourbaki A.VI.10 Prop 7 +@[to_additive] +lemma inf_mul_sup [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : (a ⊓ b) * (a ⊔ b) = a * b := + calc + (a ⊓ b) * (a ⊔ b) = (a ⊓ b) * (a * b * (b⁻¹ ⊔ a⁻¹)) := by + rw [mul_sup b⁻¹ a⁻¹ (a * b), mul_inv_cancel_right, mul_inv_cancel_comm] + _ = (a ⊓ b) * (a * b * (a ⊓ b)⁻¹) := by rw [inv_inf, sup_comm] + _ = a * b := by rw [mul_comm, inv_mul_cancel_right] +#align inf_mul_sup inf_mul_sup +#align inf_add_sup inf_add_sup + +/-- Every lattice ordered commutative group is a distributive lattice. -/ +-- Non-comm case needs cancellation law https://ncatlab.org/nlab/show/distributive+lattice +@[to_additive "Every lattice ordered commutative additive group is a distributive lattice"] +def CommGroup.toDistribLattice (α : Type*) [Lattice α] [CommGroup α] + [CovariantClass α α (· * ·) (· ≤ ·)] : DistribLattice α where + le_sup_inf x y z := by + rw [← mul_le_mul_iff_left (x ⊓ (y ⊓ z)), inf_mul_sup x (y ⊓ z), ← inv_mul_le_iff_le_mul, + le_inf_iff] + constructor + · rw [inv_mul_le_iff_le_mul, ← inf_mul_sup x y] + exact mul_le_mul' (inf_le_inf_left _ inf_le_left) inf_le_left + · rw [inv_mul_le_iff_le_mul, ← inf_mul_sup x z] + exact mul_le_mul' (inf_le_inf_left _ inf_le_right) inf_le_right +#align lattice_ordered_comm_group.lattice_ordered_comm_group_to_distrib_lattice CommGroup.toDistribLattice +#align lattice_ordered_comm_group.lattice_ordered_add_comm_group_to_distrib_lattice AddCommGroup.toDistribLattice diff --git a/Mathlib/Algebra/Order/Group/OrderIso.lean b/Mathlib/Algebra/Order/Group/OrderIso.lean index 09c9a2c85a3ac..14e123a3b7fb8 100644 --- a/Mathlib/Algebra/Order/Group/OrderIso.lean +++ b/Mathlib/Algebra/Order/Group/OrderIso.lean @@ -5,6 +5,7 @@ Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ import Mathlib.Algebra.Group.Units.Equiv import Mathlib.Algebra.Order.Group.Defs +import Mathlib.Order.Hom.Basic #align_import algebra.order.group.order_iso from "leanprover-community/mathlib"@"6632ca2081e55ff5cf228ca63011979a0efb495b" diff --git a/Mathlib/Algebra/Order/Group/PosPart.lean b/Mathlib/Algebra/Order/Group/PosPart.lean new file mode 100644 index 0000000000000..59eb96cee3a05 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/PosPart.lean @@ -0,0 +1,264 @@ +/- +Copyright (c) 2021 Christopher Hoskin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christopher Hoskin, Yaël Dillies +-/ +import Mathlib.Algebra.Order.Group.Abs +import Mathlib.Algebra.Order.Group.Lattice + +#align_import algebra.order.lattice_group from "leanprover-community/mathlib"@"5dc275ec639221ca4d5f56938eb966f6ad9bc89f" + +/-! +# Positive & negative parts + +Mathematical structures possessing an absolute value often also possess a unique decomposition of +elements into "positive" and "negative" parts which are in some sense "disjoint" (e.g. the Jordan +decomposition of a measure). + +This file defines `posPart` and `negPart`, the positive and negative parts of an element in a +lattice ordered group. + +## Main statements + +* `posPart_sub_negPart`: Every element `a` can be decomposed into `a⁺ - a⁻`, the difference of its + positive and negative parts. +* `posPart_inf_negPart_eq_zero`: The positive and negative parts are coprime. + +## Notations + +* `a⁺ᵐ = a ⊔ 1`: *Positive component* of an element `a` of a multiplicative lattice ordered group +* `a⁻ᵐ = a⁻¹ ⊔ 1`: *Negative component* of an element `a` of a multiplicative lattice ordered group +* `a⁺ = a ⊔ 0`: *Positive component* of an element `a` of a lattice ordered group +* `a⁻ = (-a) ⊔ 0`: *Negative component* of an element `a` of a lattice ordered group + +## References + +* [Birkhoff, Lattice-ordered Groups][birkhoff1942] +* [Bourbaki, Algebra II][bourbaki1981] +* [Fuchs, Partially Ordered Algebraic Systems][fuchs1963] +* [Zaanen, Lectures on "Riesz Spaces"][zaanen1966] +* [Banasiak, Banach Lattices in Applications][banasiak] + +## Tags + +positive part, negative part +-/ + +/-- The positive part of an element admitting a decomposition into positive and negative parts. +-/ +class PosPart (α : Type*) where + /-- The positive part function. -/ + pos : α → α + +#align has_pos_part PosPart + +/-- The negative part of an element admitting a decomposition into positive and negative parts. +-/ +class NegPart (α : Type*) where + /-- The negative part function. -/ + neg : α → α + +#align has_neg_part NegPart + +@[inherit_doc] +postfix:max "⁺" => PosPart.pos + +@[inherit_doc] +postfix:max "⁻" => NegPart.neg + +open Function + +universe u v + +variable {α : Type u} {β : Type v} + +section Lattice +variable [Lattice α] + +section Group +variable [Group α] [CovariantClass α α (· * ·) (· ≤ ·)] + [CovariantClass α α (swap (· * ·)) (· ≤ ·)] {a : α} + +#noalign lattice_ordered_comm_group.has_one_lattice_has_pos_part +#noalign lattice_ordered_comm_group.has_zero_lattice_has_pos_part +#noalign lattice_ordered_comm_group.has_one_lattice_has_neg_part +#noalign lattice_ordered_comm_group.has_zero_lattice_has_neg_part + +/-- The *positive part* of an element `a` in a lattice ordered group is `a ⊔ 1`, denoted `a⁺ᵐ`. -/ +@[to_additive +"The *positive part* of an element `a` in a lattice ordered group is `a ⊔ 0`, denoted `a⁺`."] +def oneLePart (a : α) : α := a ⊔ 1 +#align lattice_ordered_comm_group.m_pos_part_def oneLePart +#align lattice_ordered_comm_group.pos_part_def posPart +#align has_pos_part.pos posPart + +/-- The *negative part* of an element `a` in a lattice ordered group is `a⁻¹ ⊔ 1`, denoted `a⁻ᵐ `. +-/ +@[to_additive +"The *negative part* of an element `a` in a lattice ordered group is `(-a) ⊔ 0`, denoted `a⁻`."] +def leOnePart (a : α) : α := a⁻¹ ⊔ 1 +#align lattice_ordered_comm_group.m_neg_part_def leOnePart +#align lattice_ordered_comm_group.neg_part_def negPart +#align has_neg_part.neg negPart + +@[inherit_doc] postfix:max "⁺ᵐ " => oneLePart +@[inherit_doc] postfix:max "⁻ᵐ" => leOnePart +@[inherit_doc] postfix:max "⁺" => posPart +@[inherit_doc] postfix:max "⁻" => negPart + +@[to_additive] lemma oneLePart_mono : Monotone (oneLePart : α → α) := + fun _a _b hab ↦ sup_le_sup_right hab _ + +@[to_additive] lemma leOnePart_anti : Antitone (leOnePart : α → α) := + fun _a _b hab ↦ sup_le_sup_right (inv_le_inv_iff.2 hab) _ + +@[to_additive (attr := simp)] lemma oneLePart_one : (1 : α)⁺ᵐ = 1 := sup_idem +#align lattice_ordered_comm_group.pos_one oneLePart_one +#align lattice_ordered_comm_group.pos_zero posPart_zero + +@[to_additive (attr := simp)] lemma leOnePart_one : (1 : α)⁻ᵐ = 1 := by simp [leOnePart] +#align lattice_ordered_comm_group.neg_one leOnePart_one +#align lattice_ordered_comm_group.neg_zero negPart_zero + +@[to_additive posPart_nonneg] lemma one_le_oneLePart (a : α) : 1 ≤ a⁺ᵐ := le_sup_right +#align lattice_ordered_comm_group.one_le_pos one_le_oneLePart +#align lattice_ordered_comm_group.pos_nonneg posPart_nonneg + +@[to_additive negPart_nonneg] lemma one_le_leOnePart (a : α) : 1 ≤ a⁻ᵐ := le_sup_right +#align lattice_ordered_comm_group.one_le_neg one_le_leOnePart +#align lattice_ordered_comm_group.neg_nonneg neg_nonneg + +-- TODO: `to_additive` guesses `nonposPart` +@[to_additive le_posPart] lemma le_oneLePart (a : α) : a ≤ a⁺ᵐ := le_sup_left +#align lattice_ordered_comm_group.m_le_pos le_oneLePart +#align lattice_ordered_comm_group.le_pos le_posPart + +@[to_additive] lemma inv_le_leOnePart (a : α) : a⁻¹ ≤ a⁻ᵐ := le_sup_left +#align lattice_ordered_comm_group.inv_le_neg inv_le_leOnePart +#align lattice_ordered_comm_group.neg_le_neg neg_le_negPart + +@[to_additive] lemma oneLePart_eq_self : a⁺ᵐ = a ↔ 1 ≤ a := sup_eq_left +#align lattice_ordered_comm_group.pos_of_one_le oneLePart_eq_self +#align lattice_ordered_comm_group.pos_of_nonneg posPart_eq_self + +@[to_additive] lemma oneLePart_eq_one : a⁺ᵐ = 1 ↔ a ≤ 1 := sup_eq_right +#align lattice_ordered_comm_group.pos_eq_one_iff oneLePart_eq_one +#align lattice_ordered_comm_group.pos_eq_zero_iff posPart_eq_zero +#align lattice_ordered_comm_group.pos_of_le_one oneLePart_eq_one +#align lattice_ordered_comm_group.pos_of_nonpos posPart_eq_zero + +@[to_additive] lemma leOnePart_eq_inv' : a⁻ᵐ = a⁻¹ ↔ 1 ≤ a⁻¹ := sup_eq_left +@[to_additive] lemma leOnePart_eq_inv : a⁻ᵐ = a⁻¹ ↔ a ≤ 1 := by simp [leOnePart] +#align lattice_ordered_comm_group.neg_of_le_one leOnePart_eq_inv +#align lattice_ordered_comm_group.neg_of_nonpos negPart_eq_neg +#align lattice_ordered_comm_group.neg_of_one_le_inv leOnePart_eq_inv +#align lattice_ordered_comm_group.neg_of_inv_nonneg negPart_eq_neg + +@[to_additive] lemma leOnePart_eq_one' : a⁻ᵐ = 1 ↔ a⁻¹ ≤ 1 := sup_eq_right +#align lattice_ordered_comm_group.neg_eq_one_iff' leOnePart_eq_one' +#align lattice_ordered_comm_group.neg_eq_zero_iff' negPart_eq_zero' +#align lattice_ordered_comm_group.neg_of_inv_le_one leOnePart_eq_one' +#align lattice_ordered_comm_group.neg_of_neg_nonpos negPart_eq_zero' + +@[to_additive] lemma leOnePart_eq_one : a⁻ᵐ = 1 ↔ 1 ≤ a := by + simp [leOnePart_eq_one'] +#align lattice_ordered_comm_group.neg_eq_one_iff leOnePart_eq_one +#align lattice_ordered_comm_group.neg_eq_zero_iff negPart_eq_zero +#align lattice_ordered_comm_group.neg_of_one_le leOnePart_eq_one +#align lattice_ordered_comm_group.neg_of_nonneg negPart_eq_zero + +@[to_additive] lemma oneLePart_le_one : a⁺ᵐ ≤ 1 ↔ a ≤ 1 := by simp [oneLePart] +#align lattice_ordered_comm_group.pos_le_one_iff oneLePart_le_one +#align lattice_ordered_comm_group.pos_nonpos_iff posPart_nonpos + +@[to_additive] lemma leOnePart_le_one' : a⁻ᵐ ≤ 1 ↔ a⁻¹ ≤ 1 := by simp [leOnePart] +#align lattice_ordered_comm_group.neg_le_one_iff leOnePart_le_one' +#align lattice_ordered_comm_group.neg_nonpos_iff negPart_nonpos' + +@[to_additive (attr := simp)] lemma oneLePart_inv (a : α) : a⁻¹⁺ᵐ = a⁻ᵐ := rfl +#align lattice_ordered_comm_group.neg_eq_pos_inv oneLePart_inv +#align lattice_ordered_comm_group.neg_eq_pos_neg posPart_neg + +@[to_additive (attr := simp)] lemma leOnePart_inv (a : α) : a⁻¹⁻ᵐ = a⁺ᵐ := by + simp [oneLePart, leOnePart] +#align lattice_ordered_comm_group.pos_eq_neg_inv leOnePart_inv +#align lattice_ordered_comm_group.pos_eq_neg_neg negPart_neg + +@[to_additive] lemma leOnePart_le_one : a⁻ᵐ ≤ 1 ↔ a⁻¹ ≤ 1 := by simp [leOnePart] + +@[to_additive] +lemma leOnePart_eq_inv_inf_one (a : α) : a⁻ᵐ = (a ⊓ 1)⁻¹ := by + rw [leOnePart, ← inv_inj, inv_sup, inv_inv, inv_inv, inv_one] +#align lattice_ordered_comm_group.neg_eq_inv_inf_one leOnePart_eq_inv_inf_one +#align lattice_ordered_comm_group.neg_eq_neg_inf_zero negPart_eq_neg_inf_zero + +-- Bourbaki A.VI.12 Prop 9 a) +@[to_additive (attr := simp)] +lemma oneLePart_div_leOnePart (a : α) : a⁺ᵐ / a⁻ᵐ = a := by + rw [div_eq_mul_inv, mul_inv_eq_iff_eq_mul, leOnePart, mul_sup, mul_one, mul_right_inv, sup_comm, + oneLePart] +#align lattice_ordered_comm_group.pos_div_neg oneLePart_div_leOnePart +#align lattice_ordered_comm_group.pos_sub_neg posPart_sub_negPart + +-- The proof from Bourbaki A.VI.12 Prop 9 d) +@[to_additive] +lemma oneLePart_mul_leOnePart + [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a : α) : + a⁺ᵐ * a⁻ᵐ = |a|ₘ := by + rw [oneLePart, sup_mul, one_mul, leOnePart, mul_sup, mul_one, mul_inv_self, sup_assoc, + ← @sup_assoc _ _ a, sup_eq_right.2 le_sup_right] + exact sup_eq_left.2 <| one_le_mabs a +#align lattice_ordered_comm_group.pos_mul_neg oneLePart_mul_leOnePart +#align lattice_ordered_comm_group.pos_add_neg posPart_add_negPart + +#noalign lattice_ordered_comm_group.m_pos_abs +#noalign lattice_ordered_comm_group.pos_abs +#noalign lattice_ordered_comm_group.m_neg_abs +#noalign lattice_ordered_comm_group.neg_abs + +-- Bourbaki A.VI.12 Prop 9 a) +-- a⁺ᵐ ⊓ a⁻ᵐ = 0 (`a⁺` and `a⁻` are co-prime, and, since they are positive, disjoint) +@[to_additive] lemma oneLePart_inf_leOnePart_eq_one (a : α) : a⁺ᵐ ⊓ a⁻ᵐ = 1 := by + rw [← mul_left_inj a⁻ᵐ⁻¹, inf_mul, one_mul, mul_right_inv, ← div_eq_mul_inv, + oneLePart_div_leOnePart, leOnePart_eq_inv_inf_one, inv_inv] +#align lattice_ordered_comm_group.pos_inf_neg_eq_one oneLePart_inf_leOnePart_eq_one +#align lattice_ordered_comm_group.pos_inf_neg_eq_zero posPart_inf_negPart_eq_zero + +end Group + +section CommGroup +variable [Lattice α] [CommGroup α] [CovariantClass α α (· * ·) (· ≤ ·)] + +-- Bourbaki A.VI.12 (with a and b swapped) +@[to_additive] lemma sup_eq_mul_oneLePart_div (a b : α) : a ⊔ b = b * (a / b)⁺ᵐ := by + simp [oneLePart, mul_sup] +#align lattice_ordered_comm_group.sup_eq_mul_pos_div sup_eq_mul_oneLePart_div +#align lattice_ordered_comm_group.sup_eq_add_pos_sub sup_eq_add_posPart_sub + +-- Bourbaki A.VI.12 (with a and b swapped) +@[to_additive] lemma inf_eq_div_oneLePart_div (a b : α) : a ⊓ b = a / (a / b)⁺ᵐ := by + simp [oneLePart, div_sup, inf_comm] +#align lattice_ordered_comm_group.inf_eq_div_pos_div inf_eq_div_oneLePart_div +#align lattice_ordered_comm_group.inf_eq_sub_pos_sub inf_eq_sub_posPart_sub + +-- Bourbaki A.VI.12 Prop 9 c) +@[to_additive] lemma le_iff_oneLePart_leOnePart (a b : α) : a ≤ b ↔ a⁺ᵐ ≤ b⁺ᵐ ∧ b⁻ᵐ ≤ a⁻ᵐ := by + refine ⟨fun h ↦ ⟨oneLePart_mono h, leOnePart_anti h⟩, fun h ↦ ?_⟩ + rw [← oneLePart_div_leOnePart a, ← oneLePart_div_leOnePart b] + exact div_le_div'' h.1 h.2 +#align lattice_ordered_comm_group.m_le_iff_pos_le_neg_ge le_iff_oneLePart_leOnePart +#align lattice_ordered_comm_group.le_iff_pos_le_neg_ge le_iff_posPart_negPart + +end CommGroup +end Lattice + +section LinearOrder +variable [LinearOrder α] [CommGroup α] {a : α} + +@[to_additive posPart_eq_of_posPart_pos] +lemma oneLePart_of_one_lt_oneLePart (ha : 1 < a⁺ᵐ) : a⁺ᵐ = a := by + rw [oneLePart, right_lt_sup, not_le] at ha; exact oneLePart_eq_self.2 ha.le +#align lattice_ordered_comm_group.pos_eq_self_of_one_lt_pos oneLePart_of_one_lt_oneLePart +#align lattice_ordered_comm_group.pos_eq_self_of_pos_pos posPart_eq_of_posPart_pos + +end LinearOrder diff --git a/Mathlib/Algebra/Order/Group/Prod.lean b/Mathlib/Algebra/Order/Group/Prod.lean index 0ee8c08d4f7aa..f049bfe47982d 100644 --- a/Mathlib/Algebra/Order/Group/Prod.lean +++ b/Mathlib/Algebra/Order/Group/Prod.lean @@ -3,7 +3,7 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ -import Mathlib.Algebra.Order.Group.Instances +import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Monoid.Prod #align_import algebra.order.group.prod from "leanprover-community/mathlib"@"ee0c179cd3c8a45aa5bffbf1b41d8dbede452865" diff --git a/Mathlib/Algebra/Order/Group/TypeTags.lean b/Mathlib/Algebra/Order/Group/TypeTags.lean index 581a18a8ad139..b82f2dee7ccda 100644 --- a/Mathlib/Algebra/Order/Group/TypeTags.lean +++ b/Mathlib/Algebra/Order/Group/TypeTags.lean @@ -3,7 +3,7 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ -import Mathlib.Algebra.Order.Group.Instances +import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Monoid.TypeTags #align_import algebra.order.group.type_tags from "leanprover-community/mathlib"@"2258b40dacd2942571c8ce136215350c702dc78f" diff --git a/Mathlib/Algebra/Order/Group/WithTop.lean b/Mathlib/Algebra/Order/Group/WithTop.lean index 8fdc8190230b8..4e57eb543c5c8 100644 --- a/Mathlib/Algebra/Order/Group/WithTop.lean +++ b/Mathlib/Algebra/Order/Group/WithTop.lean @@ -3,7 +3,7 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ -import Mathlib.Algebra.Order.Group.Instances +import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Monoid.WithTop #align_import algebra.order.group.with_top from "leanprover-community/mathlib"@"f178c0e25af359f6cbc72a96a243efd3b12423a3" @@ -28,7 +28,7 @@ instance linearOrderedAddCommGroupWithTop : LinearOrderedAddCommGroupWithTop (Wi add_neg_cancel := by rintro (a | a) ha · exact (ha rfl).elim - · exact WithTop.coe_add.symm.trans (WithTop.coe_eq_coe.2 (add_neg_self a)) + · exact (WithTop.coe_add ..).symm.trans (WithTop.coe_eq_coe.2 (add_neg_self a)) #align with_top.linear_ordered_add_comm_group_with_top WithTop.linearOrderedAddCommGroupWithTop @[simp, norm_cast] diff --git a/Mathlib/Algebra/Order/Hom/Basic.lean b/Mathlib/Algebra/Order/Hom/Basic.lean index de88cb3ba54d7..f292493292c2a 100644 --- a/Mathlib/Algebra/Order/Hom/Basic.lean +++ b/Mathlib/Algebra/Order/Hom/Basic.lean @@ -3,8 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ - -import Mathlib.Algebra.GroupPower.Order +import Mathlib.Logic.Basic import Mathlib.Tactic.Positivity.Basic #align_import algebra.order.hom.basic from "leanprover-community/mathlib"@"28aa996fc6fb4317f0083c4e6daf79878d81be33" @@ -77,14 +76,14 @@ variable {ι F α β γ δ : Type*} /-- `NonnegHomClass F α β` states that `F` is a type of nonnegative morphisms. -/ class NonnegHomClass (F : Type*) (α β : outParam (Type*)) [Zero β] [LE β] extends - FunLike F α fun _ => β where + DFunLike F α (fun _ => β) where /-- the image of any element is non negative. -/ map_nonneg (f : F) : ∀ a, 0 ≤ f a #align nonneg_hom_class NonnegHomClass /-- `SubadditiveHomClass F α β` states that `F` is a type of subadditive morphisms. -/ class SubadditiveHomClass (F : Type*) (α β : outParam (Type*)) [Add α] [Add β] [LE β] extends - FunLike F α fun _ => β where + DFunLike F α (fun _ => β) where /-- the image of a sum is less or equal than the sum of the images. -/ map_add_le_add (f : F) : ∀ a b, f (a + b) ≤ f a + f b #align subadditive_hom_class SubadditiveHomClass @@ -92,7 +91,7 @@ class SubadditiveHomClass (F : Type*) (α β : outParam (Type*)) [Add α] [Add /-- `SubmultiplicativeHomClass F α β` states that `F` is a type of submultiplicative morphisms. -/ @[to_additive SubadditiveHomClass] class SubmultiplicativeHomClass (F : Type*) (α β : outParam (Type*)) [Mul α] [Mul β] [LE β] - extends FunLike F α fun _ => β where + extends DFunLike F α (fun _ => β) where /-- the image of a product is less or equal than the product of the images. -/ map_mul_le_mul (f : F) : ∀ a b, f (a * b) ≤ f a * f b #align submultiplicative_hom_class SubmultiplicativeHomClass @@ -100,14 +99,14 @@ class SubmultiplicativeHomClass (F : Type*) (α β : outParam (Type*)) [Mul α] /-- `MulLEAddHomClass F α β` states that `F` is a type of subadditive morphisms. -/ @[to_additive SubadditiveHomClass] class MulLEAddHomClass (F : Type*) (α β : outParam (Type*)) [Mul α] [Add β] [LE β] - extends FunLike F α fun _ => β where + extends DFunLike F α (fun _ => β) where /-- the image of a product is less or equal than the sum of the images. -/ map_mul_le_add (f : F) : ∀ a b, f (a * b) ≤ f a + f b #align mul_le_add_hom_class MulLEAddHomClass /-- `NonarchimedeanHomClass F α β` states that `F` is a type of non-archimedean morphisms. -/ class NonarchimedeanHomClass (F : Type*) (α β : outParam (Type*)) [Add α] [LinearOrder β] - extends FunLike F α fun _ => β where + extends DFunLike F α (fun _ => β) where /-- the image of a sum is less or equal than the maximum of the images. -/ map_add_le_max (f : F) : ∀ a b, f (a + b) ≤ max (f a) (f b) #align nonarchimedean_hom_class NonarchimedeanHomClass @@ -157,7 +156,7 @@ namespace Mathlib.Meta.Positivity open Lean Meta Qq Function /-- Extension for the `positivity` tactic: nonnegative maps take nonnegative values. -/ -@[positivity FunLike.coe _ _] +@[positivity DFunLike.coe _ _] def evalMap : PositivityExt where eval {_ β} _ _ e := do let .app (.app _ f) a ← whnfR e | throwError "not ↑f · where f is of NonnegHomClass" diff --git a/Mathlib/Algebra/Order/Hom/Monoid.lean b/Mathlib/Algebra/Order/Hom/Monoid.lean index 7619d3caba290..6ca86e07f8c63 100644 --- a/Mathlib/Algebra/Order/Hom/Monoid.lean +++ b/Mathlib/Algebra/Order/Hom/Monoid.lean @@ -295,17 +295,17 @@ variable [Preorder α] [Preorder β] [Preorder γ] [Preorder δ] [MulOneClass α -- Porting note: -- These helper instances are unhelpful in Lean 4, so omitting: --- /-- Helper instance for when there's too many metavariables to apply `FunLike.instCoeFunForAll` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.instCoeFunForAll` -- directly. -/ -- @[to_additive "Helper instance for when there's too many metavariables to apply --- `FunLike.instCoeFunForAll` directly."] +-- `DFunLike.instCoeFunForAll` directly."] -- instance : CoeFun (α →*o β) fun _ => α → β := --- FunLike.instCoeFunForAll +-- DFunLike.instCoeFunForAll --- Other lemmas should be accessed through the `FunLike` API +-- Other lemmas should be accessed through the `DFunLike` API @[to_additive (attr := ext)] theorem ext (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align order_monoid_hom.ext OrderMonoidHom.ext #align order_add_monoid_hom.ext OrderAddMonoidHom.ext @@ -349,13 +349,13 @@ theorem coe_orderHom (f : α →*o β) : ((f : α →o β) : α → β) = f := @[to_additive] theorem toMonoidHom_injective : Injective (toMonoidHom : _ → α →* β) := fun f g h => - ext <| by convert FunLike.ext_iff.1 h using 0 + ext <| by convert DFunLike.ext_iff.1 h using 0 #align order_monoid_hom.to_monoid_hom_injective OrderMonoidHom.toMonoidHom_injective #align order_add_monoid_hom.to_add_monoid_hom_injective OrderAddMonoidHom.toAddMonoidHom_injective @[to_additive] theorem toOrderHom_injective : Injective (toOrderHom : _ → α →o β) := fun f g h => - ext <| by convert FunLike.ext_iff.1 h using 0 + ext <| by convert DFunLike.ext_iff.1 h using 0 #align order_monoid_hom.to_order_hom_injective OrderMonoidHom.toOrderHom_injective #align order_add_monoid_hom.to_order_hom_injective OrderAddMonoidHom.toOrderHom_injective @@ -376,7 +376,7 @@ theorem coe_copy (f : α →*o β) (f' : α → β) (h : f' = f) : ⇑(f.copy f' @[to_additive] theorem copy_eq (f : α →*o β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align order_monoid_hom.copy_eq OrderMonoidHom.copy_eq #align order_add_monoid_hom.copy_eq OrderAddMonoidHom.copy_eq @@ -456,7 +456,7 @@ theorem id_comp (f : α →*o β) : (OrderMonoidHom.id β).comp f = f := @[to_additive (attr := simp)] theorem cancel_right {g₁ g₂ : β →*o γ} {f : α →*o β} (hf : Function.Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun _ => by congr⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun _ => by congr⟩ #align order_monoid_hom.cancel_right OrderMonoidHom.cancel_right #align order_add_monoid_hom.cancel_right OrderAddMonoidHom.cancel_right @@ -590,15 +590,15 @@ instance : OrderMonoidWithZeroHomClass (α →*₀o β) α β where -- Porting note: -- These helper instances are unhelpful in Lean 4, so omitting: ---/-- Helper instance for when there's too many metavariables to apply `FunLike.instCoeFunForAll` +--/-- Helper instance for when there's too many metavariables to apply `DFunLike.instCoeFunForAll` --directly. -/ --instance : CoeFun (α →*₀o β) fun _ => α → β := --- FunLike.instCoeFunForAll +-- DFunLike.instCoeFunForAll --- Other lemmas should be accessed through the `FunLike` API +-- Other lemmas should be accessed through the `DFunLike` API @[ext] theorem ext (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align order_monoid_with_zero_hom.ext OrderMonoidWithZeroHom.ext theorem toFun_eq_coe (f : α →*₀o β) : f.toFun = (f : α → β) := @@ -630,11 +630,11 @@ theorem coe_orderMonoidHom (f : α →*₀o β) : ⇑(f : α →*o β) = f := #align order_monoid_with_zero_hom.coe_order_monoid_hom OrderMonoidWithZeroHom.coe_orderMonoidHom theorem toOrderMonoidHom_injective : Injective (toOrderMonoidHom : _ → α →*o β) := fun f g h => - ext <| by convert FunLike.ext_iff.1 h using 0 + ext <| by convert DFunLike.ext_iff.1 h using 0 #align order_monoid_with_zero_hom.to_order_monoid_hom_injective OrderMonoidWithZeroHom.toOrderMonoidHom_injective theorem toMonoidWithZeroHom_injective : Injective (toMonoidWithZeroHom : _ → α →*₀ β) := - fun f g h => ext <| by convert FunLike.ext_iff.1 h using 0 + fun f g h => ext <| by convert DFunLike.ext_iff.1 h using 0 #align order_monoid_with_zero_hom.to_monoid_with_zero_hom_injective OrderMonoidWithZeroHom.toMonoidWithZeroHom_injective /-- Copy of an `OrderMonoidWithZeroHom` with a new `toFun` equal to the old one. Useful to fix @@ -649,7 +649,7 @@ theorem coe_copy (f : α →*₀o β) (f' : α → β) (h : f' = f) : ⇑(f.copy #align order_monoid_with_zero_hom.coe_copy OrderMonoidWithZeroHom.coe_copy theorem copy_eq (f : α →*₀o β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align order_monoid_with_zero_hom.copy_eq OrderMonoidWithZeroHom.copy_eq variable (α) @@ -711,7 +711,7 @@ theorem id_comp (f : α →*₀o β) : (OrderMonoidWithZeroHom.id β).comp f = f @[simp] theorem cancel_right {g₁ g₂ : β →*₀o γ} {f : α →*₀o β} (hf : Function.Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun _ => by congr⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun _ => by congr⟩ #align order_monoid_with_zero_hom.cancel_right OrderMonoidWithZeroHom.cancel_right @[simp] diff --git a/Mathlib/Algebra/Order/Hom/Ring.lean b/Mathlib/Algebra/Order/Hom/Ring.lean index 5ff8583808c1d..d868b30c693e9 100644 --- a/Mathlib/Algebra/Order/Hom/Ring.lean +++ b/Mathlib/Algebra/Order/Hom/Ring.lean @@ -184,7 +184,7 @@ instance : OrderRingHomClass (α →+*o β) α β monotone f := f.monotone' -- porting note: These helper instances are unhelpful in Lean 4, so omitting: --- /-- Helper instance for when there's too many metavariables to apply `FunLike.has_coe_to_fun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.has_coe_to_fun` -- directly. -/ -- instance : CoeFun (α →+*o β) fun _ => α → β := -- ⟨fun f => f.toFun⟩ @@ -195,7 +195,7 @@ theorem toFun_eq_coe (f : α →+*o β) : f.toFun = f := @[ext] theorem ext {f g : α →+*o β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align order_ring_hom.ext OrderRingHom.ext @[simp] @@ -255,7 +255,7 @@ theorem coe_copy (f : α →+*o β) (f' : α → β) (h : f' = f) : ⇑(f.copy f #align order_ring_hom.coe_copy OrderRingHom.coe_copy theorem copy_eq (f : α →+*o β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align order_ring_hom.copy_eq OrderRingHom.copy_eq variable (α) @@ -329,7 +329,7 @@ theorem id_comp (f : α →+*o β) : (OrderRingHom.id β).comp f = f := @[simp] theorem cancel_right {f₁ f₂ : β →+*o γ} {g : α →+*o β} (hg : Surjective g) : f₁.comp g = f₂.comp g ↔ f₁ = f₂ := - ⟨fun h => ext <| hg.forall.2 <| FunLike.ext_iff.1 h, fun h => by rw [h]⟩ + ⟨fun h => ext <| hg.forall.2 <| DFunLike.ext_iff.1 h, fun h => by rw [h]⟩ #align order_ring_hom.cancel_right OrderRingHom.cancel_right @[simp] @@ -346,7 +346,7 @@ instance [Preorder β] : Preorder (OrderRingHom α β) := Preorder.lift ((⇑) : _ → α → β) instance [PartialOrder β] : PartialOrder (OrderRingHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective end OrderRingHom @@ -381,10 +381,10 @@ instance : OrderRingIsoClass (α ≃+*o β) α β right_inv f := f.right_inv -- porting note: These helper instances are unhelpful in Lean 4, so omitting: -/-- Helper instance for when there's too many metavariables to apply `FunLike.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.has_coe_to_fun` directly. -/ -- instance : CoeFun (α ≃+*o β) fun _ => α → β := --- FunLike.has_coe_to_fun +-- DFunLike.has_coe_to_fun theorem toFun_eq_coe (f : α ≃+*o β) : f.toFun = f := rfl @@ -392,7 +392,7 @@ theorem toFun_eq_coe (f : α ≃+*o β) : f.toFun = f := @[ext] theorem ext {f g : α ≃+*o β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align order_ring_iso.ext OrderRingIso.ext @[simp] @@ -420,9 +420,9 @@ theorem coe_toRingEquiv (f : α ≃+*o β) : ⇑(f : α ≃+* β) = f := rfl #align order_ring_iso.coe_to_ring_equiv OrderRingIso.coe_toRingEquiv --- Porting note: needed to add FunLike.coe on the lhs, bad Equiv coercion otherwise +-- Porting note: needed to add DFunLike.coe on the lhs, bad Equiv coercion otherwise @[simp, norm_cast] -theorem coe_toOrderIso (f : α ≃+*o β) : FunLike.coe (f : α ≃o β) = f := +theorem coe_toOrderIso (f : α ≃+*o β) : DFunLike.coe (f : α ≃o β) = f := rfl #align order_ring_iso.coe_to_order_iso OrderRingIso.coe_toOrderIso @@ -537,7 +537,7 @@ theorem coe_toOrderRingHom_refl : (OrderRingIso.refl α : α →+*o α) = OrderR #align order_ring_iso.coe_to_order_ring_hom_refl OrderRingIso.coe_toOrderRingHom_refl theorem toOrderRingHom_injective : Injective (toOrderRingHom : α ≃+*o β → α →+*o β) := - fun f g h => FunLike.coe_injective <| by convert FunLike.ext'_iff.1 h using 0 + fun f g h => DFunLike.coe_injective <| by convert DFunLike.ext'_iff.1 h using 0 #align order_ring_iso.to_order_ring_hom_injective OrderRingIso.toOrderRingHom_injective end NonAssocSemiring diff --git a/Mathlib/Algebra/Order/Interval.lean b/Mathlib/Algebra/Order/Interval.lean index f28c994d162d5..9ba08d14e05ff 100644 --- a/Mathlib/Algebra/Order/Interval.lean +++ b/Mathlib/Algebra/Order/Interval.lean @@ -8,7 +8,6 @@ import Mathlib.Algebra.Group.Prod import Mathlib.Data.Option.NAry import Mathlib.Data.Set.Pointwise.Basic import Mathlib.Order.Interval -import Mathlib.Tactic.Positivity #align_import algebra.order.interval from "leanprover-community/mathlib"@"f0c8bf9245297a541f468be517f1bde6195105e9" @@ -42,10 +41,6 @@ variable [Preorder α] [One α] instance : One (NonemptyInterval α) := ⟨NonemptyInterval.pure 1⟩ -@[to_additive] -instance : One (Interval α) := - ⟨Interval.pure 1⟩ - namespace NonemptyInterval @[to_additive (attr := simp) toProd_zero] @@ -89,15 +84,11 @@ theorem pure_one : pure (1 : α) = 1 := #align interval.pure_one Interval.pure_one #align interval.pure_zero Interval.pure_zero -@[to_additive (attr := simp)] -theorem one_ne_bot : (1 : Interval α) ≠ ⊥ := - pure_ne_bot +@[to_additive] lemma one_ne_bot : (1 : Interval α) ≠ ⊥ := pure_ne_bot #align interval.one_ne_bot Interval.one_ne_bot #align interval.zero_ne_bot Interval.zero_ne_bot -@[to_additive (attr := simp)] -theorem bot_ne_one : (⊥ : Interval α) ≠ 1 := - bot_ne_pure +@[to_additive] lemma bot_ne_one : (⊥ : Interval α) ≠ 1 := bot_ne_pure #align interval.bot_ne_one Interval.bot_ne_one #align interval.bot_ne_zero Interval.bot_ne_zero @@ -288,11 +279,9 @@ instance Interval.mulOneClass [OrderedCommMonoid α] : MulOneClass (Interval α) mul := (· * ·) one := 1 one_mul s := - (Option.map₂_coe_left _ _ _).trans <| by - simp_rw [NonemptyInterval.pure_one, one_mul, ← id_def, Option.map_id, id] + (Option.map₂_coe_left _ _ _).trans <| by simp_rw [one_mul, ← id_def, Option.map_id, id] mul_one s := - (Option.map₂_coe_right _ _ _).trans <| by - simp_rw [NonemptyInterval.pure_one, mul_one, ← id_def, Option.map_id, id] + (Option.map₂_coe_right _ _ _).trans <| by simp_rw [mul_one, ← id_def, Option.map_id, id] @[to_additive] instance Interval.commMonoid [OrderedCommMonoid α] : CommMonoid (Interval α) := diff --git a/Mathlib/Algebra/Order/Kleene.lean b/Mathlib/Algebra/Order/Kleene.lean index 5e79275e8824c..14eb9d2ae5a0b 100644 --- a/Mathlib/Algebra/Order/Kleene.lean +++ b/Mathlib/Algebra/Order/Kleene.lean @@ -3,10 +3,10 @@ Copyright (c) 2022 Siddhartha Prasad, Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Siddhartha Prasad, Yaël Dillies -/ -import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Algebra.Ring.Pi import Mathlib.Algebra.Ring.Prod -import Mathlib.Order.Hom.CompleteLattice +import Mathlib.Algebra.Ring.InjSurj +import Mathlib.Tactic.Monotonicity.Attr #align_import algebra.order.kleene from "leanprover-community/mathlib"@"98e83c3d541c77cdb7da20d79611a780ff8e7d90" diff --git a/Mathlib/Algebra/Order/LatticeGroup.lean b/Mathlib/Algebra/Order/LatticeGroup.lean deleted file mode 100644 index 9b2e287d09b67..0000000000000 --- a/Mathlib/Algebra/Order/LatticeGroup.lean +++ /dev/null @@ -1,711 +0,0 @@ -/- -Copyright (c) 2021 Christopher Hoskin. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Christopher Hoskin --/ -import Mathlib.Algebra.Order.Group.Abs -import Mathlib.Algebra.Module.Basic -import Mathlib.Order.Closure - -#align_import algebra.order.lattice_group from "leanprover-community/mathlib"@"5dc275ec639221ca4d5f56938eb966f6ad9bc89f" - -/-! -# Lattice ordered groups - -Lattice ordered groups were introduced by [Birkhoff][birkhoff1942]. -They form the algebraic underpinnings of vector lattices, Banach lattices, AL-space, AM-space etc. - -This file develops the basic theory. - -## Main statements - -- `pos_div_neg`: Every element `a` of a lattice ordered group has a decomposition `a⁺-a⁻` into the - difference of the positive and negative component. -- `pos_inf_neg_eq_one`: The positive and negative components are coprime. -- `abs_triangle`: The absolute value operation satisfies the triangle inequality (stated for a - commutative group). - -It is shown that the inf and sup operations are related to the absolute value operation by a -number of equations and inequalities. - -## Notations - -- `a⁺ = a ⊔ 0`: The *positive component* of an element `a` of a lattice ordered group -- `a⁻ = (-a) ⊔ 0`: The *negative component* of an element `a` of a lattice ordered group -- `|a| = a⊔(-a)`: The *absolute value* of an element `a` of a lattice ordered group - -## Implementation notes - -A lattice ordered group is a type `α` satisfying: - -* `[Lattice α]` -* `[CommGroup α]` -* `[CovariantClass α α (*) (≤)]` -* `[CovariantClass α α (swap (· * ·)) (· ≤ ·)]` - -The remainder of the file establishes basic properties of lattice ordered groups. It is shown that -when the group is commutative, the lattice is distributive. This also holds in the non-commutative -case ([Birkhoff][birkhoff1942],[Fuchs][fuchs1963]) but we do not yet have the machinery to establish -this in Mathlib. - -## References - -* [Birkhoff, Lattice-ordered Groups][birkhoff1942] -* [Bourbaki, Algebra II][bourbaki1981] -* [Fuchs, Partially Ordered Algebraic Systems][fuchs1963] -* [Zaanen, Lectures on "Riesz Spaces"][zaanen1966] -* [Banasiak, Banach Lattices in Applications][banasiak] - -## Tags - -lattice, ordered, group --/ - -open Function - -universe u v - -variable {α : Type u} {β : Type v} - -section Group - -variable [Lattice α] [Group α] - --- Special case of Bourbaki A.VI.9 (1) --- c + (a ⊔ b) = (c + a) ⊔ (c + b) -@[to_additive] -theorem mul_sup [CovariantClass α α (· * ·) (· ≤ ·)] (a b c : α) : c * (a ⊔ b) = c * a ⊔ c * b := - (OrderIso.mulLeft _).map_sup _ _ -#align mul_sup mul_sup -#align add_sup add_sup - -@[to_additive] -theorem sup_mul [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a b c : α) : - (a ⊔ b) * c = a * c ⊔ b * c := - (OrderIso.mulRight _).map_sup _ _ -#align sup_mul sup_mul -#align sup_add sup_add - -@[to_additive] -theorem mul_inf [CovariantClass α α (· * ·) (· ≤ ·)] (a b c : α) : c * (a ⊓ b) = c * a ⊓ c * b := - (OrderIso.mulLeft _).map_inf _ _ -#align mul_inf mul_inf -#align add_inf add_inf - -@[to_additive] -theorem inf_mul [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a b c : α) : - (a ⊓ b) * c = a * c ⊓ b * c := - (OrderIso.mulRight _).map_inf _ _ -#align inf_mul inf_mul -#align inf_add inf_add - --- Special case of Bourbaki A.VI.9 (2) --- -(a ⊔ b)=(-a) ⊓ (-b) -@[to_additive] -theorem inv_sup_eq_inv_inf_inv - [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a b : α) : - (a ⊔ b)⁻¹ = a⁻¹ ⊓ b⁻¹ := - (OrderIso.inv α).map_sup _ _ -#align inv_sup_eq_inv_inf_inv inv_sup_eq_inv_inf_inv -#align neg_sup_eq_neg_inf_neg neg_sup_eq_neg_inf_neg - --- -(a ⊓ b) = -a ⊔ -b -@[to_additive] -theorem inv_inf_eq_sup_inv - [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a b : α) : - (a ⊓ b)⁻¹ = a⁻¹ ⊔ b⁻¹ := - (OrderIso.inv α).map_inf _ _ -#align inv_inf_eq_sup_inv inv_inf_eq_sup_inv -#align neg_inf_eq_sup_neg neg_inf_eq_sup_neg - -namespace LatticeOrderedGroup - --- see Note [lower instance priority] -/-- -Let `α` be a lattice ordered commutative group with identity `1`. For an element `a` of type `α`, -the element `a ⊔ 1` is said to be the *positive component* of `a`, denoted `a⁺`. --/ -@[to_additive - "Let `α` be a lattice ordered commutative group with identity `0`. For an element `a` of type - `α`,the element `a ⊔ 0` is said to be the *positive component* of `a`, denoted `a⁺`."] -instance (priority := 100) hasOneLatticeHasPosPart : PosPart α := - ⟨fun a => a ⊔ 1⟩ -#align lattice_ordered_comm_group.has_one_lattice_has_pos_part LatticeOrderedGroup.hasOneLatticeHasPosPart -#align lattice_ordered_comm_group.has_zero_lattice_has_pos_part LatticeOrderedGroup.hasZeroLatticeHasPosPart - -@[to_additive pos_part_def] -theorem m_pos_part_def (a : α) : a⁺ = a ⊔ 1 := - rfl -#align lattice_ordered_comm_group.m_pos_part_def LatticeOrderedGroup.m_pos_part_def -#align lattice_ordered_comm_group.pos_part_def LatticeOrderedGroup.pos_part_def - --- see Note [lower instance priority] -/-- -Let `α` be a lattice ordered commutative group with identity `1`. For an element `a` of type `α`, -the element `(-a) ⊔ 1` is said to be the *negative component* of `a`, denoted `a⁻`. --/ -@[to_additive - "Let `α` be a lattice ordered commutative group with identity `0`. For an element `a` of type - `α`, the element `(-a) ⊔ 0` is said to be the *negative component* of `a`, denoted `a⁻`."] -instance (priority := 100) hasOneLatticeHasNegPart : NegPart α := - ⟨fun a => a⁻¹ ⊔ 1⟩ -#align lattice_ordered_comm_group.has_one_lattice_has_neg_part LatticeOrderedGroup.hasOneLatticeHasNegPart -#align lattice_ordered_comm_group.has_zero_lattice_has_neg_part LatticeOrderedGroup.hasZeroLatticeHasNegPart - -@[to_additive neg_part_def] -theorem m_neg_part_def (a : α) : a⁻ = a⁻¹ ⊔ 1 := - rfl -#align lattice_ordered_comm_group.m_neg_part_def LatticeOrderedGroup.m_neg_part_def -#align lattice_ordered_comm_group.neg_part_def LatticeOrderedGroup.neg_part_def - -@[to_additive (attr := simp)] -theorem pos_one : (1 : α)⁺ = 1 := - sup_idem -#align lattice_ordered_comm_group.pos_one LatticeOrderedGroup.pos_one -#align lattice_ordered_comm_group.pos_zero LatticeOrderedGroup.pos_zero - -@[to_additive (attr := simp)] -theorem neg_one : (1 : α)⁻ = 1 := by rw [m_neg_part_def, inv_one, sup_idem] -#align lattice_ordered_comm_group.neg_one LatticeOrderedGroup.neg_one -#align lattice_ordered_comm_group.neg_zero LatticeOrderedGroup.neg_zero - --- a⁻ = -(a ⊓ 0) -@[to_additive] -theorem neg_eq_inv_inf_one - [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a : α) : - a⁻ = (a ⊓ 1)⁻¹ := by - rw [m_neg_part_def, ← inv_inj, inv_sup_eq_inv_inf_inv, inv_inv, inv_inv, inv_one] -#align lattice_ordered_comm_group.neg_eq_inv_inf_one LatticeOrderedGroup.neg_eq_inv_inf_one -#align lattice_ordered_comm_group.neg_eq_neg_inf_zero LatticeOrderedGroup.neg_eq_neg_inf_zero - -@[to_additive le_abs] -theorem le_mabs (a : α) : a ≤ |a| := - le_sup_left -#align lattice_ordered_comm_group.le_mabs LatticeOrderedGroup.le_mabs -#align lattice_ordered_comm_group.le_abs LatticeOrderedGroup.le_abs - --- -a ≤ |a| -@[to_additive] -theorem inv_le_abs (a : α) : a⁻¹ ≤ |a| := - le_sup_right -#align lattice_ordered_comm_group.inv_le_abs LatticeOrderedGroup.inv_le_abs -#align lattice_ordered_comm_group.neg_le_abs LatticeOrderedGroup.neg_le_abs - -@[to_additive (attr := simp)] -theorem abs_inv (a : α) : |a⁻¹| = |a| := calc - |a⁻¹| = a⁻¹ ⊔ (a⁻¹)⁻¹ := rfl - _ = a ⊔ a⁻¹ := by rw [inv_inv, sup_comm] - --- 0 ≤ a⁺ -@[to_additive pos_nonneg] -theorem one_le_pos (a : α) : 1 ≤ a⁺ := - le_sup_right -#align lattice_ordered_comm_group.one_le_pos LatticeOrderedGroup.one_le_pos -#align lattice_ordered_comm_group.pos_nonneg LatticeOrderedGroup.pos_nonneg - --- 0 ≤ a⁻ -@[to_additive neg_nonneg] -theorem one_le_neg (a : α) : 1 ≤ a⁻ := - le_sup_right -#align lattice_ordered_comm_group.one_le_neg LatticeOrderedGroup.one_le_neg -#align lattice_ordered_comm_group.neg_nonneg LatticeOrderedGroup.neg_nonneg - --- pos_nonpos_iff -@[to_additive] -theorem pos_le_one_iff {a : α} : a⁺ ≤ 1 ↔ a ≤ 1 := by - rw [m_pos_part_def, sup_le_iff, and_iff_left le_rfl] -#align lattice_ordered_comm_group.pos_le_one_iff LatticeOrderedGroup.pos_le_one_iff -#align lattice_ordered_comm_group.pos_nonpos_iff LatticeOrderedGroup.pos_nonpos_iff - --- neg_nonpos_iff -@[to_additive] -theorem neg_le_one_iff {a : α} : a⁻ ≤ 1 ↔ a⁻¹ ≤ 1 := by - rw [m_neg_part_def, sup_le_iff, and_iff_left le_rfl] -#align lattice_ordered_comm_group.neg_le_one_iff LatticeOrderedGroup.neg_le_one_iff -#align lattice_ordered_comm_group.neg_nonpos_iff LatticeOrderedGroup.neg_nonpos_iff - -@[to_additive] -theorem pos_eq_one_iff {a : α} : a⁺ = 1 ↔ a ≤ 1 := - sup_eq_right -#align lattice_ordered_comm_group.pos_eq_one_iff LatticeOrderedGroup.pos_eq_one_iff -#align lattice_ordered_comm_group.pos_eq_zero_iff LatticeOrderedGroup.pos_eq_zero_iff - -@[to_additive] -theorem neg_eq_one_iff' {a : α} : a⁻ = 1 ↔ a⁻¹ ≤ 1 := - sup_eq_right -#align lattice_ordered_comm_group.neg_eq_one_iff' LatticeOrderedGroup.neg_eq_one_iff' -#align lattice_ordered_comm_group.neg_eq_zero_iff' LatticeOrderedGroup.neg_eq_zero_iff' - -@[to_additive] -theorem neg_eq_one_iff [CovariantClass α α HMul.hMul LE.le] {a : α} : a⁻ = 1 ↔ 1 ≤ a := by - rw [le_antisymm_iff, neg_le_one_iff, inv_le_one', and_iff_left (one_le_neg _)] -#align lattice_ordered_comm_group.neg_eq_one_iff LatticeOrderedGroup.neg_eq_one_iff -#align lattice_ordered_comm_group.neg_eq_zero_iff LatticeOrderedGroup.neg_eq_zero_iff - -@[to_additive le_pos] -theorem m_le_pos (a : α) : a ≤ a⁺ := - le_sup_left -#align lattice_ordered_comm_group.m_le_pos LatticeOrderedGroup.m_le_pos -#align lattice_ordered_comm_group.le_pos LatticeOrderedGroup.le_pos - --- -a ≤ a⁻ -@[to_additive] -theorem inv_le_neg (a : α) : a⁻¹ ≤ a⁻ := - le_sup_left -#align lattice_ordered_comm_group.inv_le_neg LatticeOrderedGroup.inv_le_neg -#align lattice_ordered_comm_group.neg_le_neg LatticeOrderedGroup.neg_le_neg - --- Bourbaki A.VI.12 --- a⁻ = (-a)⁺ -@[to_additive] -theorem neg_eq_pos_inv (a : α) : a⁻ = a⁻¹⁺ := - rfl -#align lattice_ordered_comm_group.neg_eq_pos_inv LatticeOrderedGroup.neg_eq_pos_inv -#align lattice_ordered_comm_group.neg_eq_pos_neg LatticeOrderedGroup.neg_eq_pos_neg - --- a⁺ = (-a)⁻ -@[to_additive] -theorem pos_eq_neg_inv (a : α) : a⁺ = a⁻¹⁻ := by rw [neg_eq_pos_inv, inv_inv] -#align lattice_ordered_comm_group.pos_eq_neg_inv LatticeOrderedGroup.pos_eq_neg_inv -#align lattice_ordered_comm_group.pos_eq_neg_neg LatticeOrderedGroup.pos_eq_neg_neg - --- We use this in Bourbaki A.VI.12 Prop 9 a) --- c + (a ⊓ b) = (c + a) ⊓ (c + b) -@[to_additive] -theorem mul_inf_eq_mul_inf_mul [CovariantClass α α (· * ·) (· ≤ ·)] (a b c : α) : - c * (a ⊓ b) = c * a ⊓ c * b := by - refine' le_antisymm _ _ - rw [le_inf_iff, mul_le_mul_iff_left, mul_le_mul_iff_left] - simp only [inf_le_left, inf_le_right, and_self] - rw [← mul_le_mul_iff_left c⁻¹, ← mul_assoc, inv_mul_self, one_mul, le_inf_iff, - inv_mul_le_iff_le_mul, inv_mul_le_iff_le_mul] - simp -#align lattice_ordered_comm_group.mul_inf_eq_mul_inf_mul LatticeOrderedGroup.mul_inf_eq_mul_inf_mul -#align lattice_ordered_comm_group.add_inf_eq_add_inf_add LatticeOrderedGroup.add_inf_eq_add_inf_add - --- Bourbaki A.VI.12 Prop 9 a) --- a = a⁺ - a⁻ -@[to_additive (attr := simp)] -theorem pos_div_neg [CovariantClass α α (· * ·) (· ≤ ·)] (a : α) : a⁺ / a⁻ = a := by - symm - rw [div_eq_mul_inv] - apply eq_mul_inv_of_mul_eq - rw [m_neg_part_def, mul_sup, mul_one, mul_right_inv, sup_comm, m_pos_part_def] -#align lattice_ordered_comm_group.pos_div_neg LatticeOrderedGroup.pos_div_neg -#align lattice_ordered_comm_group.pos_sub_neg LatticeOrderedGroup.pos_sub_neg - --- pos_of_nonneg -/-- If `a` is positive, then it is equal to its positive component `a⁺`. -/ -@[to_additive "If `a` is positive, then it is equal to its positive component `a⁺`."] -theorem pos_of_one_le (a : α) (h : 1 ≤ a) : a⁺ = a := by - rw [m_pos_part_def] - exact sup_of_le_left h -#align lattice_ordered_comm_group.pos_of_one_le LatticeOrderedGroup.pos_of_one_le -#align lattice_ordered_comm_group.pos_of_nonneg LatticeOrderedGroup.pos_of_nonneg - --- 0 ≤ a implies a⁺ = a --- pos_of_nonpos -@[to_additive] -theorem pos_of_le_one (a : α) (h : a ≤ 1) : a⁺ = 1 := - pos_eq_one_iff.mpr h -#align lattice_ordered_comm_group.pos_of_le_one LatticeOrderedGroup.pos_of_le_one -#align lattice_ordered_comm_group.pos_of_nonpos LatticeOrderedGroup.pos_of_nonpos - -@[to_additive neg_of_inv_nonneg] -theorem neg_of_one_le_inv (a : α) (h : 1 ≤ a⁻¹) : a⁻ = a⁻¹ := by - rw [neg_eq_pos_inv] - exact pos_of_one_le _ h -#align lattice_ordered_comm_group.neg_of_one_le_inv LatticeOrderedGroup.neg_of_one_le_inv -#align lattice_ordered_comm_group.neg_of_inv_nonneg LatticeOrderedGroup.neg_of_inv_nonneg - --- neg_of_neg_nonpos -@[to_additive] -theorem neg_of_inv_le_one (a : α) (h : a⁻¹ ≤ 1) : a⁻ = 1 := - neg_eq_one_iff'.mpr h -#align lattice_ordered_comm_group.neg_of_inv_le_one LatticeOrderedGroup.neg_of_inv_le_one -#align lattice_ordered_comm_group.neg_of_neg_nonpos LatticeOrderedGroup.neg_of_neg_nonpos - --- neg_of_nonpos -@[to_additive] -theorem neg_of_le_one [CovariantClass α α (· * ·) (· ≤ ·)] (a : α) (h : a ≤ 1) : a⁻ = a⁻¹ := - sup_eq_left.2 <| one_le_inv'.2 h -#align lattice_ordered_comm_group.neg_of_le_one LatticeOrderedGroup.neg_of_le_one -#align lattice_ordered_comm_group.neg_of_nonpos LatticeOrderedGroup.neg_of_nonpos - --- pos_eq_self_of_pos_pos -@[to_additive] -theorem pos_eq_self_of_one_lt_pos {α} [LinearOrder α] [CommGroup α] {x : α} (hx : 1 < x⁺) : - x⁺ = x := by - rw [m_pos_part_def, right_lt_sup, not_le] at hx - rw [m_pos_part_def, sup_eq_left] - exact hx.le -#align lattice_ordered_comm_group.pos_eq_self_of_one_lt_pos LatticeOrderedGroup.pos_eq_self_of_one_lt_pos -#align lattice_ordered_comm_group.pos_eq_self_of_pos_pos LatticeOrderedGroup.pos_eq_self_of_pos_pos - --- neg_of_nonneg' -@[to_additive] -theorem neg_of_one_le [CovariantClass α α (· * ·) (· ≤ ·)] (a : α) (h : 1 ≤ a) : a⁻ = 1 := - neg_eq_one_iff.mpr h -#align lattice_ordered_comm_group.neg_of_one_le LatticeOrderedGroup.neg_of_one_le -#align lattice_ordered_comm_group.neg_of_nonneg LatticeOrderedGroup.neg_of_nonneg - --- 0 ≤ a implies |a| = a -@[to_additive abs_of_nonneg] -theorem mabs_of_one_le [CovariantClass α α (· * ·) (· ≤ ·)] (a : α) (h : 1 ≤ a) : |a| = a := - sup_eq_left.2 <| Left.inv_le_self h -#align lattice_ordered_comm_group.mabs_of_one_le LatticeOrderedGroup.mabs_of_one_le -#align lattice_ordered_comm_group.abs_of_nonneg LatticeOrderedGroup.abs_of_nonneg - --- |a - b| = |b - a| -@[to_additive] -theorem abs_div_comm (a b : α) : |a / b| = |b / a| := by - dsimp only [Abs.abs] - rw [inv_div a b, ← inv_inv (a / b), inv_div, sup_comm] -#align lattice_ordered_comm_group.abs_inv_comm LatticeOrderedGroup.abs_div_comm -#align lattice_ordered_comm_group.abs_neg_comm LatticeOrderedGroup.abs_sub_comm - --- In fact 0 ≤ n•a implies 0 ≤ a, see L. Fuchs, "Partially ordered algebraic systems" --- Chapter V, 1.E -@[to_additive] -lemma pow_two_semiclosed - [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a : α) : - (1 : α) ≤ a^2 → 1 ≤ a := by - intro h - have e1 : (a ⊓ 1) * (a ⊓ 1) = a⊓1 := by - rw [mul_inf, inf_mul, ← pow_two, mul_one, one_mul, inf_assoc, inf_left_idem, inf_comm, - inf_assoc, (inf_of_le_left h)] - rw [← inf_eq_right] - exact mul_right_eq_self.mp e1 - -@[to_additive abs_nonneg] -theorem one_le_abs - [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a : α) : - 1 ≤ |a| := by - apply pow_two_semiclosed _ _ - rw [abs_eq_sup_inv, pow_two, mul_sup, sup_mul, ← pow_two, mul_left_inv, sup_comm, ← sup_assoc] - apply le_sup_right - --- The proof from Bourbaki A.VI.12 Prop 9 d) --- |a| = a⁺ - a⁻ -@[to_additive] -theorem pos_mul_neg - [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a : α) : - |a| = a⁺ * a⁻ := by - rw [m_pos_part_def, sup_mul, one_mul, m_neg_part_def, mul_sup, mul_one, mul_inv_self, sup_assoc, - ← @sup_assoc _ _ a, sup_eq_right.2 le_sup_right] - exact (sup_eq_left.2 <| one_le_abs a).symm -#align lattice_ordered_comm_group.pos_mul_neg LatticeOrderedGroup.pos_mul_neg -#align lattice_ordered_comm_group.pos_add_neg LatticeOrderedGroup.pos_add_neg - -@[to_additive pos_abs] -theorem m_pos_abs [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] - (a : α) : |a|⁺ = |a| := by - rw [m_pos_part_def] - apply sup_of_le_left - apply one_le_abs -#align lattice_ordered_comm_group.m_pos_abs LatticeOrderedGroup.m_pos_abs -#align lattice_ordered_comm_group.pos_abs LatticeOrderedGroup.pos_abs - -@[to_additive neg_abs] -theorem m_neg_abs [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] - (a : α) : |a|⁻ = 1 := by - rw [m_neg_part_def] - apply sup_of_le_right - rw [Left.inv_le_one_iff] - apply one_le_abs -#align lattice_ordered_comm_group.m_neg_abs LatticeOrderedGroup.m_neg_abs -#align lattice_ordered_comm_group.neg_abs LatticeOrderedGroup.neg_abs - --- a ⊔ b - (a ⊓ b) = |b - a| -@[to_additive] -theorem sup_div_inf_eq_abs_div - [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a b : α) : - (a ⊔ b) / (a ⊓ b) = |b / a| := -calc - (a ⊔ b) / (a ⊓ b) = (a ⊔ b) * (a⁻¹ ⊔ b⁻¹) := by rw [div_eq_mul_inv, ← inv_inf_eq_sup_inv] - _ = (a * a⁻¹ ⊔ b * a⁻¹) ⊔ (a * b⁻¹ ⊔ b * b⁻¹) := by rw [mul_sup, sup_mul, sup_mul] - _ = (1 ⊔ b / a) ⊔ (a / b ⊔ 1) := by - rw [mul_right_inv, mul_right_inv, ← div_eq_mul_inv, ← div_eq_mul_inv] - _ = 1 ⊔ b / a ⊔ (1 / (b / a) ⊔ 1) := by rw [one_div_div] - _ = 1 ⊔ (b / a) ⊔ ((b / a)⁻¹ ⊔ 1) := by rw [inv_eq_one_div] - _ = 1 ⊔ (((b / a) ⊔ (b / a)⁻¹) ⊔ 1) := by rw [sup_assoc, sup_assoc] - _= 1 ⊔ (|b / a| ⊔ 1) := by rw [abs_eq_sup_inv] - _= 1 ⊔ |b / a| := by rw [← m_pos_part_def, m_pos_abs] - _= |b / a| ⊔ 1 := by rw [sup_comm] - _= |b / a| := by rw [← m_pos_part_def, m_pos_abs] -#align lattice_ordered_comm_group.sup_div_inf_eq_abs_div LatticeOrderedGroup.sup_div_inf_eq_abs_div -#align lattice_ordered_comm_group.sup_sub_inf_eq_abs_sub LatticeOrderedGroup.sup_sub_inf_eq_abs_sub - -/-- The unary operation of taking the absolute value is idempotent. -/ -@[to_additive (attr := simp) abs_abs - "The unary operation of taking the absolute value is idempotent."] -theorem mabs_mabs [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] - (a : α) : |(|a|)| = |a| := - mabs_of_one_le _ (one_le_abs _) -#align lattice_ordered_comm_group.mabs_mabs LatticeOrderedGroup.mabs_mabs -#align lattice_ordered_comm_group.abs_abs LatticeOrderedGroup.abs_abs - --- Bourbaki A.VI.12 Prop 9 a) --- a⁺ ⊓ a⁻ = 0 (`a⁺` and `a⁻` are co-prime, and, since they are positive, disjoint) -@[to_additive] -theorem pos_inf_neg_eq_one - [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a : α) : - a⁺ ⊓ a⁻ = 1 := by - rw [← mul_left_inj (a⁻)⁻¹, inf_mul, one_mul, mul_right_inv, ← div_eq_mul_inv, - pos_div_neg, neg_eq_inv_inf_one, inv_inv] -#align lattice_ordered_comm_group.pos_inf_neg_eq_one LatticeOrderedGroup.pos_inf_neg_eq_one -#align lattice_ordered_comm_group.pos_inf_neg_eq_zero LatticeOrderedGroup.pos_inf_neg_eq_zero - -end LatticeOrderedGroup - -end Group - -variable [Lattice α] [CommGroup α] - --- Fuchs p67 --- Bourbaki A.VI.10 Prop 7 --- a ⊓ b + (a ⊔ b) = a + b -@[to_additive] -theorem inf_mul_sup [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : (a ⊓ b) * (a ⊔ b) = a * b := - calc - (a ⊓ b) * (a ⊔ b) = (a ⊓ b) * (a * b * (b⁻¹ ⊔ a⁻¹)) := by - rw [mul_sup b⁻¹ a⁻¹ (a * b), mul_inv_cancel_right, mul_inv_cancel_comm] - _ = (a ⊓ b) * (a * b * (a ⊓ b)⁻¹) := by rw [inv_inf_eq_sup_inv, sup_comm] - _ = a * b := by rw [mul_comm, inv_mul_cancel_right] -#align inf_mul_sup inf_mul_sup -#align inf_add_sup inf_add_sup - -namespace LatticeOrderedCommGroup - -open LatticeOrderedGroup - --- Bourbaki A.VI.12 (with a and b swapped) --- a⊔b = b + (a - b)⁺ -@[to_additive] -theorem sup_eq_mul_pos_div [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : a ⊔ b = b * (a / b)⁺ := - calc - a ⊔ b = b * (a / b) ⊔ b * 1 := - by rw [mul_one b, div_eq_mul_inv, mul_comm a, mul_inv_cancel_left] - _ = b * (a / b ⊔ 1) := by rw [← mul_sup (a / b) 1 b] -#align lattice_ordered_comm_group.sup_eq_mul_pos_div LatticeOrderedCommGroup.sup_eq_mul_pos_div -#align lattice_ordered_comm_group.sup_eq_add_pos_sub LatticeOrderedCommGroup.sup_eq_add_pos_sub - --- Bourbaki A.VI.12 (with a and b swapped) --- a⊓b = a - (a - b)⁺ -@[to_additive] -theorem inf_eq_div_pos_div [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : a ⊓ b = a / (a / b)⁺ := - calc - a ⊓ b = a * 1 ⊓ a * (b / a) := - by rw [mul_one a, div_eq_mul_inv, mul_comm b, mul_inv_cancel_left] - _ = a * (1 ⊓ b / a) := by rw [← mul_inf 1 (b / a) a] - _ = a * (b / a ⊓ 1) := by rw [inf_comm] - _ = a * ((a / b)⁻¹ ⊓ 1) := by - rw [div_eq_mul_inv] - nth_rw 1 [← inv_inv b] - rw [← mul_inv, mul_comm b⁻¹, ← div_eq_mul_inv] - _ = a * ((a / b)⁻¹ ⊓ 1⁻¹) := by rw [inv_one] - _ = a / (a / b ⊔ 1) := by rw [← inv_sup_eq_inv_inf_inv, ← div_eq_mul_inv] -#align lattice_ordered_comm_group.inf_eq_div_pos_div LatticeOrderedCommGroup.inf_eq_div_pos_div -#align lattice_ordered_comm_group.inf_eq_sub_pos_sub LatticeOrderedCommGroup.inf_eq_sub_pos_sub - --- Bourbaki A.VI.12 Prop 9 c) -@[to_additive le_iff_pos_le_neg_ge] -theorem m_le_iff_pos_le_neg_ge [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : - a ≤ b ↔ a⁺ ≤ b⁺ ∧ b⁻ ≤ a⁻ := by - constructor <;> intro h - · constructor - · exact sup_le (h.trans (m_le_pos b)) (one_le_pos b) - · rw [← inv_le_inv_iff] at h - exact sup_le (h.trans (inv_le_neg a)) (one_le_neg a) - · rw [← pos_div_neg a, ← pos_div_neg b] - exact div_le_div'' h.1 h.2 -#align lattice_ordered_comm_group.m_le_iff_pos_le_neg_ge LatticeOrderedCommGroup.m_le_iff_pos_le_neg_ge -#align lattice_ordered_comm_group.le_iff_pos_le_neg_ge LatticeOrderedCommGroup.le_iff_pos_le_neg_ge - --- 2•(a ⊔ b) = a + b + |b - a| -@[to_additive two_sup_eq_add_add_abs_sub] -theorem sup_sq_eq_mul_mul_abs_div [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : - (a ⊔ b) ^ 2 = a * b * |b / a| := by - rw [← inf_mul_sup a b, ← sup_div_inf_eq_abs_div, div_eq_mul_inv, ← mul_assoc, mul_comm, mul_assoc, - ← pow_two, inv_mul_cancel_left] -#align lattice_ordered_comm_group.sup_sq_eq_mul_mul_abs_div LatticeOrderedCommGroup.sup_sq_eq_mul_mul_abs_div -#align lattice_ordered_comm_group.two_sup_eq_add_add_abs_sub LatticeOrderedCommGroup.two_sup_eq_add_add_abs_sub - --- 2•(a ⊓ b) = a + b - |b - a| -@[to_additive two_inf_eq_add_sub_abs_sub] -theorem inf_sq_eq_mul_div_abs_div [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : - (a ⊓ b) ^ 2 = a * b / |b / a| := by - rw [← inf_mul_sup a b, ← sup_div_inf_eq_abs_div, div_eq_mul_inv, div_eq_mul_inv, mul_inv_rev, - inv_inv, mul_assoc, mul_inv_cancel_comm_assoc, ← pow_two] -#align lattice_ordered_comm_group.inf_sq_eq_mul_div_abs_div LatticeOrderedCommGroup.inf_sq_eq_mul_div_abs_div -#align lattice_ordered_comm_group.two_inf_eq_add_sub_abs_sub LatticeOrderedCommGroup.two_inf_eq_add_sub_abs_sub - -/-- Every lattice ordered commutative group is a distributive lattice --/ --- Non-comm case needs cancellation law https://ncatlab.org/nlab/show/distributive+lattice -@[to_additive "Every lattice ordered commutative additive group is a distributive lattice"] -def latticeOrderedCommGroupToDistribLattice (α : Type u) [s : Lattice α] [CommGroup α] - [CovariantClass α α (· * ·) (· ≤ ·)] : DistribLattice α := - { s with - le_sup_inf := by - intros x y z - rw [← mul_le_mul_iff_left (x ⊓ (y ⊓ z)), inf_mul_sup x (y ⊓ z), ← inv_mul_le_iff_le_mul, - le_inf_iff] - constructor - · rw [inv_mul_le_iff_le_mul, ← inf_mul_sup x y] - apply mul_le_mul' - · apply inf_le_inf_left - apply inf_le_left - · apply inf_le_left - · rw [inv_mul_le_iff_le_mul, ← inf_mul_sup x z] - apply mul_le_mul' - · apply inf_le_inf_left - apply inf_le_right - · apply inf_le_right } -#align lattice_ordered_comm_group.lattice_ordered_comm_group_to_distrib_lattice LatticeOrderedCommGroup.latticeOrderedCommGroupToDistribLattice -#align lattice_ordered_comm_group.lattice_ordered_add_comm_group_to_distrib_lattice LatticeOrderedCommGroup.latticeOrderedAddCommGroupToDistribLattice - --- See, e.g. Zaanen, Lectures on Riesz Spaces --- 3rd lecture --- |a ⊔ c - (b ⊔ c)| + |a ⊓ c-b ⊓ c| = |a - b| -@[to_additive] -theorem abs_div_sup_mul_abs_div_inf [CovariantClass α α (· * ·) (· ≤ ·)] (a b c : α) : - |(a ⊔ c) / (b ⊔ c)| * |(a ⊓ c) / (b ⊓ c)| = |a / b| := by - letI : DistribLattice α := LatticeOrderedCommGroup.latticeOrderedCommGroupToDistribLattice α - calc - |(a ⊔ c) / (b ⊔ c)| * |(a ⊓ c) / (b ⊓ c)| = - (b ⊔ c ⊔ (a ⊔ c)) / ((b ⊔ c) ⊓ (a ⊔ c)) * |(a ⊓ c) / (b ⊓ c)| := - by rw [sup_div_inf_eq_abs_div] - _ = (b ⊔ c ⊔ (a ⊔ c)) / ((b ⊔ c) ⊓ (a ⊔ c)) * ((b ⊓ c ⊔ a ⊓ c) / (b ⊓ c ⊓ (a ⊓ c))) := - by rw [sup_div_inf_eq_abs_div (b ⊓ c) (a ⊓ c)] - _ = (b ⊔ a ⊔ c) / (b ⊓ a ⊔ c) * (((b ⊔ a) ⊓ c) / (b ⊓ a ⊓ c)) := by - rw [← sup_inf_right, ← inf_sup_right, sup_assoc, @sup_comm _ _ c (a ⊔ c), sup_right_idem, - sup_assoc, inf_assoc, @inf_comm _ _ c (a ⊓ c), inf_right_idem, inf_assoc] - _ = (b ⊔ a ⊔ c) * ((b ⊔ a) ⊓ c) / ((b ⊓ a ⊔ c) * (b ⊓ a ⊓ c)) := by rw [div_mul_div_comm] - _ = (b ⊔ a) * c / ((b ⊓ a) * c) := - by rw [mul_comm, inf_mul_sup, mul_comm (b ⊓ a ⊔ c), inf_mul_sup] - _ = (b ⊔ a) / (b ⊓ a) := - by rw [div_eq_mul_inv, mul_inv_rev, mul_assoc, mul_inv_cancel_left, ← div_eq_mul_inv] - _ = |a / b| := by rw [sup_div_inf_eq_abs_div] -#align lattice_ordered_comm_group.abs_div_sup_mul_abs_div_inf LatticeOrderedCommGroup.abs_div_sup_mul_abs_div_inf -#align lattice_ordered_comm_group.abs_sub_sup_add_abs_sub_inf LatticeOrderedCommGroup.abs_sub_sup_add_abs_sub_inf - -@[to_additive abs_sup_sub_sup_le_abs] -theorem mabs_sup_div_sup_le_mabs [CovariantClass α α (· * ·) (· ≤ ·)] (a b c : α) : - |(a ⊔ c) / (b ⊔ c)| ≤ |a / b| := by - apply le_of_mul_le_of_one_le_left - · rw [abs_div_sup_mul_abs_div_inf] - · exact one_le_abs _ -#align lattice_ordered_comm_group.mabs_sup_div_sup_le_mabs LatticeOrderedCommGroup.mabs_sup_div_sup_le_mabs -#align lattice_ordered_comm_group.abs_sup_sub_sup_le_abs LatticeOrderedCommGroup.abs_sup_sub_sup_le_abs - -@[to_additive abs_inf_sub_inf_le_abs] -theorem mabs_inf_div_inf_le_mabs [CovariantClass α α (· * ·) (· ≤ ·)] (a b c : α) : - |(a ⊓ c) / (b ⊓ c)| ≤ |a / b| := by - apply le_of_mul_le_of_one_le_right - · rw [abs_div_sup_mul_abs_div_inf] - · exact one_le_abs _ -#align lattice_ordered_comm_group.mabs_inf_div_inf_le_mabs LatticeOrderedCommGroup.mabs_inf_div_inf_le_mabs -#align lattice_ordered_comm_group.abs_inf_sub_inf_le_abs LatticeOrderedCommGroup.abs_inf_sub_inf_le_abs - --- Commutative case, Zaanen, 3rd lecture --- For the non-commutative case, see Birkhoff Theorem 19 (27) --- |(a ⊔ c) - (b ⊔ c)| ⊔ |(a ⊓ c) - (b ⊓ c)| ≤ |a - b| -@[to_additive Birkhoff_inequalities] -theorem m_Birkhoff_inequalities [CovariantClass α α (· * ·) (· ≤ ·)] (a b c : α) : - |(a ⊔ c) / (b ⊔ c)| ⊔ |(a ⊓ c) / (b ⊓ c)| ≤ |a / b| := - sup_le (mabs_sup_div_sup_le_mabs a b c) (mabs_inf_div_inf_le_mabs a b c) -set_option linter.uppercaseLean3 false in -#align lattice_ordered_comm_group.m_Birkhoff_inequalities LatticeOrderedCommGroup.m_Birkhoff_inequalities -set_option linter.uppercaseLean3 false in -#align lattice_ordered_comm_group.Birkhoff_inequalities LatticeOrderedCommGroup.Birkhoff_inequalities - --- Banasiak Proposition 2.12, Zaanen 2nd lecture -/-- The absolute value satisfies the triangle inequality. --/ -@[to_additive abs_add_le "The absolute value satisfies the triangle inequality."] -theorem mabs_mul_le [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : |a * b| ≤ |a| * |b| := by - apply sup_le - · exact mul_le_mul' (le_mabs a) (le_mabs b) - · rw [mul_inv] - exact mul_le_mul' (inv_le_abs _) (inv_le_abs _) -#align lattice_ordered_comm_group.mabs_mul_le LatticeOrderedCommGroup.mabs_mul_le -#align lattice_ordered_comm_group.abs_add_le LatticeOrderedCommGroup.abs_add_le - --- | |a| - |b| | ≤ |a - b| -@[to_additive] -theorem abs_abs_div_abs_le [CovariantClass α α (· * ·) (· ≤ ·)] (a b : α) : - |(|a| / |b|)| ≤ |a / b| := by - rw [abs_eq_sup_inv, sup_le_iff] - constructor - · apply div_le_iff_le_mul.2 - convert mabs_mul_le (a / b) b - rw [div_mul_cancel'] - · rw [div_eq_mul_inv, mul_inv_rev, inv_inv, mul_inv_le_iff_le_mul, abs_div_comm] - convert mabs_mul_le (b / a) a - · rw [div_mul_cancel'] -#align lattice_ordered_comm_group.abs_abs_div_abs_le LatticeOrderedCommGroup.abs_abs_div_abs_le -#align lattice_ordered_comm_group.abs_abs_sub_abs_le LatticeOrderedCommGroup.abs_abs_sub_abs_le - -end LatticeOrderedCommGroup - -section invertible - -variable (α) -variable [Semiring α] [Invertible (2 : α)] [Lattice β] [AddCommGroup β] [Module α β] - [CovariantClass β β (· + ·) (· ≤ ·)] - -lemma inf_eq_half_smul_add_sub_abs_sub (x y : β) : - x ⊓ y = (⅟2 : α) • (x + y - |y - x|) := by - rw [← LatticeOrderedCommGroup.two_inf_eq_add_sub_abs_sub x y, two_smul, ← two_smul α, - smul_smul, invOf_mul_self, one_smul] - -lemma sup_eq_half_smul_add_add_abs_sub (x y : β) : - x ⊔ y = (⅟2 : α) • (x + y + |y - x|) := by - rw [← LatticeOrderedCommGroup.two_sup_eq_add_add_abs_sub x y, two_smul, ← two_smul α, - smul_smul, invOf_mul_self, one_smul] - -end invertible - -section DivisionSemiring - -variable (α) -variable [DivisionSemiring α] [NeZero (2 : α)] [Lattice β] [AddCommGroup β] [Module α β] - [CovariantClass β β (· + ·) (· ≤ ·)] - -lemma inf_eq_half_smul_add_sub_abs_sub' (x y : β) : x ⊓ y = (2⁻¹ : α) • (x + y - |y - x|) := by - letI := invertibleOfNonzero (two_ne_zero' α) - exact inf_eq_half_smul_add_sub_abs_sub α x y - -lemma sup_eq_half_smul_add_add_abs_sub' (x y : β) : x ⊔ y = (2⁻¹ : α) • (x + y + |y - x|) := by - letI := invertibleOfNonzero (two_ne_zero' α) - exact sup_eq_half_smul_add_add_abs_sub α x y - -end DivisionSemiring - -namespace LatticeOrderedAddCommGroup - -variable [Lattice β] [AddCommGroup β] - -section solid - -/-- A subset `s ⊆ β`, with `β` an `AddCommGroup` with a `Lattice` structure, is solid if for -all `x ∈ s` and all `y ∈ β` such that `|y| ≤ |x|`, then `y ∈ s`. -/ -def IsSolid (s : Set β) : Prop := ∀ ⦃x⦄, x ∈ s → ∀ ⦃y⦄, |y| ≤ |x| → y ∈ s -#align lattice_ordered_add_comm_group.is_solid LatticeOrderedAddCommGroup.IsSolid - -/-- The solid closure of a subset `s` is the smallest superset of `s` that is solid. -/ -def solidClosure (s : Set β) : Set β := { y | ∃ x ∈ s, |y| ≤ |x| } -#align lattice_ordered_add_comm_group.solid_closure LatticeOrderedAddCommGroup.solidClosure - -theorem isSolid_solidClosure (s : Set β) : IsSolid (solidClosure s) := - fun _ ⟨y, hy, hxy⟩ _ hzx => ⟨y, hy, hzx.trans hxy⟩ -#align lattice_ordered_add_comm_group.is_solid_solid_closure LatticeOrderedAddCommGroup.isSolid_solidClosure - -theorem solidClosure_min (s t : Set β) (h1 : s ⊆ t) (h2 : IsSolid t) : solidClosure s ⊆ t := - fun _ ⟨_, hy, hxy⟩ => h2 (h1 hy) hxy -#align lattice_ordered_add_comm_group.solid_closure_min LatticeOrderedAddCommGroup.solidClosure_min - -end solid - -end LatticeOrderedAddCommGroup diff --git a/Mathlib/Algebra/Order/Module/Algebra.lean b/Mathlib/Algebra/Order/Module/Algebra.lean new file mode 100644 index 0000000000000..01c3c3f97475f --- /dev/null +++ b/Mathlib/Algebra/Order/Module/Algebra.lean @@ -0,0 +1,72 @@ +/- +Copyright (c) 2023 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies +-/ +import Mathlib.Algebra.Algebra.Basic +import Mathlib.Algebra.Order.Module.Defs + +/-! +# Ordered algebras + +This file proves properties of algebras where both rings are ordered compatibly. + +### TODO + +`positivity` extension for `algebraMap` +-/ + +variable {α β : Type*} [OrderedCommSemiring α] + +section OrderedSemiring +variable (β) +variable [OrderedSemiring β] [Algebra α β] [SMulPosMono α β] {a : α} + +@[mono] lemma algebraMap_mono : Monotone (algebraMap α β) := + fun a₁ a₂ ha ↦ by + simpa only [Algebra.algebraMap_eq_smul_one] using smul_le_smul_of_nonneg_right ha zero_le_one + +/-- A version of `algebraMap_mono` for use by `gcongr` since it currently does not preprocess +`Monotone` conclusions. -/ +@[gcongr] protected lemma GCongr.algebraMap_le_algebraMap {a₁ a₂ : α} (ha : a₁ ≤ a₂) : + algebraMap α β a₁ ≤ algebraMap α β a₂ := algebraMap_mono _ ha + +lemma algebraMap_nonneg (ha : 0 ≤ a) : 0 ≤ algebraMap α β a := by simpa using algebraMap_mono β ha + +end OrderedSemiring + +section StrictOrderedSemiring +variable [StrictOrderedSemiring β] [Algebra α β] + +section SMulPosMono +variable [SMulPosMono α β] [SMulPosReflectLE α β] {a₁ a₂ : α} + +@[simp] lemma algebraMap_le_algebraMap : algebraMap α β a₁ ≤ algebraMap α β a₂ ↔ a₁ ≤ a₂ := by + simp [Algebra.algebraMap_eq_smul_one] + +end SMulPosMono + +section SMulPosStrictMono +variable [SMulPosStrictMono α β] {a a₁ a₂ : α} +variable (β) + +@[mono] lemma algebraMap_strictMono : StrictMono (algebraMap α β) := + fun a₁ a₂ ha ↦ by + simpa only [Algebra.algebraMap_eq_smul_one] using smul_lt_smul_of_pos_right ha zero_lt_one + +/-- A version of `algebraMap_strictMono` for use by `gcongr` since it currently does not preprocess +`Monotone` conclusions. -/ +@[gcongr] protected lemma GCongr.algebraMap_lt_algebraMap {a₁ a₂ : α} (ha : a₁ < a₂) : + algebraMap α β a₁ < algebraMap α β a₂ := algebraMap_strictMono _ ha + +lemma algebraMap_pos (ha : 0 < a) : 0 < algebraMap α β a := by + simpa using algebraMap_strictMono β ha + +variable {β} +variable [SMulPosReflectLT α β] + +@[simp] lemma algebraMap_lt_algebraMap : algebraMap α β a₁ < algebraMap α β a₂ ↔ a₁ < a₂ := by + simp [Algebra.algebraMap_eq_smul_one] + +end SMulPosStrictMono +end StrictOrderedSemiring diff --git a/Mathlib/Algebra/Order/Module/Defs.lean b/Mathlib/Algebra/Order/Module/Defs.lean index 9ef6ffe4e513c..43e251ee3e3a4 100644 --- a/Mathlib/Algebra/Order/Module/Defs.lean +++ b/Mathlib/Algebra/Order/Module/Defs.lean @@ -5,6 +5,7 @@ Authors: Yaël Dillies -/ import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Algebra.Order.Ring.Lemmas +import Mathlib.Tactic.Positivity.Core /-! # Monotonicity of scalar multiplication by positive elements @@ -374,7 +375,7 @@ instance (priority := 100) PosSMulStrictMono.toPosSMulReflectLE [PosSMulStrictMo elim _a ha _b₁ _b₂ := (strictMono_smul_left_of_pos ha).le_iff_le.1 lemma PosSMulReflectLE.toPosSMulStrictMono [PosSMulReflectLE α β] : PosSMulStrictMono α β where - elim _a ha _b₁ _b₂ hb := not_le.1 fun h ↦ hb.not_le $ le_of_smul_le_smul_left h ha + elim _a ha _b₁ _b₂ hb := not_le.1 fun h ↦ hb.not_le <| le_of_smul_le_smul_left h ha lemma posSMulStrictMono_iff_PosSMulReflectLE : PosSMulStrictMono α β ↔ PosSMulReflectLE α β := ⟨fun _ ↦ inferInstance, fun _ ↦ PosSMulReflectLE.toPosSMulStrictMono⟩ @@ -383,7 +384,7 @@ instance PosSMulMono.toPosSMulReflectLT [PosSMulMono α β] : PosSMulReflectLT elim _a ha _b₁ _b₂ := (monotone_smul_left_of_nonneg ha).reflect_lt lemma PosSMulReflectLT.toPosSMulMono [PosSMulReflectLT α β] : PosSMulMono α β where - elim _a ha _b₁ _b₂ hb := not_lt.1 fun h ↦ hb.not_lt $ lt_of_smul_lt_smul_left h ha + elim _a ha _b₁ _b₂ hb := not_lt.1 fun h ↦ hb.not_lt <| lt_of_smul_lt_smul_left h ha lemma posSMulMono_iff_posSMulReflectLT : PosSMulMono α β ↔ PosSMulReflectLT α β := ⟨fun _ ↦ PosSMulMono.toPosSMulReflectLT, fun _ ↦ PosSMulReflectLT.toPosSMulMono⟩ @@ -402,10 +403,10 @@ section Right variable [Zero β] lemma SMulPosReflectLE.toSMulPosStrictMono [SMulPosReflectLE α β] : SMulPosStrictMono α β where - elim _b hb _a₁ _a₂ ha := not_le.1 fun h ↦ ha.not_le $ le_of_smul_le_smul_of_pos_right h hb + elim _b hb _a₁ _a₂ ha := not_le.1 fun h ↦ ha.not_le <| le_of_smul_le_smul_of_pos_right h hb lemma SMulPosReflectLT.toSMulPosMono [SMulPosReflectLT α β] : SMulPosMono α β where - elim _b hb _a₁ _a₂ ha := not_lt.1 fun h ↦ ha.not_lt $ lt_of_smul_lt_smul_right h hb + elim _b hb _a₁ _a₂ ha := not_lt.1 fun h ↦ ha.not_lt <| lt_of_smul_lt_smul_right h hb end Right end LinearOrder @@ -419,10 +420,10 @@ variable [Zero β] -- See note [lower instance priority] instance (priority := 100) SMulPosStrictMono.toSMulPosReflectLE [SMulPosStrictMono α β] : SMulPosReflectLE α β where - elim _b hb _a₁ _a₂ h := not_lt.1 fun ha ↦ h.not_lt $ smul_lt_smul_of_pos_right ha hb + elim _b hb _a₁ _a₂ h := not_lt.1 fun ha ↦ h.not_lt <| smul_lt_smul_of_pos_right ha hb lemma SMulPosMono.toSMulPosReflectLT [SMulPosMono α β] : SMulPosReflectLT α β where - elim _b hb _a₁ _a₂ h := not_le.1 fun ha ↦ h.not_le $ smul_le_smul_of_nonneg_right ha hb + elim _b hb _a₁ _a₂ h := not_le.1 fun ha ↦ h.not_le <| smul_le_smul_of_nonneg_right ha hb end Right end LinearOrder @@ -530,9 +531,9 @@ variable [PartialOrder α] [Preorder β] lemma PosSMulMono.of_pos (h₀ : ∀ a : α, 0 < a → ∀ b₁ b₂ : β, b₁ ≤ b₂ → a • b₁ ≤ a • b₂) : PosSMulMono α β where elim a ha b₁ b₂ h := by - obtain ha | ha := ha.eq_or_lt - · simp [← ha] - · exact h₀ _ ha _ _ h + obtain ha | ha := ha.eq_or_lt + · simp [← ha] + · exact h₀ _ ha _ _ h /-- A constructor for `PosSMulReflectLT` requiring you to prove `a • b₁ < a • b₂ → b₁ < b₂` only when `0 < a`-/ @@ -561,7 +562,7 @@ lemma SMulPosMono.of_pos (h₀ : ∀ b : β, 0 < b → ∀ a₁ a₂ : α, a₁ when `0 < b`-/ lemma SMulPosReflectLT.of_pos (h₀ : ∀ b : β, 0 < b → ∀ a₁ a₂ : α, a₁ • b < a₂ • b → a₁ < a₂) : SMulPosReflectLT α β where - elim b hb a₁ a₂ h := by + elim b hb a₁ a₂ h := by obtain hb | hb := hb.eq_or_lt · simp [← hb] at h · exact h₀ _ hb _ _ h @@ -585,13 +586,13 @@ instance (priority := 100) SMulPosStrictMono.toSMulPosMono [SMulPosStrictMono α instance (priority := 100) PosSMulReflectLE.toPosSMulReflectLT [PosSMulReflectLE α β] : PosSMulReflectLT α β := PosSMulReflectLT.of_pos fun a ha b₁ b₂ h ↦ - (le_of_smul_le_smul_of_pos_left h.le ha).lt_of_ne $ by rintro rfl; simp at h + (le_of_smul_le_smul_of_pos_left h.le ha).lt_of_ne <| by rintro rfl; simp at h -- See note [lower instance priority] instance (priority := 100) SMulPosReflectLE.toSMulPosReflectLT [SMulPosReflectLE α β] : SMulPosReflectLT α β := SMulPosReflectLT.of_pos fun b hb a₁ a₂ h ↦ - (le_of_smul_le_smul_of_pos_right h.le hb).lt_of_ne $ by rintro rfl; simp at h + (le_of_smul_le_smul_of_pos_right h.le hb).lt_of_ne <| by rintro rfl; simp at h lemma smul_eq_smul_iff_eq_and_eq_of_pos [PosSMulStrictMono α β] [SMulPosStrictMono α β] (ha : a₁ ≤ a₂) (hb : b₁ ≤ b₂) (h₁ : 0 < a₁) (h₂ : 0 < b₂) : @@ -689,7 +690,7 @@ section PartialOrder variable [Preorder α] [PartialOrder β] lemma PosSMulMono.toPosSMulStrictMono [PosSMulMono α β] : PosSMulStrictMono α β := - ⟨fun _a ha _b₁ _b₂ hb ↦ (smul_le_smul_of_nonneg_left hb.le ha.le).lt_of_ne $ + ⟨fun _a ha _b₁ _b₂ hb ↦ (smul_le_smul_of_nonneg_left hb.le ha.le).lt_of_ne <| (smul_right_injective _ ha.ne').ne hb.ne⟩ instance PosSMulReflectLT.toPosSMulReflectLE [PosSMulReflectLT α β] : PosSMulReflectLE α β := @@ -717,7 +718,7 @@ section PartialOrder variable [PartialOrder α] [PartialOrder β] lemma SMulPosMono.toSMulPosStrictMono [SMulPosMono α β] : SMulPosStrictMono α β := - ⟨fun _b hb _a₁ _a₂ ha ↦ (smul_le_smul_of_nonneg_right ha.le hb.le).lt_of_ne $ + ⟨fun _b hb _a₁ _a₂ ha ↦ (smul_le_smul_of_nonneg_right ha.le hb.le).lt_of_ne <| (smul_left_injective _ hb.ne').ne ha.ne⟩ lemma smulPosMono_iff_smulPosStrictMono : SMulPosMono α β ↔ SMulPosStrictMono α β := @@ -785,22 +786,22 @@ variable [Preorder α] [Ring α] [OrderedAddCommGroup β] [Module α β] instance instSMulPosMono [SMulPosMono α β] : SMulPosMono α βᵒᵈ where elim _b hb a₁ a₂ ha := by rw [← neg_le_neg_iff, ← smul_neg, ← smul_neg] - exact smul_le_smul_of_nonneg_right (β := β) ha $ neg_nonneg.2 hb + exact smul_le_smul_of_nonneg_right (β := β) ha <| neg_nonneg.2 hb instance instSMulPosStrictMono [SMulPosStrictMono α β] : SMulPosStrictMono α βᵒᵈ where elim _b hb a₁ a₂ ha := by rw [← neg_lt_neg_iff, ← smul_neg, ← smul_neg] - exact smul_lt_smul_of_pos_right (β := β) ha $ neg_pos.2 hb + exact smul_lt_smul_of_pos_right (β := β) ha <| neg_pos.2 hb instance instSMulPosReflectLT [SMulPosReflectLT α β] : SMulPosReflectLT α βᵒᵈ where elim _b hb a₁ a₂ h := by rw [← neg_lt_neg_iff, ← smul_neg, ← smul_neg] at h - exact lt_of_smul_lt_smul_right (β := β) h $ neg_nonneg.2 hb + exact lt_of_smul_lt_smul_right (β := β) h <| neg_nonneg.2 hb instance instSMulPosReflectLE [SMulPosReflectLE α β] : SMulPosReflectLE α βᵒᵈ where elim _b hb a₁ a₂ h := by rw [← neg_le_neg_iff, ← smul_neg, ← smul_neg] at h - exact le_of_smul_le_smul_right (β := β) h $ neg_pos.2 hb + exact le_of_smul_le_smul_right (β := β) h <| neg_pos.2 hb end Right end OrderDual @@ -850,7 +851,7 @@ end PosSMulStrictMono lemma le_of_smul_le_smul_of_neg [PosSMulReflectLE α β] (h : a • b₁ ≤ a • b₂) (ha : a < 0) : b₂ ≤ b₁ := by rw [← neg_neg a, neg_smul, neg_smul (-a), neg_le_neg_iff] at h - exact le_of_smul_le_smul_of_pos_left h $ neg_pos.2 ha + exact le_of_smul_le_smul_of_pos_left h <| neg_pos.2 ha lemma lt_of_smul_lt_smul_of_nonpos [PosSMulReflectLT α β] (h : a • b₁ < a • b₂) (ha : a ≤ 0) : b₂ < b₁ := by @@ -961,7 +962,7 @@ lemma smul_nonpos_iff : a • b ≤ 0 ↔ 0 ≤ a ∧ b ≤ 0 ∨ a ≤ 0 ∧ 0 rw [← neg_nonneg, ← smul_neg, smul_nonneg_iff, neg_nonneg, neg_nonpos] lemma smul_nonneg_iff_pos_imp_nonneg : 0 ≤ a • b ↔ (0 < a → 0 ≤ b) ∧ (0 < b → 0 ≤ a) := - smul_nonneg_iff.trans $ by + smul_nonneg_iff.trans <| by simp_rw [← not_le, ← or_iff_not_imp_left]; have := le_total a 0; have := le_total b 0; tauto lemma smul_nonneg_iff_neg_imp_nonpos : 0 ≤ a • b ↔ (a < 0 → b ≤ 0) ∧ (b < 0 → a ≤ 0) := by @@ -981,13 +982,13 @@ variable [LinearOrderedSemifield α] [AddCommGroup β] [PartialOrder β] -- See note [lower instance priority] instance (priority := 100) PosSMulMono.toPosSMulReflectLE [MulAction α β] [PosSMulMono α β] : PosSMulReflectLE α β where - elim _a ha b₁ b₂ h := by simpa [ha.ne'] using smul_le_smul_of_nonneg_left h $ inv_nonneg.2 ha.le + elim _a ha b₁ b₂ h := by simpa [ha.ne'] using smul_le_smul_of_nonneg_left h <| inv_nonneg.2 ha.le -- See note [lower instance priority] instance (priority := 100) PosSMulStrictMono.toPosSMulReflectLT [MulActionWithZero α β] [PosSMulStrictMono α β] : PosSMulReflectLT α β := PosSMulReflectLT.of_pos fun a ha b₁ b₂ h ↦ by - simpa [ha.ne'] using smul_lt_smul_of_pos_left h $ inv_pos.2 ha + simpa [ha.ne'] using smul_lt_smul_of_pos_left h <| inv_pos.2 ha end LinearOrderedSemifield @@ -1077,7 +1078,7 @@ instance instSMulPosReflectLT [∀ i, SMulPosReflectLT α (β i)] : SMulPosRefle elim := by simp_rw [lt_def] rintro b hb _a₁ _a₂ ⟨-, i, hi⟩ - exact lt_of_smul_lt_smul_right hi $ hb _ + exact lt_of_smul_lt_smul_right hi <| hb _ end SMulWithZero end Pi @@ -1091,11 +1092,11 @@ lemma PosSMulMono.lift [PosSMulMono α γ] : PosSMulMono α β where elim a ha b₁ b₂ hb := by simp only [← hf, smul] at *; exact smul_le_smul_of_nonneg_left hb ha lemma PosSMulStrictMono.lift [PosSMulStrictMono α γ] : PosSMulStrictMono α β where - elim a ha b₁ b₂ hb := by + elim a ha b₁ b₂ hb := by simp only [← lt_iff_lt_of_le_iff_le' hf hf, smul] at *; exact smul_lt_smul_of_pos_left hb ha lemma PosSMulReflectLE.lift [PosSMulReflectLE α γ] : PosSMulReflectLE α β where - elim a ha b₁ b₂ h := hf.1 $ le_of_smul_le_smul_left (by simpa only [smul] using hf.2 h) ha + elim a ha b₁ b₂ h := hf.1 <| le_of_smul_le_smul_left (by simpa only [smul] using hf.2 h) ha lemma PosSMulReflectLT.lift [PosSMulReflectLT α γ] : PosSMulReflectLT α β where elim a ha b₁ b₂ h := by @@ -1122,6 +1123,26 @@ lemma SMulPosReflectLT.lift [SMulPosReflectLT α γ] : SMulPosReflectLT α β wh end Lift +section Nat + +instance OrderedSemiring.toPosSMulMonoNat [OrderedSemiring α] : PosSMulMono ℕ α where + elim _n _ _a _b hab := nsmul_le_nsmul_right hab _ + +instance OrderedSemiring.toSMulPosMonoNat [OrderedSemiring α] : SMulPosMono ℕ α where + elim _a ha _m _n hmn := nsmul_le_nsmul_left ha hmn + +instance StrictOrderedSemiring.toPosSMulStrictMonoNat [StrictOrderedSemiring α] : + PosSMulStrictMono ℕ α where + elim _n hn _a _b hab := nsmul_right_strictMono hn.ne' hab + +instance StrictOrderedSemiring.toSMulPosStrictMonoNat [StrictOrderedSemiring α] : + SMulPosStrictMono ℕ α where + elim _a ha _m _n hmn := nsmul_lt_nsmul_left ha hmn + +end Nat + +-- TODO: Instances for `Int` and `Rat` + namespace Mathlib.Meta.Positivity section OrderedSMul variable [Zero α] [Zero β] [SMulZeroClass α β] [Preorder α] [Preorder β] [PosSMulMono α β] {a : α} diff --git a/Mathlib/Algebra/Order/Module/OrderedSMul.lean b/Mathlib/Algebra/Order/Module/OrderedSMul.lean index bc47e3a949e5f..ac52a988c8111 100644 --- a/Mathlib/Algebra/Order/Module/OrderedSMul.lean +++ b/Mathlib/Algebra/Order/Module/OrderedSMul.lean @@ -8,9 +8,7 @@ import Mathlib.Algebra.Module.Prod import Mathlib.Algebra.Order.Module.Defs import Mathlib.Algebra.Order.Monoid.Prod import Mathlib.Algebra.Order.Pi -import Mathlib.Data.Set.Pointwise.SMul import Mathlib.Tactic.GCongr.Core -import Mathlib.Tactic.Positivity #align_import algebra.order.smul from "leanprover-community/mathlib"@"3ba15165bd6927679be7c22d6091a87337e3cd0c" @@ -145,3 +143,33 @@ instance Pi.orderedSMul {M : ι → Type*} [∀ i, OrderedAddCommMonoid (M i)] #noalign pi.ordered_smul'' end LinearOrderedSemifield + +section Invertible +variable (α : Type*) {β : Type*} +variable [Semiring α] [Invertible (2 : α)] [Lattice β] [AddCommGroup β] [Module α β] + [CovariantClass β β (· + ·) (· ≤ ·)] + +lemma inf_eq_half_smul_add_sub_abs_sub (x y : β) : x ⊓ y = (⅟2 : α) • (x + y - |y - x|) := by + rw [← two_nsmul_inf_eq_add_sub_abs_sub x y, two_smul, ← two_smul α, + smul_smul, invOf_mul_self, one_smul] + +lemma sup_eq_half_smul_add_add_abs_sub (x y : β) : x ⊔ y = (⅟2 : α) • (x + y + |y - x|) := by + rw [← two_nsmul_sup_eq_add_add_abs_sub x y, two_smul, ← two_smul α, + smul_smul, invOf_mul_self, one_smul] + +end Invertible + +section DivisionSemiring +variable (α : Type*) {β : Type*} +variable [DivisionSemiring α] [NeZero (2 : α)] [Lattice β] [AddCommGroup β] [Module α β] + [CovariantClass β β (· + ·) (· ≤ ·)] + +lemma inf_eq_half_smul_add_sub_abs_sub' (x y : β) : x ⊓ y = (2⁻¹ : α) • (x + y - |y - x|) := by + letI := invertibleOfNonzero (two_ne_zero' α) + exact inf_eq_half_smul_add_sub_abs_sub α x y + +lemma sup_eq_half_smul_add_add_abs_sub' (x y : β) : x ⊔ y = (2⁻¹ : α) • (x + y + |y - x|) := by + letI := invertibleOfNonzero (two_ne_zero' α) + exact sup_eq_half_smul_add_add_abs_sub α x y + +end DivisionSemiring diff --git a/Mathlib/Algebra/Order/Module/Synonym.lean b/Mathlib/Algebra/Order/Module/Synonym.lean index 6cd27a45ddc60..773e8572b8912 100644 --- a/Mathlib/Algebra/Order/Module/Synonym.lean +++ b/Mathlib/Algebra/Order/Module/Synonym.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Module.Basic -import Mathlib.Algebra.Order.Pi import Mathlib.Algebra.Ring.OrderSynonym /-! diff --git a/Mathlib/Algebra/Order/Monoid/ToMulBot.lean b/Mathlib/Algebra/Order/Monoid/ToMulBot.lean index ef10b84da2190..33cf5857bff2e 100644 --- a/Mathlib/Algebra/Order/Monoid/ToMulBot.lean +++ b/Mathlib/Algebra/Order/Monoid/ToMulBot.lean @@ -3,9 +3,10 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ -import Mathlib.Algebra.Order.WithZero -import Mathlib.Algebra.Order.Monoid.WithTop +import Mathlib.Algebra.Order.Monoid.WithZero.Defs import Mathlib.Algebra.Order.Monoid.TypeTags +import Mathlib.Algebra.Order.Monoid.WithTop +import Mathlib.Algebra.Group.Equiv.Basic #align_import algebra.order.monoid.to_mul_bot from "leanprover-community/mathlib"@"ee0c179cd3c8a45aa5bffbf1b41d8dbede452865" diff --git a/Mathlib/Algebra/Order/Monoid/WithTop.lean b/Mathlib/Algebra/Order/Monoid/WithTop.lean index 83b1bd2bd680d..be2fe23005cfe 100644 --- a/Mathlib/Algebra/Order/Monoid/WithTop.lean +++ b/Mathlib/Algebra/Order/Monoid/WithTop.lean @@ -5,10 +5,11 @@ Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ import Mathlib.Algebra.CharZero.Defs import Mathlib.Algebra.Group.Hom.Defs +import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Algebra.Order.Monoid.OrderDual -import Mathlib.Algebra.Order.Monoid.WithZero.Basic import Mathlib.Algebra.Order.ZeroLEOne import Mathlib.Data.Nat.Cast.Defs +import Mathlib.Order.WithBot #align_import algebra.order.monoid.with_top from "leanprover-community/mathlib"@"0111834459f5d7400215223ea95ae38a1265a907" @@ -25,7 +26,7 @@ namespace WithTop section One -variable [One α] +variable [One α] {a : α} @[to_additive] instance one : One (WithTop α) := @@ -40,11 +41,23 @@ theorem coe_one : ((1 : α) : WithTop α) = 1 := #align with_top.coe_zero WithTop.coe_zero @[to_additive (attr := simp, norm_cast)] -theorem coe_eq_one {a : α} : (a : WithTop α) = 1 ↔ a = 1 := - coe_eq_coe +lemma coe_eq_one : (a : WithTop α) = 1 ↔ a = 1 := coe_eq_coe #align with_top.coe_eq_one WithTop.coe_eq_one #align with_top.coe_eq_zero WithTop.coe_eq_zero +@[to_additive (attr := simp, norm_cast)] +lemma one_eq_coe : 1 = (a : WithTop α) ↔ a = 1 := eq_comm.trans coe_eq_one +#align with_top.one_eq_coe WithTop.one_eq_coe +#align with_top.zero_eq_coe WithTop.zero_eq_coe + +@[to_additive (attr := simp)] lemma top_ne_one : (⊤ : WithTop α) ≠ 1 := top_ne_coe +#align with_top.top_ne_one WithTop.top_ne_one +#align with_top.top_ne_zero WithTop.top_ne_zero + +@[to_additive (attr := simp)] lemma one_ne_top : (1 : WithTop α) ≠ ⊤ := coe_ne_top +#align with_top.one_ne_top WithTop.one_ne_top +#align with_top.zero_ne_top WithTop.zero_ne_top + @[to_additive (attr := simp)] theorem untop_one : (1 : WithTop α).untop coe_ne_top = 1 := rfl @@ -87,24 +100,6 @@ protected theorem map_one {β} (f : α → β) : (1 : WithTop α).map f = (f 1 : #align with_top.map_one WithTop.map_one #align with_top.map_zero WithTop.map_zero -@[to_additive (attr := simp, norm_cast)] -theorem one_eq_coe {a : α} : 1 = (a : WithTop α) ↔ a = 1 := - Trans.trans eq_comm coe_eq_one -#align with_top.one_eq_coe WithTop.one_eq_coe -#align with_top.zero_eq_coe WithTop.zero_eq_coe - -@[to_additive (attr := simp)] -theorem top_ne_one : ⊤ ≠ (1 : WithTop α) := - fun. -#align with_top.top_ne_one WithTop.top_ne_one -#align with_top.top_ne_zero WithTop.top_ne_zero - -@[to_additive (attr := simp)] -theorem one_ne_top : (1 : WithTop α) ≠ ⊤ := - fun. -#align with_top.one_ne_top WithTop.one_ne_top -#align with_top.zero_ne_top WithTop.zero_ne_top - instance zeroLEOneClass [Zero α] [LE α] [ZeroLEOneClass α] : ZeroLEOneClass (WithTop α) := ⟨some_le_some.2 zero_le_one⟩ @@ -118,9 +113,7 @@ instance add : Add (WithTop α) := ⟨Option.map₂ (· + ·)⟩ #align with_top.has_add WithTop.add -@[norm_cast] -theorem coe_add : ((x + y : α) : WithTop α) = x + y := - rfl +@[norm_cast] lemma coe_add (a b : α) : ↑(a + b) = (a + b : WithTop α) := rfl #align with_top.coe_add WithTop.coe_add section deprecated @@ -335,13 +328,35 @@ instance addZeroClass [AddZeroClass α] : AddZeroClass (WithTop α) := zero_add := Option.map₂_left_identity zero_add add_zero := Option.map₂_right_identity add_zero } -instance addMonoid [AddMonoid α] : AddMonoid (WithTop α) := +section AddMonoid +variable [AddMonoid α] + +instance addMonoid : AddMonoid (WithTop α) := { WithTop.addSemigroup, WithTop.addZeroClass with } +/-- Coercion from `α` to `WithTop α` as an `AddMonoidHom`. -/ +def addHom : α →+ WithTop α where + toFun := WithTop.some + map_zero' := rfl + map_add' _ _ := rfl +#align with_top.coe_add_hom WithTop.addHom + +@[simp, norm_cast] lemma coe_addHom : ⇑(addHom : α →+ WithTop α) = WithTop.some := rfl +#align with_top.coe_coe_add_hom WithTop.coe_addHom + +@[simp, norm_cast] +lemma coe_nsmul (a : α) (n : ℕ) : ↑(n • a) = n • (a : WithTop α) := + (addHom : α →+ WithTop α).map_nsmul _ _ + +end AddMonoid + instance addCommMonoid [AddCommMonoid α] : AddCommMonoid (WithTop α) := { WithTop.addMonoid, WithTop.addCommSemigroup with } -instance addMonoidWithOne [AddMonoidWithOne α] : AddMonoidWithOne (WithTop α) := +section AddMonoidWithOne +variable [AddMonoidWithOne α] + +instance addMonoidWithOne : AddMonoidWithOne (WithTop α) := { WithTop.one, WithTop.addMonoid with natCast := fun n => ↑(n : α), natCast_zero := by @@ -352,6 +367,17 @@ instance addMonoidWithOne [AddMonoidWithOne α] : AddMonoidWithOne (WithTop α) rw [Nat.cast_add_one, WithTop.coe_add, WithTop.coe_one] } +@[simp, norm_cast] lemma coe_nat (n : ℕ) : ((n : α) : WithTop α) = n := rfl +#align with_top.coe_nat WithTop.coe_nat + +@[simp] lemma nat_ne_top (n : ℕ) : (n : WithTop α) ≠ ⊤ := coe_ne_top +#align with_top.nat_ne_top WithTop.nat_ne_top + +@[simp] lemma top_ne_nat (n : ℕ) : (⊤ : WithTop α) ≠ n := top_ne_coe +#align with_top.top_ne_nat WithTop.top_ne_nat + +end AddMonoidWithOne + instance charZero [AddMonoidWithOne α] [CharZero α] : CharZero (WithTop α) := { cast_injective := Function.Injective.comp (f := Nat.cast (R := α)) (fun _ _ => WithTop.coe_eq_coe.1) Nat.cast_injective} @@ -397,36 +423,6 @@ instance [CanonicallyLinearOrderedAddCommMonoid α] : CanonicallyLinearOrderedAddCommMonoid (WithTop α) := { WithTop.canonicallyOrderedAddCommMonoid, WithTop.linearOrder with } -@[simp, norm_cast] -theorem coe_nat [AddMonoidWithOne α] (n : ℕ) : ((n : α) : WithTop α) = n := - rfl -#align with_top.coe_nat WithTop.coe_nat - -@[simp] -theorem nat_ne_top [AddMonoidWithOne α] (n : ℕ) : (n : WithTop α) ≠ ⊤ := - coe_ne_top -#align with_top.nat_ne_top WithTop.nat_ne_top - -@[simp] -theorem top_ne_nat [AddMonoidWithOne α] (n : ℕ) : (⊤ : WithTop α) ≠ n := - top_ne_coe -#align with_top.top_ne_nat WithTop.top_ne_nat - -/-- Coercion from `α` to `WithTop α` as an `AddMonoidHom`. -/ -def addHom [AddMonoid α] : α →+ WithTop α := - -- Porting note: why does the old proof not work? - -- ⟨WithTop.some, rfl, fun _ _ => rfl⟩ - { toFun := WithTop.some, - map_zero' := rfl, - map_add' := fun _ _ => rfl } -#align with_top.coe_add_hom WithTop.addHom - --- Porting note: It seems like that kind of coe-lemmas is not needed anymore. --- @[simp] --- theorem coe_coe_add_hom [AddMonoid α] : (coeAddHom : α →+ WithTop α).toFun = WithTop.some := --- rfl --- #align with_top.coe_coe_add_hom WithTop.coe_coe_add_hom - @[simp] theorem zero_lt_top [OrderedAddCommMonoid α] : (0 : WithTop α) < ⊤ := coe_lt_top 0 @@ -470,55 +466,26 @@ protected def _root_.AddMonoidHom.withTopMap {M N : Type*} [AddZeroClass M] [Add end WithTop namespace WithBot +section One +variable [One α] {a : α} -@[to_additive] -instance one [One α] : One (WithBot α) := - WithTop.one - -instance add [Add α] : Add (WithBot α) := - WithTop.add - -instance AddSemigroup [AddSemigroup α] : AddSemigroup (WithBot α) := - WithTop.addSemigroup - -instance addCommSemigroup [AddCommSemigroup α] : AddCommSemigroup (WithBot α) := - WithTop.addCommSemigroup - -instance addZeroClass [AddZeroClass α] : AddZeroClass (WithBot α) := - WithTop.addZeroClass - -instance addMonoid [AddMonoid α] : AddMonoid (WithBot α) := - WithTop.addMonoid - -instance addCommMonoid [AddCommMonoid α] : AddCommMonoid (WithBot α) := - WithTop.addCommMonoid - -instance addMonoidWithOne [AddMonoidWithOne α] : AddMonoidWithOne (WithBot α) := - WithTop.addMonoidWithOne - -instance charZero [AddMonoidWithOne α] [CharZero α] : CharZero (WithBot α) := - WithTop.charZero - -instance addCommMonoidWithOne [AddCommMonoidWithOne α] : AddCommMonoidWithOne (WithBot α) := - WithTop.addCommMonoidWithOne - -instance zeroLEOneClass [Zero α] [One α] [LE α] [ZeroLEOneClass α] : ZeroLEOneClass (WithBot α) := - ⟨some_le_some.2 zero_le_one⟩ +@[to_additive] instance one : One (WithBot α) := WithTop.one --- `by norm_cast` proves this lemma, so I did not tag it with `norm_cast` -@[to_additive] -theorem coe_one [One α] : ((1 : α) : WithBot α) = 1 := - rfl +@[to_additive (attr := simp, norm_cast)] lemma coe_one : ((1 : α) : WithBot α) = 1 := rfl #align with_bot.coe_one WithBot.coe_one #align with_bot.coe_zero WithBot.coe_zero --- `by norm_cast` proves this lemma, so I did not tag it with `norm_cast` -@[to_additive] -theorem coe_eq_one [One α] {a : α} : (a : WithBot α) = 1 ↔ a = 1 := - WithTop.coe_eq_one +@[to_additive (attr := simp, norm_cast)] +lemma coe_eq_one : (a : WithBot α) = 1 ↔ a = 1 := coe_eq_coe #align with_bot.coe_eq_one WithBot.coe_eq_one #align with_bot.coe_eq_zero WithBot.coe_eq_zero +@[to_additive (attr := simp, norm_cast)] +lemma one_eq_coe : 1 = (a : WithBot α) ↔ a = 1 := eq_comm.trans coe_eq_one + +@[to_additive (attr := simp)] lemma bot_ne_one : (⊥ : WithBot α) ≠ 1 := bot_ne_coe +@[to_additive (attr := simp)] lemma one_ne_bot : (1 : WithBot α) ≠ ⊥ := coe_ne_bot + @[to_additive (attr := simp)] theorem unbot_one [One α] : (1 : WithBot α).unbot coe_ne_bot = 1 := rfl @@ -526,56 +493,99 @@ theorem unbot_one [One α] : (1 : WithBot α).unbot coe_ne_bot = 1 := #align with_bot.unbot_zero WithBot.unbot_zero @[to_additive (attr := simp)] -theorem unbot_one' [One α] (d : α) : (1 : WithBot α).unbot' d = 1 := +theorem unbot_one' (d : α) : (1 : WithBot α).unbot' d = 1 := rfl #align with_bot.unbot_one' WithBot.unbot_one' #align with_bot.unbot_zero' WithBot.unbot_zero' @[to_additive (attr := simp, norm_cast) coe_nonneg] -theorem one_le_coe [One α] [LE α] {a : α} : 1 ≤ (a : WithBot α) ↔ 1 ≤ a := - coe_le_coe +theorem one_le_coe [LE α] : 1 ≤ (a : WithBot α) ↔ 1 ≤ a := coe_le_coe #align with_bot.one_le_coe WithBot.one_le_coe #align with_bot.coe_nonneg WithBot.coe_nonneg @[to_additive (attr := simp, norm_cast) coe_le_zero] -theorem coe_le_one [One α] [LE α] {a : α} : (a : WithBot α) ≤ 1 ↔ a ≤ 1 := - coe_le_coe +theorem coe_le_one [LE α] : (a : WithBot α) ≤ 1 ↔ a ≤ 1 := coe_le_coe #align with_bot.coe_le_one WithBot.coe_le_one #align with_bot.coe_le_zero WithBot.coe_le_zero @[to_additive (attr := simp, norm_cast) coe_pos] -theorem one_lt_coe [One α] [LT α] {a : α} : 1 < (a : WithBot α) ↔ 1 < a := - coe_lt_coe +theorem one_lt_coe [LT α] : 1 < (a : WithBot α) ↔ 1 < a := coe_lt_coe #align with_bot.one_lt_coe WithBot.one_lt_coe #align with_bot.coe_pos WithBot.coe_pos @[to_additive (attr := simp, norm_cast) coe_lt_zero] -theorem coe_lt_one [One α] [LT α] {a : α} : (a : WithBot α) < 1 ↔ a < 1 := - coe_lt_coe +theorem coe_lt_one [LT α] : (a : WithBot α) < 1 ↔ a < 1 := coe_lt_coe #align with_bot.coe_lt_one WithBot.coe_lt_one #align with_bot.coe_lt_zero WithBot.coe_lt_zero @[to_additive (attr := simp)] -protected theorem map_one {β} [One α] (f : α → β) : (1 : WithBot α).map f = (f 1 : WithBot β) := +protected theorem map_one {β} (f : α → β) : (1 : WithBot α).map f = (f 1 : WithBot β) := rfl #align with_bot.map_one WithBot.map_one #align with_bot.map_zero WithBot.map_zero -@[norm_cast] -theorem coe_nat [AddMonoidWithOne α] (n : ℕ) : ((n : α) : WithBot α) = n := - rfl +instance zeroLEOneClass [Zero α] [LE α] [ZeroLEOneClass α] : ZeroLEOneClass (WithBot α) := + ⟨some_le_some.2 zero_le_one⟩ + +end One + +instance add [Add α] : Add (WithBot α) := + WithTop.add + +instance AddSemigroup [AddSemigroup α] : AddSemigroup (WithBot α) := + WithTop.addSemigroup + +instance addCommSemigroup [AddCommSemigroup α] : AddCommSemigroup (WithBot α) := + WithTop.addCommSemigroup + +instance addZeroClass [AddZeroClass α] : AddZeroClass (WithBot α) := + WithTop.addZeroClass + +section AddMonoid +variable [AddMonoid α] + +instance addMonoid : AddMonoid (WithBot α) := WithTop.addMonoid + +/-- Coercion from `α` to `WithBot α` as an `AddMonoidHom`. -/ +def addHom : α →+ WithBot α where + toFun := WithTop.some + map_zero' := rfl + map_add' _ _ := rfl + +@[simp, norm_cast] lemma coe_addHom : ⇑(addHom : α →+ WithBot α) = WithBot.some := rfl + +@[simp, norm_cast] +lemma coe_nsmul (a : α) (n : ℕ) : ↑(n • a) = n • (a : WithBot α) := + (addHom : α →+ WithBot α).map_nsmul _ _ +#align with_bot.coe_nsmul WithBot.coe_nsmul + +end AddMonoid + +instance addCommMonoid [AddCommMonoid α] : AddCommMonoid (WithBot α) := + WithTop.addCommMonoid + +section AddMonoidWithOne +variable [AddMonoidWithOne α] + +instance addMonoidWithOne : AddMonoidWithOne (WithBot α) := WithTop.addMonoidWithOne + +@[norm_cast] lemma coe_nat (n : ℕ) : ((n : α) : WithBot α) = n := rfl #align with_bot.coe_nat WithBot.coe_nat -@[simp] -theorem nat_ne_bot [AddMonoidWithOne α] (n : ℕ) : (n : WithBot α) ≠ ⊥ := - coe_ne_bot +@[simp] lemma nat_ne_bot (n : ℕ) : (n : WithBot α) ≠ ⊥ := coe_ne_bot #align with_bot.nat_ne_bot WithBot.nat_ne_bot -@[simp] -theorem bot_ne_nat [AddMonoidWithOne α] (n : ℕ) : (⊥ : WithBot α) ≠ n := - bot_ne_coe +@[simp] lemma bot_ne_nat (n : ℕ) : (⊥ : WithBot α) ≠ n := bot_ne_coe #align with_bot.bot_ne_nat WithBot.bot_ne_nat +end AddMonoidWithOne + +instance charZero [AddMonoidWithOne α] [CharZero α] : CharZero (WithBot α) := + WithTop.charZero + +instance addCommMonoidWithOne [AddCommMonoidWithOne α] : AddCommMonoidWithOne (WithBot α) := + WithTop.addCommMonoidWithOne + section Add variable [Add α] {a b c d : WithBot α} {x y : α} diff --git a/Mathlib/Algebra/Order/Monovary.lean b/Mathlib/Algebra/Order/Monovary.lean index 6c95814ac2db3..ad4b83eef36f5 100644 --- a/Mathlib/Algebra/Order/Monovary.lean +++ b/Mathlib/Algebra/Order/Monovary.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Order.Group.Defs +import Mathlib.Algebra.Order.Group.Instances import Mathlib.Algebra.Order.Module.OrderedSMul import Mathlib.Algebra.Order.Monoid.MinMax import Mathlib.Order.Monotone.Monovary @@ -121,25 +122,25 @@ variable [OrderedCommGroup α] [LinearOrderedCommGroup β] {s : Set ι} {f f₁ @[to_additive] lemma MonovaryOn.mul_right (h₁ : MonovaryOn f g₁ s) (h₂ : MonovaryOn f g₂ s) : MonovaryOn f (g₁ * g₂) s := - fun _i hi _j hj hij ↦ (lt_or_lt_of_mul_lt_mul hij).elim (h₁ hi hj) $ h₂ hi hj + fun _i hi _j hj hij ↦ (lt_or_lt_of_mul_lt_mul hij).elim (h₁ hi hj) <| h₂ hi hj @[to_additive] lemma AntivaryOn.mul_right (h₁ : AntivaryOn f g₁ s) (h₂ : AntivaryOn f g₂ s) : AntivaryOn f (g₁ * g₂) s := - fun _i hi _j hj hij ↦ (lt_or_lt_of_mul_lt_mul hij).elim (h₁ hi hj) $ h₂ hi hj + fun _i hi _j hj hij ↦ (lt_or_lt_of_mul_lt_mul hij).elim (h₁ hi hj) <| h₂ hi hj @[to_additive] lemma MonovaryOn.div_right (h₁ : MonovaryOn f g₁ s) (h₂ : AntivaryOn f g₂ s) : MonovaryOn f (g₁ / g₂) s := - fun _i hi _j hj hij ↦ (lt_or_lt_of_div_lt_div hij).elim (h₁ hi hj) $ h₂ hj hi + fun _i hi _j hj hij ↦ (lt_or_lt_of_div_lt_div hij).elim (h₁ hi hj) <| h₂ hj hi @[to_additive] lemma AntivaryOn.div_right (h₁ : AntivaryOn f g₁ s) (h₂ : MonovaryOn f g₂ s) : AntivaryOn f (g₁ / g₂) s := - fun _i hi _j hj hij ↦ (lt_or_lt_of_div_lt_div hij).elim (h₁ hi hj) $ h₂ hj hi + fun _i hi _j hj hij ↦ (lt_or_lt_of_div_lt_div hij).elim (h₁ hi hj) <| h₂ hj hi @[to_additive] lemma MonovaryOn.pow_right (hfg : MonovaryOn f g s) (n : ℕ) : - MonovaryOn f (g ^ n) s := fun _i hi _j hj hij ↦ hfg hi hj $ lt_of_pow_lt_pow_left' _ hij + MonovaryOn f (g ^ n) s := fun _i hi _j hj hij ↦ hfg hi hj <| lt_of_pow_lt_pow_left' _ hij @[to_additive] lemma AntivaryOn.pow_right (hfg : AntivaryOn f g s) (n : ℕ) : - AntivaryOn f (g ^ n) s := fun _i hi _j hj hij ↦ hfg hi hj $ lt_of_pow_lt_pow_left' _ hij + AntivaryOn f (g ^ n) s := fun _i hi _j hj hij ↦ hfg hi hj <| lt_of_pow_lt_pow_left' _ hij @[to_additive] lemma Monovary.mul_right (h₁ : Monovary f g₁) (h₂ : Monovary f g₂) : Monovary f (g₁ * g₂) := @@ -158,10 +159,10 @@ variable [OrderedCommGroup α] [LinearOrderedCommGroup β] {s : Set ι} {f f₁ fun _i _j hij ↦ (lt_or_lt_of_div_lt_div hij).elim (fun h ↦ h₁ h) fun h ↦ h₂ h @[to_additive] lemma Monovary.pow_right (hfg : Monovary f g) (n : ℕ) : Monovary f (g ^ n) := - fun _i _j hij ↦ hfg $ lt_of_pow_lt_pow_left' _ hij + fun _i _j hij ↦ hfg <| lt_of_pow_lt_pow_left' _ hij @[to_additive] lemma Antivary.pow_right (hfg : Antivary f g) (n : ℕ) : Antivary f (g ^ n) := - fun _i _j hij ↦ hfg $ lt_of_pow_lt_pow_left' _ hij + fun _i _j hij ↦ hfg <| lt_of_pow_lt_pow_left' _ hij end LinearOrderedCommGroup @@ -244,11 +245,11 @@ lemma antivaryOn_inv_left₀ (hf : ∀ i ∈ s, 0 < f i) : AntivaryOn f⁻¹ g s @[simp] lemma monovaryOn_inv_right₀ (hg : ∀ i ∈ s, 0 < g i) : MonovaryOn f g⁻¹ s ↔ AntivaryOn f g s := - forall₂_swap.trans $ forall₄_congr fun i hi j hj ↦ by erw [inv_lt_inv (hg _ hj) (hg _ hi)] + forall₂_swap.trans <| forall₄_congr fun i hi j hj ↦ by erw [inv_lt_inv (hg _ hj) (hg _ hi)] @[simp] lemma antivaryOn_inv_right₀ (hg : ∀ i ∈ s, 0 < g i) : AntivaryOn f g⁻¹ s ↔ MonovaryOn f g s := - forall₂_swap.trans $ forall₄_congr fun i hi j hj ↦ by erw [inv_lt_inv (hg _ hj) (hg _ hi)] + forall₂_swap.trans <| forall₄_congr fun i hi j hj ↦ by erw [inv_lt_inv (hg _ hj) (hg _ hi)] lemma monovaryOn_inv₀ (hf : ∀ i ∈ s, 0 < f i) (hg : ∀ i ∈ s, 0 < g i) : MonovaryOn f⁻¹ g⁻¹ s ↔ MonovaryOn f g s := by @@ -264,10 +265,10 @@ lemma antivaryOn_inv₀ (hf : ∀ i ∈ s, 0 < f i) (hg : ∀ i ∈ s, 0 < g i) forall₃_congr fun _i _j _ ↦ inv_le_inv (hf _) (hf _) @[simp] lemma monovary_inv_right₀ (hg : StrongLT 0 g) : Monovary f g⁻¹ ↔ Antivary f g := - forall_swap.trans $ forall₂_congr fun i j ↦ by erw [inv_lt_inv (hg _) (hg _)] + forall_swap.trans <| forall₂_congr fun i j ↦ by erw [inv_lt_inv (hg _) (hg _)] @[simp] lemma antivary_inv_right₀ (hg : StrongLT 0 g) : Antivary f g⁻¹ ↔ Monovary f g := - forall_swap.trans $ forall₂_congr fun i j ↦ by erw [inv_lt_inv (hg _) (hg _)] + forall_swap.trans <| forall₂_congr fun i j ↦ by erw [inv_lt_inv (hg _) (hg _)] lemma monovary_inv₀ (hf : StrongLT 0 f) (hg : StrongLT 0 g) : Monovary f⁻¹ g⁻¹ ↔ Monovary f g := by rw [monovary_inv_left₀ hf, antivary_inv_right₀ hg] @@ -289,19 +290,19 @@ alias ⟨Antivary.of_inv₀, Antivary.inv₀⟩ := antivary_inv₀ lemma MonovaryOn.div_left₀ (hf₁ : ∀ i ∈ s, 0 ≤ f₁ i) (hf₂ : ∀ i ∈ s, 0 < f₂ i) (h₁ : MonovaryOn f₁ g s) (h₂ : AntivaryOn f₂ g s) : MonovaryOn (f₁ / f₂) g s := - fun _i hi _j hj hij ↦ div_le_div (hf₁ _ hj) (h₁ hi hj hij) (hf₂ _ hj) $ h₂ hi hj hij + fun _i hi _j hj hij ↦ div_le_div (hf₁ _ hj) (h₁ hi hj hij) (hf₂ _ hj) <| h₂ hi hj hij lemma AntivaryOn.div_left₀ (hf₁ : ∀ i ∈ s, 0 ≤ f₁ i) (hf₂ : ∀ i ∈ s, 0 < f₂ i) (h₁ : AntivaryOn f₁ g s) (h₂ : MonovaryOn f₂ g s) : AntivaryOn (f₁ / f₂) g s := - fun _i hi _j hj hij ↦ div_le_div (hf₁ _ hi) (h₁ hi hj hij) (hf₂ _ hi) $ h₂ hi hj hij + fun _i hi _j hj hij ↦ div_le_div (hf₁ _ hi) (h₁ hi hj hij) (hf₂ _ hi) <| h₂ hi hj hij lemma Monovary.div_left₀ (hf₁ : 0 ≤ f₁) (hf₂ : StrongLT 0 f₂) (h₁ : Monovary f₁ g) (h₂ : Antivary f₂ g) : Monovary (f₁ / f₂) g := - fun _i _j hij ↦ div_le_div (hf₁ _) (h₁ hij) (hf₂ _) $ h₂ hij + fun _i _j hij ↦ div_le_div (hf₁ _) (h₁ hij) (hf₂ _) <| h₂ hij lemma Antivary.div_left₀ (hf₁ : 0 ≤ f₁) (hf₂ : StrongLT 0 f₂) (h₁ : Antivary f₁ g) (h₂ : Monovary f₂ g) : Antivary (f₁ / f₂) g := - fun _i _j hij ↦ div_le_div (hf₁ _) (h₁ hij) (hf₂ _) $ h₂ hij + fun _i _j hij ↦ div_le_div (hf₁ _) (h₁ hij) (hf₂ _) <| h₂ hij lemma MonovaryOn.div_right₀ (hg₁ : ∀ i ∈ s, 0 ≤ g₁ i) (hg₂ : ∀ i ∈ s, 0 < g₂ i) (h₁ : MonovaryOn f g₁ s) (h₂ : AntivaryOn f g₂ s) : MonovaryOn f (g₁ / g₂) s := @@ -332,20 +333,20 @@ lemma monovaryOn_iff_forall_smul_nonneg : lemma antivaryOn_iff_forall_smul_nonpos : AntivaryOn f g s ↔ ∀ ⦃i⦄, i ∈ s → ∀ ⦃j⦄, j ∈ s → (f j - f i) • (g j - g i) ≤ 0 := - monovaryOn_toDual_right.symm.trans $ by rw [monovaryOn_iff_forall_smul_nonneg]; rfl + monovaryOn_toDual_right.symm.trans <| by rw [monovaryOn_iff_forall_smul_nonneg]; rfl lemma monovary_iff_forall_smul_nonneg : Monovary f g ↔ ∀ i j, 0 ≤ (f j - f i) • (g j - g i) := - monovaryOn_univ.symm.trans $ monovaryOn_iff_forall_smul_nonneg.trans $ by + monovaryOn_univ.symm.trans <| monovaryOn_iff_forall_smul_nonneg.trans <| by simp only [Set.mem_univ, forall_true_left] lemma antivary_iff_forall_smul_nonpos : Antivary f g ↔ ∀ i j, (f j - f i) • (g j - g i) ≤ 0 := -monovary_toDual_right.symm.trans $ by rw [monovary_iff_forall_smul_nonneg]; rfl +monovary_toDual_right.symm.trans <| by rw [monovary_iff_forall_smul_nonneg]; rfl /-- Two functions monovary iff the rearrangement inequality holds. -/ lemma monovaryOn_iff_smul_rearrangement : MonovaryOn f g s ↔ ∀ ⦃i⦄, i ∈ s → ∀ ⦃j⦄, j ∈ s → f i • g j + f j • g i ≤ f i • g i + f j • g j := - monovaryOn_iff_forall_smul_nonneg.trans $ forall₄_congr fun i _ j _ ↦ by + monovaryOn_iff_forall_smul_nonneg.trans <| forall₄_congr fun i _ j _ ↦ by simp [smul_sub, sub_smul, ← add_sub_right_comm, le_sub_iff_add_le, add_comm (f i • g i), add_comm (f i • g j)] @@ -353,18 +354,18 @@ lemma monovaryOn_iff_smul_rearrangement : lemma antivaryOn_iff_smul_rearrangement : AntivaryOn f g s ↔ ∀ ⦃i⦄, i ∈ s → ∀ ⦃j⦄, j ∈ s → f i • g i + f j • g j ≤ f i • g j + f j • g i := - monovaryOn_toDual_right.symm.trans $ by rw [monovaryOn_iff_smul_rearrangement]; rfl + monovaryOn_toDual_right.symm.trans <| by rw [monovaryOn_iff_smul_rearrangement]; rfl /-- Two functions monovary iff the rearrangement inequality holds. -/ lemma monovary_iff_smul_rearrangement : Monovary f g ↔ ∀ i j, f i • g j + f j • g i ≤ f i • g i + f j • g j := - monovaryOn_univ.symm.trans $ monovaryOn_iff_smul_rearrangement.trans $ by + monovaryOn_univ.symm.trans <| monovaryOn_iff_smul_rearrangement.trans <| by simp only [Set.mem_univ, forall_true_left] /-- Two functions antivary iff the rearrangement inequality holds. -/ lemma antivary_iff_smul_rearrangement : Antivary f g ↔ ∀ i j, f i • g i + f j • g j ≤ f i • g j + f j • g i := - monovary_toDual_right.symm.trans $ by rw [monovary_iff_smul_rearrangement]; rfl + monovary_toDual_right.symm.trans <| by rw [monovary_iff_smul_rearrangement]; rfl alias ⟨MonovaryOn.sub_smul_sub_nonneg, _⟩ := monovaryOn_iff_forall_smul_nonneg alias ⟨AntivaryOn.sub_smul_sub_nonpos, _⟩ := antivaryOn_iff_forall_smul_nonpos diff --git a/Mathlib/Algebra/Order/Nonneg/Ring.lean b/Mathlib/Algebra/Order/Nonneg/Ring.lean index a9d2b5e920057..4f96236e9a9cf 100644 --- a/Mathlib/Algebra/Order/Nonneg/Ring.lean +++ b/Mathlib/Algebra/Order/Nonneg/Ring.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ import Mathlib.Data.Nat.Cast.Order +import Mathlib.Algebra.GroupPower.CovariantClass import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Order.Ring.InjSurj -import Mathlib.Algebra.GroupPower.Order import Mathlib.Order.CompleteLatticeIntervals import Mathlib.Order.LatticeIntervals diff --git a/Mathlib/Algebra/Order/Pi.lean b/Mathlib/Algebra/Order/Pi.lean index d31fd255718cf..d2673efc7bf3d 100644 --- a/Mathlib/Algebra/Order/Pi.lean +++ b/Mathlib/Algebra/Order/Pi.lean @@ -5,7 +5,6 @@ Authors: Simon Hudon, Patrick Massot -/ import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Ring.Pi -import Mathlib.Tactic.Positivity #align_import algebra.order.pi from "leanprover-community/mathlib"@"422e70f7ce183d2900c586a8cda8381e788a0c62" diff --git a/Mathlib/Algebra/Order/Rearrangement.lean b/Mathlib/Algebra/Order/Rearrangement.lean index 1174e8d0c058c..429d4f83aa510 100644 --- a/Mathlib/Algebra/Order/Rearrangement.lean +++ b/Mathlib/Algebra/Order/Rearrangement.lean @@ -5,7 +5,9 @@ Authors: Mantas Bakšys -/ import Mathlib.Algebra.BigOperators.Basic import Mathlib.Algebra.Order.Module.OrderedSMul +import Mathlib.Algebra.Order.Group.Instances import Mathlib.Data.Prod.Lex +import Mathlib.Data.Set.Image import Mathlib.GroupTheory.Perm.Support import Mathlib.Order.Monotone.Monovary import Mathlib.Tactic.Abel @@ -167,10 +169,10 @@ theorem MonovaryOn.sum_comp_perm_smul_eq_sum_smul_iff (hfg : MonovaryOn f g s) rw [σ.sum_comp' s (fun i j ↦ f i • g j) hσ] congr · convert h.comp_right σ - · rw [comp.assoc, inv_def, symm_comp_self, comp.right_id] + · rw [comp.assoc, inv_def, symm_comp_self, comp_id] · rw [σ.eq_preimage_iff_image_eq, Set.image_perm hσ] · convert h.comp_right σ.symm - · rw [comp.assoc, self_comp_symm, comp.right_id] + · rw [comp.assoc, self_comp_symm, comp_id] · rw [σ.symm.eq_preimage_iff_image_eq] exact Set.image_perm hσinv #align monovary_on.sum_comp_perm_smul_eq_sum_smul_iff MonovaryOn.sum_comp_perm_smul_eq_sum_smul_iff diff --git a/Mathlib/Algebra/Order/Ring/Abs.lean b/Mathlib/Algebra/Order/Ring/Abs.lean index 56c757b6b3c26..c5d59c19e19a3 100644 --- a/Mathlib/Algebra/Order/Ring/Abs.lean +++ b/Mathlib/Algebra/Order/Ring/Abs.lean @@ -3,9 +3,9 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro -/ -import Mathlib.Algebra.Order.Ring.Defs -import Mathlib.Algebra.Ring.Divisibility.Basic -import Mathlib.Algebra.Order.Group.Abs +import Mathlib.Algebra.GroupPower.Order +import Mathlib.Data.Int.Order.Basic +import Mathlib.Data.Nat.Cast.Order #align_import algebra.order.ring.abs from "leanprover-community/mathlib"@"10b4e499f43088dd3bb7b5796184ad5216648ab1" @@ -16,21 +16,31 @@ import Mathlib.Algebra.Order.Group.Abs variable {α : Type*} +section LinearOrderedAddCommGroup +variable [LinearOrderedCommGroup α] {a b : α} + +@[to_additive] lemma mabs_zpow (n : ℤ) (a : α) : |a ^ n|ₘ = |a|ₘ ^ |n| := by + obtain n0 | n0 := le_total 0 n + · obtain ⟨n, rfl⟩ := Int.eq_ofNat_of_zero_le n0 + simp only [mabs_pow, zpow_coe_nat, Nat.abs_cast] + · obtain ⟨m, h⟩ := Int.eq_ofNat_of_zero_le (neg_nonneg.2 n0) + rw [← mabs_inv, ← zpow_neg, ← abs_neg, h, zpow_coe_nat, Nat.abs_cast, zpow_coe_nat] + exact mabs_pow m _ +#align abs_zsmul abs_zsmul + +end LinearOrderedAddCommGroup + section LinearOrderedRing -variable [LinearOrderedRing α] {a b c : α} +variable [LinearOrderedRing α] {n : ℕ} {a b c : α} -@[simp] -theorem abs_one : |(1 : α)| = 1 := - abs_of_pos zero_lt_one +@[simp] lemma abs_one : |(1 : α)| = 1 := abs_of_pos zero_lt_one #align abs_one abs_one -@[simp] -theorem abs_two : |(2 : α)| = 2 := - abs_of_pos zero_lt_two +@[simp] lemma abs_two : |(2 : α)| = 2 := abs_of_pos zero_lt_two #align abs_two abs_two -theorem abs_mul (a b : α) : |a * b| = |a| * |b| := by +lemma abs_mul (a b : α) : |a * b| = |a| * |b| := by rw [abs_eq (mul_nonneg (abs_nonneg a) (abs_nonneg b))] rcases le_total a 0 with ha | ha <;> rcases le_total b 0 with hb | hb <;> simp only [abs_of_nonpos, abs_of_nonneg, true_or_iff, or_true_iff, eq_self_iff_true, neg_mul, @@ -38,41 +48,122 @@ theorem abs_mul (a b : α) : |a * b| = |a| * |b| := by #align abs_mul abs_mul /-- `abs` as a `MonoidWithZeroHom`. -/ -def absHom : α →*₀ α := - { toFun := abs - map_zero' := abs_zero - map_one' := abs_one - map_mul' := abs_mul } +def absHom : α →*₀ α where + toFun := abs + map_zero' := abs_zero + map_one' := abs_one + map_mul' := abs_mul #align abs_hom absHom @[simp] -theorem abs_mul_abs_self (a : α) : |a| * |a| = a * a := +lemma abs_pow (a : α) (n : ℕ) : |a ^ n| = |a| ^ n := (absHom.toMonoidHom : α →* α).map_pow _ _ +#align abs_pow abs_pow + +lemma pow_abs (a : α) (n : ℕ) : |a| ^ n = |a ^ n| := (abs_pow a n).symm +#align pow_abs pow_abs + +lemma abs_neg_one_pow (n : ℕ) : |(-1 : α) ^ n| = 1 := by rw [← pow_abs, abs_neg, abs_one, one_pow] +#align abs_neg_one_pow abs_neg_one_pow + +lemma abs_pow_eq_one (a : α) (h : n ≠ 0) : |a ^ n| = 1 ↔ |a| = 1 := by + convert pow_left_inj (abs_nonneg a) zero_le_one h + exacts [(pow_abs _ _).symm, (one_pow _).symm] +#align abs_pow_eq_one abs_pow_eq_one + +@[simp] lemma abs_mul_abs_self (a : α) : |a| * |a| = a * a := abs_by_cases (fun x => x * x = a * a) rfl (neg_mul_neg a a) #align abs_mul_abs_self abs_mul_abs_self @[simp] -theorem abs_mul_self (a : α) : |a * a| = a * a := by rw [abs_mul, abs_mul_abs_self] +lemma abs_mul_self (a : α) : |a * a| = a * a := by rw [abs_mul, abs_mul_abs_self] #align abs_mul_self abs_mul_self -theorem abs_eq_iff_mul_self_eq : |a| = |b| ↔ a * a = b * b := by +lemma abs_eq_iff_mul_self_eq : |a| = |b| ↔ a * a = b * b := by rw [← abs_mul_abs_self, ← abs_mul_abs_self b] exact (mul_self_inj (abs_nonneg a) (abs_nonneg b)).symm #align abs_eq_iff_mul_self_eq abs_eq_iff_mul_self_eq -theorem abs_lt_iff_mul_self_lt : |a| < |b| ↔ a * a < b * b := by +lemma abs_lt_iff_mul_self_lt : |a| < |b| ↔ a * a < b * b := by rw [← abs_mul_abs_self, ← abs_mul_abs_self b] exact mul_self_lt_mul_self_iff (abs_nonneg a) (abs_nonneg b) #align abs_lt_iff_mul_self_lt abs_lt_iff_mul_self_lt -theorem abs_le_iff_mul_self_le : |a| ≤ |b| ↔ a * a ≤ b * b := by +lemma abs_le_iff_mul_self_le : |a| ≤ |b| ↔ a * a ≤ b * b := by rw [← abs_mul_abs_self, ← abs_mul_abs_self b] exact mul_self_le_mul_self_iff (abs_nonneg a) (abs_nonneg b) #align abs_le_iff_mul_self_le abs_le_iff_mul_self_le -theorem abs_le_one_iff_mul_self_le_one : |a| ≤ 1 ↔ a * a ≤ 1 := by +lemma abs_le_one_iff_mul_self_le_one : |a| ≤ 1 ↔ a * a ≤ 1 := by simpa only [abs_one, one_mul] using @abs_le_iff_mul_self_le α _ a 1 #align abs_le_one_iff_mul_self_le_one abs_le_one_iff_mul_self_le_one +-- Porting note: added `simp` to replace `pow_bit0_abs` +@[simp] lemma sq_abs (a : α) : |a| ^ 2 = a ^ 2 := by simpa only [sq] using abs_mul_abs_self a +#align sq_abs sq_abs + +lemma abs_sq (x : α) : |x ^ 2| = x ^ 2 := by simpa only [sq] using abs_mul_self x +#align abs_sq abs_sq + +lemma sq_lt_sq : a ^ 2 < b ^ 2 ↔ |a| < |b| := by + simpa only [sq_abs] using + (pow_left_strictMonoOn two_ne_zero).lt_iff_lt (abs_nonneg a) (abs_nonneg b) +#align sq_lt_sq sq_lt_sq + +lemma sq_lt_sq' (h1 : -b < a) (h2 : a < b) : a ^ 2 < b ^ 2 := + sq_lt_sq.2 (lt_of_lt_of_le (abs_lt.2 ⟨h1, h2⟩) (le_abs_self _)) +#align sq_lt_sq' sq_lt_sq' + +lemma sq_le_sq : a ^ 2 ≤ b ^ 2 ↔ |a| ≤ |b| := by + simpa only [sq_abs] using + (pow_left_strictMonoOn two_ne_zero).le_iff_le (abs_nonneg a) (abs_nonneg b) +#align sq_le_sq sq_le_sq + +lemma sq_le_sq' (h1 : -b ≤ a) (h2 : a ≤ b) : a ^ 2 ≤ b ^ 2 := + sq_le_sq.2 (le_trans (abs_le.mpr ⟨h1, h2⟩) (le_abs_self _)) +#align sq_le_sq' sq_le_sq' + +lemma abs_lt_of_sq_lt_sq (h : a ^ 2 < b ^ 2) (hb : 0 ≤ b) : |a| < b := by + rwa [← abs_of_nonneg hb, ← sq_lt_sq] +#align abs_lt_of_sq_lt_sq abs_lt_of_sq_lt_sq + +lemma abs_lt_of_sq_lt_sq' (h : a ^ 2 < b ^ 2) (hb : 0 ≤ b) : -b < a ∧ a < b := + abs_lt.1 $ abs_lt_of_sq_lt_sq h hb +#align abs_lt_of_sq_lt_sq' abs_lt_of_sq_lt_sq' + +lemma abs_le_of_sq_le_sq (h : a ^ 2 ≤ b ^ 2) (hb : 0 ≤ b) : |a| ≤ b := by + rwa [← abs_of_nonneg hb, ← sq_le_sq] +#align abs_le_of_sq_le_sq abs_le_of_sq_le_sq + +lemma abs_le_of_sq_le_sq' (h : a ^ 2 ≤ b ^ 2) (hb : 0 ≤ b) : -b ≤ a ∧ a ≤ b := + abs_le.1 $ abs_le_of_sq_le_sq h hb +#align abs_le_of_sq_le_sq' abs_le_of_sq_le_sq' + +lemma sq_eq_sq_iff_abs_eq_abs (a b : α) : a ^ 2 = b ^ 2 ↔ |a| = |b| := by + simp only [le_antisymm_iff, sq_le_sq] +#align sq_eq_sq_iff_abs_eq_abs sq_eq_sq_iff_abs_eq_abs + +@[simp] lemma sq_le_one_iff_abs_le_one (a : α) : a ^ 2 ≤ 1 ↔ |a| ≤ 1 := by + simpa only [one_pow, abs_one] using @sq_le_sq _ _ a 1 +#align sq_le_one_iff_abs_le_one sq_le_one_iff_abs_le_one + +@[simp] lemma sq_lt_one_iff_abs_lt_one (a : α) : a ^ 2 < 1 ↔ |a| < 1 := by + simpa only [one_pow, abs_one] using @sq_lt_sq _ _ a 1 +#align sq_lt_one_iff_abs_lt_one sq_lt_one_iff_abs_lt_one + +@[simp] lemma one_le_sq_iff_one_le_abs (a : α) : 1 ≤ a ^ 2 ↔ 1 ≤ |a| := by + simpa only [one_pow, abs_one] using @sq_le_sq _ _ 1 a +#align one_le_sq_iff_one_le_abs one_le_sq_iff_one_le_abs + +@[simp] lemma one_lt_sq_iff_one_lt_abs (a : α) : 1 < a ^ 2 ↔ 1 < |a| := by + simpa only [one_pow, abs_one] using @sq_lt_sq _ _ 1 a +#align one_lt_sq_iff_one_lt_abs one_lt_sq_iff_one_lt_abs + +lemma exists_abs_lt {α : Type*} [LinearOrderedRing α] (a : α) : ∃ b > 0, |a| < b := by + refine ⟨|a| + 1, lt_of_lt_of_le zero_lt_one <| by simp, ?_⟩ + cases' le_or_lt 0 a with ht ht + · simp only [abs_of_nonneg ht, lt_add_iff_pos_right, zero_lt_one] + · simp only [abs_of_neg ht, lt_add_iff_pos_right, zero_lt_one] + end LinearOrderedRing section LinearOrderedCommRing diff --git a/Mathlib/Algebra/Order/Ring/Defs.lean b/Mathlib/Algebra/Order/Ring/Defs.lean index 3835425993a34..f3ac783c1d4ed 100644 --- a/Mathlib/Algebra/Order/Ring/Defs.lean +++ b/Mathlib/Algebra/Order/Ring/Defs.lean @@ -340,7 +340,7 @@ theorem mul_le_mul_of_nonpos_left (h : b ≤ a) (hc : c ≤ 0) : c * a ≤ c * b refine le_of_add_le_add_right (a := d * b + d * a) ?_ calc _ = d * b := by rw [add_left_comm, ← add_mul, ← hcd, zero_mul, add_zero] - _ ≤ d * a := mul_le_mul_of_nonneg_left h $ hcd.trans_le $ add_le_of_nonpos_left hc + _ ≤ d * a := mul_le_mul_of_nonneg_left h <| hcd.trans_le <| add_le_of_nonpos_left hc _ = _ := by rw [← add_assoc, ← add_mul, ← hcd, zero_mul, zero_add] #align mul_le_mul_of_nonpos_left mul_le_mul_of_nonpos_left @@ -349,7 +349,7 @@ theorem mul_le_mul_of_nonpos_right (h : b ≤ a) (hc : c ≤ 0) : a * c ≤ b * refine le_of_add_le_add_right (a := b * d + a * d) ?_ calc _ = b * d := by rw [add_left_comm, ← mul_add, ← hcd, mul_zero, add_zero] - _ ≤ a * d := mul_le_mul_of_nonneg_right h $ hcd.trans_le $ add_le_of_nonpos_left hc + _ ≤ a * d := mul_le_mul_of_nonneg_right h <| hcd.trans_le <| add_le_of_nonpos_left hc _ = _ := by rw [← add_assoc, ← mul_add, ← hcd, mul_zero, zero_add] #align mul_le_mul_of_nonpos_right mul_le_mul_of_nonpos_right @@ -651,7 +651,7 @@ theorem mul_lt_mul_of_neg_left (h : b < a) (hc : c < 0) : c * a < c * b := by refine (add_lt_add_iff_right (d * b + d * a)).1 ?_ calc _ = d * b := by rw [add_left_comm, ← add_mul, ← hcd, zero_mul, add_zero] - _ < d * a := mul_lt_mul_of_pos_left h $ hcd.trans_lt $ add_lt_of_neg_left _ hc + _ < d * a := mul_lt_mul_of_pos_left h <| hcd.trans_lt <| add_lt_of_neg_left _ hc _ = _ := by rw [← add_assoc, ← add_mul, ← hcd, zero_mul, zero_add] #align mul_lt_mul_of_neg_left mul_lt_mul_of_neg_left @@ -660,7 +660,7 @@ theorem mul_lt_mul_of_neg_right (h : b < a) (hc : c < 0) : a * c < b * c := by refine (add_lt_add_iff_right (b * d + a * d)).1 ?_ calc _ = b * d := by rw [add_left_comm, ← mul_add, ← hcd, mul_zero, add_zero] - _ < a * d := mul_lt_mul_of_pos_right h $ hcd.trans_lt $ add_lt_of_neg_left _ hc + _ < a * d := mul_lt_mul_of_pos_right h <| hcd.trans_lt <| add_lt_of_neg_left _ hc _ = _ := by rw [← add_assoc, ← mul_add, ← hcd, mul_zero, zero_add] #align mul_lt_mul_of_neg_right mul_lt_mul_of_neg_right @@ -1189,7 +1189,7 @@ lemma sq_nonneg (a : α) : 0 ≤ a ^ 2 := by · exact pow_nonneg ha _ obtain ⟨b, hab⟩ := exists_add_of_le ha calc - 0 ≤ b ^ 2 := pow_nonneg (not_lt.1 fun hb ↦ hab.not_gt $ add_neg_of_nonpos_of_neg ha hb) _ + 0 ≤ b ^ 2 := pow_nonneg (not_lt.1 fun hb ↦ hab.not_gt <| add_neg_of_nonpos_of_neg ha hb) _ _ = a ^ 2 := add_left_injective (a * b) ?_ calc b ^ 2 + a * b = (a + b) * b := by rw [add_comm, sq, add_mul] @@ -1288,12 +1288,13 @@ lemma mul_nonpos_iff_neg_imp_nonneg : a * b ≤ 0 ↔ (a < 0 → 0 ≤ b) ∧ (0 lemma neg_one_lt_zero : -1 < (0 : α) := neg_lt_zero.2 zero_lt_one #align neg_one_lt_zero neg_one_lt_zero -lemma sub_one_lt (a : α) : a - 1 < a := sub_lt_iff_lt_add.2 $ lt_add_one a +lemma sub_one_lt (a : α) : a - 1 < a := sub_lt_iff_lt_add.2 <| lt_add_one a #align sub_one_lt sub_one_lt lemma mul_self_le_mul_self_of_le_of_neg_le (h₁ : a ≤ b) (h₂ : -a ≤ b) : a * a ≤ b * b := (le_total 0 a).elim (mul_self_le_mul_self · h₁) fun h ↦ - (neg_mul_neg a a).symm.trans_le $ mul_le_mul h₂ h₂ (neg_nonneg.2 h) $ (neg_nonneg.2 h).trans h₂ + (neg_mul_neg a a).symm.trans_le <| + mul_le_mul h₂ h₂ (neg_nonneg.2 h) <| (neg_nonneg.2 h).trans h₂ #align mul_self_le_mul_self_of_le_of_neg_le mul_self_le_mul_self_of_le_of_neg_le end LinearOrderedRing diff --git a/Mathlib/Algebra/Order/Ring/Pow.lean b/Mathlib/Algebra/Order/Ring/Pow.lean new file mode 100644 index 0000000000000..e1f2685c9d1ed --- /dev/null +++ b/Mathlib/Algebra/Order/Ring/Pow.lean @@ -0,0 +1,55 @@ +/- +Copyright (c) 2019 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Data.Nat.Cast.Commute +import Mathlib.Data.Nat.Cast.Order + +/-! # Bernoulli's inequality -/ + +variable {R : Type*} + +section OrderedSemiring +variable [OrderedSemiring R] {a : R} + +/-- **Bernoulli's inequality**. This version works for semirings but requires +additional hypotheses `0 ≤ a * a` and `0 ≤ (1 + a) * (1 + a)`. -/ +lemma one_add_mul_le_pow' (Hsq : 0 ≤ a * a) (Hsq' : 0 ≤ (1 + a) * (1 + a)) (H : 0 ≤ 2 + a) : + ∀ n : ℕ, 1 + n * a ≤ (1 + a) ^ n + | 0 => by simp + | 1 => by simp + | n + 2 => + have : 0 ≤ n * (a * a * (2 + a)) + a * a := + add_nonneg (mul_nonneg n.cast_nonneg (mul_nonneg Hsq H)) Hsq + calc + _ ≤ 1 + ↑(n + 2) * a + (n * (a * a * (2 + a)) + a * a) := le_add_of_nonneg_right this + _ = (1 + a) * (1 + a) * (1 + n * a) := by + simp only [Nat.cast_add, add_mul, mul_add, one_mul, mul_one, ← one_add_one_eq_two, + Nat.cast_one, add_assoc, add_right_inj] + simp only [← add_assoc, add_comm _ (↑n * a)] + simp only [add_assoc, (n.cast_commute (_ : R)).left_comm] + simp only [add_comm, add_left_comm] + _ ≤ (1 + a) * (1 + a) * (1 + a) ^ n := + mul_le_mul_of_nonneg_left (one_add_mul_le_pow' Hsq Hsq' H _) Hsq' + _ = (1 + a) ^ (n + 2) := by simp only [pow_succ, mul_assoc] +#align one_add_mul_le_pow' one_add_mul_le_pow' + +end OrderedSemiring + +section LinearOrderedRing +variable [LinearOrderedRing R] {a : R} {n : ℕ} + +/-- **Bernoulli's inequality** for `n : ℕ`, `-2 ≤ a`. -/ +lemma one_add_mul_le_pow (H : -2 ≤ a) (n : ℕ) : 1 + n * a ≤ (1 + a) ^ n := + one_add_mul_le_pow' (mul_self_nonneg _) (mul_self_nonneg _) (neg_le_iff_add_nonneg'.1 H) _ +#align one_add_mul_le_pow one_add_mul_le_pow + +/-- **Bernoulli's inequality** reformulated to estimate `a^n`. -/ +lemma one_add_mul_sub_le_pow (H : -1 ≤ a) (n : ℕ) : 1 + n * (a - 1) ≤ a ^ n := by + have : -2 ≤ a - 1 := by + rwa [← one_add_one_eq_two, neg_add, ← sub_eq_add_neg, sub_le_sub_iff_right] + simpa only [add_sub_cancel'_right] using one_add_mul_le_pow this n +#align one_add_mul_sub_le_pow one_add_mul_sub_le_pow + +end LinearOrderedRing diff --git a/Mathlib/Algebra/Order/Ring/WithTop.lean b/Mathlib/Algebra/Order/Ring/WithTop.lean index 0c40b6bedf032..b0a063f02a375 100644 --- a/Mathlib/Algebra/Order/Ring/WithTop.lean +++ b/Mathlib/Algebra/Order/Ring/WithTop.lean @@ -240,7 +240,6 @@ theorem bot_mul {a : WithBot α} (h : a ≠ 0) : ⊥ * a = ⊥ := WithTop.top_mul h #align with_bot.bot_mul WithBot.bot_mul -@[simp] theorem bot_mul_bot : (⊥ * ⊥ : WithBot α) = ⊥ := WithTop.top_mul_top #align with_bot.bot_mul_bot WithBot.bot_mul_bot diff --git a/Mathlib/Algebra/Order/Sub/Prod.lean b/Mathlib/Algebra/Order/Sub/Prod.lean index 2e664b1f0aae3..6b07253dbd573 100644 --- a/Mathlib/Algebra/Order/Sub/Prod.lean +++ b/Mathlib/Algebra/Order/Sub/Prod.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Mathlib.Algebra.Group.Prod -import Mathlib.Algebra.Order.Sub.Basic +import Mathlib.Algebra.Order.Sub.Defs /-! # Products of `OrderedSub` types. diff --git a/Mathlib/Algebra/Order/Support.lean b/Mathlib/Algebra/Order/Support.lean index 00240d105fb77..39f71f19518bc 100644 --- a/Mathlib/Algebra/Order/Support.lean +++ b/Mathlib/Algebra/Order/Support.lean @@ -234,6 +234,8 @@ end CanonicallyOrderedCommMonoid section LinearOrderedAddCommGroup variable [LinearOrderedAddCommGroup M] +open scoped symmDiff + lemma abs_indicator_symmDiff (s t : Set α) (f : α → M) (x : α) : |indicator (s ∆ t) f x| = |indicator s f x - indicator t f x| := apply_indicator_symmDiff abs_neg s t f x diff --git a/Mathlib/Algebra/Order/ToIntervalMod.lean b/Mathlib/Algebra/Order/ToIntervalMod.lean index d5a5aed5b96c2..6702415949361 100644 --- a/Mathlib/Algebra/Order/ToIntervalMod.lean +++ b/Mathlib/Algebra/Order/ToIntervalMod.lean @@ -690,23 +690,23 @@ theorem Ico_eq_locus_Ioc_eq_iUnion_Ioo : Classical.not_not] #align Ico_eq_locus_Ioc_eq_Union_Ioo Ico_eq_locus_Ioc_eq_iUnion_Ioo -theorem toIocDiv_wcovby_toIcoDiv (a b : α) : toIocDiv hp a b ⩿ toIcoDiv hp a b := by +theorem toIocDiv_wcovBy_toIcoDiv (a b : α) : toIocDiv hp a b ⩿ toIcoDiv hp a b := by suffices toIocDiv hp a b = toIcoDiv hp a b ∨ toIocDiv hp a b + 1 = toIcoDiv hp a b by - rwa [wcovby_iff_eq_or_covby, ← Order.succ_eq_iff_covby] + rwa [wcovBy_iff_eq_or_covBy, ← Order.succ_eq_iff_covBy] rw [eq_comm, ← not_modEq_iff_toIcoDiv_eq_toIocDiv, eq_comm, ← modEq_iff_toIcoDiv_eq_toIocDiv_add_one] exact em' _ -#align to_Ioc_div_wcovby_to_Ico_div toIocDiv_wcovby_toIcoDiv +#align to_Ioc_div_wcovby_to_Ico_div toIocDiv_wcovBy_toIcoDiv theorem toIcoMod_le_toIocMod (a b : α) : toIcoMod hp a b ≤ toIocMod hp a b := by rw [toIcoMod, toIocMod, sub_le_sub_iff_left] - exact zsmul_mono_left hp.le (toIocDiv_wcovby_toIcoDiv _ _ _).le + exact zsmul_mono_left hp.le (toIocDiv_wcovBy_toIcoDiv _ _ _).le #align to_Ico_mod_le_to_Ioc_mod toIcoMod_le_toIocMod theorem toIocMod_le_toIcoMod_add (a b : α) : toIocMod hp a b ≤ toIcoMod hp a b + p := by rw [toIcoMod, toIocMod, sub_add, sub_le_sub_iff_left, sub_le_iff_le_add, ← add_one_zsmul, (zsmul_strictMono_left hp).le_iff_le] - apply (toIocDiv_wcovby_toIcoDiv _ _ _).le_succ + apply (toIocDiv_wcovBy_toIcoDiv _ _ _).le_succ #align to_Ioc_mod_le_to_Ico_mod_add toIocMod_le_toIcoMod_add end IcoIoc diff --git a/Mathlib/Algebra/Order/UpperLower.lean b/Mathlib/Algebra/Order/UpperLower.lean index 1c1aa15569129..8f476379bf431 100644 --- a/Mathlib/Algebra/Order/UpperLower.lean +++ b/Mathlib/Algebra/Order/UpperLower.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Order.Group.Defs +import Mathlib.Algebra.Order.Group.Instances import Mathlib.Data.Set.Pointwise.SMul import Mathlib.Order.UpperLower.Basic diff --git a/Mathlib/Algebra/Order/WithZero.lean b/Mathlib/Algebra/Order/WithZero.lean index 74102a839763e..cdd14805e328d 100644 --- a/Mathlib/Algebra/Order/WithZero.lean +++ b/Mathlib/Algebra/Order/WithZero.lean @@ -7,9 +7,9 @@ import Mathlib.Algebra.GroupWithZero.InjSurj import Mathlib.Algebra.GroupWithZero.Units.Equiv import Mathlib.Algebra.Order.Group.Units import Mathlib.Algebra.Order.Monoid.Basic -import Mathlib.Algebra.Order.Monoid.WithZero.Defs -import Mathlib.Algebra.Order.Group.Instances +import Mathlib.Algebra.Order.Monoid.OrderDual import Mathlib.Algebra.Order.Monoid.TypeTags +import Mathlib.Algebra.Order.Monoid.WithZero.Defs #align_import algebra.order.with_zero from "leanprover-community/mathlib"@"655994e298904d7e5bbd1e18c95defd7b543eb94" diff --git a/Mathlib/Algebra/Parity.lean b/Mathlib/Algebra/Parity.lean index b12908269c6f4..09b20f37dee62 100644 --- a/Mathlib/Algebra/Parity.lean +++ b/Mathlib/Algebra/Parity.lean @@ -3,8 +3,10 @@ Copyright (c) 2022 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.Algebra.GroupPower.Lemmas -import Mathlib.Data.Nat.Cast.Basic +import Mathlib.Algebra.Group.Opposite +import Mathlib.Algebra.Order.Ring.Abs +import Mathlib.Data.Nat.Cast.Commute +import Mathlib.Data.Set.Basic #align_import algebra.parity from "leanprover-community/mathlib"@"8631e2d5ea77f6c13054d9151d82b83069680cb1" @@ -225,7 +227,7 @@ theorem Even.neg_one_zpow (h : Even n) : (-1 : α) ^ n = 1 := by rw [h.neg_zpow, end DivisionMonoid -theorem even_abs [SubtractionMonoid α] [LinearOrder α] {a : α} : Even |a| ↔ Even a := by +theorem even_abs [AddGroup α] [LinearOrder α] {a : α} : Even |a| ↔ Even a := by cases abs_choice a · have h : abs a = a := by assumption simp only [h, even_neg] diff --git a/Mathlib/Algebra/Periodic.lean b/Mathlib/Algebra/Periodic.lean index 1e09393eba982..9acd7ed2534da 100644 --- a/Mathlib/Algebra/Periodic.lean +++ b/Mathlib/Algebra/Periodic.lean @@ -3,11 +3,8 @@ Copyright (c) 2021 Benjamin Davidson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Benjamin Davidson -/ -import Mathlib.Algebra.BigOperators.Basic import Mathlib.Algebra.Field.Opposite -import Mathlib.Algebra.Module.Basic import Mathlib.Algebra.Order.Archimedean -import Mathlib.Data.Int.Parity import Mathlib.GroupTheory.Coset import Mathlib.GroupTheory.Subgroup.ZPowers import Mathlib.GroupTheory.Submonoid.Membership diff --git a/Mathlib/Algebra/Pointwise/Stabilizer.lean b/Mathlib/Algebra/Pointwise/Stabilizer.lean index e28e090d6d7bb..62eb662c083d1 100644 --- a/Mathlib/Algebra/Pointwise/Stabilizer.lean +++ b/Mathlib/Algebra/Pointwise/Stabilizer.lean @@ -24,7 +24,7 @@ section Set @[to_additive (attr := simp)] lemma stabilizer_empty : stabilizer G (∅ : Set α) = ⊤ := - Subgroup.coe_eq_univ.1 $ eq_univ_of_forall fun _a ↦ smul_set_empty + Subgroup.coe_eq_univ.1 <| eq_univ_of_forall fun _a ↦ smul_set_empty @[to_additive (attr := simp)] lemma stabilizer_singleton (b : α) : stabilizer G ({b} : Set α) = stabilizer G b := by ext; simp @@ -34,7 +34,7 @@ lemma mem_stabilizer_set {s : Set α} : a ∈ stabilizer G s ↔ ∀ b, a • b refine mem_stabilizer_iff.trans ⟨fun h b ↦ ?_, fun h ↦ ?_⟩ · rw [← (smul_mem_smul_set_iff : a • b ∈ _ ↔ _), h] simp_rw [Set.ext_iff, mem_smul_set_iff_inv_smul_mem] - exact ((MulAction.toPerm a).forall_congr' $ by simp [Iff.comm]).1 h + exact ((MulAction.toPerm a).forall_congr' <| by simp [Iff.comm]).1 h @[to_additive] lemma map_stabilizer_le (f : G →* H) (s : Set G) : @@ -93,7 +93,7 @@ lemma stabilizer_coe_finset (s : Finset α) : stabilizer G (s : Set α) = stabil @[to_additive (attr := simp)] lemma stabilizer_finset_empty : stabilizer G (∅ : Finset α) = ⊤ := - Subgroup.coe_eq_univ.1 $ eq_univ_of_forall Finset.smul_finset_empty + Subgroup.coe_eq_univ.1 <| eq_univ_of_forall Finset.smul_finset_empty @[to_additive (attr := simp)] lemma stabilizer_finset_singleton (b : α) : stabilizer G ({b} : Finset α) = stabilizer G b := by @@ -163,7 +163,7 @@ lemma stabilizer_image_coe_quotient : stabilizer Q (q '' s) = ⊥ := by induction' a using QuotientGroup.induction_on' with a simp only [mem_stabilizer_iff, Subgroup.mem_bot, QuotientGroup.eq_one_iff] have : q a • q '' s = q '' (a • s) := - (image_smul_distrib (QuotientGroup.mk' $ stabilizer G s) _ _).symm + (image_smul_distrib (QuotientGroup.mk' <| stabilizer G s) _ _).symm rw [this] refine ⟨fun h ↦ ?_, fun h ↦ by rw [h]⟩ rwa [QuotientGroup.image_coe_inj, mul_smul_comm, stabilizer_mul_self] at h diff --git a/Mathlib/Algebra/Polynomial/GroupRingAction.lean b/Mathlib/Algebra/Polynomial/GroupRingAction.lean index 30489a2bfb521..0a06188134d5b 100644 --- a/Mathlib/Algebra/Polynomial/GroupRingAction.lean +++ b/Mathlib/Algebra/Polynomial/GroupRingAction.lean @@ -34,7 +34,7 @@ theorem smul_eq_map [MulSemiringAction M R] (m : M) : suffices DistribMulAction.toAddMonoidHom R[X] m = (mapRingHom (MulSemiringAction.toRingHom M R m)).toAddMonoidHom by ext1 r - exact FunLike.congr_fun this r + exact DFunLike.congr_fun this r ext n r : 2 change m • monomial n r = map (MulSemiringAction.toRingHom M R m) (monomial n r) rw [Polynomial.map_monomial, Polynomial.smul_monomial, MulSemiringAction.toRingHom_apply] diff --git a/Mathlib/Algebra/QuadraticDiscriminant.lean b/Mathlib/Algebra/QuadraticDiscriminant.lean index 536356a38689c..d702a97359bd5 100644 --- a/Mathlib/Algebra/QuadraticDiscriminant.lean +++ b/Mathlib/Algebra/QuadraticDiscriminant.lean @@ -3,10 +3,10 @@ Copyright (c) 2019 Zhouhang Zhou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Zhouhang Zhou -/ -import Mathlib.Algebra.CharP.Invertible import Mathlib.Order.Filter.AtTopBot import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.LinearCombination +import Mathlib.Tactic.Linarith.Frontend #align_import algebra.quadratic_discriminant from "leanprover-community/mathlib"@"e085d1df33274f4b32f611f483aae678ba0b42df" diff --git a/Mathlib/Algebra/Quandle.lean b/Mathlib/Algebra/Quandle.lean index 72522e50dd61b..4514901aa455f 100644 --- a/Mathlib/Algebra/Quandle.lean +++ b/Mathlib/Algebra/Quandle.lean @@ -358,7 +358,7 @@ namespace ShelfHom variable {S₁ : Type*} {S₂ : Type*} {S₃ : Type*} [Shelf S₁] [Shelf S₂] [Shelf S₃] -instance : FunLike (S₁ →◃ S₂) S₁ fun _ => S₂ where +instance : FunLike (S₁ →◃ S₂) S₁ S₂ where coe := toFun coe_injective' | ⟨_, _⟩, ⟨_, _⟩, rfl => rfl diff --git a/Mathlib/Algebra/Regular/Basic.lean b/Mathlib/Algebra/Regular/Basic.lean index 1d72eeaac3c6e..82a96e3e01c77 100644 --- a/Mathlib/Algebra/Regular/Basic.lean +++ b/Mathlib/Algebra/Regular/Basic.lean @@ -6,7 +6,6 @@ Authors: Damiano Testa import Mathlib.Algebra.Group.Commute.Defs import Mathlib.Algebra.Group.Units import Mathlib.Algebra.Order.Monoid.Lemmas -import Mathlib.Algebra.GroupWithZero.Basic import Mathlib.Tactic.NthRewrite #align_import algebra.regular.basic from "leanprover-community/mathlib"@"5cd3c25312f210fec96ba1edb2aebfb2ccf2010f" diff --git a/Mathlib/Algebra/Ring/BooleanRing.lean b/Mathlib/Algebra/Ring/BooleanRing.lean index bf44a5c95fc12..ae75c55d39791 100644 --- a/Mathlib/Algebra/Ring/BooleanRing.lean +++ b/Mathlib/Algebra/Ring/BooleanRing.lean @@ -40,6 +40,7 @@ purposes and because it is easier than dealing with boolean ring, boolean algebra -/ +open scoped symmDiff variable {α β γ : Type*} diff --git a/Mathlib/Algebra/Ring/CentroidHom.lean b/Mathlib/Algebra/Ring/CentroidHom.lean index 5fe0f91ff3ab4..34ef3daa713b2 100644 --- a/Mathlib/Algebra/Ring/CentroidHom.lean +++ b/Mathlib/Algebra/Ring/CentroidHom.lean @@ -23,7 +23,7 @@ $$ In mathlib we call elements of the centroid "centroid homomorphisms" (`CentroidHom`) in keeping with `AddMonoidHom` etc. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -81,7 +81,6 @@ instance [NonUnitalNonAssocSemiring α] [CentroidHomClass F α] : CoeTC F (Centr /-! ### Centroid homomorphisms -/ - namespace CentroidHom section NonUnitalNonAssocSemiring @@ -101,9 +100,9 @@ instance : CentroidHomClass (CentroidHom α) α where map_mul_right f := f.map_mul_right' -/-- Helper instance for when there's too many metavariables to apply `FunLike.CoeFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.CoeFun` directly. -/ -/- Porting note: Lean gave me `unknown constant 'FunLike.CoeFun'` and says `CoeFun` is a type +/- Porting note: Lean gave me `unknown constant 'DFunLike.CoeFun'` and says `CoeFun` is a type mismatch, so I used `library_search`. -/ instance : CoeFun (CentroidHom α) fun _ ↦ α → α := inferInstanceAs (CoeFun (CentroidHom α) fun _ ↦ α → α) @@ -115,7 +114,7 @@ theorem toFun_eq_coe {f : CentroidHom α} : f.toFun = f := rfl @[ext] theorem ext {f g : CentroidHom α} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align centroid_hom.ext CentroidHom.ext @[simp, norm_cast] @@ -130,7 +129,7 @@ theorem toAddMonoidHom_eq_coe (f : CentroidHom α) : f.toAddMonoidHom = f := theorem coe_toAddMonoidHom_injective : Injective ((↑) : CentroidHom α → α →+ α) := fun _f _g h => ext fun a ↦ - haveI := FunLike.congr_fun h a + haveI := DFunLike.congr_fun h a this #align centroid_hom.coe_to_add_monoid_hom_injective CentroidHom.coe_toAddMonoidHom_injective @@ -158,7 +157,7 @@ theorem coe_copy (f : CentroidHom α) (f' : α → α) (h : f' = f) : ⇑(f.copy #align centroid_hom.coe_copy CentroidHom.coe_copy theorem copy_eq (f : CentroidHom α) (f' : α → α) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align centroid_hom.copy_eq CentroidHom.copy_eq variable (α) @@ -231,7 +230,7 @@ theorem id_comp (f : CentroidHom α) : (CentroidHom.id α).comp f = f := @[simp] theorem cancel_right {g₁ g₂ f : CentroidHom α} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h ↦ ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun a ↦ congrFun (congrArg comp a) f⟩ + ⟨fun h ↦ ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun a ↦ congrFun (congrArg comp a) f⟩ #align centroid_hom.cancel_right CentroidHom.cancel_right @[simp] @@ -514,18 +513,19 @@ def centerToCentroid : NonUnitalSubsemiring.center α →ₙ+* CentroidHom α wh ext a exact (((Set.mem_center_iff _).mp z₁.prop).left_assoc z₂ a).symm -lemma centerToCentroid_apply (z : { x // x ∈ NonUnitalSubsemiring.center α }) (a : α) : +lemma centerToCentroid_apply (z : NonUnitalSubsemiring.center α) (a : α) : (centerToCentroid z) a = z * a := rfl -lemma center_iff_op_centroid (a : α) : - a ∈ NonUnitalSubsemiring.center α ↔ L a = R a ∧ (L a) ∈ Set.range CentroidHom.toEnd := by +lemma _root_.NonUnitalNonAssocSemiring.mem_center_iff (a : α) : + a ∈ NonUnitalSubsemiring.center α ↔ R a = L a ∧ (L a) ∈ RingHom.rangeS (toEndRingHom α) := by constructor - · exact fun ha ↦ ⟨AddMonoidHom.ext <| IsMulCentral.comm ha, ⟨centerToCentroid ⟨a, ha⟩, rfl⟩⟩ + · exact fun ha ↦ ⟨AddMonoidHom.ext <| fun _ => (IsMulCentral.comm ha _).symm, + ⟨centerToCentroid ⟨a, ha⟩, rfl⟩⟩ · rintro ⟨hc, ⟨T, hT⟩⟩ have e1 (d : α) : T d = a * d := congr($hT d) - have e2 (d : α) : T d = d * a := congr($(hT.trans hc) d) + have e2 (d : α) : T d = d * a := congr($(hT.trans hc.symm) d) constructor - case comm => exact (congr($hc ·)) + case comm => exact (congr($hc.symm ·)) case left_assoc => simpa [e1] using (map_mul_right T · ·) case mid_assoc => exact fun b c ↦ by simpa [e1 c, e2 b] using (map_mul_right T b c).symm.trans <| map_mul_left T b c @@ -533,12 +533,29 @@ lemma center_iff_op_centroid (a : α) : end NonUnitalNonAssocSemiring +section NonUnitalNonAssocCommSemiring + +variable [NonUnitalNonAssocCommSemiring α] + +/- +Left and right multiplication coincide as α is commutative +-/ +local notation "L" => AddMonoid.End.mulLeft + +lemma _root_.NonUnitalNonAssocCommSemiring.mem_center_iff (a : α) : + a ∈ NonUnitalSubsemiring.center α ↔ ∀ b : α, Commute (L b) (L a) := by + rw [NonUnitalNonAssocSemiring.mem_center_iff, CentroidHom.centroid_eq_centralizer_mulLeftRight, + Subsemiring.mem_centralizer_iff, AddMonoid.End.mulRight_eq_mulLeft, Set.union_self] + aesop + +end NonUnitalNonAssocCommSemiring + section NonAssocSemiring variable [NonAssocSemiring α] /-- The canonical isomorphism from the center of a (non-associative) semiring onto its centroid. -/ -def centerIsoCentroid : NonUnitalSubsemiring.center α ≃+* CentroidHom α := +def centerIsoCentroid : Subsemiring.center α ≃+* CentroidHom α := { centerToCentroid with invFun := fun T ↦ ⟨T 1, by refine ⟨?_, ?_, ?_, ?_⟩; all_goals simp [← map_mul_left, ← map_mul_right]⟩ diff --git a/Mathlib/Algebra/Ring/Defs.lean b/Mathlib/Algebra/Ring/Defs.lean index 2661b1dc5bdfa..c691b238ae363 100644 --- a/Mathlib/Algebra/Ring/Defs.lean +++ b/Mathlib/Algebra/Ring/Defs.lean @@ -137,9 +137,13 @@ class NonAssocRing (α : Type*) extends NonUnitalNonAssocRing α, NonAssocSemiri AddCommGroupWithOne α #align non_assoc_ring NonAssocRing +/-- A `Semiring` is a type with addition, multiplication, a `0` and a `1` where addition is +commutative and associative, multiplication is associative and left and right distributive over +addition, and `0` and `1` are additive and multiplicative identities. -/ class Semiring (α : Type u) extends NonUnitalSemiring α, NonAssocSemiring α, MonoidWithZero α #align semiring Semiring +/-- A `Ring` is a `Semiring` with negation making it an additive group. -/ class Ring (R : Type u) extends Semiring R, AddCommGroup R, AddGroupWithOne R #align ring Ring diff --git a/Mathlib/Algebra/Ring/Equiv.lean b/Mathlib/Algebra/Ring/Equiv.lean index 6b4fc70930171..55e4280407f40 100644 --- a/Mathlib/Algebra/Ring/Equiv.lean +++ b/Mathlib/Algebra/Ring/Equiv.lean @@ -102,7 +102,7 @@ instance (priority := 100) toRingHomClass [NonAssocSemiring R] [NonAssocSemiring [h : RingEquivClass F R S] : RingHomClass F R S := { h with coe := h.coe - coe_injective' := FunLike.coe_injective + coe_injective' := DFunLike.coe_injective map_zero := map_zero map_one := map_one } #align ring_equiv_class.to_ring_hom_class RingEquivClass.toRingHomClass @@ -112,7 +112,7 @@ instance (priority := 100) toNonUnitalRingHomClass [NonUnitalNonAssocSemiring R] [NonUnitalNonAssocSemiring S] [h : RingEquivClass F R S] : NonUnitalRingHomClass F R S := { h with coe := h.coe - coe_injective' := FunLike.coe_injective + coe_injective' := DFunLike.coe_injective map_zero := map_zero } #align ring_equiv_class.to_non_unital_ring_hom_class RingEquivClass.toNonUnitalRingHomClass @@ -176,7 +176,7 @@ protected theorem map_add (e : R ≃+* S) (x y : R) : e (x + y) = e x + e y := same underlying function. -/ @[ext] theorem ext {f g : R ≃+* S} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align ring_equiv.ext RingEquiv.ext @[simp] @@ -193,15 +193,15 @@ theorem mk_coe (e : R ≃+* S) (e' h₁ h₂ h₃ h₄) : (⟨⟨e, e', h₁, h #align ring_equiv.mk_coe RingEquiv.mk_coe protected theorem congr_arg {f : R ≃+* S} {x x' : R} : x = x' → f x = f x' := - FunLike.congr_arg f + DFunLike.congr_arg f #align ring_equiv.congr_arg RingEquiv.congr_arg protected theorem congr_fun {f g : R ≃+* S} (h : f = g) (x : R) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align ring_equiv.congr_fun RingEquiv.congr_fun protected theorem ext_iff {f g : R ≃+* S} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align ring_equiv.ext_iff RingEquiv.ext_iff @[simp] @@ -798,8 +798,8 @@ def ofHomInv' {R S F G : Type*} [NonUnitalNonAssocSemiring R] [NonUnitalNonAssoc R ≃+* S where toFun := hom invFun := inv - left_inv := FunLike.congr_fun hom_inv_id - right_inv := FunLike.congr_fun inv_hom_id + left_inv := DFunLike.congr_fun hom_inv_id + right_inv := DFunLike.congr_fun inv_hom_id map_mul' := map_mul hom map_add' := map_add hom #align ring_equiv.of_hom_inv' RingEquiv.ofHomInv' @@ -817,8 +817,8 @@ def ofHomInv {R S F G : Type*} [NonAssocSemiring R] [NonAssocSemiring S] [RingHo R ≃+* S where toFun := hom invFun := inv - left_inv := FunLike.congr_fun hom_inv_id - right_inv := FunLike.congr_fun inv_hom_id + left_inv := DFunLike.congr_fun hom_inv_id + right_inv := DFunLike.congr_fun inv_hom_id map_mul' := map_mul hom map_add' := map_add hom #align ring_equiv.of_hom_inv RingEquiv.ofHomInv diff --git a/Mathlib/Algebra/Ring/Hom/Basic.lean b/Mathlib/Algebra/Ring/Hom/Basic.lean index db3fb05f106f3..aca9e2a4ddbfe 100644 --- a/Mathlib/Algebra/Ring/Hom/Basic.lean +++ b/Mathlib/Algebra/Ring/Hom/Basic.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.Divisibility.Basic import Mathlib.Algebra.Group.Units.Hom import Mathlib.Algebra.GroupWithZero.InjSurj import Mathlib.Algebra.Ring.Hom.Defs -import Mathlib.Data.Set.Image +import Mathlib.Data.Set.Basic #align_import algebra.hom.ring from "leanprover-community/mathlib"@"cf9386b56953fb40904843af98b7a80757bbe7f9" diff --git a/Mathlib/Algebra/Ring/Hom/Defs.lean b/Mathlib/Algebra/Ring/Hom/Defs.lean index f1de7e94319a4..82cfbb50b754d 100644 --- a/Mathlib/Algebra/Ring/Hom/Defs.lean +++ b/Mathlib/Algebra/Ring/Hom/Defs.lean @@ -107,7 +107,7 @@ instance : NonUnitalRingHomClass (α →ₙ+* β) α β where cases f cases g congr - apply FunLike.coe_injective' + apply DFunLike.coe_injective' exact h map_add := NonUnitalRingHom.map_add' map_zero := NonUnitalRingHom.map_zero' @@ -115,7 +115,7 @@ instance : NonUnitalRingHomClass (α →ₙ+* β) α β where -- Porting note: -- These helper instances are unhelpful in Lean 4, so omitting: --- /-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` -- directly. -/ -- instance : CoeFun (α →ₙ+* β) fun _ => α → β := -- ⟨fun f => f.toFun⟩ @@ -159,7 +159,7 @@ theorem coe_copy (f : α →ₙ+* β) (f' : α → β) (h : f' = f) : ⇑(f.copy #align non_unital_ring_hom.coe_copy NonUnitalRingHom.coe_copy theorem copy_eq (f : α →ₙ+* β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align non_unital_ring_hom.copy_eq NonUnitalRingHom.copy_eq end coe @@ -171,11 +171,11 @@ variable (f : α →ₙ+* β) {x y : α} @[ext] theorem ext ⦃f g : α →ₙ+* β⦄ : (∀ x, f x = g x) → f = g := - FunLike.ext _ _ + DFunLike.ext _ _ #align non_unital_ring_hom.ext NonUnitalRingHom.ext theorem ext_iff {f g : α →ₙ+* β} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align non_unital_ring_hom.ext_iff NonUnitalRingHom.ext_iff @[simp] @@ -184,7 +184,7 @@ theorem mk_coe (f : α →ₙ+* β) (h₁ h₂ h₃) : NonUnitalRingHom.mk (MulH #align non_unital_ring_hom.mk_coe NonUnitalRingHom.mk_coe theorem coe_addMonoidHom_injective : Injective fun f : α →ₙ+* β => (f : α →+ β) := - fun _ _ h => ext <| FunLike.congr_fun (F := α →+ β) h + fun _ _ h => ext <| DFunLike.congr_fun (F := α →+ β) h #align non_unital_ring_hom.coe_add_monoid_hom_injective NonUnitalRingHom.coe_addMonoidHom_injective set_option linter.deprecated false in @@ -419,7 +419,7 @@ instance instRingHomClass : RingHomClass (α →+* β) α β where cases f cases g congr - apply FunLike.coe_injective' + apply DFunLike.coe_injective' exact h map_add := RingHom.map_add' map_zero := RingHom.map_zero' @@ -428,7 +428,7 @@ instance instRingHomClass : RingHomClass (α →+* β) α β where -- Porting note: -- These helper instances are unhelpful in Lean 4, so omitting: --- /-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` -- directly. -- -/ -- instance : CoeFun (α →+* β) fun _ => α → β := @@ -506,7 +506,7 @@ theorem coe_copy (f : α →+* β) (f' : α → β) (h : f' = f) : ⇑(f.copy f' #align ring_hom.coe_copy RingHom.coe_copy theorem copy_eq (f : α →+* β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align ring_hom.copy_eq RingHom.copy_eq end coe @@ -516,24 +516,24 @@ section variable {_ : NonAssocSemiring α} {_ : NonAssocSemiring β} (f : α →+* β) {x y : α} theorem congr_fun {f g : α →+* β} (h : f = g) (x : α) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align ring_hom.congr_fun RingHom.congr_fun theorem congr_arg (f : α →+* β) {x y : α} (h : x = y) : f x = f y := - FunLike.congr_arg f h + DFunLike.congr_arg f h #align ring_hom.congr_arg RingHom.congr_arg theorem coe_inj ⦃f g : α →+* β⦄ (h : (f : α → β) = g) : f = g := - FunLike.coe_injective h + DFunLike.coe_injective h #align ring_hom.coe_inj RingHom.coe_inj @[ext] theorem ext ⦃f g : α →+* β⦄ : (∀ x, f x = g x) → f = g := - FunLike.ext _ _ + DFunLike.ext _ _ #align ring_hom.ext RingHom.ext theorem ext_iff {f g : α →+* β} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align ring_hom.ext_iff RingHom.ext_iff @[simp] @@ -542,7 +542,7 @@ theorem mk_coe (f : α →+* β) (h₁ h₂ h₃ h₄) : RingHom.mk ⟨⟨f, h #align ring_hom.mk_coe RingHom.mk_coe theorem coe_addMonoidHom_injective : Injective (fun f : α →+* β => (f : α →+ β)) := fun _ _ h => - ext <| FunLike.congr_fun (F := α →+ β) h + ext <| DFunLike.congr_fun (F := α →+ β) h #align ring_hom.coe_add_monoid_hom_injective RingHom.coe_addMonoidHom_injective set_option linter.deprecated false in diff --git a/Mathlib/Algebra/Ring/Idempotents.lean b/Mathlib/Algebra/Ring/Idempotents.lean index f7699e3dc8c9e..9fb919d04b7c8 100644 --- a/Mathlib/Algebra/Ring/Idempotents.lean +++ b/Mathlib/Algebra/Ring/Idempotents.lean @@ -5,7 +5,7 @@ Authors: Christopher Hoskin -/ import Mathlib.Algebra.GroupPower.Basic import Mathlib.Algebra.Ring.Defs -import Mathlib.Order.Basic +import Mathlib.Order.Notation import Mathlib.Tactic.Conv #align_import algebra.ring.idempotents from "leanprover-community/mathlib"@"655994e298904d7e5bbd1e18c95defd7b543eb94" diff --git a/Mathlib/Algebra/Ring/Opposite.lean b/Mathlib/Algebra/Ring/Opposite.lean index 175ca522376bf..822ec7c81267e 100644 --- a/Mathlib/Algebra/Ring/Opposite.lean +++ b/Mathlib/Algebra/Ring/Opposite.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ import Mathlib.Algebra.Group.Opposite -import Mathlib.Algebra.GroupWithZero.Basic import Mathlib.Algebra.Ring.Hom.Defs #align_import algebra.ring.opposite from "leanprover-community/mathlib"@"76de8ae01554c3b37d66544866659ff174e66e1f" diff --git a/Mathlib/Algebra/Ring/Prod.lean b/Mathlib/Algebra/Ring/Prod.lean index 6ec6665a9951a..611bdcab005a0 100644 --- a/Mathlib/Algebra/Ring/Prod.lean +++ b/Mathlib/Algebra/Ring/Prod.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Int.Cast.Prod import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Ring.Equiv import Mathlib.Algebra.Order.Group.Prod +import Mathlib.Algebra.Order.Ring.Defs #align_import algebra.ring.prod from "leanprover-community/mathlib"@"cd391184c85986113f8c00844cfe6dda1d34be3d" diff --git a/Mathlib/Algebra/SMulWithZero.lean b/Mathlib/Algebra/SMulWithZero.lean index 651dcc4fd98bb..bce313a84125c 100644 --- a/Mathlib/Algebra/SMulWithZero.lean +++ b/Mathlib/Algebra/SMulWithZero.lean @@ -79,7 +79,7 @@ lemma smul_eq_zero_of_right (a : R) (h : b = 0) : a • b = 0 := h.symm ▸ smul #align smul_eq_zero_of_right smul_eq_zero_of_right lemma left_ne_zero_of_smul : a • b ≠ 0 → a ≠ 0 := mt fun h ↦ smul_eq_zero_of_left h b #align left_ne_zero_of_smul left_ne_zero_of_smul -lemma right_ne_zero_of_smul : a • b ≠ 0 → b ≠ 0 := mt $ smul_eq_zero_of_right a +lemma right_ne_zero_of_smul : a • b ≠ 0 → b ≠ 0 := mt <| smul_eq_zero_of_right a #align right_ne_zero_of_smul right_ne_zero_of_smul variable [Zero R'] [Zero M'] [SMul R M'] @@ -178,7 +178,6 @@ protected lemma MulActionWithZero.nontrivial variable {R M} variable [MulActionWithZero R M] [Zero M'] [SMul R M'] (p : Prop) [Decidable p] -@[simp] lemma ite_zero_smul (a : R) (b : M) : (if p then a else 0 : R) • b = if p then a • b else 0 := by rw [ite_smul, zero_smul] diff --git a/Mathlib/Algebra/Star/Basic.lean b/Mathlib/Algebra/Star/Basic.lean index b139858543a93..1a300789cb705 100644 --- a/Mathlib/Algebra/Star/Basic.lean +++ b/Mathlib/Algebra/Star/Basic.lean @@ -3,11 +3,14 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ +import Mathlib.Algebra.Field.Opposite +import Mathlib.Algebra.Invertible.Defs import Mathlib.Algebra.Ring.Aut import Mathlib.Algebra.Ring.CompTypeclasses import Mathlib.Algebra.Field.Opposite -import Mathlib.Data.Rat.Cast.CharZero +import Mathlib.Algebra.Invertible.Defs import Mathlib.GroupTheory.GroupAction.Opposite +import Mathlib.Data.Rat.Cast.Defs import Mathlib.Data.SetLike.Basic #align_import algebra.star.basic from "leanprover-community/mathlib"@"31c24aa72e7b3e5ed97a8412470e904f82b81004" @@ -71,6 +74,8 @@ variable {S : Type w} [Star R] [SetLike S R] [hS : StarMemClass S R] (s : S) instance instStar : Star s where star r := ⟨star (r : R), star_mem r.prop⟩ +@[simp] lemma coe_star (x : s) : star x = star (x : R) := rfl + end StarMemClass /-- Typeclass for a star operation with is involutive. @@ -351,10 +356,12 @@ theorem star_ratCast [DivisionRing R] [StarRing R] (r : ℚ) : star (r : R) = r end +section CommSemiring +variable [CommSemiring R] [StarRing R] + /-- `star` as a ring automorphism, for commutative `R`. -/ @[simps apply] -def starRingAut [CommSemiring R] [StarRing R] : RingAut R := - { starAddEquiv, starMulAut (R := R) with toFun := star } +def starRingAut : RingAut R := { starAddEquiv, starMulAut (R := R) with toFun := star } #align star_ring_aut starRingAut #align star_ring_aut_apply starRingAut_apply @@ -367,8 +374,7 @@ Note that this is the preferred form (over `starRingAut`, available under the sa because the notation `E →ₗ⋆[R] F` for an `R`-conjugate-linear map (short for `E →ₛₗ[starRingEnd R] F`) does not pretty-print if there is a coercion involved, as would be the case for `(↑starRingAut : R →* R)`. -/ -def starRingEnd [CommSemiring R] [StarRing R] : R →+* R := - @starRingAut R _ _ +def starRingEnd : R →+* R := @starRingAut R _ _ #align star_ring_end starRingEnd variable {R} @@ -379,8 +385,7 @@ scoped[ComplexConjugate] notation "conj" => starRingEnd _ /-- This is not a simp lemma, since we usually want simp to keep `starRingEnd` bundled. For example, for complex conjugation, we don't want simp to turn `conj x` into the bare function `star x` automatically since most lemmas are about `conj x`. -/ -theorem starRingEnd_apply [CommSemiring R] [StarRing R] {x : R} : starRingEnd R x = star x := - rfl +theorem starRingEnd_apply (x : R) : starRingEnd R x = star x := rfl #align star_ring_end_apply starRingEnd_apply /- Porting note: removed `simp` attribute due to report by linter: @@ -391,13 +396,10 @@ One of the lemmas above could be a duplicate. If that's not the case try reordering lemmas or adding @[priority]. -/ -- @[simp] -theorem starRingEnd_self_apply [CommSemiring R] [StarRing R] (x : R) : - starRingEnd R (starRingEnd R x) = x := - star_star x +theorem starRingEnd_self_apply (x : R) : starRingEnd R (starRingEnd R x) = x := star_star x #align star_ring_end_self_apply starRingEnd_self_apply -instance RingHom.involutiveStar {S : Type*} [NonAssocSemiring S] [CommSemiring R] [StarRing R] : - InvolutiveStar (S →+* R) where +instance RingHom.involutiveStar {S : Type*} [NonAssocSemiring S] : InvolutiveStar (S →+* R) where toStar := { star := fun f => RingHom.comp (starRingEnd R) f } star_involutive := by intro @@ -405,14 +407,12 @@ instance RingHom.involutiveStar {S : Type*} [NonAssocSemiring S] [CommSemiring R simp only [RingHom.coe_comp, Function.comp_apply, starRingEnd_self_apply] #align ring_hom.has_involutive_star RingHom.involutiveStar -theorem RingHom.star_def {S : Type*} [NonAssocSemiring S] [CommSemiring R] [StarRing R] - (f : S →+* R) : Star.star f = RingHom.comp (starRingEnd R) f := - rfl +theorem RingHom.star_def {S : Type*} [NonAssocSemiring S] (f : S →+* R) : + Star.star f = RingHom.comp (starRingEnd R) f := rfl #align ring_hom.star_def RingHom.star_def -theorem RingHom.star_apply {S : Type*} [NonAssocSemiring S] [CommSemiring R] [StarRing R] - (f : S →+* R) (s : S) : star f s = star (f s) := - rfl +theorem RingHom.star_apply {S : Type*} [NonAssocSemiring S] (f : S →+* R) (s : S) : + star f s = star (f s) := rfl #align ring_hom.star_apply RingHom.star_apply -- A more convenient name for complex conjugation @@ -423,6 +423,12 @@ alias IsROrC.conj_conj := starRingEnd_self_apply set_option linter.uppercaseLean3 false in #align is_R_or_C.conj_conj IsROrC.conj_conj +open scoped ComplexConjugate + +@[simp] lemma conj_trivial [TrivialStar R] (a : R) : conj a = a := star_trivial _ + +end CommSemiring + @[simp] theorem star_inv' [DivisionSemiring R] [StarRing R] (x : R) : star x⁻¹ = (star x)⁻¹ := op_injective <| (map_inv₀ (starRingEquiv : R ≃+* Rᵐᵒᵖ) x).trans (op_inv (star x)).symm @@ -466,6 +472,11 @@ def starRingOfComm {R : Type*} [CommSemiring R] : StarRing R := star_add := fun _ _ => rfl } #align star_ring_of_comm starRingOfComm +instance Nat.instStarRing : StarRing ℕ := starRingOfComm +instance Rat.instStarRing : StarRing ℚ := starRingOfComm +instance Nat.instTrivialStar : TrivialStar ℕ := ⟨fun _ ↦ rfl⟩ +instance Rat.instTrivialStar : TrivialStar ℚ := ⟨fun _ ↦ rfl⟩ + /-- A star module `A` over a star ring `R` is a module which is a star add monoid, and the two star structures are compatible in the sense `star (r • a) = star r • star a`. @@ -492,6 +503,9 @@ instance StarMul.toStarModule [CommMonoid R] [StarMul R] : StarModule R R := ⟨star_mul'⟩ #align star_semigroup.to_star_module StarMul.toStarModule +instance StarAddMonoid.toStarModuleNat {α} [AddCommMonoid α] [StarAddMonoid α] : StarModule ℕ α := + ⟨fun n a ↦ by rw [star_nsmul, star_trivial n]⟩ + namespace RingHomInvPair /-- Instance needed to define star-linear maps over a commutative star ring @@ -505,7 +519,7 @@ section /-- `StarHomClass F R S` states that `F` is a type of `star`-preserving maps from `R` to `S`. -/ class StarHomClass (F : Type*) (R S : outParam (Type*)) [Star R] [Star S] extends - FunLike F R fun _ => S where + DFunLike F R fun _ => S where /-- the maps preserve star -/ map_star : ∀ (f : F) (r : R), f (star r) = star (f r) #align star_hom_class StarHomClass diff --git a/Mathlib/Algebra/Star/Pi.lean b/Mathlib/Algebra/Star/Pi.lean index 1d42c8e243b08..c302b0cbca670 100644 --- a/Mathlib/Algebra/Star/Pi.lean +++ b/Mathlib/Algebra/Star/Pi.lean @@ -61,6 +61,12 @@ theorem single_star [∀ i, AddMonoid (f i)] [∀ i, StarAddMonoid (f i)] [Decid single_op (fun i => @star (f i) _) (fun _ => star_zero _) i a #align pi.single_star Pi.single_star +open scoped ComplexConjugate + +@[simp] +lemma conj_apply {ι : Type*} {α : ι → Type*} [∀ i, CommSemiring (α i)] [∀ i, StarRing (α i)] + (f : ∀ i, α i) (i : ι) : conj f i = conj (f i) := rfl + end Pi namespace Function diff --git a/Mathlib/Algebra/Star/Prod.lean b/Mathlib/Algebra/Star/Prod.lean index 4718a0c0f29d1..84ca0a8b3b999 100644 --- a/Mathlib/Algebra/Star/Prod.lean +++ b/Mathlib/Algebra/Star/Prod.lean @@ -5,7 +5,7 @@ Authors: Eric Wieser -/ import Mathlib.Algebra.Star.Basic import Mathlib.Algebra.Ring.Prod -import Mathlib.Algebra.Module.Prod +import Mathlib.GroupTheory.GroupAction.Prod #align_import algebra.star.prod from "leanprover-community/mathlib"@"9abfa6f0727d5adc99067e325e15d1a9de17fd8e" diff --git a/Mathlib/Algebra/Star/SelfAdjoint.lean b/Mathlib/Algebra/Star/SelfAdjoint.lean index 6dc9d349a9aca..0aeca9d7e5cd2 100644 --- a/Mathlib/Algebra/Star/SelfAdjoint.lean +++ b/Mathlib/Algebra/Star/SelfAdjoint.lean @@ -3,9 +3,10 @@ Copyright (c) 2021 Frédéric Dupuis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Frédéric Dupuis -/ -import Mathlib.Algebra.Star.Basic -import Mathlib.GroupTheory.Subgroup.Basic import Mathlib.Init.Data.Subtype.Basic +import Mathlib.Algebra.Module.Basic +import Mathlib.Algebra.Star.Pi +import Mathlib.GroupTheory.Subgroup.Basic #align_import algebra.star.self_adjoint from "leanprover-community/mathlib"@"a6ece35404f60597c651689c1b46ead86de5ac1b" @@ -40,6 +41,7 @@ We also define `IsStarNormal R`, a `Prop` that states that an element `x` satisf -/ +open Function variable {R A : Type*} @@ -116,8 +118,7 @@ variable [AddMonoid R] [StarAddMonoid R] variable (R) -theorem _root_.isSelfAdjoint_zero : IsSelfAdjoint (0 : R) := - star_zero R +@[simp] theorem _root_.isSelfAdjoint_zero : IsSelfAdjoint (0 : R) := star_zero R #align is_self_adjoint_zero isSelfAdjoint_zero variable {R} @@ -186,7 +187,7 @@ variable [MulOneClass R] [StarMul R] variable (R) -theorem _root_.isSelfAdjoint_one : IsSelfAdjoint (1 : R) := +@[simp] theorem _root_.isSelfAdjoint_one : IsSelfAdjoint (1 : R) := star_one R #align is_self_adjoint_one isSelfAdjoint_one @@ -229,6 +230,15 @@ theorem mul {x y : R} (hx : IsSelfAdjoint x) (hy : IsSelfAdjoint y) : IsSelfAdjo end CommSemigroup +section CommSemiring +variable {α : Type*} [CommSemiring α] [StarRing α] {a : α} + +open scoped ComplexConjugate + +lemma conj_eq (ha : IsSelfAdjoint a) : conj a = a := ha.star_eq + +end CommSemiring + section Ring variable [Ring R] [StarRing R] @@ -577,10 +587,14 @@ instance isStarNormal_one [MulOneClass R] [StarMul R] : IsStarNormal (1 : R) := ⟨by simp only [Commute.refl, star_comm_self, star_one]⟩ #align is_star_normal_one isStarNormal_one -instance isStarNormal_star_self [Mul R] [StarMul R] {x : R} [IsStarNormal x] : +protected instance IsStarNormal.star [Mul R] [StarMul R] {x : R} [IsStarNormal x] : IsStarNormal (star x) := ⟨show star (star x) * star x = star x * star (star x) by rw [star_star, star_comm_self']⟩ -#align is_star_normal_star_self isStarNormal_star_self +#align is_star_normal_star_self IsStarNormal.star + +protected instance IsStarNormal.neg [Ring R] [StarAddMonoid R] {x : R} [IsStarNormal x] : + IsStarNormal (-x) := + ⟨show star (-x) * -x = -x * star (-x) by simp_rw [star_neg, neg_mul_neg, star_comm_self']⟩ -- see Note [lower instance priority] instance (priority := 100) TrivialStar.isStarNormal [Mul R] [StarMul R] [TrivialStar R] @@ -593,3 +607,13 @@ instance (priority := 100) CommMonoid.isStarNormal [CommMonoid R] [StarMul R] {x IsStarNormal x := ⟨mul_comm _ _⟩ #align comm_monoid.is_star_normal CommMonoid.isStarNormal + + +namespace Pi +variable {ι : Type*} {α : ι → Type*} [∀ i, Star (α i)] {f : ∀ i, α i} + +protected lemma isSelfAdjoint : IsSelfAdjoint f ↔ ∀ i, IsSelfAdjoint (f i) := funext_iff + +alias ⟨_root_.IsSelfAdjoint.apply, _⟩ := Pi.isSelfAdjoint + +end Pi diff --git a/Mathlib/Algebra/Star/StarAlgHom.lean b/Mathlib/Algebra/Star/StarAlgHom.lean index d7c8a3c477c70..0c92c3b6c592f 100644 --- a/Mathlib/Algebra/Star/StarAlgHom.lean +++ b/Mathlib/Algebra/Star/StarAlgHom.lean @@ -121,10 +121,10 @@ instance : NonUnitalStarAlgHomClass (A →⋆ₙₐ[R] B) R A B map_star f := f.map_star' -- Porting note: this is no longer useful ---/-- Helper instance for when there's too many metavariables to apply `FunLike.CoeFun` +--/-- Helper instance for when there's too many metavariables to apply `DFunLike.CoeFun` --directly. -/ --instance : CoeFun (A →⋆ₙₐ[R] B) fun _ => A → B := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun -- Porting note: in mathlib3 we didn't need the `Simps.apply` hint. /-- See Note [custom simps projection] -/ @@ -145,7 +145,7 @@ theorem coe_toNonUnitalAlgHom {f : A →⋆ₙₐ[R] B} : (f.toNonUnitalAlgHom : @[ext] theorem ext {f g : A →⋆ₙₐ[R] B} (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align non_unital_star_alg_hom.ext NonUnitalStarAlgHom.ext /-- Copy of a `NonUnitalStarAlgHom` with a new `toFun` equal to the old one. Useful @@ -166,7 +166,7 @@ theorem coe_copy (f : A →⋆ₙₐ[R] B) (f' : A → B) (h : f' = f) : ⇑(f.c #align non_unital_star_alg_hom.coe_copy NonUnitalStarAlgHom.coe_copy theorem copy_eq (f : A →⋆ₙₐ[R] B) (f' : A → B) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align non_unital_star_alg_hom.copy_eq NonUnitalStarAlgHom.copy_eq -- porting note: doesn't align with Mathlib 3 because `NonUnitalStarAlgHom.mk` has a new signature @@ -390,7 +390,7 @@ theorem coe_toAlgHom {f : A →⋆ₐ[R] B} : (f.toAlgHom : A → B) = f := @[ext] theorem ext {f g : A →⋆ₐ[R] B} (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align star_alg_hom.ext StarAlgHom.ext /-- Copy of a `StarAlgHom` with a new `toFun` equal to the old one. Useful @@ -412,7 +412,7 @@ theorem coe_copy (f : A →⋆ₐ[R] B) (f' : A → B) (h : f' = f) : ⇑(f.copy #align star_alg_hom.coe_copy StarAlgHom.coe_copy theorem copy_eq (f : A →⋆ₐ[R] B) (f' : A → B) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align star_alg_hom.copy_eq StarAlgHom.copy_eq -- porting note: doesn't align with Mathlib 3 because `StarAlgHom.mk` has a new signature @@ -568,7 +568,7 @@ theorem snd_prod (f : A →⋆ₙₐ[R] B) (g : A →⋆ₙₐ[R] C) : (snd R B @[simp] theorem prod_fst_snd : prod (fst R A B) (snd R A B) = 1 := - FunLike.coe_injective Pi.prod_fst_snd + DFunLike.coe_injective Pi.prod_fst_snd #align non_unital_star_alg_hom.prod_fst_snd NonUnitalStarAlgHom.prod_fst_snd /-- Taking the product of two maps with the same domain is equivalent to taking the product of @@ -665,7 +665,7 @@ theorem snd_prod (f : A →⋆ₐ[R] B) (g : A →⋆ₐ[R] C) : (snd R B C).com @[simp] theorem prod_fst_snd : prod (fst R A B) (snd R A B) = 1 := - FunLike.coe_injective Pi.prod_fst_snd + DFunLike.coe_injective Pi.prod_fst_snd #align star_alg_hom.prod_fst_snd StarAlgHom.prod_fst_snd /-- Taking the product of two maps with the same domain is equivalent to taking the product of @@ -731,7 +731,7 @@ instance (priority := 50) {F R A B : Type*} [Add A] [Mul A] [SMul R A] [Star A] StarHomClass F A B := { hF with coe := fun f => f - coe_injective' := FunLike.coe_injective } + coe_injective' := DFunLike.coe_injective } -- Porting note: no longer needed ---- `R` becomes a metavariable but that's fine because it's an `outParam` @@ -743,7 +743,7 @@ instance (priority := 50) {F R A B : Type*} [Add A] [Mul A] [Star A] [SMul R A] SMulHomClass F R A B := { hF with coe := fun f => f - coe_injective' := FunLike.coe_injective } + coe_injective' := DFunLike.coe_injective } -- Porting note: no longer needed ---- `R` becomes a metavariable but that's fine because it's an `outParam` @@ -756,7 +756,7 @@ instance (priority := 100) {F R A B : Type*} [Monoid R] [NonUnitalNonAssocSemiri NonUnitalStarAlgHomClass F R A B := { hF with coe := fun f => f - coe_injective' := FunLike.coe_injective + coe_injective' := DFunLike.coe_injective map_zero := map_zero } -- See note [lower instance priority] @@ -765,7 +765,7 @@ instance (priority := 100) instStarAlgHomClass (F R A B : Type*) [CommSemiring R [hF : StarAlgEquivClass F R A B] : StarAlgHomClass F R A B := { hF with coe := fun f => f - coe_injective' := FunLike.coe_injective + coe_injective' := DFunLike.coe_injective map_one := map_one map_zero := map_zero commutes := fun f r => by simp only [Algebra.algebraMap_eq_smul_one, map_smul, map_one] } @@ -809,17 +809,17 @@ theorem toRingEquiv_eq_coe (e : A ≃⋆ₐ[R] B) : e.toRingEquiv = e := -- Porting note: this is no longer useful --/-- Helper instance for when there's too many metavariables to apply ---`FunLike.CoeFun` directly. -/ +--`DFunLike.CoeFun` directly. -/ --instance : CoeFun (A ≃⋆ₐ[R] B) fun _ => A → B := -- ⟨StarAlgEquiv.toFun⟩ @[ext] theorem ext {f g : A ≃⋆ₐ[R] B} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align star_alg_equiv.ext StarAlgEquiv.ext theorem ext_iff {f g : A ≃⋆ₐ[R] B} : f = g ↔ ∀ a, f a = g a := - FunLike.ext_iff + DFunLike.ext_iff #align star_alg_equiv.ext_iff StarAlgEquiv.ext_iff /-- Star algebra equivalences are reflexive. -/ diff --git a/Mathlib/Algebra/Star/Subalgebra.lean b/Mathlib/Algebra/Star/Subalgebra.lean index 85a26c0f1e140..a2646525c3d20 100644 --- a/Mathlib/Algebra/Star/Subalgebra.lean +++ b/Mathlib/Algebra/Star/Subalgebra.lean @@ -750,7 +750,7 @@ theorem adjoin_le_equalizer {s : Set A} (h : s.EqOn f g) : adjoin R s ≤ StarAl #align star_alg_hom.adjoin_le_equalizer StarAlgHom.adjoin_le_equalizer theorem ext_of_adjoin_eq_top {s : Set A} (h : adjoin R s = ⊤) ⦃f g : F⦄ (hs : s.EqOn f g) : f = g := - FunLike.ext f g fun _x => StarAlgHom.adjoin_le_equalizer f g hs <| h.symm ▸ trivial + DFunLike.ext f g fun _x => StarAlgHom.adjoin_le_equalizer f g hs <| h.symm ▸ trivial #align star_alg_hom.ext_of_adjoin_eq_top StarAlgHom.ext_of_adjoin_eq_top theorem map_adjoin [StarModule R B] (f : A →⋆ₐ[R] B) (s : Set A) : @@ -761,7 +761,7 @@ theorem map_adjoin [StarModule R B] (f : A →⋆ₐ[R] B) (s : Set A) : theorem ext_adjoin {s : Set A} [StarAlgHomClass F R (adjoin R s) B] {f g : F} (h : ∀ x : adjoin R s, (x : A) ∈ s → f x = g x) : f = g := by - refine' FunLike.ext f g fun a => + refine' DFunLike.ext f g fun a => adjoin_induction' (p := fun y => f y = g y) a (fun x hx => _) (fun r => _) (fun x y hx hy => _) (fun x y hx hy => _) fun x hx => _ · exact h ⟨x, subset_adjoin R s hx⟩ hx @@ -838,7 +838,7 @@ def StarAlgHom.restrictScalars (f : A →⋆ₐ[S] B) : A →⋆ₐ[R] B where theorem StarAlgHom.restrictScalars_injective : Function.Injective (StarAlgHom.restrictScalars R : (A →⋆ₐ[S] B) → A →⋆ₐ[R] B) := fun f g h => StarAlgHom.ext fun x => - show f.restrictScalars R x = g.restrictScalars R x from FunLike.congr_fun h x + show f.restrictScalars R x = g.restrictScalars R x from DFunLike.congr_fun h x @[simps] def StarAlgEquiv.restrictScalars (f : A ≃⋆ₐ[S] B) : A ≃⋆ₐ[R] B := @@ -849,6 +849,6 @@ def StarAlgEquiv.restrictScalars (f : A ≃⋆ₐ[S] B) : A ≃⋆ₐ[R] B := theorem StarAlgEquiv.restrictScalars_injective : Function.Injective (StarAlgEquiv.restrictScalars R : (A ≃⋆ₐ[S] B) → A ≃⋆ₐ[R] B) := fun f g h => StarAlgEquiv.ext fun x => - show f.restrictScalars R x = g.restrictScalars R x from FunLike.congr_fun h x + show f.restrictScalars R x = g.restrictScalars R x from DFunLike.congr_fun h x end RestrictScalars diff --git a/Mathlib/Algebra/Tropical/Basic.lean b/Mathlib/Algebra/Tropical/Basic.lean index 495b3e58845ad..dd61cdfe6bd2f 100644 --- a/Mathlib/Algebra/Tropical/Basic.lean +++ b/Mathlib/Algebra/Tropical/Basic.lean @@ -3,10 +3,11 @@ Copyright (c) 2021 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Algebra.GroupPower.Order +import Mathlib.Algebra.GroupPower.CovariantClass import Mathlib.Algebra.Order.Monoid.WithTop import Mathlib.Algebra.SMulWithZero -import Mathlib.Algebra.Order.Monoid.MinMax +import Mathlib.Order.Hom.Basic +import Mathlib.Data.Nat.Order.Basic #align_import algebra.tropical.basic from "leanprover-community/mathlib"@"9116dd6709f303dcf781632e15fdef382b0fc579" diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean index c9b1671554fd5..3bc0c0897497f 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean @@ -99,7 +99,7 @@ local macro "derivative_simp" : tactic => local macro "eval_simp" : tactic => `(tactic| simp only [eval_C, eval_X, eval_neg, eval_add, eval_sub, eval_mul, eval_pow]) -universe u v w +universe t u v w /-! ## Weierstrass curves -/ @@ -637,13 +637,14 @@ section Group /-- A nonsingular rational point on a Weierstrass curve `W` in affine coordinates. This is either the unique point at infinity `WeierstrassCurve.Affine.Point.zero` or the nonsingular affine points `WeierstrassCurve.Affine.Point.some` $(x, y)$ satisfying the Weierstrass equation of `W`. -/ +@[pp_dot] inductive Point | zero | some {x y : R} (h : W.nonsingular x y) #align weierstrass_curve.point WeierstrassCurve.Affine.Point /-- For an algebraic extension `S` of `R`, the type of nonsingular `S`-rational points on `W`. -/ -scoped[WeierstrassCurve] notation W "⟮" S "⟯" => Affine.Point (baseChange W S) +scoped[WeierstrassCurve] notation W "⟮" S "⟯" => Affine.Point <| baseChange W <| algebraMap _ S namespace Point @@ -781,41 +782,36 @@ section BaseChange /-! ### Base changes -/ -variable (A : Type v) [CommRing A] [Algebra R A] (B : Type w) [CommRing B] [Algebra R B] - [Algebra A B] [IsScalarTower R A B] +variable {A : Type v} [CommRing A] (φ : R →+* A) {B : Type w} [CommRing B] (ψ : A →+* B) -lemma equation_iff_baseChange [Nontrivial A] [NoZeroSMulDivisors R A] (x y : R) : - W.equation x y ↔ (W.baseChange A).toAffine.equation (algebraMap R A x) (algebraMap R A y) := by - simpa only [equation_iff] - using ⟨fun h => by convert congr_arg (algebraMap R A) h <;> map_simp <;> rfl, - fun h => by apply NoZeroSMulDivisors.algebraMap_injective R A; map_simp; exact h⟩ +lemma equation_iff_baseChange {φ : R →+* A} (hφ : Function.Injective φ) (x y : R) : + W.equation x y ↔ (W.baseChange φ).toAffine.equation (φ x) (φ y) := by + simpa only [equation_iff] using + ⟨fun h => by convert congr_arg φ h <;> map_simp <;> rfl, fun h => hφ <| by map_simp; exact h⟩ #align weierstrass_curve.equation_iff_base_change WeierstrassCurve.Affine.equation_iff_baseChange -lemma equation_iff_baseChange_of_baseChange [Nontrivial B] [NoZeroSMulDivisors A B] (x y : A) : - (W.baseChange A).toAffine.equation x y ↔ - (W.baseChange B).toAffine.equation (algebraMap A B x) (algebraMap A B y) := by - rw [(W.baseChange A).toAffine.equation_iff_baseChange B, baseChange_baseChange] +lemma equation_iff_baseChange_of_baseChange {ψ : A →+* B} (hψ : Function.Injective ψ) (x y : A) : + (W.baseChange φ).toAffine.equation x y ↔ + (W.baseChange <| ψ.comp φ).toAffine.equation (ψ x) (ψ y) := by + rw [(W.baseChange φ).toAffine.equation_iff_baseChange hψ, baseChange_baseChange] #align weierstrass_curve.equation_iff_base_change_of_base_change WeierstrassCurve.Affine.equation_iff_baseChange_of_baseChange -lemma nonsingular_iff_baseChange [Nontrivial A] [NoZeroSMulDivisors R A] (x y : R) : - W.nonsingular x y ↔ - (W.baseChange A).toAffine.nonsingular (algebraMap R A x) (algebraMap R A y) := by - rw [nonsingular_iff, nonsingular_iff, and_congr <| W.equation_iff_baseChange A x y] +lemma nonsingular_iff_baseChange {φ : R →+* A} (hφ : Function.Injective φ) (x y : R) : + W.nonsingular x y ↔ (W.baseChange φ).toAffine.nonsingular (φ x) (φ y) := by + rw [nonsingular_iff, nonsingular_iff, and_congr <| W.equation_iff_baseChange hφ x y] refine ⟨Or.imp (not_imp_not.mpr fun h => ?_) (not_imp_not.mpr fun h => ?_), Or.imp (not_imp_not.mpr fun h => ?_) (not_imp_not.mpr fun h => ?_)⟩ - any_goals apply NoZeroSMulDivisors.algebraMap_injective R A; map_simp; exact h - any_goals convert congr_arg (algebraMap R A) h <;> map_simp <;> rfl + any_goals apply hφ; map_simp; exact h + any_goals convert congr_arg φ h <;> map_simp <;> rfl #align weierstrass_curve.nonsingular_iff_base_change WeierstrassCurve.Affine.nonsingular_iff_baseChange -lemma nonsingular_iff_baseChange_of_baseChange [Nontrivial B] [NoZeroSMulDivisors A B] (x y : A) : - (W.baseChange A).toAffine.nonsingular x y ↔ - (W.baseChange B).toAffine.nonsingular (algebraMap A B x) (algebraMap A B y) := by - rw [(W.baseChange A).toAffine.nonsingular_iff_baseChange B, baseChange_baseChange] +lemma nonsingular_iff_baseChange_of_baseChange {ψ : A →+* B} (hψ : Function.Injective ψ) (x y : A) : + (W.baseChange φ).toAffine.nonsingular x y ↔ + (W.baseChange <| ψ.comp φ).toAffine.nonsingular (ψ x) (ψ y) := by + rw [(W.baseChange φ).toAffine.nonsingular_iff_baseChange hψ, baseChange_baseChange] #align weierstrass_curve.nonsingular_iff_base_change_of_base_change WeierstrassCurve.Affine.nonsingular_iff_baseChange_of_baseChange -lemma baseChange_negY (x y : R) : - (W.baseChange A).toAffine.negY (algebraMap R A x) (algebraMap R A y) = - algebraMap R A (W.negY x y) := by +lemma baseChange_negY (x y : R) : (W.baseChange φ).toAffine.negY (φ x) (φ y) = φ (W.negY x y) := by simp only [negY] map_simp rfl @@ -823,15 +819,14 @@ set_option linter.uppercaseLean3 false in #align weierstrass_curve.base_change_neg_Y WeierstrassCurve.Affine.baseChange_negY lemma baseChange_negY_of_baseChange (x y : A) : - (W.baseChange B).toAffine.negY (algebraMap A B x) (algebraMap A B y) = - algebraMap A B ((W.baseChange A).toAffine.negY x y) := by + (W.baseChange <| ψ.comp φ).toAffine.negY (ψ x) (ψ y) = + ψ ((W.baseChange φ).toAffine.negY x y) := by rw [← baseChange_negY, baseChange_baseChange] set_option linter.uppercaseLean3 false in #align weierstrass_curve.base_change_neg_Y_of_base_change WeierstrassCurve.Affine.baseChange_negY_of_baseChange lemma baseChange_addX (x₁ x₂ L : R) : - (W.baseChange A).toAffine.addX (algebraMap R A x₁) (algebraMap R A x₂) (algebraMap R A L) = - algebraMap R A (W.addX x₁ x₂ L) := by + (W.baseChange φ).toAffine.addX (φ x₁) (φ x₂) (φ L) = φ (W.addX x₁ x₂ L) := by simp only [addX] map_simp rfl @@ -839,45 +834,42 @@ set_option linter.uppercaseLean3 false in #align weierstrass_curve.base_change_add_X WeierstrassCurve.Affine.baseChange_addX lemma baseChange_addX_of_baseChange (x₁ x₂ L : A) : - (W.baseChange B).toAffine.addX (algebraMap A B x₁) (algebraMap A B x₂) (algebraMap A B L) = - algebraMap A B ((W.baseChange A).toAffine.addX x₁ x₂ L) := by + (W.baseChange <| ψ.comp φ).toAffine.addX (ψ x₁) (ψ x₂) (ψ L) = + ψ ((W.baseChange φ).toAffine.addX x₁ x₂ L) := by rw [← baseChange_addX, baseChange_baseChange] set_option linter.uppercaseLean3 false in #align weierstrass_curve.base_change_add_X_of_base_change WeierstrassCurve.Affine.baseChange_addX_of_baseChange lemma baseChange_addY' (x₁ x₂ y₁ L : R) : - (W.baseChange A).toAffine.addY' (algebraMap R A x₁) (algebraMap R A x₂) (algebraMap R A y₁) - (algebraMap R A L) = algebraMap R A (W.addY' x₁ x₂ y₁ L) := by + (W.baseChange φ).toAffine.addY' (φ x₁) (φ x₂) (φ y₁) (φ L) = φ (W.addY' x₁ x₂ y₁ L) := by simp only [addY', baseChange_addX] map_simp set_option linter.uppercaseLean3 false in #align weierstrass_curve.base_change_add_Y' WeierstrassCurve.Affine.baseChange_addY' lemma baseChange_addY'_of_baseChange (x₁ x₂ y₁ L : A) : - (W.baseChange B).toAffine.addY' (algebraMap A B x₁) (algebraMap A B x₂) (algebraMap A B y₁) - (algebraMap A B L) = algebraMap A B ((W.baseChange A).toAffine.addY' x₁ x₂ y₁ L) := by + (W.baseChange <| ψ.comp φ).toAffine.addY' (ψ x₁) (ψ x₂) (ψ y₁) (ψ L) = + ψ ((W.baseChange φ).toAffine.addY' x₁ x₂ y₁ L) := by rw [← baseChange_addY', baseChange_baseChange] set_option linter.uppercaseLean3 false in #align weierstrass_curve.base_change_add_Y'_of_base_change WeierstrassCurve.Affine.baseChange_addY'_of_baseChange lemma baseChange_addY (x₁ x₂ y₁ L : R) : - (W.baseChange A).toAffine.addY (algebraMap R A x₁) (algebraMap R A x₂) (algebraMap R A y₁) - (algebraMap R A L) = algebraMap R A (W.toAffine.addY x₁ x₂ y₁ L) := by + (W.baseChange φ).toAffine.addY (φ x₁) (φ x₂) (φ y₁) (φ L) = φ (W.toAffine.addY x₁ x₂ y₁ L) := by simp only [addY, baseChange_addY', baseChange_addX, baseChange_negY] set_option linter.uppercaseLean3 false in #align weierstrass_curve.base_change_add_Y WeierstrassCurve.Affine.baseChange_addY lemma baseChange_addY_of_baseChange (x₁ x₂ y₁ L : A) : - (W.baseChange B).toAffine.addY (algebraMap A B x₁) (algebraMap A B x₂) (algebraMap A B y₁) - (algebraMap A B L) = algebraMap A B ((W.baseChange A).toAffine.addY x₁ x₂ y₁ L) := by + (W.baseChange <| ψ.comp φ).toAffine.addY (ψ x₁) (ψ x₂) (ψ y₁) (ψ L) = + ψ ((W.baseChange φ).toAffine.addY x₁ x₂ y₁ L) := by rw [← baseChange_addY, baseChange_baseChange] set_option linter.uppercaseLean3 false in #align weierstrass_curve.base_change_add_Y_of_base_change WeierstrassCurve.Affine.baseChange_addY_of_baseChange -lemma baseChange_slope {F : Type u} [Field F] (W : Affine F) (K : Type v) [Field K] [Algebra F K] - (x₁ x₂ y₁ y₂ : F) : - (W.baseChange K).toAffine.slope (algebraMap F K x₁) (algebraMap F K x₂) (algebraMap F K y₁) - (algebraMap F K y₂) = algebraMap F K (W.slope x₁ x₂ y₁ y₂) := by +lemma baseChange_slope {F : Type u} [Field F] (W : Affine F) {K : Type v} [Field K] (φ : F →+* K) + (x₁ x₂ y₁ y₂ : F) : (W.baseChange φ).toAffine.slope (φ x₁) (φ x₂) (φ y₁) (φ y₂) = + φ (W.slope x₁ x₂ y₁ y₂) := by by_cases hx : x₁ = x₂ · by_cases hy : y₁ = W.negY x₂ y₂ · rw [slope_of_Yeq hx hy, slope_of_Yeq <| congr_arg _ hx, map_zero] @@ -888,68 +880,69 @@ lemma baseChange_slope {F : Type u} [Field F] (W : Affine F) (K : Type v) [Field rfl · rw [baseChange_negY] contrapose! hy - exact NoZeroSMulDivisors.algebraMap_injective F K hy + exact φ.injective hy · rw [slope_of_Xne hx, slope_of_Xne] · map_simp · contrapose! hx - exact NoZeroSMulDivisors.algebraMap_injective F K hx + exact φ.injective hx #align weierstrass_curve.base_change_slope WeierstrassCurve.Affine.baseChange_slope -lemma baseChange_slope_of_baseChange {R : Type u} [CommRing R] (W : Affine R) (F : Type v) [Field F] - [Algebra R F] (K : Type w) [Field K] [Algebra R K] [Algebra F K] [IsScalarTower R F K] - (x₁ x₂ y₁ y₂ : F) : - (W.baseChange K).toAffine.slope (algebraMap F K x₁) (algebraMap F K x₂) (algebraMap F K y₁) - (algebraMap F K y₂) = algebraMap F K ((W.baseChange F).toAffine.slope x₁ x₂ y₁ y₂) := by +lemma baseChange_slope_of_baseChange {R : Type u} [CommRing R] (W : Affine R) {F : Type v} [Field F] + {K : Type w} [Field K] (φ : R →+* F) (ψ : F →+* K) (x₁ x₂ y₁ y₂ : F) : + (W.baseChange <| ψ.comp φ).toAffine.slope (ψ x₁) (ψ x₂) (ψ y₁) (ψ y₂) = + ψ ((W.baseChange φ).toAffine.slope x₁ x₂ y₁ y₂) := by rw [← baseChange_slope, baseChange_baseChange] #align weierstrass_curve.base_change_slope_of_base_change WeierstrassCurve.Affine.baseChange_slope_of_baseChange namespace Point -open WeierstrassCurve - -variable {R : Type u} [CommRing R] (W : Affine R) (F : Type v) [Field F] [Algebra R F] - (K : Type w) [Field K] [Algebra R K] [Algebra F K] [IsScalarTower R F K] +variable [Algebra R A] {K : Type w} [Field K] [Algebra R K] [Algebra A K] [IsScalarTower R A K] + {L : Type t} [Field L] [Algebra R L] [Algebra A L] [IsScalarTower R A L] (φ : K →ₐ[A] L) -/-- The function from `W⟮F⟯` to `W⟮K⟯` induced by a base change from `F` to `K`. -/ -def ofBaseChangeFun : W⟮F⟯ → W⟮K⟯ +/-- The function from `W⟮K⟯` to `W⟮L⟯` induced by an algebra homomorphism `φ : K →ₐ[A] L`, +where `W` is defined over a subring of a ring `A`, and `K` and `L` are field extensions of `A`. -/ +def ofBaseChangeFun : W⟮K⟯ → W⟮L⟯ | 0 => 0 - | Point.some h => Point.some <| (nonsingular_iff_baseChange_of_baseChange W F K ..).mp h + | Point.some h => Point.some <| by + convert (W.nonsingular_iff_baseChange_of_baseChange (algebraMap R K) φ.injective _ _).mp h + exact (φ.restrictScalars R).comp_algebraMap.symm #align weierstrass_curve.point.of_base_change_fun WeierstrassCurve.Affine.Point.ofBaseChangeFun -/-- The group homomorphism from `W⟮F⟯` to `W⟮K⟯` induced by a base change from `F` to `K`. -/ +/-- The group homomorphism from `W⟮K⟯` to `W⟮L⟯` induced by an algebra homomorphism `φ : K →ₐ[A] L`, +where `W` is defined over a subring of a ring `A`, and `K` and `L` are field extensions of `A`. -/ @[simps] -def ofBaseChange : W⟮F⟯ →+ W⟮K⟯ where - toFun := ofBaseChangeFun W F K +def ofBaseChange : W⟮K⟯ →+ W⟮L⟯ where + toFun := ofBaseChangeFun W φ map_zero' := rfl map_add' := by rintro (_ | @⟨x₁, y₁, _⟩) (_ | @⟨x₂, y₂, _⟩) any_goals rfl by_cases hx : x₁ = x₂ - · by_cases hy : y₁ = (W.baseChange F).toAffine.negY x₂ y₂ + · by_cases hy : y₁ = (W.baseChange <| algebraMap R K).toAffine.negY x₂ y₂ · simp only [some_add_some_of_Yeq hx hy, ofBaseChangeFun] rw [some_add_some_of_Yeq <| congr_arg _ hx] - · rw [hy, baseChange_negY_of_baseChange] + · erw [hy, ← φ.comp_algebraMap_of_tower R, baseChange_negY_of_baseChange] + rfl · simp only [some_add_some_of_Yne hx hy, ofBaseChangeFun] rw [some_add_some_of_Yne <| congr_arg _ hx] - · simp only [baseChange_addX_of_baseChange, baseChange_addY_of_baseChange, - baseChange_slope_of_baseChange] - · rw [baseChange_negY_of_baseChange] + · simp only [← φ.comp_algebraMap_of_tower R, ← baseChange_addX_of_baseChange, + ← baseChange_addY_of_baseChange, ← baseChange_slope_of_baseChange] + · erw [← φ.comp_algebraMap_of_tower R, baseChange_negY_of_baseChange] contrapose! hy - exact NoZeroSMulDivisors.algebraMap_injective F K hy + exact φ.injective hy · simp only [some_add_some_of_Xne hx, ofBaseChangeFun] rw [some_add_some_of_Xne] - · simp only [baseChange_addX_of_baseChange, baseChange_addY_of_baseChange, - baseChange_slope_of_baseChange] + · simp only [← φ.comp_algebraMap_of_tower R, ← baseChange_addX_of_baseChange, + ← baseChange_addY_of_baseChange, ← baseChange_slope_of_baseChange] · contrapose! hx - exact NoZeroSMulDivisors.algebraMap_injective F K hx + exact φ.injective hx #align weierstrass_curve.point.of_base_change WeierstrassCurve.Affine.Point.ofBaseChange -lemma ofBaseChange_injective : Function.Injective <| ofBaseChange W F K := by +lemma ofBaseChange_injective : Function.Injective <| ofBaseChange W φ := by rintro (_ | _) (_ | _) h any_goals contradiction · rfl - · simpa only [some.injEq] using ⟨NoZeroSMulDivisors.algebraMap_injective F K (some.inj h).left, - NoZeroSMulDivisors.algebraMap_injective F K (some.inj h).right⟩ + · simpa only [some.injEq] using ⟨φ.injective (some.inj h).left, φ.injective (some.inj h).right⟩ #align weierstrass_curve.point.of_base_change_injective WeierstrassCurve.Affine.Point.ofBaseChange_injective end Point diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean index 1e83ecfaf4fa5..dbd055dc72893 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean @@ -138,7 +138,7 @@ lemma YClass_ne_zero [Nontrivial R] (y : R[X]) : YClass W y ≠ 0 := set_option linter.uppercaseLean3 false in #align weierstrass_curve.coordinate_ring.Y_class_ne_zero WeierstrassCurve.Affine.CoordinateRing.YClass_ne_zero -lemma C_addPolynomial (x y L : R) : mk W (C (W.addPolynomial x y L)) = +lemma C_addPolynomial (x y L : R) : mk W (C <| W.addPolynomial x y L) = mk W ((Y - C (linePolynomial x y L)) * (W.negPolynomial - C (linePolynomial x y L))) := AdjoinRoot.mk_eq_mk.mpr ⟨1, by rw [W.C_addPolynomial, add_sub_cancel', mul_one]⟩ set_option linter.uppercaseLean3 false in @@ -207,7 +207,7 @@ lemma XYIdeal_eq₂ {x₁ x₂ y₁ y₂ : F} (h₁ : W.equation x₁ y₁) have hy₂ : y₂ = (linePolynomial x₁ y₁ <| W.slope x₁ x₂ y₁ y₂).eval x₂ := by by_cases hx : x₁ = x₂ · rcases hx, Yeq_of_Yne h₁ h₂ hx <| hxy hx with ⟨rfl, rfl⟩ - field_simp [linePolynomial, sub_ne_zero_of_ne (hxy rfl)] + field_simp [linePolynomial, sub_ne_zero_of_ne <| hxy rfl] · field_simp [linePolynomial, slope_of_Xne hx, sub_ne_zero_of_ne hx] ring1 nth_rw 1 [hy₂] @@ -223,14 +223,14 @@ set_option linter.uppercaseLean3 false in lemma XYIdeal_neg_mul {x y : F} (h : W.nonsingular x y) : XYIdeal W x (C <| W.negY x y) * XYIdeal W x (C y) = XIdeal W x := by - have Y_rw : (Y - C (C y)) * (Y - C (C (W.negY x y))) - + have Y_rw : (Y - C (C y)) * (Y - C (C <| W.negY x y)) - C (X - C x) * (C (X ^ 2 + C (x + W.a₂) * X + C (x ^ 2 + W.a₂ * x + W.a₄)) - C (C W.a₁) * Y) = W.polynomial * 1 := by linear_combination (norm := (rw [negY, polynomial]; C_simp; ring1)) congr_arg C (congr_arg C ((W.equation_iff _ _).mp h.left).symm) simp_rw [XYIdeal, XClass, YClass, span_pair_mul_span_pair, mul_comm, ← _root_.map_mul, AdjoinRoot.mk_eq_mk.mpr ⟨1, Y_rw⟩, _root_.map_mul, span_insert, - ← span_singleton_mul_span_singleton, ← mul_sup, ← span_insert] + ← span_singleton_mul_span_singleton, ← Ideal.mul_sup, ← span_insert] convert mul_top (_ : Ideal W.CoordinateRing) using 2 simp_rw [← @Set.image_singleton _ _ <| mk W, ← Set.image_insert_eq, ← map_span] convert map_top (R := F[X][Y]) (mk W) using 1 @@ -239,13 +239,13 @@ lemma XYIdeal_neg_mul {x y : F} (h : W.nonsingular x y) : rcases ((W.nonsingular_iff' _ _).mp h).right with hx | hy · let W_X := W.a₁ * y - (3 * x ^ 2 + 2 * W.a₂ * x + W.a₄) refine - ⟨C (C W_X⁻¹ * -(X + C (2 * x + W.a₂))), C (C <| W_X⁻¹ * W.a₁), 0, C (C <| W_X⁻¹ * -1), ?_⟩ + ⟨C <| C W_X⁻¹ * -(X + C (2 * x + W.a₂)), C <| C <| W_X⁻¹ * W.a₁, 0, C <| C <| W_X⁻¹ * -1, ?_⟩ rw [← mul_right_inj' <| C_ne_zero.mpr <| C_ne_zero.mpr hx] simp only [mul_add, ← mul_assoc, ← C_mul, mul_inv_cancel hx] C_simp ring1 · let W_Y := 2 * y + W.a₁ * x + W.a₃ - refine ⟨0, C (C W_Y⁻¹), C (C <| W_Y⁻¹ * -1), 0, ?_⟩ + refine ⟨0, C <| C W_Y⁻¹, C <| C <| W_Y⁻¹ * -1, 0, ?_⟩ rw [negY, ← mul_right_inj' <| C_ne_zero.mpr <| C_ne_zero.mpr hy] simp only [mul_add, ← mul_assoc, ← C_mul, mul_inv_cancel hy] C_simp @@ -269,28 +269,27 @@ lemma XYIdeal_mul_XYIdeal {x₁ x₂ y₁ y₂ : F} (h₁ : W.equation x₁ y₁ fun _ _ c _ => by rw [← sup_assoc, @sup_comm _ _ c, sup_sup_sup_comm, ← sup_assoc] rw [XYIdeal_add_eq, XIdeal, mul_comm, XYIdeal_eq₁ W x₁ y₁ <| W.slope x₁ x₂ y₁ y₂, XYIdeal, XYIdeal_eq₂ h₁ h₂ hxy, XYIdeal, span_pair_mul_span_pair] - simp_rw [span_insert, sup_rw, sup_mul, span_singleton_mul_span_singleton] + simp_rw [span_insert, sup_rw, Ideal.sup_mul, span_singleton_mul_span_singleton] rw [← neg_eq_iff_eq_neg.mpr <| C_addPolynomial_slope h₁ h₂ hxy, span_singleton_neg, C_addPolynomial, _root_.map_mul, YClass] - simp_rw [mul_comm <| XClass W x₁, mul_assoc, ← span_singleton_mul_span_singleton, ← mul_sup] + simp_rw [mul_comm <| XClass W x₁, mul_assoc, ← span_singleton_mul_span_singleton, ← Ideal.mul_sup] rw [span_singleton_mul_span_singleton, ← span_insert, ← span_pair_add_mul_right <| -(XClass W <| W.addX x₁ x₂ <| W.slope x₁ x₂ y₁ y₂), mul_neg, - ← sub_eq_add_neg, ← sub_mul, ← map_sub <| mk W, sub_sub_sub_cancel_right, - span_insert, ← span_singleton_mul_span_singleton, ← sup_rw, ← sup_mul, ← sup_mul] + ← sub_eq_add_neg, ← sub_mul, ← map_sub <| mk W, sub_sub_sub_cancel_right, span_insert, + ← span_singleton_mul_span_singleton, ← sup_rw, ← Ideal.sup_mul, ← Ideal.sup_mul] apply congr_arg (_ ∘ _) convert top_mul (_ : Ideal W.CoordinateRing) - simp_rw [XClass, ← @Set.image_singleton _ _ <| mk W, ← map_span, ← Ideal.map_sup, - eq_top_iff_one, mem_map_iff_of_surjective _ AdjoinRoot.mk_surjective, ← span_insert, - mem_span_insert', mem_span_singleton'] + simp_rw [XClass, ← @Set.image_singleton _ _ <| mk W, ← map_span, ← Ideal.map_sup, eq_top_iff_one, + mem_map_iff_of_surjective _ AdjoinRoot.mk_surjective, ← span_insert, mem_span_insert', + mem_span_singleton'] by_cases hx : x₁ = x₂ · rcases hx, Yeq_of_Yne h₁ h₂ hx (hxy hx) with ⟨rfl, rfl⟩ let y := (y₁ - W.negY x₁ y₁) ^ 2 - replace hxy := pow_ne_zero 2 (sub_ne_zero_of_ne <| hxy rfl) + replace hxy := pow_ne_zero 2 <| sub_ne_zero_of_ne <| hxy rfl refine ⟨1 + C (C <| y⁻¹ * 4) * W.polynomial, ⟨C <| C y⁻¹ * (C 4 * X ^ 2 + C (4 * x₁ + W.b₂) * X + C (4 * x₁ ^ 2 + W.b₂ * x₁ + 2 * W.b₄)), 0, C (C y⁻¹) * (Y - W.negPolynomial), ?_⟩, by - rw [map_add, map_one, _root_.map_mul <| mk W, AdjoinRoot.mk_self, mul_zero, - add_zero]⟩ + rw [map_add, map_one, _root_.map_mul <| mk W, AdjoinRoot.mk_self, mul_zero, add_zero]⟩ rw [polynomial, negPolynomial, ← mul_right_inj' <| C_ne_zero.mpr <| C_ne_zero.mpr hxy] simp only [mul_add, ← mul_assoc, ← C_mul, mul_inv_cancel hxy] linear_combination (norm := (rw [b₂, b₄, negY]; C_simp; ring1)) @@ -467,7 +466,7 @@ lemma norm_smul_basis (p q : R[X]) : #align weierstrass_curve.coordinate_ring.norm_smul_basis WeierstrassCurve.Affine.CoordinateRing.norm_smul_basis lemma coe_norm_smul_basis (p q : R[X]) : - ↑(Algebra.norm R[X] <| p • (1 : W.CoordinateRing) + q • mk W Y) = + Algebra.norm R[X] (p • (1 : W.CoordinateRing) + q • mk W Y) = mk W ((C p + C q * X) * (C p + C q * (-Y - C (C W.a₁ * X + C W.a₃)))) := AdjoinRoot.mk_eq_mk.mpr ⟨C q ^ 2, by simp only [norm_smul_basis, polynomial]; C_simp; ring1⟩ @@ -632,9 +631,6 @@ lemma add_assoc (P Q R : W.Point) : P + Q + R = P + (Q + R) := #align weierstrass_curve.point.add_assoc WeierstrassCurve.Affine.Point.add_assoc noncomputable instance instAddCommGroupPoint : AddCommGroup W.Point where - zero := zero - neg := neg - add := add zero_add := zero_add add_zero := add_zero add_left_neg := add_left_neg diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean index d6900169ca509..b91bded813904 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean @@ -37,7 +37,7 @@ splitting field of `R` are precisely the $X$-coordinates of the non-zero 2-torsi * `WeierstrassCurve.ofJ`: a Weierstrass curve whose j-invariant is neither 0 nor 1728. * `WeierstrassCurve.VariableChange`: a change of variables of Weierstrass curves. * `WeierstrassCurve.variableChange`: the Weierstrass curve induced by a change of variables. - * `WeierstrassCurve.baseChange`: the Weierstrass curve base changed over an algebra. + * `WeierstrassCurve.baseChange`: the Weierstrass curve base changed over a ring homomorphism. * `WeierstrassCurve.twoTorsionPolynomial`: the 2-torsion polynomial of a Weierstrass curve. * `EllipticCurve`: an elliptic curve over a commutative ring. * `EllipticCurve.j`: the j-invariant of an elliptic curve. @@ -215,16 +215,16 @@ def id : VariableChange R := /-- The composition of two linear changes of variables given by matrix multiplication. -/ def comp : VariableChange R where u := C.u * C'.u - r := C.r * ↑C'.u ^ 2 + C'.r - s := ↑C'.u * C.s + C'.s - t := C.t * ↑C'.u ^ 3 + C.r * C'.s * ↑C'.u ^ 2 + C'.t + r := C.r * C'.u ^ 2 + C'.r + s := C'.u * C.s + C'.s + t := C.t * C'.u ^ 3 + C.r * C'.s * C'.u ^ 2 + C'.t /-- The inverse of a linear change of variables given by matrix inversion. -/ def inv : VariableChange R where u := C.u⁻¹ - r := -C.r * ↑C.u⁻¹ ^ 2 - s := -C.s * ↑C.u⁻¹ - t := (C.r * C.s - C.t) * ↑C.u⁻¹ ^ 3 + r := -C.r * C.u⁻¹ ^ 2 + s := -C.s * C.u⁻¹ + t := (C.r * C.s - C.t) * C.u⁻¹ ^ 3 lemma id_comp (C : VariableChange R) : comp id C = C := by simp only [comp, id, zero_add, zero_mul, mul_zero, one_mul] @@ -261,12 +261,12 @@ variable (C : VariableChange R) $(X, Y) \mapsto (u^2X + r, u^3Y + u^2sX + t)$ for some $u \in R^\times$ and some $r, s, t \in R$. -/ @[pp_dot, simps] def variableChange : WeierstrassCurve R where - a₁ := ↑C.u⁻¹ * (W.a₁ + 2 * C.s) - a₂ := ↑C.u⁻¹ ^ 2 * (W.a₂ - C.s * W.a₁ + 3 * C.r - C.s ^ 2) - a₃ := ↑C.u⁻¹ ^ 3 * (W.a₃ + C.r * W.a₁ + 2 * C.t) - a₄ := ↑C.u⁻¹ ^ 4 * (W.a₄ - C.s * W.a₃ + 2 * C.r * W.a₂ - (C.t + C.r * C.s) * W.a₁ + 3 * C.r ^ 2 + a₁ := C.u⁻¹ * (W.a₁ + 2 * C.s) + a₂ := C.u⁻¹ ^ 2 * (W.a₂ - C.s * W.a₁ + 3 * C.r - C.s ^ 2) + a₃ := C.u⁻¹ ^ 3 * (W.a₃ + C.r * W.a₁ + 2 * C.t) + a₄ := C.u⁻¹ ^ 4 * (W.a₄ - C.s * W.a₃ + 2 * C.r * W.a₂ - (C.t + C.r * C.s) * W.a₁ + 3 * C.r ^ 2 - 2 * C.s * C.t) - a₆ := ↑C.u⁻¹ ^ 6 * (W.a₆ + C.r * W.a₄ + C.r ^ 2 * W.a₂ + C.r ^ 3 - C.t * W.a₃ - C.t ^ 2 + a₆ := C.u⁻¹ ^ 6 * (W.a₆ + C.r * W.a₄ + C.r ^ 2 * W.a₂ + C.r ^ 3 - C.t * W.a₃ - C.t ^ 2 - C.r * C.t * W.a₁) #align weierstrass_curve.variable_change WeierstrassCurve.variableChange @@ -278,33 +278,29 @@ lemma variableChange_comp (C C' : VariableChange R) (W : WeierstrassCurve R) : W.variableChange (C.comp C') = (W.variableChange C').variableChange C := by simp only [VariableChange.comp, variableChange] ext <;> simp only [mul_inv, Units.val_mul] - · linear_combination (norm := ring1) ↑C.u⁻¹ * C.s * 2 * C'.u.inv_mul + · linear_combination (norm := ring1) C.u⁻¹ * C.s * 2 * C'.u.inv_mul · linear_combination (norm := ring1) - C.s * (-C'.s * 2 - W.a₁) * (↑C.u⁻¹ : R) ^ 2 * ↑C'.u⁻¹ * C'.u.inv_mul - + (C.r * 3 - C.s ^ 2) * (↑C.u⁻¹ : R) ^ 2 * pow_mul_pow_eq_one 2 C'.u.inv_mul + C.s * (-C'.s * 2 - W.a₁) * C.u⁻¹ ^ 2 * C'.u⁻¹ * C'.u.inv_mul + + (C.r * 3 - C.s ^ 2) * C.u⁻¹ ^ 2 * pow_mul_pow_eq_one 2 C'.u.inv_mul · linear_combination (norm := ring1) - C.r * (C'.s * 2 + W.a₁) * (↑C.u⁻¹ : R) ^ 3 * ↑C'.u⁻¹ * pow_mul_pow_eq_one 2 C'.u.inv_mul - + C.t * 2 * (↑C.u⁻¹ : R) ^ 3 * pow_mul_pow_eq_one 3 C'.u.inv_mul + C.r * (C'.s * 2 + W.a₁) * C.u⁻¹ ^ 3 * C'.u⁻¹ * pow_mul_pow_eq_one 2 C'.u.inv_mul + + C.t * 2 * C.u⁻¹ ^ 3 * pow_mul_pow_eq_one 3 C'.u.inv_mul · linear_combination (norm := ring1) - C.s * (-W.a₃ - C'.r * W.a₁ - C'.t * 2) * (↑C.u⁻¹ : R) ^ 4 * (↑C'.u⁻¹ : R) ^ 3 * C'.u.inv_mul - + (↑C.u⁻¹ : R) ^ 4 * (↑C'.u⁻¹ : R) ^ 2 - * (C.r * C'.r * 6 + C.r * W.a₂ * 2 - C'.s * C.r * W.a₁ * 2 - C'.s ^ 2 * C.r * 2) - * pow_mul_pow_eq_one 2 C'.u.inv_mul - + -(↑C.u⁻¹ : R) ^ 4 - * ↑C'.u⁻¹ * (C.s * C'.s * C.r * 2 + C.s * C.r * W.a₁ + C'.s * C.t * 2 + C.t * W.a₁) - * pow_mul_pow_eq_one 3 C'.u.inv_mul - + (↑C.u⁻¹ : R) ^ 4 * (C.r ^ 2 * 3 - C.s * C.t * 2) * pow_mul_pow_eq_one 4 C'.u.inv_mul + C.s * (-W.a₃ - C'.r * W.a₁ - C'.t * 2) * C.u⁻¹ ^ 4 * C'.u⁻¹ ^ 3 * C'.u.inv_mul + + C.u⁻¹ ^ 4 * C'.u⁻¹ ^ 2 * (C.r * C'.r * 6 + C.r * W.a₂ * 2 - C'.s * C.r * W.a₁ * 2 + - C'.s ^ 2 * C.r * 2) * pow_mul_pow_eq_one 2 C'.u.inv_mul + - C.u⁻¹ ^ 4 * C'.u⁻¹ * (C.s * C'.s * C.r * 2 + C.s * C.r * W.a₁ + C'.s * C.t * 2 + + C.t * W.a₁) * pow_mul_pow_eq_one 3 C'.u.inv_mul + + C.u⁻¹ ^ 4 * (C.r ^ 2 * 3 - C.s * C.t * 2) * pow_mul_pow_eq_one 4 C'.u.inv_mul · linear_combination (norm := ring1) - C.r * (↑C.u⁻¹ : R) ^ 6 * (↑C'.u⁻¹ : R) ^ 4 * (C'.r * W.a₂ * 2 - C'.r * C'.s * W.a₁ - + C'.r ^ 2 * 3 + W.a₄ - C'.s * C'.t * 2 - C'.s * W.a₃ - C'.t * W.a₁) - * pow_mul_pow_eq_one 2 C'.u.inv_mul - + -(↑C.u⁻¹ : R) ^ 6 * (↑C'.u⁻¹ : R) ^ 3 * C.t * (C'.r * W.a₁ + C'.t * 2 + W.a₃) + C.r * C.u⁻¹ ^ 6 * C'.u⁻¹ ^ 4 * (C'.r * W.a₂ * 2 - C'.r * C'.s * W.a₁ + C'.r ^ 2 * 3 + W.a₄ + - C'.s * C'.t * 2 - C'.s * W.a₃ - C'.t * W.a₁) * pow_mul_pow_eq_one 2 C'.u.inv_mul + - C.u⁻¹ ^ 6 * C'.u⁻¹ ^ 3 * C.t * (C'.r * W.a₁ + C'.t * 2 + W.a₃) * pow_mul_pow_eq_one 3 C'.u.inv_mul - + C.r ^ 2 * (↑C.u⁻¹ : R) ^ 6 * (↑C'.u⁻¹ : R) ^ 2 - * (C'.r * 3 + W.a₂ - C'.s * W.a₁ - C'.s ^ 2) * pow_mul_pow_eq_one 4 C'.u.inv_mul - + -C.r * C.t * (↑C.u⁻¹ : R) ^ 6 * ↑C'.u⁻¹ * (C'.s * 2 + W.a₁) - * pow_mul_pow_eq_one 5 C'.u.inv_mul - + (↑C.u⁻¹ : R) ^ 6 * (C.r ^ 3 - C.t ^ 2) * pow_mul_pow_eq_one 6 C'.u.inv_mul + + C.r ^ 2 * C.u⁻¹ ^ 6 * C'.u⁻¹ ^ 2 * (C'.r * 3 + W.a₂ - C'.s * W.a₁ - C'.s ^ 2) + * pow_mul_pow_eq_one 4 C'.u.inv_mul + - C.r * C.t * C.u⁻¹ ^ 6 * C'.u⁻¹ * (C'.s * 2 + W.a₁) * pow_mul_pow_eq_one 5 C'.u.inv_mul + + C.u⁻¹ ^ 6 * (C.r ^ 3 - C.t ^ 2) * pow_mul_pow_eq_one 6 C'.u.inv_mul instance instMulActionVariableChange : MulAction (VariableChange R) (WeierstrassCurve R) where smul := fun C W => W.variableChange C @@ -312,27 +308,27 @@ instance instMulActionVariableChange : MulAction (VariableChange R) (Weierstrass mul_smul := variableChange_comp @[simp] -lemma variableChange_b₂ : (W.variableChange C).b₂ = (↑C.u⁻¹ : R) ^ 2 * (W.b₂ + 12 * C.r) := by +lemma variableChange_b₂ : (W.variableChange C).b₂ = C.u⁻¹ ^ 2 * (W.b₂ + 12 * C.r) := by simp only [b₂, variableChange_a₁, variableChange_a₂] ring1 #align weierstrass_curve.variable_change_b₂ WeierstrassCurve.variableChange_b₂ @[simp] lemma variableChange_b₄ : - (W.variableChange C).b₄ = (↑C.u⁻¹ : R) ^ 4 * (W.b₄ + C.r * W.b₂ + 6 * C.r ^ 2) := by + (W.variableChange C).b₄ = C.u⁻¹ ^ 4 * (W.b₄ + C.r * W.b₂ + 6 * C.r ^ 2) := by simp only [b₂, b₄, variableChange_a₁, variableChange_a₃, variableChange_a₄] ring1 #align weierstrass_curve.variable_change_b₄ WeierstrassCurve.variableChange_b₄ @[simp] lemma variableChange_b₆ : (W.variableChange C).b₆ = - (↑C.u⁻¹ : R) ^ 6 * (W.b₆ + 2 * C.r * W.b₄ + C.r ^ 2 * W.b₂ + 4 * C.r ^ 3) := by + C.u⁻¹ ^ 6 * (W.b₆ + 2 * C.r * W.b₄ + C.r ^ 2 * W.b₂ + 4 * C.r ^ 3) := by simp only [b₂, b₄, b₆, variableChange_a₃, variableChange_a₆] ring1 #align weierstrass_curve.variable_change_b₆ WeierstrassCurve.variableChange_b₆ @[simp] -lemma variableChange_b₈ : (W.variableChange C).b₈ = (↑C.u⁻¹ : R) ^ 8 * +lemma variableChange_b₈ : (W.variableChange C).b₈ = C.u⁻¹ ^ 8 * (W.b₈ + 3 * C.r * W.b₆ + 3 * C.r ^ 2 * W.b₄ + C.r ^ 3 * W.b₂ + 3 * C.r ^ 4) := by simp only [b₂, b₄, b₆, b₈, variableChange_a₁, variableChange_a₂, variableChange_a₃, variableChange_a₄, variableChange_a₆] @@ -340,19 +336,19 @@ lemma variableChange_b₈ : (W.variableChange C).b₈ = (↑C.u⁻¹ : R) ^ 8 * #align weierstrass_curve.variable_change_b₈ WeierstrassCurve.variableChange_b₈ @[simp] -lemma variableChange_c₄ : (W.variableChange C).c₄ = (↑C.u⁻¹ : R) ^ 4 * W.c₄ := by +lemma variableChange_c₄ : (W.variableChange C).c₄ = C.u⁻¹ ^ 4 * W.c₄ := by simp only [c₄, variableChange_b₂, variableChange_b₄] ring1 #align weierstrass_curve.variable_change_c₄ WeierstrassCurve.variableChange_c₄ @[simp] -lemma variableChange_c₆ : (W.variableChange C).c₆ = (↑C.u⁻¹ : R) ^ 6 * W.c₆ := by +lemma variableChange_c₆ : (W.variableChange C).c₆ = C.u⁻¹ ^ 6 * W.c₆ := by simp only [c₆, variableChange_b₂, variableChange_b₄, variableChange_b₆] ring1 #align weierstrass_curve.variable_change_c₆ WeierstrassCurve.variableChange_c₆ @[simp] -lemma variableChange_Δ : (W.variableChange C).Δ = (↑C.u⁻¹ : R) ^ 12 * W.Δ := by +lemma variableChange_Δ : (W.variableChange C).Δ = C.u⁻¹ ^ 12 * W.Δ := by simp only [b₂, b₄, b₆, b₈, Δ, variableChange_a₁, variableChange_a₂, variableChange_a₃, variableChange_a₄, variableChange_a₆] ring1 @@ -364,111 +360,109 @@ section BaseChange /-! ### Base changes -/ -variable (A : Type v) [CommRing A] [Algebra R A] (B : Type w) [CommRing B] [Algebra R B] - [Algebra A B] [IsScalarTower R A B] +variable {A : Type v} [CommRing A] (φ : R →+* A) {B : Type w} [CommRing B] (ψ : A →+* B) -/-- The Weierstrass curve over `R` base changed to `A`. -/ +/-- The Weierstrass curve base changed over a ring homomorphism `φ : R →+* A`. -/ @[pp_dot, simps] def baseChange : WeierstrassCurve A := - ⟨algebraMap R A W.a₁, algebraMap R A W.a₂, algebraMap R A W.a₃, algebraMap R A W.a₄, - algebraMap R A W.a₆⟩ + ⟨φ W.a₁, φ W.a₂, φ W.a₃, φ W.a₄, φ W.a₆⟩ #align weierstrass_curve.base_change WeierstrassCurve.baseChange @[simp] -lemma baseChange_b₂ : (W.baseChange A).b₂ = algebraMap R A W.b₂ := by +lemma baseChange_b₂ : (W.baseChange φ).b₂ = φ W.b₂ := by simp only [b₂, baseChange_a₁, baseChange_a₂] map_simp #align weierstrass_curve.base_change_b₂ WeierstrassCurve.baseChange_b₂ @[simp] -lemma baseChange_b₄ : (W.baseChange A).b₄ = algebraMap R A W.b₄ := by +lemma baseChange_b₄ : (W.baseChange φ).b₄ = φ W.b₄ := by simp only [b₄, baseChange_a₁, baseChange_a₃, baseChange_a₄] map_simp #align weierstrass_curve.base_change_b₄ WeierstrassCurve.baseChange_b₄ @[simp] -lemma baseChange_b₆ : (W.baseChange A).b₆ = algebraMap R A W.b₆ := by +lemma baseChange_b₆ : (W.baseChange φ).b₆ = φ W.b₆ := by simp only [b₆, baseChange_a₃, baseChange_a₆] map_simp #align weierstrass_curve.base_change_b₆ WeierstrassCurve.baseChange_b₆ @[simp] -lemma baseChange_b₈ : (W.baseChange A).b₈ = algebraMap R A W.b₈ := by +lemma baseChange_b₈ : (W.baseChange φ).b₈ = φ W.b₈ := by simp only [b₈, baseChange_a₁, baseChange_a₂, baseChange_a₃, baseChange_a₄, baseChange_a₆] map_simp #align weierstrass_curve.base_change_b₈ WeierstrassCurve.baseChange_b₈ @[simp] -lemma baseChange_c₄ : (W.baseChange A).c₄ = algebraMap R A W.c₄ := by +lemma baseChange_c₄ : (W.baseChange φ).c₄ = φ W.c₄ := by simp only [c₄, baseChange_b₂, baseChange_b₄] map_simp #align weierstrass_curve.base_change_c₄ WeierstrassCurve.baseChange_c₄ @[simp] -lemma baseChange_c₆ : (W.baseChange A).c₆ = algebraMap R A W.c₆ := by +lemma baseChange_c₆ : (W.baseChange φ).c₆ = φ W.c₆ := by simp only [c₆, baseChange_b₂, baseChange_b₄, baseChange_b₆] map_simp #align weierstrass_curve.base_change_c₆ WeierstrassCurve.baseChange_c₆ @[simp] -lemma baseChange_Δ : (W.baseChange A).Δ = algebraMap R A W.Δ := by +lemma baseChange_Δ : (W.baseChange φ).Δ = φ W.Δ := by simp only [Δ, baseChange_b₂, baseChange_b₄, baseChange_b₆, baseChange_b₈] map_simp #align weierstrass_curve.base_change_Δ WeierstrassCurve.baseChange_Δ -lemma baseChange_self : W.baseChange R = W := by - ext <;> rfl +lemma baseChange_self : W.baseChange (RingHom.id R) = W := + rfl #align weierstrass_curve.base_change_self WeierstrassCurve.baseChange_self -lemma baseChange_baseChange : (W.baseChange A).baseChange B = W.baseChange B := by - ext <;> exact (IsScalarTower.algebraMap_apply R A B _).symm +lemma baseChange_baseChange : (W.baseChange φ).baseChange ψ = W.baseChange (ψ.comp φ) := + rfl #align weierstrass_curve.base_change_base_change WeierstrassCurve.baseChange_baseChange -lemma baseChange_injective (h : Function.Injective <| algebraMap R A) : - Function.Injective <| baseChange (R := R) (A := A) := fun W W' h1 => by - rcases mk.inj h1 with ⟨_, _, _, _, _⟩ - ext <;> apply_fun _ using h <;> assumption +lemma baseChange_injective {φ : R →+* A} (hφ : Function.Injective φ) : + Function.Injective <| baseChange (φ := φ) := fun _ _ h => by + rcases mk.inj h with ⟨_, _, _, _, _⟩ + ext <;> apply_fun _ using hφ <;> assumption namespace VariableChange variable (C : VariableChange R) -/-- The change of variables over `R` base changed to `A`. -/ +/-- The change of variables base changed over a ring homomorphism `φ : R →+* A`. -/ @[simps] def baseChange : VariableChange A := - ⟨Units.map (algebraMap R A) C.u, algebraMap R A C.r, algebraMap R A C.s, algebraMap R A C.t⟩ + ⟨Units.map φ C.u, φ C.r, φ C.s, φ C.t⟩ -lemma baseChange_id : baseChange A (id : VariableChange R) = id := by +lemma baseChange_id : (id : VariableChange R).baseChange φ = id := by simp only [id, baseChange] ext <;> simp only [map_one, Units.val_one, map_zero] lemma baseChange_comp (C' : VariableChange R) : - baseChange A (C.comp C') = (baseChange A C).comp (baseChange A C') := by + (C.comp C').baseChange φ = (C.baseChange φ).comp (C'.baseChange φ) := by simp only [comp, baseChange] ext <;> map_simp <;> simp only [Units.coe_map, Units.coe_map_inv, MonoidHom.coe_coe] -/-- The base change to `A` of a change of variables over `R` is a group homomorphism. -/ +/-- The base change of a change of variables over a ring homomorphism is a group homomorphism. -/ def baseChangeMap : VariableChange R →* VariableChange A where - toFun := baseChange A - map_one' := baseChange_id A - map_mul' := baseChange_comp A + toFun := baseChange φ + map_one' := baseChange_id φ + map_mul' := baseChange_comp φ -lemma baseChange_self : C.baseChange R = C := +lemma baseChange_self : C.baseChange (RingHom.id R) = C := rfl -lemma baseChange_baseChange : (C.baseChange A).baseChange B = C.baseChange B := by - ext <;> exact (IsScalarTower.algebraMap_apply R A B _).symm +lemma baseChange_baseChange : (C.baseChange φ).baseChange ψ = C.baseChange (ψ.comp φ) := + rfl -lemma baseChange_injective (h : Function.Injective <| algebraMap R A) : - Function.Injective <| baseChange (R := R) A := fun C C' h1 => by - rcases mk.inj h1 with ⟨h1, _, _, _⟩ - replace h1 := (Units.mk.inj h1).left - ext <;> apply_fun _ using h <;> assumption +lemma baseChange_injective {φ : R →+* A} (hφ : Function.Injective φ) : + Function.Injective <| baseChange (φ := φ) := fun _ _ h => by + rcases mk.inj h with ⟨h, _, _, _⟩ + replace h := (Units.mk.inj h).left + ext <;> apply_fun _ using hφ <;> assumption end VariableChange lemma baseChange_variableChange (C : VariableChange R) : - (W.baseChange A).variableChange (C.baseChange A) = (W.variableChange C).baseChange A := by + (W.baseChange φ).variableChange (C.baseChange φ) = (W.variableChange C).baseChange φ := by simp only [baseChange, variableChange, VariableChange.baseChange] ext <;> map_simp <;> simp only [Units.coe_map, Units.coe_map_inv, MonoidHom.coe_coe] @@ -560,7 +554,7 @@ accurate for certain rings whose Picard group has trivial 12-torsion, such as a @[ext] structure EllipticCurve (R : Type u) [CommRing R] extends WeierstrassCurve R where Δ' : Rˣ - coe_Δ' : ↑Δ' = toWeierstrassCurve.Δ + coe_Δ' : Δ' = toWeierstrassCurve.Δ #align elliptic_curve EllipticCurve namespace EllipticCurve @@ -577,7 +571,7 @@ variable {R : Type u} [CommRing R] (E : EllipticCurve R) /-- The j-invariant `j` of an elliptic curve, which is invariant under isomorphisms over `R`. -/ @[pp_dot] def j : R := - ↑E.Δ'⁻¹ * E.c₄ ^ 3 + E.Δ'⁻¹ * E.c₄ ^ 3 #align elliptic_curve.j EllipticCurve.j lemma twoTorsionPolynomial_disc_ne_zero [Nontrivial R] [Invertible (2 : R)] : @@ -616,21 +610,20 @@ instance instMulActionVariableChange : one_smul := variableChange_id mul_smul := variableChange_comp -lemma coe_variableChange_Δ' : (↑(E.variableChange C).Δ' : R) = (↑C.u⁻¹ : R) ^ 12 * E.Δ' := by - rw [variableChange_Δ', Units.val_mul, Units.val_pow_eq_pow_val] +lemma coe_variableChange_Δ' : (E.variableChange C).Δ' = C.u⁻¹ ^ 12 * E.Δ' := + rfl #align elliptic_curve.coe_variable_change_Δ' EllipticCurve.coe_variableChange_Δ' -lemma coe_inv_variableChange_Δ' : - (↑(E.variableChange C).Δ'⁻¹ : R) = (C.u : R) ^ 12 * ↑E.Δ'⁻¹ := by - rw [variableChange_Δ', mul_inv, inv_pow, inv_inv, Units.val_mul, Units.val_pow_eq_pow_val] +lemma coe_inv_variableChange_Δ' : (E.variableChange C).Δ'⁻¹ = C.u ^ 12 * E.Δ'⁻¹ := by + rw [variableChange_Δ', mul_inv, inv_pow, inv_inv] #align elliptic_curve.coe_inv_variable_change_Δ' EllipticCurve.coe_inv_variableChange_Δ' @[simp] lemma variableChange_j : (E.variableChange C).j = E.j := by - rw [j, coe_inv_variableChange_Δ'] - have hu : (C.u * ↑C.u⁻¹ : R) ^ 12 = 1 := by rw [C.u.mul_inv, one_pow] - linear_combination (norm := (rw [variableChange_toWeierstrassCurve, - WeierstrassCurve.variableChange_c₄, j]; ring1)) E.j * hu + rw [j, coe_inv_variableChange_Δ', Units.val_mul, Units.val_pow_eq_pow_val, + variableChange_toWeierstrassCurve, WeierstrassCurve.variableChange_c₄] + have hu : (C.u * C.u⁻¹ : R) ^ 12 = 1 := by rw [C.u.mul_inv, one_pow] + linear_combination (norm := (rw [j]; ring1)) E.j * hu #align elliptic_curve.variable_change_j EllipticCurve.variableChange_j end VariableChange @@ -639,37 +632,37 @@ section BaseChange /-! ### Base changes -/ -variable (A : Type v) [CommRing A] [Algebra R A] +variable {A : Type v} [CommRing A] (φ : R →+* A) -- porting note: was just `@[simps]` -/-- The elliptic curve over `R` base changed to `A`. -/ +/-- The elliptic curve base changed over a ring homomorphism `φ : R →+* A`. -/ @[pp_dot, simps (config := { rhsMd := .default }) a₁ a₂ a₃ a₄ a₆ Δ' toWeierstrassCurve] def baseChange : EllipticCurve A := - ⟨E.toWeierstrassCurve.baseChange A, Units.map (↑(algebraMap R A)) E.Δ', + ⟨E.toWeierstrassCurve.baseChange φ, Units.map φ E.Δ', by simp only [Units.coe_map, coe_Δ', E.baseChange_Δ]; rfl⟩ #align elliptic_curve.base_change EllipticCurve.baseChange -lemma coeBaseChange_Δ' : ↑(E.baseChange A).Δ' = algebraMap R A E.Δ' := +lemma coeBaseChange_Δ' : (E.baseChange φ).Δ' = φ E.Δ' := rfl #align elliptic_curve.coe_base_change_Δ' EllipticCurve.coeBaseChange_Δ' -lemma coe_inv_baseChange_Δ' : ↑(E.baseChange A).Δ'⁻¹ = algebraMap R A ↑E.Δ'⁻¹ := +lemma coe_inv_baseChange_Δ' : (E.baseChange φ).Δ'⁻¹ = φ ↑E.Δ'⁻¹ := rfl #align elliptic_curve.coe_inv_base_change_Δ' EllipticCurve.coe_inv_baseChange_Δ' @[simp] -lemma baseChange_j : (E.baseChange A).j = algebraMap R A E.j := by +lemma baseChange_j : (E.baseChange φ).j = φ E.j := by simp only [j, baseChange, E.baseChange_c₄] map_simp rfl #align elliptic_curve.base_change_j EllipticCurve.baseChange_j -lemma baseChange_injective (h : Function.Injective <| algebraMap R A) : - Function.Injective <| baseChange (R := R) (A := A) := fun E E' h1 => by - rcases mk.inj h1 with ⟨h1, h2⟩ +lemma baseChange_injective {φ : R →+* A} (hφ : Function.Injective φ) : + Function.Injective <| baseChange (φ := φ) := fun _ _ h => by + rcases mk.inj h with ⟨h1, h2⟩ replace h2 := (Units.mk.inj h2).left rcases WeierstrassCurve.mk.inj h1 with ⟨_, _, _, _, _⟩ - ext <;> apply_fun _ using h <;> assumption + ext <;> apply_fun _ using hφ <;> assumption end BaseChange diff --git a/Mathlib/AlgebraicGeometry/Limits.lean b/Mathlib/AlgebraicGeometry/Limits.lean index 29a3e37e415e9..918b1807523fb 100644 --- a/Mathlib/AlgebraicGeometry/Limits.lean +++ b/Mathlib/AlgebraicGeometry/Limits.lean @@ -96,7 +96,7 @@ instance (priority := 100) isOpenImmersion_of_isEmpty {X Y : Scheme} (f : X ⟶ · apply openEmbedding_of_continuous_injective_open · continuity · rintro (i : X.carrier); exact isEmptyElim i - · intro U _; convert isOpen_empty (α := Y); ext; rw [Set.mem_empty_iff_false, iff_false_iff] + · intro U _; convert isOpen_empty (X := Y); ext; rw [Set.mem_empty_iff_false, iff_false_iff] exact fun x => isEmptyElim (show X.carrier from x.choose) · rintro (i : X.carrier); exact isEmptyElim i #align algebraic_geometry.is_open_immersion_of_is_empty AlgebraicGeometry.isOpenImmersion_of_isEmpty diff --git a/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean b/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean index b9aba7a2bb1bf..6247403ae8e27 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean @@ -57,7 +57,7 @@ theorem universallyClosed_stableUnderBaseChange : StableUnderBaseChange @Univers theorem universallyClosed_stableUnderComposition : StableUnderComposition @UniversallyClosed := by rw [universallyClosed_eq] exact StableUnderComposition.universally (fun X Y Z f g hf hg => - @IsClosedMap.comp _ _ _ _ _ _ g.1.base f.1.base hg hf) + IsClosedMap.comp (f := f.1.base) (g := g.1.base) hg hf) #align algebraic_geometry.universally_closed_stable_under_composition AlgebraicGeometry.universallyClosed_stableUnderComposition instance universallyClosedTypeComp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) @@ -84,7 +84,7 @@ theorem universallyClosed_is_local_at_target : PropertyIsLocalAtTarget @Universa rw [universallyClosed_eq] apply universallyIsLocalAtTargetOfMorphismRestrict · exact StableUnderComposition.respectsIso (fun X Y Z f g hf hg => - @IsClosedMap.comp _ _ _ _ _ _ g.1.base f.1.base hg hf) + IsClosedMap.comp (f := f.1.base) (g := g.1.base) hg hf) (fun f => (TopCat.homeoOfIso (Scheme.forgetToTop.mapIso f)).isClosedMap) · intro X Y f ι U hU H simp_rw [topologically, morphismRestrict_base] at H diff --git a/Mathlib/AlgebraicGeometry/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/OpenImmersion.lean index 82829800fab70..96f7efa185333 100644 --- a/Mathlib/AlgebraicGeometry/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/OpenImmersion.lean @@ -87,7 +87,7 @@ structure OpenCover (X : Scheme.{u}) where /-- index set of an open cover of a scheme `X` -/ J : Type v /-- the subschemes of an open cover -/ - obj : ∀ _ : J, Scheme + obj : J → Scheme /-- the embedding of subschemes to `X` -/ map : ∀ j : J, obj j ⟶ X /-- given a point of `x : X`, `f x` is the index of the subscheme which contains `x` -/ diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean index d396af7afdcd6..4f4c3d8d2614e 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean @@ -15,9 +15,9 @@ import Mathlib.Topology.Sober #align_import algebraic_geometry.prime_spectrum.basic from "leanprover-community/mathlib"@"a7c017d750512a352b623b1824d75da5998457d0" /-! -# Prime spectrum of a commutative ring +# Prime spectrum of a commutative (semi)ring -The prime spectrum of a commutative ring is the type of all prime ideals. +The prime spectrum of a commutative (semi)ring is the type of all prime ideals. It is naturally endowed with a topology: the Zariski topology. (It is also naturally endowed with a sheaf of rings, @@ -25,7 +25,7 @@ which is constructed in `AlgebraicGeometry.StructureSheaf`.) ## Main definitions -* `PrimeSpectrum R`: The prime spectrum of a commutative ring `R`, +* `PrimeSpectrum R`: The prime spectrum of a commutative (semi)ring `R`, i.e., the set of all prime ideals of `R`. * `zeroLocus s`: The zero locus of a subset `s` of `R` is the subset of `PrimeSpectrum R` consisting of all prime ideals that contain `s`. @@ -34,7 +34,7 @@ which is constructed in `AlgebraicGeometry.StructureSheaf`.) ## Conventions -We denote subsets of rings with `s`, `s'`, etc... +We denote subsets of (semi)rings with `s`, `s'`, etc... whereas we denote subsets of prime spectra with `t`, `t'`, etc... ## Inspiration/contributors @@ -51,15 +51,15 @@ open Classical universe u v -variable (R : Type u) (S : Type v) [CommRing R] [CommRing S] +variable (R : Type u) (S : Type v) -/-- The prime spectrum of a commutative ring `R` is the type of all prime ideals of `R`. +/-- The prime spectrum of a commutative (semi)ring `R` is the type of all prime ideals of `R`. It is naturally endowed with a topology (the Zariski topology), and a sheaf of commutative rings (see `AlgebraicGeometry.StructureSheaf`). It is a fundamental building block in algebraic geometry. -/ @[ext] -structure PrimeSpectrum where +structure PrimeSpectrum [CommSemiring R] where asIdeal : Ideal R IsPrime : asIdeal.IsPrime #align prime_spectrum PrimeSpectrum @@ -68,6 +68,10 @@ attribute [instance] PrimeSpectrum.IsPrime namespace PrimeSpectrum +section CommSemiRing + +variable [CommSemiring R] [CommSemiring S] + variable {R S} instance [Nontrivial R] : Nonempty <| PrimeSpectrum R := @@ -123,8 +127,8 @@ theorem primeSpectrumProd_symm_inr_asIdeal (x : PrimeSpectrum S) : rfl #align prime_spectrum.prime_spectrum_prod_symm_inr_as_ideal PrimeSpectrum.primeSpectrumProd_symm_inr_asIdeal -/-- The zero locus of a set `s` of elements of a commutative ring `R` is the set of all prime ideals -of the ring that contain the set `s`. +/-- The zero locus of a set `s` of elements of a commutative (semi)ring `R` is the set of all +prime ideals of the ring that contain the set `s`. An element `f` of `R` can be thought of as a dependent function on the prime spectrum of `R`. At a point `x` (a prime ideal) the function (i.e., element) `f` takes values in the quotient ring @@ -395,8 +399,8 @@ theorem mem_compl_zeroLocus_iff_not_mem {f : R} {I : PrimeSpectrum R} : rw [Set.mem_compl_iff, mem_zeroLocus, Set.singleton_subset_iff]; rfl #align prime_spectrum.mem_compl_zero_locus_iff_not_mem PrimeSpectrum.mem_compl_zeroLocus_iff_not_mem -/-- The Zariski topology on the prime spectrum of a commutative ring is defined via the closed sets -of the topology: they are exactly those sets that are the zero locus of a subset of the ring. -/ +/-- The Zariski topology on the prime spectrum of a commutative (semi)ring is defined via the closed +sets of the topology: they are exactly those sets that are the zero locus of a subset of the ring.-/ instance zariskiTopology : TopologicalSpace (PrimeSpectrum R) := TopologicalSpace.ofClosed (Set.range PrimeSpectrum.zeroLocus) ⟨Set.univ, by simp⟩ (by @@ -484,7 +488,7 @@ theorem vanishingIdeal_strict_anti_mono_iff {s t : Set (PrimeSpectrum R)} (hs : #align prime_spectrum.vanishing_ideal_strict_anti_mono_iff PrimeSpectrum.vanishingIdeal_strict_anti_mono_iff /-- The antitone order embedding of closed subsets of `Spec R` into ideals of `R`. -/ -def closedsEmbedding (R : Type*) [CommRing R] : +def closedsEmbedding (R : Type*) [CommSemiring R] : (TopologicalSpace.Closeds <| PrimeSpectrum R)ᵒᵈ ↪o Ideal R := OrderEmbedding.ofMapLEIff (fun s => vanishingIdeal ↑(OrderDual.ofDual s)) fun s _ => (vanishingIdeal_anti_mono_iff s.2).symm @@ -502,7 +506,7 @@ theorem t1Space_iff_isField [IsDomain R] : T1Space (PrimeSpectrum R) ↔ IsField (by aesop)) · refine' ⟨fun x => (isClosed_singleton_iff_isMaximal x).2 _⟩ by_cases hx : x.asIdeal = ⊥ - · letI := h.toField + · letI := h.toSemifield exact hx.symm ▸ Ideal.bot_isMaximal · exact absurd h (Ring.not_isField_iff_exists_prime.2 ⟨x.asIdeal, ⟨hx, x.2⟩⟩) #align prime_spectrum.t1_space_iff_is_field PrimeSpectrum.t1Space_iff_isField @@ -545,13 +549,13 @@ theorem isIrreducible_iff_vanishingIdeal_isPrime {s : Set (PrimeSpectrum R)} : isIrreducible_zeroLocus_iff_of_radical _ (isRadical_vanishingIdeal s)] #align prime_spectrum.is_irreducible_iff_vanishing_ideal_is_prime PrimeSpectrum.isIrreducible_iff_vanishingIdeal_isPrime -lemma vanishingIdeal_isIrreducible {R} [CommRing R] : +lemma vanishingIdeal_isIrreducible : vanishingIdeal (R := R) '' {s | IsIrreducible s} = {P | P.IsPrime} := Set.ext fun I ↦ ⟨fun ⟨_, hs, e⟩ ↦ e ▸ isIrreducible_iff_vanishingIdeal_isPrime.mp hs, fun h ↦ ⟨zeroLocus I, (isIrreducible_zeroLocus_iff_of_radical _ h.isRadical).mpr h, (vanishingIdeal_zeroLocus_eq_radical I).trans h.radical⟩⟩ -lemma vanishingIdeal_isClosed_isIrreducible {R} [CommRing R] : +lemma vanishingIdeal_isClosed_isIrreducible : vanishingIdeal (R := R) '' {s | IsClosed s ∧ IsIrreducible s} = {P | P.IsPrime} := by refine (subset_antisymm ?_ ?_).trans vanishingIdeal_isIrreducible · exact Set.image_subset _ fun _ ↦ And.right @@ -567,7 +571,7 @@ instance quasiSober : QuasiSober (PrimeSpectrum R) := ⟨⟨_, isIrreducible_iff_vanishingIdeal_isPrime.1 h₁⟩, by rw [IsGenericPoint, closure_singleton, zeroLocus_vanishingIdeal_eq_closure, h₂.closure_eq]⟩⟩ -/-- The prime spectrum of a commutative ring is a compact topological space. -/ +/-- The prime spectrum of a commutative (semi)ring is a compact topological space. -/ instance compactSpace : CompactSpace (PrimeSpectrum R) := by refine compactSpace_of_finite_subfamily_closed fun S S_closed S_empty ↦ ?_ choose I hI using fun i ↦ (isClosed_iff_zeroLocus_ideal (S i)).mp (S_closed i) @@ -576,7 +580,7 @@ instance compactSpace : CompactSpace (PrimeSpectrum R) := by section Comap -variable {S' : Type*} [CommRing S'] +variable {S' : Type*} [CommSemiring S'] theorem preimage_comap_zeroLocus_aux (f : R →+* S) (s : Set R) : (fun y => ⟨Ideal.comap f y.asIdeal, inferInstance⟩ : PrimeSpectrum S → PrimeSpectrum R) ⁻¹' @@ -586,7 +590,7 @@ theorem preimage_comap_zeroLocus_aux (f : R →+* S) (s : Set R) : simp only [mem_zeroLocus, Set.image_subset_iff, Set.mem_preimage, mem_zeroLocus, Ideal.coe_comap] #align prime_spectrum.preimage_comap_zero_locus_aux PrimeSpectrum.preimage_comap_zeroLocus_aux -/-- The function between prime spectra of commutative rings induced by a ring homomorphism. +/-- The function between prime spectra of commutative (semi)rings induced by a ring homomorphism. This function is continuous. -/ def comap (f : R →+* S) : C(PrimeSpectrum S, PrimeSpectrum R) where toFun y := ⟨Ideal.comap f y.asIdeal, inferInstance⟩ @@ -631,21 +635,6 @@ theorem comap_injective_of_surjective (f : R →+* S) (hf : Function.Surjective (congr_arg PrimeSpectrum.asIdeal h : (comap f x).asIdeal = (comap f y).asIdeal)) #align prime_spectrum.comap_injective_of_surjective PrimeSpectrum.comap_injective_of_surjective -theorem comap_singleton_isClosed_of_surjective (f : R →+* S) (hf : Function.Surjective f) - (x : PrimeSpectrum S) (hx : IsClosed ({x} : Set (PrimeSpectrum S))) : - IsClosed ({comap f x} : Set (PrimeSpectrum R)) := - haveI : x.asIdeal.IsMaximal := (isClosed_singleton_iff_isMaximal x).1 hx - (isClosed_singleton_iff_isMaximal _).2 (Ideal.comap_isMaximal_of_surjective f hf) -#align prime_spectrum.comap_singleton_is_closed_of_surjective PrimeSpectrum.comap_singleton_isClosed_of_surjective - -theorem comap_singleton_isClosed_of_isIntegral (f : R →+* S) (hf : f.IsIntegral) - (x : PrimeSpectrum S) (hx : IsClosed ({x} : Set (PrimeSpectrum S))) : - IsClosed ({comap f x} : Set (PrimeSpectrum R)) := - (isClosed_singleton_iff_isMaximal _).2 - (Ideal.isMaximal_comap_of_isIntegral_of_isMaximal' f hf x.asIdeal <| - (isClosed_singleton_iff_isMaximal x).1 hx) -#align prime_spectrum.comap_singleton_is_closed_of_is_integral PrimeSpectrum.comap_singleton_isClosed_of_isIntegral - variable (S) theorem localization_comap_inducing [Algebra R S] (M : Submonoid R) [IsLocalization M S] : @@ -653,7 +642,7 @@ theorem localization_comap_inducing [Algebra R S] (M : Submonoid R) [IsLocalizat constructor rw [TopologicalSpace.ext_iff] intro U - rw [← isClosed_compl_iff, ← @isClosed_compl_iff (α := PrimeSpectrum S) (s := U)] + rw [← isClosed_compl_iff, ← @isClosed_compl_iff (X := PrimeSpectrum S) (s := U)] generalize Uᶜ = Z simp_rw [isClosed_induced_iff, isClosed_iff_zeroLocus] constructor @@ -696,11 +685,6 @@ theorem localization_comap_range [Algebra R S] (M : Submonoid R) [IsLocalization exact IsLocalization.comap_map_of_isPrime_disjoint M S _ x.2 h #align prime_spectrum.localization_comap_range PrimeSpectrum.localization_comap_range -section SpecOfSurjective - -/-! The comap of a surjective ring homomorphism is a closed embedding between the prime spectra. -/ - - open Function RingHom theorem comap_inducing_of_surjective (hf : Surjective f) : Inducing (comap f) where @@ -718,6 +702,36 @@ theorem comap_inducing_of_surjective (hf : Surjective f) : Inducing (comap f) wh exact ⟨f '' F, hF.symm.trans (preimage_comap_zeroLocus f F)⟩ #align prime_spectrum.comap_inducing_of_surjective PrimeSpectrum.comap_inducing_of_surjective + +end Comap +end CommSemiRing + +section SpecOfSurjective + +/-! The comap of a surjective ring homomorphism is a closed embedding between the prime spectra. -/ + + +open Function RingHom + +variable [CommRing R] [CommRing S] +variable (f : R →+* S) +variable {R} + +theorem comap_singleton_isClosed_of_surjective (f : R →+* S) (hf : Function.Surjective f) + (x : PrimeSpectrum S) (hx : IsClosed ({x} : Set (PrimeSpectrum S))) : + IsClosed ({comap f x} : Set (PrimeSpectrum R)) := + haveI : x.asIdeal.IsMaximal := (isClosed_singleton_iff_isMaximal x).1 hx + (isClosed_singleton_iff_isMaximal _).2 (Ideal.comap_isMaximal_of_surjective f hf) +#align prime_spectrum.comap_singleton_is_closed_of_surjective PrimeSpectrum.comap_singleton_isClosed_of_surjective + +theorem comap_singleton_isClosed_of_isIntegral (f : R →+* S) (hf : f.IsIntegral) + (x : PrimeSpectrum S) (hx : IsClosed ({x} : Set (PrimeSpectrum S))) : + IsClosed ({comap f x} : Set (PrimeSpectrum R)) := + (isClosed_singleton_iff_isMaximal _).2 + (Ideal.isMaximal_comap_of_isIntegral_of_isMaximal' f hf x.asIdeal <| + (isClosed_singleton_iff_isMaximal x).1 hx) +#align prime_spectrum.comap_singleton_is_closed_of_is_integral PrimeSpectrum.comap_singleton_isClosed_of_isIntegral + theorem image_comap_zeroLocus_eq_zeroLocus_comap (hf : Surjective f) (I : Ideal S) : comap f '' zeroLocus I = zeroLocus (I.comap f) := by simp only [Set.ext_iff, Set.mem_image, mem_zeroLocus, SetLike.coe_subset_coe] @@ -758,7 +772,10 @@ theorem closedEmbedding_comap_of_surjective (hf : Surjective f) : ClosedEmbeddin end SpecOfSurjective -end Comap +section CommSemiRing + +variable [CommSemiring R] [CommSemiring S] +variable {R S} section BasicOpen @@ -848,7 +865,7 @@ theorem basicOpen_eq_bot_iff (f : R) : basicOpen f = ⊥ ↔ IsNilpotent f := by exact ⟨fun h I hI => h ⟨I, hI⟩, fun h ⟨I, hI⟩ => h I hI⟩ #align prime_spectrum.basic_open_eq_bot_iff PrimeSpectrum.basicOpen_eq_bot_iff -theorem localization_away_comap_range (S : Type v) [CommRing S] [Algebra R S] (r : R) +theorem localization_away_comap_range (S : Type v) [CommSemiring S] [Algebra R S] (r : R) [IsLocalization.Away r S] : Set.range (comap (algebraMap R S)) = basicOpen r := by rw [localization_comap_range S (Submonoid.powers r)] ext x @@ -861,7 +878,7 @@ theorem localization_away_comap_range (S : Type v) [CommRing S] [Algebra R S] (r exact h₁ (x.2.mem_of_pow_mem _ h₃) #align prime_spectrum.localization_away_comap_range PrimeSpectrum.localization_away_comap_range -theorem localization_away_openEmbedding (S : Type v) [CommRing S] [Algebra R S] (r : R) +theorem localization_away_openEmbedding (S : Type v) [CommSemiring S] [Algebra R S] (r : R) [IsLocalization.Away r S] : OpenEmbedding (comap (algebraMap R S)) := { toEmbedding := localization_comap_embedding S (Submonoid.powers r) open_range := by @@ -952,8 +969,13 @@ protected def pointsEquivIrreducibleCloseds : map_rel_iff' {p q} := (RelIso.symm irreducibleSetEquivPoints).map_rel_iff.trans (le_iff_specializes p q).symm +end CommSemiRing + end PrimeSpectrum +section CommSemiring +variable [CommSemiring R] + open PrimeSpectrum in /-- [Stacks: Lemma 00ES (3)](https://stacks.math.columbia.edu/tag/00ES) @@ -1002,9 +1024,11 @@ lemma zeroLocus_ideal_mem_irreducibleComponents {I : Ideal R} : end PrimeSpectrum +end CommSemiring + namespace LocalRing -variable [LocalRing R] +variable [CommSemiring R] [LocalRing R] /-- The closed point in the prime spectrum of a local ring. -/ def closedPoint : PrimeSpectrum R := @@ -1013,8 +1037,8 @@ def closedPoint : PrimeSpectrum R := variable {R} -theorem isLocalRingHom_iff_comap_closedPoint {S : Type v} [CommRing S] [LocalRing S] (f : R →+* S) : - IsLocalRingHom f ↔ PrimeSpectrum.comap f (closedPoint S) = closedPoint R := by +theorem isLocalRingHom_iff_comap_closedPoint {S : Type v} [CommSemiring S] [LocalRing S] + (f : R →+* S) : IsLocalRingHom f ↔ PrimeSpectrum.comap f (closedPoint S) = closedPoint R := by -- Porting note : inline `this` does **not** work have := (local_hom_TFAE f).out 0 4 rw [this, PrimeSpectrum.ext_iff] @@ -1022,8 +1046,8 @@ theorem isLocalRingHom_iff_comap_closedPoint {S : Type v} [CommRing S] [LocalRin #align local_ring.is_local_ring_hom_iff_comap_closed_point LocalRing.isLocalRingHom_iff_comap_closedPoint @[simp] -theorem comap_closedPoint {S : Type v} [CommRing S] [LocalRing S] (f : R →+* S) [IsLocalRingHom f] : - PrimeSpectrum.comap f (closedPoint S) = closedPoint R := +theorem comap_closedPoint {S : Type v} [CommSemiring S] [LocalRing S] (f : R →+* S) + [IsLocalRingHom f] : PrimeSpectrum.comap f (closedPoint S) = closedPoint R := (isLocalRingHom_iff_comap_closedPoint f).mp inferInstance #align local_ring.comap_closed_point LocalRing.comap_closedPoint @@ -1041,8 +1065,8 @@ theorem closedPoint_mem_iff (U : TopologicalSpace.Opens <| PrimeSpectrum R) : #align local_ring.closed_point_mem_iff LocalRing.closedPoint_mem_iff @[simp] -theorem PrimeSpectrum.comap_residue (x : PrimeSpectrum (ResidueField R)) : - PrimeSpectrum.comap (residue R) x = closedPoint R := by +theorem PrimeSpectrum.comap_residue (T : Type u) [CommRing T] [LocalRing T] + (x : PrimeSpectrum (ResidueField T)) : PrimeSpectrum.comap (residue T) x = closedPoint T := by rw [Subsingleton.elim x ⊥] ext1 exact Ideal.mk_ker diff --git a/Mathlib/AlgebraicGeometry/Spec.lean b/Mathlib/AlgebraicGeometry/Spec.lean index 4e103f98edae2..40064439fa014 100644 --- a/Mathlib/AlgebraicGeometry/Spec.lean +++ b/Mathlib/AlgebraicGeometry/Spec.lean @@ -117,7 +117,7 @@ theorem Spec.sheafedSpaceMap_id {R : CommRingCat} : AlgebraicGeometry.PresheafedSpace.Hom.ext _ _ (Spec.topMap_id R) <| by ext U dsimp - erw [NatTrans.comp_app, sheafedSpaceMap_c_app, PresheafedSpace.id_c_app, comap_id]; swap + erw [PresheafedSpace.id_c_app, comap_id]; swap · rw [Spec.topMap_id, TopologicalSpace.Opens.map_id_obj_unop] simp [eqToHom_map] set_option linter.uppercaseLean3 false in diff --git a/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean b/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean index 362a3da24f2e0..43f1e34af8c57 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.AlgebraicTopology.DoldKan.SplitSimplicialObject +import Mathlib.AlgebraicTopology.SplitSimplicialObject +import Mathlib.AlgebraicTopology.DoldKan.PInfty #align_import algebraic_topology.dold_kan.functor_gamma from "leanprover-community/mathlib"@"32a7e535287f9c73f2e4d2aef306a39190f0b504" diff --git a/Mathlib/AlgebraicTopology/DoldKan/GammaCompN.lean b/Mathlib/AlgebraicTopology/DoldKan/GammaCompN.lean index 0f9927406eb58..66a41489f4055 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/GammaCompN.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/GammaCompN.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.AlgebraicTopology.DoldKan.FunctorGamma +import Mathlib.AlgebraicTopology.DoldKan.SplitSimplicialObject import Mathlib.CategoryTheory.Idempotents.HomologicalComplex #align_import algebraic_topology.dold_kan.gamma_comp_n from "leanprover-community/mathlib"@"32a7e535287f9c73f2e4d2aef306a39190f0b504" diff --git a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean index 90854e42090ec..d61c3bd48f37b 100644 --- a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean +++ b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean @@ -168,7 +168,7 @@ set_option linter.uppercaseLean3 false in #align sSet.augmented.standard_simplex.shift_fun_succ SSet.Augmented.StandardSimplex.shiftFun_succ /-- The shift of a morphism `f : [n] → Δ` in `SimplexCategory` corresponds to -the monotone map which sends `0` to `0` and `i.succ` to `f.to_order_hom i`. -/ +the monotone map which sends `0` to `0` and `i.succ` to `f.toOrderHom i`. -/ @[simp] def shift {n : ℕ} {Δ : SimplexCategory} (f : ([n] : SimplexCategory) ⟶ Δ) : ([n + 1] : SimplexCategory) ⟶ Δ := @@ -189,31 +189,38 @@ def shift {n : ℕ} {Δ : SimplexCategory} set_option linter.uppercaseLean3 false in #align sSet.augmented.standard_simplex.shift SSet.Augmented.StandardSimplex.shift +open SSet.standardSimplex in /-- The obvious extra degeneracy on the standard simplex. -/ protected noncomputable def extraDegeneracy (Δ : SimplexCategory) : SimplicialObject.Augmented.ExtraDegeneracy (standardSimplex.obj Δ) where - s' _ := SimplexCategory.Hom.mk (OrderHom.const _ 0) - s n f := shift f + s' _ := objMk (OrderHom.const _ 0) + s n f := (objEquiv _ _).symm + (shift (objEquiv _ _ f)) s'_comp_ε := by dsimp apply Subsingleton.elim s₀_comp_δ₁ := by + dsimp ext1 x - apply SimplexCategory.Hom.ext + apply (objEquiv _ _).injective ext j fin_cases j rfl s_comp_δ₀ n := by ext1 φ + apply (objEquiv _ _).injective apply SimplexCategory.Hom.ext ext i : 2 - dsimp [SimplicialObject.δ, SimplexCategory.δ, SSet.standardSimplex] + dsimp [SimplicialObject.δ, SimplexCategory.δ, SSet.standardSimplex, + objEquiv, Equiv.ulift, uliftFunctor] simp only [shiftFun_succ] s_comp_δ n i := by ext1 φ + apply (objEquiv _ _).injective apply SimplexCategory.Hom.ext ext j : 2 - dsimp [SimplicialObject.δ, SimplexCategory.δ, SSet.standardSimplex] + dsimp [SimplicialObject.δ, SimplexCategory.δ, SSet.standardSimplex, + objEquiv, Equiv.ulift, uliftFunctor] by_cases h : j = 0 · subst h simp only [Fin.succ_succAbove_zero, shiftFun_0] @@ -222,13 +229,14 @@ protected noncomputable def extraDegeneracy (Δ : SimplexCategory) : Fin.succAboveEmb_apply] s_comp_σ n i := by ext1 φ + apply (objEquiv _ _).injective apply SimplexCategory.Hom.ext ext j : 2 - dsimp [SimplicialObject.σ, SimplexCategory.σ, SSet.standardSimplex] + dsimp [SimplicialObject.σ, SimplexCategory.σ, SSet.standardSimplex, + objEquiv, Equiv.ulift, uliftFunctor] by_cases h : j = 0 · subst h - simp only [shiftFun_0] - exact shiftFun_0 φ.toOrderHom + rfl · obtain ⟨_, rfl⟩ := Fin.eq_succ_of_ne_zero h simp only [Fin.succ_predAbove_succ, shiftFun_succ, Function.comp_apply] set_option linter.uppercaseLean3 false in diff --git a/Mathlib/AlgebraicTopology/Quasicategory.lean b/Mathlib/AlgebraicTopology/Quasicategory.lean index 43984872f3089..3397073352f9a 100644 --- a/Mathlib/AlgebraicTopology/Quasicategory.lean +++ b/Mathlib/AlgebraicTopology/Quasicategory.lean @@ -34,8 +34,8 @@ every map of simplicial sets `σ₀ : Λ[n, i] → S` can be extended to a map ` [Kerodon, 003A] -/ class Quasicategory (S : SSet) : Prop where hornFilling' : ∀ ⦃n : ℕ⦄ ⦃i : Fin (n+3)⦄ (σ₀ : Λ[n+2, i] ⟶ S) - (_h0 : 0 < i) (_hn : i < Fin.last (n+2)), - ∃ σ : Δ[n+2] ⟶ S, σ₀ = hornInclusion (n+2) i ≫ σ + (_h0 : 0 < i) (_hn : i < Fin.last (n+2)), + ∃ σ : Δ[n+2] ⟶ S, σ₀ = hornInclusion (n+2) i ≫ σ lemma Quasicategory.hornFilling {S : SSet} [Quasicategory S] ⦃n : ℕ⦄ ⦃i : Fin (n+1)⦄ (h0 : 0 < i) (hn : i < Fin.last n) @@ -55,4 +55,17 @@ lemma Quasicategory.hornFilling {S : SSet} [Quasicategory S] ⦃n : ℕ⦄ ⦃i instance (S : SSet) [KanComplex S] : Quasicategory S where hornFilling' _ _ σ₀ _ _ := KanComplex.hornFilling σ₀ +lemma quasicategory_of_filler (S : SSet) + (filler : ∀ ⦃n : ℕ⦄ ⦃i : Fin (n+3)⦄ (σ₀ : Λ[n+2, i] ⟶ S) + (_h0 : 0 < i) (_hn : i < Fin.last (n+2)), + ∃ σ : S _[n+2], ∀ (j) (h : j ≠ i), S.δ j σ = σ₀.app _ (horn.face i j h)) : + Quasicategory S where + hornFilling' n i σ₀ h₀ hₙ := by + obtain ⟨σ, h⟩ := filler σ₀ h₀ hₙ + refine' ⟨(S.yonedaEquiv _).symm σ, _⟩ + apply horn.hom_ext + intro j hj + rw [← h j hj, NatTrans.comp_app] + rfl + end SSet diff --git a/Mathlib/AlgebraicTopology/SimplexCategory.lean b/Mathlib/AlgebraicTopology/SimplexCategory.lean index a04e56aa8a06e..1aef771a54ef3 100644 --- a/Mathlib/AlgebraicTopology/SimplexCategory.lean +++ b/Mathlib/AlgebraicTopology/SimplexCategory.lean @@ -85,7 +85,7 @@ theorem mk_len (n : SimplexCategory) : ([n.len] : SimplexCategory) = n := #align simplex_category.mk_len SimplexCategory.mk_len /-- A recursor for `SimplexCategory`. Use it as `induction Δ using SimplexCategory.rec`. -/ -protected def rec {F : ∀ _ : SimplexCategory, Sort*} (h : ∀ n : ℕ, F [n]) : ∀ X, F X := fun n => +protected def rec {F : SimplexCategory → Sort*} (h : ∀ n : ℕ, F [n]) : ∀ X, F X := fun n => h n.len #align simplex_category.rec SimplexCategory.rec @@ -256,16 +256,22 @@ theorem δ_comp_δ_self' {n} {i : Fin (n + 2)} {j : Fin (n + 3)} (H : j = Fin.ca @[reassoc] theorem δ_comp_σ_of_le {n} {i : Fin (n + 2)} {j : Fin (n + 1)} (H : i ≤ Fin.castSucc j) : δ (Fin.castSucc i) ≫ σ j.succ = σ j ≫ δ i := by - rcases i with ⟨i, hi⟩ - rcases j with ⟨j, hj⟩ - ext ⟨k, hk⟩ - simp? at H hk says simp only [Fin.castSucc_mk, Fin.mk_le_mk, len_mk] at H hk - dsimp [σ, δ, Fin.predAbove, Fin.succAbove] - simp only [Fin.lt_iff_val_lt_val, Fin.dite_val, Fin.ite_val, Fin.coe_pred, ge_iff_le, - Fin.coe_castLT, dite_eq_ite, Fin.coe_castSucc, Fin.val_succ] - split_ifs - all_goals try simp <;> linarith - all_goals cases k <;> simp at * <;> linarith + ext k : 3 + dsimp [σ, δ] + rcases le_or_lt i k with (hik | hik) + · rw [Fin.succAbove_above _ _ (Fin.castSucc_le_castSucc_iff.mpr hik), + Fin.succ_predAbove_succ, Fin.succAbove_above] + rcases le_or_lt k (j.castSucc) with (hjk | hjk) + · rwa [Fin.predAbove_below _ _ hjk, Fin.castSucc_castPred] + · rw [Fin.le_castSucc_iff, Fin.predAbove_above _ _ hjk, Fin.succ_pred] + exact H.trans_lt hjk + · rw [Fin.succAbove_below _ _ (Fin.castSucc_lt_castSucc_iff.mpr hik)] + have hjk := H.trans_lt' hik + rw [Fin.predAbove_below _ _ (Fin.castSucc_le_castSucc_iff.mpr + (hjk.trans (Fin.castSucc_lt_succ _)).le), + Fin.predAbove_below _ _ hjk.le, Fin.castPred_castSucc, Fin.succAbove_below, + Fin.castSucc_castPred] + rwa [Fin.castSucc_castPred] #align simplex_category.δ_comp_σ_of_le SimplexCategory.δ_comp_σ_of_le /-- The first part of the third simplicial identity -/ @@ -311,16 +317,23 @@ theorem δ_comp_σ_succ' {n} (j : Fin (n + 2)) (i : Fin (n + 1)) (H : j = i.succ @[reassoc] theorem δ_comp_σ_of_gt {n} {i : Fin (n + 2)} {j : Fin (n + 1)} (H : Fin.castSucc j < i) : δ i.succ ≫ σ (Fin.castSucc j) = σ j ≫ δ i := by - ext ⟨k, hk⟩ - rcases i with ⟨i, hi⟩ - rcases j with ⟨j, hj⟩ - simp? at H hk says simp only [Fin.castSucc_mk, Fin.mk_lt_mk, len_mk] at H hk - dsimp [δ, σ, Fin.predAbove, Fin.succAbove] - simp only [Fin.lt_iff_val_lt_val, Fin.dite_val, Fin.ite_val, Fin.coe_pred, ge_iff_le, - Fin.coe_castLT, dite_eq_ite, Fin.coe_castSucc, Fin.val_succ] - split_ifs - all_goals try simp <;> linarith - all_goals cases k <;> simp at * <;> linarith + ext k : 3 + dsimp [δ, σ] + rcases le_or_lt k i with (hik | hik) + · rw [Fin.succAbove_below _ _ (Fin.castSucc_lt_succ_iff.mpr hik)] + rcases le_or_lt k (j.castSucc) with (hjk | hjk) + · rw [Fin.predAbove_below _ _ (Fin.castSucc_le_castSucc_iff.mpr hjk), Fin.castPred_castSucc, + Fin.predAbove_below _ _ hjk, Fin.succAbove_below, Fin.castSucc_castPred] + rw [Fin.castSucc_castPred] + exact hjk.trans_lt H + · rw [Fin.predAbove_above _ _ (Fin.castSucc_lt_castSucc_iff.mpr hjk), + Fin.predAbove_above _ _ hjk, Fin.succAbove_below, Fin.castSucc_pred_eq_pred_castSucc] + rwa [Fin.castSucc_lt_iff_succ_le, Fin.succ_pred] + · rw [Fin.succAbove_above _ _ (Fin.succ_le_castSucc_iff.mpr hik)] + have hjk := H.trans hik + rw [Fin.predAbove_above _ _ hjk, Fin.predAbove_above _ _ (Fin.castSucc_lt_succ_iff.mpr hjk.le), + Fin.pred_succ, Fin.succAbove_above, Fin.succ_pred] + rwa [Fin.le_castSucc_pred_iff] #align simplex_category.δ_comp_σ_of_gt SimplexCategory.δ_comp_σ_of_gt @[reassoc] @@ -337,18 +350,71 @@ theorem δ_comp_σ_of_gt' {n} {i : Fin (n + 3)} {j : Fin (n + 2)} (H : j.succ < @[reassoc] theorem σ_comp_σ {n} {i j : Fin (n + 1)} (H : i ≤ j) : σ (Fin.castSucc i) ≫ σ j = σ j.succ ≫ σ i := by - ext ⟨k, hk⟩ - rcases i with ⟨i, hi⟩ - rcases j with ⟨j, hj⟩ - simp? at H hk says simp only [Fin.mk_le_mk, len_mk] at H hk - dsimp [σ, Fin.predAbove] - simp only [Fin.lt_iff_val_lt_val, Fin.ite_val, Fin.coe_pred, ge_iff_le, dite_eq_ite, - Fin.coe_castLT] - split_ifs - all_goals try linarith - all_goals cases k <;> simp at *; linarith + ext k : 3 + dsimp [σ] + cases' k using Fin.lastCases with k + · simp only [len_mk, Fin.predAbove_right_last] + · cases' k using Fin.cases with k + · rw [Fin.castSucc_zero, Fin.predAbove_below _ 0 (Fin.zero_le _), + Fin.predAbove_below _ _ (Fin.zero_le _), Fin.castPred_zero, + Fin.predAbove_below _ 0 (Fin.zero_le _), Fin.predAbove_below _ _ (Fin.zero_le _)] + · rcases le_or_lt i k with (h | h) + · simp_rw [Fin.predAbove_above i.castSucc _ (Fin.castSucc_lt_castSucc_iff.mpr + (Fin.castSucc_lt_succ_iff.mpr h)), ← Fin.succ_castSucc, Fin.pred_succ, + Fin.succ_predAbove_succ] + rw [Fin.predAbove_above i _ (Fin.castSucc_lt_succ_iff.mpr _), Fin.pred_succ] + rcases le_or_lt k j with (hkj | hkj) + · rwa [Fin.predAbove_below _ _ (Fin.castSucc_le_castSucc_iff.mpr hkj), + Fin.castPred_castSucc] + · rw [Fin.predAbove_above _ _ (Fin.castSucc_lt_castSucc_iff.mpr hkj), Fin.le_pred_iff, + Fin.succ_le_castSucc_iff] + exact H.trans_lt hkj + · simp_rw [Fin.predAbove_below i.castSucc _ (Fin.castSucc_le_castSucc_iff.mpr + (Fin.succ_le_castSucc_iff.mpr h)), Fin.castPred_castSucc, ← Fin.succ_castSucc, + Fin.succ_predAbove_succ] + rw [Fin.predAbove_below _ k.castSucc (Fin.castSucc_le_castSucc_iff.mpr (h.le.trans H)), + Fin.castPred_castSucc, Fin.predAbove_below _ k.succ + (Fin.succ_le_castSucc_iff.mpr (H.trans_lt' h)), Fin.predAbove_below _ k.succ + (Fin.succ_le_castSucc_iff.mpr h)] #align simplex_category.σ_comp_σ SimplexCategory.σ_comp_σ +/-- +If `f : [m] ⟶ [n+1]` is a morphism and `j` is not in the range of `f`, +then `factor_δ f j` is a morphism `[m] ⟶ [n]` such that +`factor_δ f j ≫ δ j = f` (as witnessed by `factor_δ_spec`). +-/ +def factor_δ {m n : ℕ} (f : ([m] : SimplexCategory) ⟶ [n+1]) (j : Fin (n+2)) : + ([m] : SimplexCategory) ⟶ [n] := + f ≫ σ (Fin.predAbove 0 j) + +open Fin in +lemma factor_δ_spec {m n : ℕ} (f : ([m] : SimplexCategory) ⟶ [n+1]) (j : Fin (n+2)) + (hj : ∀ (k : Fin (m+1)), f.toOrderHom k ≠ j) : + factor_δ f j ≫ δ j = f := by + ext k : 3 + specialize hj k + dsimp [factor_δ, δ, σ] + cases' j using cases with j + · rw [predAbove_below _ _ (zero_le _), castPred_zero, predAbove_above 0 _ + (castSucc_zero ▸ pos_of_ne_zero hj), + zero_succAbove, succ_pred] + · rw [predAbove_above 0 _ (castSucc_zero ▸ succ_pos _), pred_succ] + rcases hj.lt_or_lt with (hj | hj) + · rw [predAbove_below j _] + swap + · exact (le_castSucc_iff.mpr hj) + · rw [succAbove_below] + swap + · rwa [castSucc_lt_succ_iff, castPred_le_iff, le_castSucc_iff] + rw [castSucc_castPred] + · rw [predAbove_above] + swap + · exact (castSucc_lt_succ _).trans hj + rw [succAbove_above] + swap + · rwa [succ_le_castSucc_iff, lt_pred_iff] + rw [succ_pred] + end Generators section Skeleton @@ -517,7 +583,8 @@ instance {n : ℕ} {i : Fin (n + 1)} : Epi (σ i) := by -- This was not needed before leanprover/lean4#2644 dsimp rw [Fin.predAbove_below i b (by simpa only [Fin.coe_eq_castSucc] using h)] - simp only [len_mk, Fin.coe_eq_castSucc, Fin.castPred_castSucc] + simp only [len_mk, Fin.coe_eq_castSucc] + rfl · use b.succ -- This was not needed before leanprover/lean4#2644 dsimp @@ -597,12 +664,11 @@ theorem eq_σ_comp_of_not_injective' {n : ℕ} {Δ' : SimplexCategory} (θ : mk · -- This was not needed before leanprover/lean4#2644 dsimp rw [Fin.predAbove_below i x h'] - have eq := Fin.castSucc_castPred (gt_of_gt_of_ge (Fin.castSucc_lt_last i) h') dsimp [δ] - erw [Fin.succAbove_below i.succ x.castPred _] + erw [Fin.succAbove_below _ _ _] swap - · rwa [eq, ← Fin.le_castSucc_iff] - rw [eq] + · exact (Fin.castSucc_lt_succ_iff.mpr h') + rfl · simp only [not_le] at h' let y := x.pred <| by rintro (rfl : x = 0); simp at h' have hy : x = y.succ := (Fin.succ_pred x _).symm @@ -647,22 +713,18 @@ theorem eq_σ_comp_of_not_injective {n : ℕ} {Δ' : SimplexCategory} (θ : mk ( · exfalso exact h₂ h'.symm rcases hθ₂ with ⟨x, y, ⟨h₁, h₂⟩⟩ - let z := x.castPred - use z - rw [← show Fin.castSucc z = x from - Fin.castSucc_castPred (lt_of_lt_of_le h₂ (Fin.le_last y))] at h₁ h₂ + use x.castPred ((Fin.le_last _).trans_lt' h₂).ne apply eq_σ_comp_of_not_injective' - rw [Fin.castSucc_lt_iff_succ_le] at h₂ apply le_antisymm - · exact θ.toOrderHom.monotone (le_of_lt (Fin.castSucc_lt_succ z)) - · rw [h₁] - exact θ.toOrderHom.monotone h₂ + · exact θ.toOrderHom.monotone (le_of_lt (Fin.castSucc_lt_succ _)) + · rw [Fin.castSucc_castPred, h₁] + exact θ.toOrderHom.monotone ((Fin.succ_castPred_le_iff _).mpr h₂) #align simplex_category.eq_σ_comp_of_not_injective SimplexCategory.eq_σ_comp_of_not_injective theorem eq_comp_δ_of_not_surjective' {n : ℕ} {Δ : SimplexCategory} (θ : Δ ⟶ mk (n + 1)) (i : Fin (n + 2)) (hi : ∀ x, θ.toOrderHom x ≠ i) : ∃ θ' : Δ ⟶ mk n, θ = θ' ≫ δ i := by by_cases h : i < Fin.last (n + 1) - · use θ ≫ σ (Fin.castPred i) + · use θ ≫ σ (Fin.castPred i h.ne) ext1 ext1 ext1 x @@ -673,23 +735,18 @@ theorem eq_comp_δ_of_not_surjective' {n : ℕ} {Δ : SimplexCategory} (θ : Δ -- This was not needed before leanprover/lean4#2644 dsimp -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [Fin.predAbove_below (Fin.castPred i) (θ.toOrderHom x) - (by simpa [Fin.castSucc_castPred h] using h')] + erw [Fin.predAbove_below _ _ (by exact h')] dsimp [δ] erw [Fin.succAbove_below i] swap - · simp only [Fin.lt_iff_val_lt_val, Fin.coe_castSucc] - exact - lt_of_le_of_lt (Fin.coe_castPred_le_self _) - (Fin.lt_iff_val_lt_val.mp ((Ne.le_iff_lt (hi x)).mp h')) - rw [Fin.castSucc_castPred] - apply lt_of_le_of_lt h' h + · rw [(hi x).le_iff_lt] at h' + exact h' + rfl · simp only [not_le] at h' -- The next three tactics used to be a simp only call before leanprover/lean4#2644 rw [σ, mkHom, Hom.toOrderHom_mk, OrderHom.coe_mk, OrderHom.coe_mk] erw [OrderHom.coe_mk] - erw [Fin.predAbove_above (Fin.castPred i) (θ.toOrderHom x) - (by simpa only [Fin.castSucc_castPred h] using h')] + erw [Fin.predAbove_above _ _ (by exact h')] dsimp [δ] rw [Fin.succAbove_above i _] -- This was not needed before leanprover/lean4#2644 @@ -699,11 +756,12 @@ theorem eq_comp_δ_of_not_surjective' {n : ℕ} {Δ : SimplexCategory} (θ : Δ Nat.le_sub_one_of_lt (Fin.lt_iff_val_lt_val.mp h') · obtain rfl := le_antisymm (Fin.le_last i) (not_lt.mp h) use θ ≫ σ (Fin.last _) - ext x : 4 + ext x : 3 dsimp [δ, σ] - dsimp only [Fin.castPred] - rw [Fin.predAbove_last, Fin.succAbove_last, Fin.castSucc_castPred] - exact (Ne.le_iff_lt (hi x)).mp (Fin.le_last _) + simp_rw [Fin.succAbove_last, Fin.predAbove_last_apply] + split_ifs with h + · exact ((hi x) h).elim + · rfl #align simplex_category.eq_comp_δ_of_not_surjective' SimplexCategory.eq_comp_δ_of_not_surjective' theorem eq_comp_δ_of_not_surjective {n : ℕ} {Δ : SimplexCategory} (θ : Δ ⟶ mk (n + 1)) diff --git a/Mathlib/AlgebraicTopology/SimplicialObject.lean b/Mathlib/AlgebraicTopology/SimplicialObject.lean index 32e1b97f96a42..71910449f6b60 100644 --- a/Mathlib/AlgebraicTopology/SimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/SimplicialObject.lean @@ -53,7 +53,7 @@ namespace SimplicialObject set_option quotPrecheck false in /-- `X _[n]` denotes the `n`th-term of the simplicial object X -/ scoped[Simplicial] - notation:1000 X " _[" n "]" => + notation3:1000 X " _[" n "]" => (X : CategoryTheory.SimplicialObject _).obj (Opposite.op (SimplexCategory.mk n)) open Simplicial diff --git a/Mathlib/AlgebraicTopology/SimplicialSet.lean b/Mathlib/AlgebraicTopology/SimplicialSet.lean index 97ac48140b7e6..c2c4154902e8c 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet.lean @@ -4,15 +4,16 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Scott Morrison, Adam Topaz -/ import Mathlib.AlgebraicTopology.SimplicialObject -import Mathlib.AlgebraicTopology.TopologicalSimplex -import Mathlib.CategoryTheory.Limits.Presheaf import Mathlib.CategoryTheory.Limits.Shapes.Types import Mathlib.CategoryTheory.Yoneda -import Mathlib.Topology.Category.TopCat.Limits.Basic +import Mathlib.Data.Fin.VecNotation +import Mathlib.Tactic.FinCases #align_import algebraic_topology.simplicial_set from "leanprover-community/mathlib"@"178a32653e369dce2da68dc6b2694e385d484ef1" /-! +# Simplicial sets + A simplicial set is just a simplicial object in `Type`, i.e. a `Type`-valued presheaf on the simplex category. @@ -69,10 +70,14 @@ instance hasColimits : HasColimits SSet := by lemma hom_ext {X Y : SSet} {f g : X ⟶ Y} (w : ∀ n, f.app n = g.app n) : f = g := SimplicialObject.hom_ext _ _ w +/-- The ulift functor `SSet.{u} ⥤ SSet.{max u v}` on simplicial sets. -/ +def uliftFunctor : SSet.{u} ⥤ SSet.{max u v} := + (SimplicialObject.whiskering _ _).obj CategoryTheory.uliftFunctor.{v, u} + /-- The `n`-th standard simplex `Δ[n]` associated with a nonempty finite linear order `n` is the Yoneda embedding of `n`. -/ -def standardSimplex : SimplexCategory ⥤ SSet := - yoneda +def standardSimplex : SimplexCategory ⥤ SSet.{u} := + yoneda ⋙ uliftFunctor set_option linter.uppercaseLean3 false in #align sSet.standard_simplex SSet.standardSimplex @@ -82,12 +87,76 @@ scoped[Simplicial] notation3 "Δ[" n "]" => SSet.standardSimplex.obj (SimplexCat instance : Inhabited SSet := ⟨Δ[0]⟩ +namespace standardSimplex + +open Finset Opposite SimplexCategory + +@[simp] +lemma map_id (n : SimplexCategory) : + (SSet.standardSimplex.map (SimplexCategory.Hom.mk OrderHom.id : n ⟶ n)) = 𝟙 _ := + CategoryTheory.Functor.map_id _ _ + +/-- Simplices of the standard simplex identify to morphisms in `SimplexCategory`. -/ +def objEquiv (n : SimplexCategory) (m : SimplexCategoryᵒᵖ) : + (standardSimplex.{u}.obj n).obj m ≃ (m.unop ⟶ n) := + Equiv.ulift.{u, 0} + +/-- Constructor for simplices of the standard simplex which takes a `OrderHom` as an input. -/ +abbrev objMk {n : SimplexCategory} {m : SimplexCategoryᵒᵖ} + (f : Fin (len m.unop + 1) →o Fin (n.len + 1)) : + (standardSimplex.{u}.obj n).obj m := + (objEquiv _ _).symm (Hom.mk f) + +lemma map_apply {m₁ m₂ : SimplexCategoryᵒᵖ} (f : m₁ ⟶ m₂) {n : SimplexCategory} + (x : (standardSimplex.{u}.obj n).obj m₁) : + (standardSimplex.{u}.obj n).map f x = (objEquiv _ _).symm (f.unop ≫ (objEquiv _ _) x) := by + rfl + +/-- The canonical bijection `(standardSimplex.obj n ⟶ X) ≃ X.obj (op n)`. -/ +def _root_.SSet.yonedaEquiv (X : SSet.{u}) (n : SimplexCategory) : + (standardSimplex.obj n ⟶ X) ≃ X.obj (op n) := + yonedaCompUliftFunctorEquiv X n + +/-- The (degenerate) `m`-simplex in the standard simplex concentrated in vertex `k`. -/ +def const (n : ℕ) (k : Fin (n+1)) (m : SimplexCategoryᵒᵖ) : Δ[n].obj m := + objMk (OrderHom.const _ k ) + +@[simp] +lemma const_down_toOrderHom (n : ℕ) (k : Fin (n+1)) (m : SimplexCategoryᵒᵖ) : + (const n k m).down.toOrderHom = OrderHom.const _ k := + rfl + +/-- The edge of the standard simplex with endpoints `a` and `b`. -/ +def edge (n : ℕ) (a b : Fin (n+1)) (hab : a ≤ b) : Δ[n] _[1] := by + refine objMk ⟨![a, b], ?_⟩ + rw [Fin.monotone_iff_le_succ] + simp only [unop_op, len_mk, Fin.forall_fin_one] + apply Fin.mk_le_mk.mpr hab + +lemma coe_edge_down_toOrderHom (n : ℕ) (a b : Fin (n+1)) (hab : a ≤ b) : + ↑(edge n a b hab).down.toOrderHom = ![a, b] := + rfl + +/-- The triangle in the standard simplex with vertices `a`, `b`, and `c`. -/ +def triangle {n : ℕ} (a b c : Fin (n+1)) (hab : a ≤ b) (hbc : b ≤ c) : Δ[n] _[2] := by + refine objMk ⟨![a, b, c], ?_⟩ + rw [Fin.monotone_iff_le_succ] + simp only [unop_op, len_mk, Fin.forall_fin_two] + dsimp + simp only [*, Matrix.tail_cons, Matrix.head_cons, true_and] + +lemma coe_triangle_down_toOrderHom {n : ℕ} (a b c : Fin (n+1)) (hab : a ≤ b) (hbc : b ≤ c) : + ↑(triangle a b c hab hbc).down.toOrderHom = ![a, b, c] := + rfl + +end standardSimplex + section /-- The `m`-simplices of the `n`-th standard simplex are the monotone maps from `Fin (m+1)` to `Fin (n+1)`. -/ def asOrderHom {n} {m} (α : Δ[n].obj m) : OrderHom (Fin (m.unop.len + 1)) (Fin (n + 1)) := - α.toOrderHom + α.down.toOrderHom set_option linter.uppercaseLean3 false in #align sSet.as_order_hom SSet.asOrderHom @@ -96,10 +165,10 @@ end /-- The boundary `∂Δ[n]` of the `n`-th standard simplex consists of all `m`-simplices of `standardSimplex n` that are not surjective (when viewed as monotone function `m → n`). -/ -def boundary (n : ℕ) : SSet where +def boundary (n : ℕ) : SSet.{u} where obj m := { α : Δ[n].obj m // ¬Function.Surjective (asOrderHom α) } map {m₁ m₂} f α := - ⟨f.unop ≫ (α : Δ[n].obj m₁), by + ⟨Δ[n].map f α.1, by intro h apply α.property exact Function.Surjective.of_comp h⟩ @@ -107,7 +176,7 @@ set_option linter.uppercaseLean3 false in #align sSet.boundary SSet.boundary -- mathport name: sSet.boundary -scoped[Simplicial] notation "∂Δ[" n "]" => SSet.boundary n +scoped[Simplicial] notation3 "∂Δ[" n "]" => SSet.boundary n /-- The inclusion of the boundary of the `n`-th standard simplex into that standard simplex. -/ def boundaryInclusion (n : ℕ) : ∂Δ[n] ⟶ Δ[n] where app m (α : { α : Δ[n].obj m // _ }) := α @@ -121,7 +190,7 @@ for which the union of `{i}` and the range of `α` is not all of `n` def horn (n : ℕ) (i : Fin (n + 1)) : SSet where obj m := { α : Δ[n].obj m // Set.range (asOrderHom α) ∪ {i} ≠ Set.univ } map {m₁ m₂} f α := - ⟨f.unop ≫ (α : Δ[n].obj m₁), by + ⟨Δ[n].map f α.1, by intro h; apply α.property rw [Set.eq_univ_iff_forall] at h ⊢; intro j apply Or.imp _ id (h j) @@ -139,6 +208,125 @@ def hornInclusion (n : ℕ) (i : Fin (n + 1)) : Λ[n, i] ⟶ Δ[n] where set_option linter.uppercaseLean3 false in #align sSet.horn_inclusion SSet.hornInclusion +namespace horn + +open SimplexCategory Finset Opposite + +/-- The (degenerate) subsimplex of `Λ[n+2, i]` concentrated in vertex `k`. -/ +@[simps] +def const (n : ℕ) (i k : Fin (n+3)) (m : SimplexCategoryᵒᵖ) : Λ[n+2, i].obj m := by + refine ⟨standardSimplex.const _ k _, ?_⟩ + suffices ¬ Finset.univ ⊆ {i, k} by + simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, not_or, Fin.forall_fin_one, + subset_iff, mem_univ, @eq_comm _ _ k] + intro h + have := (card_le_card h).trans card_le_two + rw [card_fin] at this + omega + +/-- The edge of `Λ[n, i]` with endpoints `a` and `b`. + +This edge only exists if `{i, a, b}` has cardinality less than `n`. -/ +@[simps] +def edge (n : ℕ) (i a b : Fin (n+1)) (hab : a ≤ b) (H : Finset.card {i, a, b} ≤ n) : + Λ[n, i] _[1] := by + refine ⟨standardSimplex.edge n a b hab, ?range⟩ + case range => + suffices ∃ x, ¬i = x ∧ ¬a = x ∧ ¬b = x by + simpa only [unop_op, SimplexCategory.len_mk, asOrderHom, SimplexCategory.Hom.toOrderHom_mk, + Set.union_singleton, ne_eq, ← Set.univ_subset_iff, Set.subset_def, Set.mem_univ, + Set.mem_insert_iff, @eq_comm _ _ i, Set.mem_range, forall_true_left, not_forall, not_or, + not_exists, Fin.forall_fin_two] + contrapose! H + replace H : univ ⊆ {i, a, b} := + fun x _ ↦ by simpa [or_iff_not_imp_left, eq_comm] using H x + replace H := card_le_card H + rwa [card_fin] at H + +/-- Alternative constructor for the edge of `Λ[n, i]` with endpoints `a` and `b`, +assuming `3 ≤ n`. -/ +@[simps!] +def edge₃ (n : ℕ) (i a b : Fin (n+1)) (hab : a ≤ b) (H : 3 ≤ n) : + Λ[n, i] _[1] := + horn.edge n i a b hab <| Finset.card_le_three.trans H + +/-- The edge of `Λ[n, i]` with endpoints `j` and `j+1`. + +This constructor assumes `0 < i < n`, +which is the type of horn that occurs in the horn-filling condition of quasicategories. -/ +@[simps!] +def primitiveEdge {n : ℕ} {i : Fin (n+1)} + (h₀ : 0 < i) (hₙ : i < Fin.last n) (j : Fin n) : + Λ[n, i] _[1] := by + refine horn.edge n i j.castSucc j.succ ?_ ?_ + · simp only [← Fin.val_fin_le, Fin.coe_castSucc, Fin.val_succ, le_add_iff_nonneg_right, zero_le] + simp only [← Fin.val_fin_lt, Fin.val_zero, Fin.val_last] at h₀ hₙ + obtain rfl|hn : n = 2 ∨ 2 < n := by + rw [eq_comm, or_comm, ← le_iff_lt_or_eq]; omega + · revert i j; decide + · exact Finset.card_le_three.trans hn + +/-- The triangle in the standard simplex with vertices `k`, `k+1`, and `k+2`. + +This constructor assumes `0 < i < n`, +which is the type of horn that occurs in the horn-filling condition of quasicategories. -/ +@[simps] +def primitiveTriangle {n : ℕ} (i : Fin (n+4)) + (h₀ : 0 < i) (hₙ : i < Fin.last (n+3)) + (k : ℕ) (h : k < n+2) : Λ[n+3, i] _[2] := by + refine ⟨standardSimplex.triangle + (n := n+3) ⟨k, by omega⟩ ⟨k+1, by omega⟩ ⟨k+2, by omega⟩ ?_ ?_, ?_⟩ + · simp only [Fin.mk_le_mk, le_add_iff_nonneg_right, zero_le] + · simp only [Fin.mk_le_mk, add_le_add_iff_left, one_le_two] + simp only [unop_op, SimplexCategory.len_mk, asOrderHom, SimplexCategory.Hom.toOrderHom_mk, + OrderHom.const_coe_coe, Set.union_singleton, ne_eq, ← Set.univ_subset_iff, Set.subset_def, + Set.mem_univ, Set.mem_insert_iff, Set.mem_range, Function.const_apply, exists_const, + forall_true_left, not_forall, not_or, unop_op, not_exists, + standardSimplex.triangle, OrderHom.coe_mk, @eq_comm _ _ i, + standardSimplex.objMk, standardSimplex.objEquiv, Equiv.ulift] + dsimp + by_cases hk0 : k = 0 + · subst hk0 + use Fin.last (n+3) + simp only [hₙ.ne, not_false_eq_true, Fin.zero_eta, zero_add, true_and] + intro j + fin_cases j <;> simp [Fin.ext_iff] <;> omega + · use 0 + simp only [h₀.ne', not_false_eq_true, true_and] + intro j + fin_cases j <;> simp [Fin.ext_iff, hk0] + +/-- The `j`th subface of the `i`-th horn. -/ +@[simps] +def face {n : ℕ} (i j : Fin (n+2)) (h : j ≠ i) : Λ[n+1, i] _[n] := + ⟨(standardSimplex.objEquiv _ _).symm (SimplexCategory.δ j), by + simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, SimplexCategory.δ, not_or, + standardSimplex.objEquiv, asOrderHom, Equiv.ulift]⟩ + +/-- Two morphisms from a horn are equal if they are equal on all suitable faces. -/ +protected +lemma hom_ext {n : ℕ} {i : Fin (n+2)} {S : SSet} (σ₁ σ₂ : Λ[n+1, i] ⟶ S) + (h : ∀ (j) (h : j ≠ i), σ₁.app _ (face i j h) = σ₂.app _ (face i j h)) : + σ₁ = σ₂ := by + apply NatTrans.ext; apply funext; apply Opposite.rec; apply SimplexCategory.rec + intro m; ext f + obtain ⟨f', hf⟩ := (standardSimplex.objEquiv _ _).symm.surjective f.1 + obtain ⟨j, hji, hfj⟩ : ∃ j, ¬j = i ∧ ∀ k, f'.toOrderHom k ≠ j := by + obtain ⟨f, hf'⟩ := f + subst hf + simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, not_or] using hf' + have H : f = (Λ[n+1, i].map (factor_δ f' j).op) (face i j hji) := by + apply Subtype.ext + apply (standardSimplex.objEquiv _ _).injective + rw [← hf] + exact (factor_δ_spec f' j hfj).symm + have H₁ := congrFun (σ₁.naturality (factor_δ f' j).op) (face i j hji) + have H₂ := congrFun (σ₂.naturality (factor_δ f' j).op) (face i j hji) + dsimp at H₁ H₂ + erw [H, H₁, H₂, h _ hji] + +end horn + section Examples open Simplicial @@ -195,16 +383,12 @@ set_option linter.uppercaseLean3 false in namespace Augmented --- porting note: added to ease the automation of the proofs in the definition --- of `standardSimplex` -attribute [local simp] SSet.standardSimplex - -- porting note: an instance of `Subsingleton (⊤_ (Type u))` was added in -- `CategoryTheory.Limits.Types` to ease the automation in this definition /-- The functor which sends `[n]` to the simplicial set `Δ[n]` equipped by the obvious augmentation towards the terminal object of the category of sets. -/ @[simps] -noncomputable def standardSimplex : SimplexCategory ⥤ SSet.Augmented where +noncomputable def standardSimplex : SimplexCategory ⥤ SSet.Augmented.{u} where obj Δ := { left := SSet.standardSimplex.obj Δ right := terminal _ @@ -218,29 +402,3 @@ set_option linter.uppercaseLean3 false in end Augmented end SSet - -/-- The functor associating the singular simplicial set to a topological space. -/ -noncomputable def TopCat.toSSet : TopCat ⥤ SSet := - ColimitAdj.restrictedYoneda SimplexCategory.toTop -set_option linter.uppercaseLean3 false in -#align Top.to_sSet TopCat.toSSet - -/-- The geometric realization functor. -/ -noncomputable def SSet.toTop : SSet ⥤ TopCat := - ColimitAdj.extendAlongYoneda SimplexCategory.toTop -set_option linter.uppercaseLean3 false in -#align sSet.to_Top SSet.toTop - -/-- Geometric realization is left adjoint to the singular simplicial set construction. -/ -noncomputable def sSetTopAdj : SSet.toTop ⊣ TopCat.toSSet := - ColimitAdj.yonedaAdjunction _ -set_option linter.uppercaseLean3 false in -#align sSet_Top_adj sSetTopAdj - -/-- The geometric realization of the representable simplicial sets agree - with the usual topological simplices. -/ -noncomputable def SSet.toTopSimplex : - (yoneda : SimplexCategory ⥤ _) ⋙ SSet.toTop ≅ SimplexCategory.toTop := - ColimitAdj.isExtensionAlongYoneda _ -set_option linter.uppercaseLean3 false in -#align sSet.to_Top_simplex SSet.toTopSimplex diff --git a/Mathlib/AlgebraicTopology/SingularSet.lean b/Mathlib/AlgebraicTopology/SingularSet.lean new file mode 100644 index 0000000000000..4b223086f4994 --- /dev/null +++ b/Mathlib/AlgebraicTopology/SingularSet.lean @@ -0,0 +1,73 @@ +/- +Copyright (c) 2023 Johan Commelin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johan Commelin, Scott Morrison, Adam Topaz +-/ +import Mathlib.AlgebraicTopology.SimplicialSet +import Mathlib.AlgebraicTopology.TopologicalSimplex +import Mathlib.CategoryTheory.Limits.Presheaf +import Mathlib.Topology.Category.TopCat.Limits.Basic + +/-! +# The singular simplicial set of a topological space and geometric realization of a simplicial set + +The *singular simplicial set* `TopCat.to_SSet.obj X` of a topological space `X` +has as `n`-simplices the continuous maps `[n].toTop → X`. +Here, `[n].toTop` is the standard topological `n`-simplex, +defined as `{ f : Fin (n+1) → ℝ≥0 // ∑ i, f i = 1 }` with its subspace topology. + +The *geometric realization* functor `SSet.toTop.obj` is left adjoint to `TopCat.toSSet`. +It is the left Kan extension of `SimplexCategory.toTop` along the Yoneda embedding. + +# Main definitions + +* `TopCat.toSSet : TopCat ⥤ SSet` is the functor + assigning the singular simplicial set to a topological space. +* `SSet.toTop : SSet ⥤ TopCat` is the functor + assigning the geometric realization to a simplicial set. +* `sSetTopAdj : SSet.toTop ⊣ TopCat.toSSet` is the adjunction between these two functors. + +## TODO + +- Generalize to an adjunction between `SSet.{u}` and `TopCat.{u}` for any universe `u` +- Show that the singular simplicial set is a Kan complex. +- Show the adjunction `sSetTopAdj` is a Quillen adjunction. + +-/ + +open CategoryTheory + +/-- The functor associating the *singular simplicial set* to a topological space. + +Let `X` be a topological space. +Then the singular simplicial set of `X` +has as `n`-simplices the continuous maps `[n].toTop → X`. +Here, `[n].toTop` is the standard topological `n`-simplex, +defined as `{ f : Fin (n+1) → ℝ≥0 // ∑ i, f i = 1 }` with its subspace topology. -/ +noncomputable def TopCat.toSSet : TopCat ⥤ SSet := + ColimitAdj.restrictedYoneda SimplexCategory.toTop +set_option linter.uppercaseLean3 false in +#align Top.to_sSet TopCat.toSSet + +/-- The *geometric realization functor* is +the left Kan extension of `SimplexCategory.toTop` along the Yoneda embedding. + +It is left adjoint to `TopCat.toSSet`, as witnessed by `sSetTopAdj`. -/ +noncomputable def SSet.toTop : SSet ⥤ TopCat := + ColimitAdj.extendAlongYoneda SimplexCategory.toTop +set_option linter.uppercaseLean3 false in +#align sSet.to_Top SSet.toTop + +/-- Geometric realization is left adjoint to the singular simplicial set construction. -/ +noncomputable def sSetTopAdj : SSet.toTop ⊣ TopCat.toSSet := + ColimitAdj.yonedaAdjunction _ +set_option linter.uppercaseLean3 false in +#align sSet_Top_adj sSetTopAdj + +/-- The geometric realization of the representable simplicial sets agree + with the usual topological simplices. -/ +noncomputable def SSet.toTopSimplex : + (yoneda : SimplexCategory ⥤ _) ⋙ SSet.toTop ≅ SimplexCategory.toTop := + ColimitAdj.isExtensionAlongYoneda _ +set_option linter.uppercaseLean3 false in +#align sSet.to_Top_simplex SSet.toTopSimplex diff --git a/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean b/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean index 69bafbf60a98b..3c37f676ffcb3 100644 --- a/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.AlgebraicTopology.SimplicialObject -import Mathlib.CategoryTheory.Limits.Shapes.FiniteProducts +import Mathlib.CategoryTheory.Limits.Shapes.Products #align_import algebraic_topology.split_simplicial_object from "leanprover-community/mathlib"@"dd1f8496baa505636a82748e6b652165ea888733" diff --git a/Mathlib/AlgebraicTopology/TopologicalSimplex.lean b/Mathlib/AlgebraicTopology/TopologicalSimplex.lean index c82c145c8499c..cc94952e80cd2 100644 --- a/Mathlib/AlgebraicTopology/TopologicalSimplex.lean +++ b/Mathlib/AlgebraicTopology/TopologicalSimplex.lean @@ -14,9 +14,10 @@ import Mathlib.Topology.Instances.NNReal We define the natural functor from `SimplexCategory` to `TopCat` sending `[n]` to the topological `n`-simplex. -This is used to define `TopCat.toSSet` in `AlgebraicTopology.SimplicialSet`. +This is used to define `TopCat.toSSet` in `AlgebraicTopology.SingularSet`. -/ +set_option linter.uppercaseLean3 false noncomputable section @@ -24,19 +25,15 @@ namespace SimplexCategory open Simplicial NNReal BigOperators Classical CategoryTheory -attribute [local instance] - CategoryTheory.ConcreteCategory.hasCoeToSort CategoryTheory.ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike -- porting note: added, should be moved -instance (x : SimplexCategory) : Fintype (CategoryTheory.ConcreteCategory.forget.obj x) := by - change (Fintype (Fin _)) - infer_instance +instance (x : SimplexCategory) : Fintype (ConcreteCategory.forget.obj x) := + inferInstanceAs (Fintype (Fin _)) /-- The topological simplex associated to `x : SimplexCategory`. This is the object part of the functor `SimplexCategory.toTop`. -/ -def toTopObj (x : SimplexCategory) := - { f : x → ℝ≥0 | ∑ i, f i = 1 } -set_option linter.uppercaseLean3 false in +def toTopObj (x : SimplexCategory) := { f : x → ℝ≥0 | ∑ i, f i = 1 } #align simplex_category.to_Top_obj SimplexCategory.toTopObj instance (x : SimplexCategory) : CoeFun x.toTopObj fun _ => x → ℝ≥0 := @@ -45,35 +42,23 @@ instance (x : SimplexCategory) : CoeFun x.toTopObj fun _ => x → ℝ≥0 := @[ext] theorem toTopObj.ext {x : SimplexCategory} (f g : x.toTopObj) : (f : x → ℝ≥0) = g → f = g := Subtype.ext -set_option linter.uppercaseLean3 false in #align simplex_category.to_Top_obj.ext SimplexCategory.toTopObj.ext /-- A morphism in `SimplexCategory` induces a map on the associated topological spaces. -/ -def toTopMap {x y : SimplexCategory} (f : x ⟶ y) : x.toTopObj → y.toTopObj := fun g => - ⟨fun i => ∑ j in Finset.univ.filter fun k => f k = i, g j, by - simp only [Finset.sum_congr, toTopObj, Set.mem_setOf] +def toTopMap {x y : SimplexCategory} (f : x ⟶ y) (g : x.toTopObj) : y.toTopObj := + ⟨fun i => ∑ j in Finset.univ.filter (f · = i), g j, by + simp only [toTopObj, Set.mem_setOf] rw [← Finset.sum_biUnion] - have hg := g.2 - dsimp [toTopObj] at hg - convert hg - · simp [Finset.eq_univ_iff_forall] - · intro i _ j _ h - rw [Function.onFun, disjoint_iff_inf_le] - intro e he - simp only [Finset.bot_eq_empty, Finset.not_mem_empty] - apply h - simp only [Finset.mem_univ, forall_true_left, - ge_iff_le, Finset.le_eq_subset, Finset.inf_eq_inter, Finset.mem_inter, - Finset.mem_filter, true_and] at he - rw [← he.1, he.2]⟩ -set_option linter.uppercaseLean3 false in + · have hg : ∑ i : (forget SimplexCategory).obj x, g i = 1 := g.2 + convert hg + simp [Finset.eq_univ_iff_forall] + · apply Set.pairwiseDisjoint_filter⟩ #align simplex_category.to_Top_map SimplexCategory.toTopMap @[simp] theorem coe_toTopMap {x y : SimplexCategory} (f : x ⟶ y) (g : x.toTopObj) (i : y) : - toTopMap f g i = ∑ j in Finset.univ.filter fun k => f k = i, g j := + toTopMap f g i = ∑ j in Finset.univ.filter (f · = i), g j := rfl -set_option linter.uppercaseLean3 false in #align simplex_category.coe_to_Top_map SimplexCategory.coe_toTopMap @[continuity] @@ -81,7 +66,6 @@ theorem continuous_toTopMap {x y : SimplexCategory} (f : x ⟶ y) : Continuous ( refine' Continuous.subtype_mk (continuous_pi fun i => _) _ dsimp only [coe_toTopMap] exact continuous_finset_sum _ (fun j _ => (continuous_apply _).comp continuous_subtype_val) -set_option linter.uppercaseLean3 false in #align simplex_category.continuous_to_Top_map SimplexCategory.continuous_toTopMap /-- The functor associating the topological `n`-simplex to `[n] : SimplexCategory`. -/ @@ -94,7 +78,7 @@ def toTop : SimplexCategory ⥤ TopCat where ext f apply toTopObj.ext funext i - change (Finset.univ.filter fun k => k = i).sum _ = _ + change (Finset.univ.filter (· = i)).sum _ = _ simp [Finset.sum_filter, CategoryTheory.id_apply] map_comp := fun f g => by ext h @@ -109,16 +93,7 @@ def toTop : SimplexCategory ⥤ TopCat where · apply Finset.sum_congr · exact Finset.ext (fun j => ⟨fun hj => by simpa using hj, fun hj => by simpa using hj⟩) · tauto - · intro j _ k _ h - rw [Function.onFun, disjoint_iff_inf_le] - intro e he - simp only [Finset.bot_eq_empty, Finset.not_mem_empty] - apply h - simp only [Finset.mem_univ, forall_true_left, - ge_iff_le, Finset.le_eq_subset, Finset.inf_eq_inter, Finset.mem_inter, - Finset.mem_filter, true_and] at he - rw [← he.1, he.2] -set_option linter.uppercaseLean3 false in + · apply Set.pairwiseDisjoint_filter #align simplex_category.to_Top SimplexCategory.toTop -- These lemmas have always been bad (#7657), but leanprover/lean4#2644 made `simp` start noticing diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index a274ece0a5b77..6822cbfc09fe2 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -602,7 +602,7 @@ theorem analyticOn_congr' {s : Set E} (h : f =ᶠ[𝓝ˢ s] g) : AnalyticOn 𝕜 theorem AnalyticOn.congr {s : Set E} (hs : IsOpen s) (hf : AnalyticOn 𝕜 f s) (hg : s.EqOn f g) : AnalyticOn 𝕜 g s := - hf.congr' $ mem_nhdsSet_iff_forall.mpr + hf.congr' <| mem_nhdsSet_iff_forall.mpr (fun _ hz => eventuallyEq_iff_exists_mem.mpr ⟨s, hs.mem_nhds hz, hg⟩) theorem analyticOn_congr {s : Set E} (hs : IsOpen s) (h : s.EqOn f g) : AnalyticOn 𝕜 f s ↔ @@ -706,9 +706,9 @@ theorem HasFPowerSeriesOnBall.uniform_geometric_approx {r' : ℝ≥0} hf.uniform_geometric_approx' h refine' ⟨a, ha, C, hC, fun y hy n => (hp y hy n).trans _⟩ have yr' : ‖y‖ < r' := by rwa [ball_zero_eq] at hy + have := ha.1.le -- needed to discharge a side goal on the next line gcongr - exacts [mul_nonneg ha.1.le (div_nonneg (norm_nonneg y) r'.coe_nonneg), - mul_le_of_le_one_right ha.1.le (div_le_one_of_le yr'.le r'.coe_nonneg)] + exact mul_le_of_le_one_right ha.1.le (div_le_one_of_le yr'.le r'.coe_nonneg) #align has_fpower_series_on_ball.uniform_geometric_approx HasFPowerSeriesOnBall.uniform_geometric_approx /-- Taylor formula for an analytic function, `IsBigO` version. -/ @@ -1192,7 +1192,7 @@ The forward map sends `(k, l, s)` to `(k + l, s)` and the inverse map sends `(n, with non-definitional equalities. -/ @[simps] def changeOriginIndexEquiv : - (Σk l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) ≃ Σn : ℕ, Finset (Fin n) where + (Σ k l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) ≃ Σ n : ℕ, Finset (Fin n) where toFun s := ⟨s.1 + s.2.1, s.2.2⟩ invFun s := ⟨s.1 - s.2.card, s.2.card, @@ -1216,6 +1216,16 @@ def changeOriginIndexEquiv : simp [tsub_add_cancel_of_le (card_finset_fin_le s), Fin.castIso_to_equiv] #align formal_multilinear_series.change_origin_index_equiv FormalMultilinearSeries.changeOriginIndexEquiv +lemma changeOriginSeriesTerm_changeOriginIndexEquiv_symm (n t) : + let s := changeOriginIndexEquiv.symm ⟨n, t⟩ + p.changeOriginSeriesTerm s.1 s.2.1 s.2.2 s.2.2.2 (fun _ ↦ x) (fun _ ↦ y) = + p n (t.piecewise (fun _ ↦ x) fun _ ↦ y) := by + have : ∀ (m) (hm : n = m), p n (t.piecewise (fun _ ↦ x) fun _ ↦ y) = + p m ((t.map (Fin.castIso hm).toEmbedding).piecewise (fun _ ↦ x) fun _ ↦ y) := by + rintro m rfl + simp (config := { unfoldPartialApp := true }) [Finset.piecewise] + simp_rw [changeOriginSeriesTerm_apply, eq_comm]; apply this + theorem changeOriginSeries_summable_aux₁ {r r' : ℝ≥0} (hr : (r + r' : ℝ≥0∞) < p.radius) : Summable fun s : Σk l : ℕ, { s : Finset (Fin (k + l)) // s.card = l } => ‖p (s.1 + s.2.1)‖₊ * r ^ s.2.1 * r' ^ s.1 := by @@ -1309,7 +1319,7 @@ theorem changeOrigin_eval (h : (‖x‖₊ + ‖y‖₊ : ℝ≥0∞) < p.radius have x_add_y_mem_ball : x + y ∈ EMetric.ball (0 : E) p.radius := by refine' mem_emetric_ball_zero_iff.2 (lt_of_le_of_lt _ h) exact mod_cast nnnorm_add_le x y - set f : (Σk l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) → F := fun s => + set f : (Σ k l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) → F := fun s => p.changeOriginSeriesTerm s.1 s.2.1 s.2.2 s.2.2.2 (fun _ => x) fun _ => y have hsf : Summable f := by refine' .of_nnnorm_bounded _ (p.changeOriginSeries_summable_aux₁ h) _ @@ -1333,17 +1343,8 @@ theorem changeOrigin_eval (h : (‖x‖₊ + ‖y‖₊ : ℝ≥0∞) < p.radius refine' HasSum.sigma_of_hasSum (p.hasSum x_add_y_mem_ball) (fun n => _) (changeOriginIndexEquiv.symm.summable_iff.2 hsf) erw [(p n).map_add_univ (fun _ => x) fun _ => y] - -- porting note: added explicit function - convert hasSum_fintype (fun c : Finset (Fin n) => f (changeOriginIndexEquiv.symm ⟨n, c⟩)) - rename_i s _ - dsimp only [changeOriginSeriesTerm, (· ∘ ·), changeOriginIndexEquiv_symm_apply_fst, - changeOriginIndexEquiv_symm_apply_snd_fst, changeOriginIndexEquiv_symm_apply_snd_snd_coe] - rw [ContinuousMultilinearMap.curryFinFinset_apply_const] - have : ∀ (m) (hm : n = m), p n (s.piecewise (fun _ => x) fun _ => y) = - p m ((s.map (Fin.castIso hm).toEquiv.toEmbedding).piecewise (fun _ => x) fun _ => y) := by - rintro m rfl - simp (config := { unfoldPartialApp := true }) [Finset.piecewise] - apply this + simp_rw [← changeOriginSeriesTerm_changeOriginIndexEquiv_symm] + exact hasSum_fintype (fun c => f (changeOriginIndexEquiv.symm ⟨n, c⟩)) #align formal_multilinear_series.change_origin_eval FormalMultilinearSeries.changeOrigin_eval /-- Power series terms are analytic as we vary the origin -/ diff --git a/Mathlib/Analysis/Analytic/CPolynomial.lean b/Mathlib/Analysis/Analytic/CPolynomial.lean new file mode 100644 index 0000000000000..ecfbc3ac4d9bb --- /dev/null +++ b/Mathlib/Analysis/Analytic/CPolynomial.lean @@ -0,0 +1,530 @@ +/- +Copyright (c) 2023 Sophie Morel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sophie Morel +-/ +import Mathlib.Analysis.Analytic.Basic + +/-! We specialize the theory fo analytic functions to the case of functions that admit a +development given by a *finite* formal multilinear series. We call them "continuously polynomial", +which is abbreviated to `CPolynomial`. One reason to do that is that we no longer need a +completeness assumption on the target space `F` to make the series converge, so some of the results +are more general. The class of continuously polynomial functions includes functions defined by +polynomials on a normed `𝕜`-algebra and continuous multilinear maps. + +## Main definitions + +Let `p` be a formal multilinear series from `E` to `F`, i.e., `p n` is a multilinear map on `E^n` +for `n : ℕ`, and let `f` be a function from `E` to `F`. + +* `HasFiniteFPowerSeriesOnBall f p x n r`: on the ball of center `x` with radius `r`, + `f (x + y) = ∑'_n pₘ yᵐ`, and moreover `pₘ = 0` if `n ≤ m`. +* `HasFiniteFPowerSeriesAt f p x n`: on some ball of center `x` with positive radius, holds + `HasFiniteFPowerSeriesOnBall f p x n r`. +* `CPolynomialAt 𝕜 f x`: there exists a power series `p` and a natural number `n` such that + holds `HasFPowerSeriesAt f p x n`. +* `CPolynomialOn 𝕜 f s`: the function `f` is analytic at every point of `s`. + +We develop the basic properties of these notions, notably: +* If a function is continuously polynomial, then it is analytic, see + `HasFiniteFPowerSeriesOnBall.hasFPowerSeriesOnBall`, `HasFiniteFPowerSeriesAt.hasFPowerSeriesAt`, + `CPolynomialAt.analyticAt` and `CPolynomialOn.analyticOn`. +* The sum of a finite formal power series with positive radius is well defined on the whole space, + see `FormalMultilinearSeries.hasFiniteFPowerSeriesOnBall_of_finite`. +* If a function admits a finite power series in a ball, then it is continuously polynimial at + any point `y` of this ball, and the power series there can be expressed in terms of the initial + power series `p` as `p.changeOrigin y`, which is finite (with the same bound as `p`) by + `changeOrigin_finite_of_finite`. See `HasFiniteFPowerSeriesOnBall.changeOrigin `. It follows in + particular that the set of points at which a given function is continuously polynomial is open, + see `isOpen_cPolynomialAt`. +-/ + +variable {𝕜 E F G : Type*} [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] + [NormedAddCommGroup F] [NormedSpace 𝕜 F] [NormedAddCommGroup G] [NormedSpace 𝕜 G] + +open Topology Classical BigOperators NNReal Filter ENNReal + +open Set Filter Asymptotics + +variable {f g : E → F} {p pf pg : FormalMultilinearSeries 𝕜 E F} {x : E} {r r' : ℝ≥0∞} {n m : ℕ} + +section FiniteFPowerSeries + +/-- Given a function `f : E → F`, a formal multilinear series `p` and `n : ℕ`, we say that +`f` has `p` as a finite power series on the ball of radius `r > 0` around `x` if +`f (x + y) = ∑' pₘ yᵐ` for all `‖y‖ < r` and `pₙ = 0` for `n ≤ m`.-/ +structure HasFiniteFPowerSeriesOnBall (f : E → F) (p : FormalMultilinearSeries 𝕜 E F) (x : E) + (n : ℕ) (r : ℝ≥0∞) extends HasFPowerSeriesOnBall f p x r : Prop where + finite : ∀ (m : ℕ), n ≤ m → p m = 0 + +/-- Given a function `f : E → F`, a formal multilinear series `p` and `n : ℕ`, we say that +`f` has `p` as a finite power series around `x` if `f (x + y) = ∑' pₙ yⁿ` for all `y` in a +neighborhood of `0`and `pₙ = 0` for `n ≤ m`.-/ +def HasFiniteFPowerSeriesAt (f : E → F) (p : FormalMultilinearSeries 𝕜 E F) (x : E) (n : ℕ) := + ∃ r, HasFiniteFPowerSeriesOnBall f p x n r + +theorem HasFiniteFPowerSeriesAt.toHasFPowerSeriesAt + (hf : HasFiniteFPowerSeriesAt f p x n) : HasFPowerSeriesAt f p x := + let ⟨r, hf⟩ := hf + ⟨r, hf.toHasFPowerSeriesOnBall⟩ + +theorem HasFiniteFPowerSeriesAt.finite (hf : HasFiniteFPowerSeriesAt f p x n) : + ∀ m : ℕ, n ≤ m → p m = 0 := let ⟨_, hf⟩ := hf; hf.finite + +variable (𝕜) + +/-- Given a function `f : E → F`, we say that `f` is continuously polynomial (cpolynomial) +at `x` if it admits a finite power series expansion around `x`. -/ +def CPolynomialAt (f : E → F) (x : E) := + ∃ (p : FormalMultilinearSeries 𝕜 E F) (n : ℕ), HasFiniteFPowerSeriesAt f p x n + +/-- Given a function `f : E → F`, we say that `f` is continuously polynomial on a set `s` +if it is continuously polynomial around every point of `s`. -/ +def CPolynomialOn (f : E → F) (s : Set E) := + ∀ x, x ∈ s → CPolynomialAt 𝕜 f x + +variable {𝕜} + +theorem HasFiniteFPowerSeriesOnBall.hasFiniteFPowerSeriesAt + (hf : HasFiniteFPowerSeriesOnBall f p x n r) : + HasFiniteFPowerSeriesAt f p x n := + ⟨r, hf⟩ + +theorem HasFiniteFPowerSeriesAt.cPolynomialAt (hf : HasFiniteFPowerSeriesAt f p x n) : + CPolynomialAt 𝕜 f x := + ⟨p, n, hf⟩ + +theorem HasFiniteFPowerSeriesOnBall.cPolynomialAt (hf : HasFiniteFPowerSeriesOnBall f p x n r) : + CPolynomialAt 𝕜 f x := + hf.hasFiniteFPowerSeriesAt.cPolynomialAt + +theorem CPolynomialAt.analyticAt (hf : CPolynomialAt 𝕜 f x) : AnalyticAt 𝕜 f x := + let ⟨p, _, hp⟩ := hf + ⟨p, hp.toHasFPowerSeriesAt⟩ + +theorem CPolynomialOn.analyticOn {s : Set E} (hf : CPolynomialOn 𝕜 f s) : AnalyticOn 𝕜 f s := + fun x hx ↦ (hf x hx).analyticAt + +theorem HasFiniteFPowerSeriesOnBall.congr (hf : HasFiniteFPowerSeriesOnBall f p x n r) + (hg : EqOn f g (EMetric.ball x r)) : HasFiniteFPowerSeriesOnBall g p x n r := + ⟨hf.1.congr hg, hf.finite⟩ + +/-- If a function `f` has a finite power series `p` around `x`, then the function +`z ↦ f (z - y)` has the same finite power series around `x + y`. -/ +theorem HasFiniteFPowerSeriesOnBall.comp_sub (hf : HasFiniteFPowerSeriesOnBall f p x n r) (y : E) : + HasFiniteFPowerSeriesOnBall (fun z => f (z - y)) p (x + y) n r := + ⟨hf.1.comp_sub y, hf.finite⟩ + +theorem HasFiniteFPowerSeriesOnBall.mono (hf : HasFiniteFPowerSeriesOnBall f p x n r) + (r'_pos : 0 < r') (hr : r' ≤ r) : HasFiniteFPowerSeriesOnBall f p x n r' := + ⟨hf.1.mono r'_pos hr, hf.finite⟩ + +theorem HasFiniteFPowerSeriesAt.congr (hf : HasFiniteFPowerSeriesAt f p x n) (hg : f =ᶠ[𝓝 x] g) : + HasFiniteFPowerSeriesAt g p x n := + Exists.imp (fun _ hg ↦ ⟨hg, hf.finite⟩) (hf.toHasFPowerSeriesAt.congr hg) + +protected theorem HasFiniteFPowerSeriesAt.eventually (hf : HasFiniteFPowerSeriesAt f p x n) : + ∀ᶠ r : ℝ≥0∞ in 𝓝[>] 0, HasFiniteFPowerSeriesOnBall f p x n r := + hf.toHasFPowerSeriesAt.eventually.mono fun _ h ↦ ⟨h, hf.finite⟩ + +theorem hasFiniteFPowerSeriesOnBall_const {c : F} {e : E} : + HasFiniteFPowerSeriesOnBall (fun _ => c) (constFormalMultilinearSeries 𝕜 E c) e 1 ⊤ := + ⟨hasFPowerSeriesOnBall_const, fun n hn ↦ constFormalMultilinearSeries_apply (id hn : 0 < n).ne'⟩ + +theorem hasFiniteFPowerSeriesAt_const {c : F} {e : E} : + HasFiniteFPowerSeriesAt (fun _ => c) (constFormalMultilinearSeries 𝕜 E c) e 1 := + ⟨⊤, hasFiniteFPowerSeriesOnBall_const⟩ + +theorem CPolynomialAt_const {v : F} : CPolynomialAt 𝕜 (fun _ => v) x := + ⟨constFormalMultilinearSeries 𝕜 E v, 1, hasFiniteFPowerSeriesAt_const⟩ + +theorem CPolynomialOn_const {v : F} {s : Set E} : CPolynomialOn 𝕜 (fun _ => v) s := + fun _ _ => CPolynomialAt_const + +theorem HasFiniteFPowerSeriesOnBall.add (hf : HasFiniteFPowerSeriesOnBall f pf x n r) + (hg : HasFiniteFPowerSeriesOnBall g pg x m r) : + HasFiniteFPowerSeriesOnBall (f + g) (pf + pg) x (max n m) r := + ⟨hf.1.add hg.1, fun N hN ↦ by + rw [Pi.add_apply, hf.finite _ ((le_max_left n m).trans hN), + hg.finite _ ((le_max_right n m).trans hN), zero_add]⟩ + +theorem HasFiniteFPowerSeriesAt.add (hf : HasFiniteFPowerSeriesAt f pf x n) + (hg : HasFiniteFPowerSeriesAt g pg x m) : + HasFiniteFPowerSeriesAt (f + g) (pf + pg) x (max n m) := by + rcases (hf.eventually.and hg.eventually).exists with ⟨r, hr⟩ + exact ⟨r, hr.1.add hr.2⟩ + +theorem CPolynomialAt.congr (hf : CPolynomialAt 𝕜 f x) (hg : f =ᶠ[𝓝 x] g) : CPolynomialAt 𝕜 g x := + let ⟨_, _, hpf⟩ := hf + (hpf.congr hg).cPolynomialAt + +theorem CPolynomialAt_congr (h : f =ᶠ[𝓝 x] g) : CPolynomialAt 𝕜 f x ↔ CPolynomialAt 𝕜 g x := + ⟨fun hf ↦ hf.congr h, fun hg ↦ hg.congr h.symm⟩ + +theorem CPolynomialAt.add (hf : CPolynomialAt 𝕜 f x) (hg : CPolynomialAt 𝕜 g x) : + CPolynomialAt 𝕜 (f + g) x := + let ⟨_, _, hpf⟩ := hf + let ⟨_, _, hqf⟩ := hg + (hpf.add hqf).cPolynomialAt + +theorem HasFiniteFPowerSeriesOnBall.neg (hf : HasFiniteFPowerSeriesOnBall f pf x n r) : + HasFiniteFPowerSeriesOnBall (-f) (-pf) x n r := + ⟨hf.1.neg, fun m hm ↦ by rw [Pi.neg_apply, hf.finite m hm, neg_zero]⟩ + +theorem HasFiniteFPowerSeriesAt.neg (hf : HasFiniteFPowerSeriesAt f pf x n) : + HasFiniteFPowerSeriesAt (-f) (-pf) x n := + let ⟨_, hrf⟩ := hf + hrf.neg.hasFiniteFPowerSeriesAt + +theorem CPolynomialAt.neg (hf : CPolynomialAt 𝕜 f x) : CPolynomialAt 𝕜 (-f) x := + let ⟨_, _, hpf⟩ := hf + hpf.neg.cPolynomialAt + +theorem HasFiniteFPowerSeriesOnBall.sub (hf : HasFiniteFPowerSeriesOnBall f pf x n r) + (hg : HasFiniteFPowerSeriesOnBall g pg x m r) : + HasFiniteFPowerSeriesOnBall (f - g) (pf - pg) x (max n m) r := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem HasFiniteFPowerSeriesAt.sub (hf : HasFiniteFPowerSeriesAt f pf x n) + (hg : HasFiniteFPowerSeriesAt g pg x m) : + HasFiniteFPowerSeriesAt (f - g) (pf - pg) x (max n m) := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem CPolynomialAt.sub (hf : CPolynomialAt 𝕜 f x) (hg : CPolynomialAt 𝕜 g x) : + CPolynomialAt 𝕜 (f - g) x := by + simpa only [sub_eq_add_neg] using hf.add hg.neg + +theorem CPolynomialOn.mono {s t : Set E} (hf : CPolynomialOn 𝕜 f t) (hst : s ⊆ t) : + CPolynomialOn 𝕜 f s := + fun z hz => hf z (hst hz) + +theorem CPolynomialOn.congr' {s : Set E} (hf : CPolynomialOn 𝕜 f s) (hg : f =ᶠ[𝓝ˢ s] g) : + CPolynomialOn 𝕜 g s := + fun z hz => (hf z hz).congr (mem_nhdsSet_iff_forall.mp hg z hz) + +theorem CPolynomialOn_congr' {s : Set E} (h : f =ᶠ[𝓝ˢ s] g) : + CPolynomialOn 𝕜 f s ↔ CPolynomialOn 𝕜 g s := + ⟨fun hf => hf.congr' h, fun hg => hg.congr' h.symm⟩ + +theorem CPolynomialOn.congr {s : Set E} (hs : IsOpen s) (hf : CPolynomialOn 𝕜 f s) + (hg : s.EqOn f g) : CPolynomialOn 𝕜 g s := + hf.congr' <| mem_nhdsSet_iff_forall.mpr + (fun _ hz => eventuallyEq_iff_exists_mem.mpr ⟨s, hs.mem_nhds hz, hg⟩) + +theorem CPolynomialOn_congr {s : Set E} (hs : IsOpen s) (h : s.EqOn f g) : + CPolynomialOn 𝕜 f s ↔ CPolynomialOn 𝕜 g s := + ⟨fun hf => hf.congr hs h, fun hg => hg.congr hs h.symm⟩ + +theorem CPolynomialOn.add {s : Set E} (hf : CPolynomialOn 𝕜 f s) (hg : CPolynomialOn 𝕜 g s) : + CPolynomialOn 𝕜 (f + g) s := + fun z hz => (hf z hz).add (hg z hz) + +theorem CPolynomialOn.sub {s : Set E} (hf : CPolynomialOn 𝕜 f s) (hg : CPolynomialOn 𝕜 g s) : + CPolynomialOn 𝕜 (f - g) s := + fun z hz => (hf z hz).sub (hg z hz) + +/-- If a function `f` has a finite power series `p` on a ball and `g` is a continuous linear map, +then `g ∘ f` has the finite power series `g ∘ p` on the same ball. -/ +theorem ContinuousLinearMap.comp_hasFiniteFPowerSeriesOnBall (g : F →L[𝕜] G) + (h : HasFiniteFPowerSeriesOnBall f p x n r) : + HasFiniteFPowerSeriesOnBall (g ∘ f) (g.compFormalMultilinearSeries p) x n r := + ⟨g.comp_hasFPowerSeriesOnBall h.1, fun m hm ↦ by + rw [compFormalMultilinearSeries_apply, h.finite m hm] + ext; exact map_zero g⟩ + +/-- If a function `f` is continuously polynomial on a set `s` and `g` is a continuous linear map, +then `g ∘ f` is continuously polynomial on `s`. -/ +theorem ContinuousLinearMap.comp_cPolynomialOn {s : Set E} (g : F →L[𝕜] G) + (h : CPolynomialOn 𝕜 f s) : CPolynomialOn 𝕜 (g ∘ f) s := by + rintro x hx + rcases h x hx with ⟨p, n, r, hp⟩ + exact ⟨g.compFormalMultilinearSeries p, n, r, g.comp_hasFiniteFPowerSeriesOnBall hp⟩ + +/-- If a function admits a finite power series expansion bounded by `n`, then it is equal to +the `m`th partial sums of this power series at every point of the disk for `n ≤ m`.-/ +theorem HasFiniteFPowerSeriesOnBall.eq_partialSum + (hf : HasFiniteFPowerSeriesOnBall f p x n r) : + ∀ y ∈ EMetric.ball (0 : E) r, ∀ m, n ≤ m → + f (x + y) = p.partialSum m y := + fun y hy m hm ↦ (hf.hasSum hy).unique (hasSum_sum_of_ne_finset_zero + (f := fun m => p m (fun _ => y)) (s := Finset.range m) + (fun N hN => by simp only; simp only [Finset.mem_range, not_lt] at hN + rw [hf.finite _ (le_trans hm hN), ContinuousMultilinearMap.zero_apply])) + +/-- Variant of the previous result with the variable expressed as `y` instead of `x + y`.-/ +theorem HasFiniteFPowerSeriesOnBall.eq_partialSum' + (hf : HasFiniteFPowerSeriesOnBall f p x n r) : + ∀ y ∈ EMetric.ball x r, ∀ m, n ≤ m → + f y = p.partialSum m (y - x) := by + intro y hy m hm + rw [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, ← mem_emetric_ball_zero_iff] at hy + rw [← (HasFiniteFPowerSeriesOnBall.eq_partialSum hf _ hy m hm), add_sub_cancel'_right] + +/-! The particular cases where `f` has a finite power series bounded by `0` or `1`.-/ + +/-- If `f` has a formal power series on a ball bounded by `0`, then `f` is equal to `0` on +the ball.-/ +theorem HasFiniteFPowerSeriesOnBall.eq_zero_of_bound_zero + (hf : HasFiniteFPowerSeriesOnBall f pf x 0 r) : ∀ y ∈ EMetric.ball x r, f y = 0 := by + intro y hy + rw [hf.eq_partialSum' y hy 0 le_rfl, FormalMultilinearSeries.partialSum] + simp only [Finset.range_zero, Finset.sum_empty] + +theorem HasFiniteFPowerSeriesOnBall.bound_zero_of_eq_zero (hf : ∀ y ∈ EMetric.ball x r, f y = 0) + (r_pos : 0 < r) (hp : ∀ n, p n = 0) : HasFiniteFPowerSeriesOnBall f p x 0 r := by + refine ⟨⟨?_, r_pos, ?_⟩, fun n _ ↦ hp n⟩ + · rw [p.radius_eq_top_of_forall_image_add_eq_zero 0 (fun n ↦ by rw [add_zero]; exact hp n)] + exact le_top + · intro y hy + rw [hf (x + y)] + · convert hasSum_zero + rw [hp, ContinuousMultilinearMap.zero_apply] + · rwa [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, add_comm, add_sub_cancel, + ← edist_eq_coe_nnnorm, ← EMetric.mem_ball] + +/-- If `f` has a formal power series at `x` bounded by `0`, then `f` is equal to `0` in a +neighborhood of `x`.-/ +theorem HasFiniteFPowerSeriesAt.eventually_zero_of_bound_zero + (hf : HasFiniteFPowerSeriesAt f pf x 0) : f =ᶠ[𝓝 x] 0 := + Filter.eventuallyEq_iff_exists_mem.mpr (let ⟨r, hf⟩ := hf; ⟨EMetric.ball x r, + EMetric.ball_mem_nhds x hf.r_pos, fun y hy ↦ hf.eq_zero_of_bound_zero y hy⟩) + +/-- If `f` has a formal power series on a ball bounded by `1`, then `f` is constant equal +to `f x` on the ball.-/ +theorem HasFiniteFPowerSeriesOnBall.eq_const_of_bound_one + (hf : HasFiniteFPowerSeriesOnBall f pf x 1 r) : ∀ y ∈ EMetric.ball x r, f y = f x := by + intro y hy + rw [hf.eq_partialSum' y hy 1 le_rfl, hf.eq_partialSum' x + (by rw [EMetric.mem_ball, edist_self]; exact hf.r_pos) 1 le_rfl] + simp only [FormalMultilinearSeries.partialSum, Finset.range_one, Finset.sum_singleton] + congr + apply funext + simp only [IsEmpty.forall_iff] + +/-- If `f` has a formal power series at x bounded by `1`, then `f` is constant equal +to `f x` in a neighborhood of `x`.-/ +theorem HasFiniteFPowerSeriesAt.eventually_const_of_bound_one + (hf : HasFiniteFPowerSeriesAt f pf x 1) : f =ᶠ[𝓝 x] (fun _ => f x) := + Filter.eventuallyEq_iff_exists_mem.mpr (let ⟨r, hf⟩ := hf; ⟨EMetric.ball x r, + EMetric.ball_mem_nhds x hf.r_pos, fun y hy ↦ hf.eq_const_of_bound_one y hy⟩) + +/-- If a function admits a finite power series expansion on a disk, then it is continuous there. -/ +protected theorem HasFiniteFPowerSeriesOnBall.continuousOn + (hf : HasFiniteFPowerSeriesOnBall f p x n r) : + ContinuousOn f (EMetric.ball x r) := hf.1.continuousOn + +protected theorem HasFiniteFPowerSeriesAt.continuousAt (hf : HasFiniteFPowerSeriesAt f p x n) : + ContinuousAt f x := hf.toHasFPowerSeriesAt.continuousAt + +protected theorem CPolynomialAt.continuousAt (hf : CPolynomialAt 𝕜 f x) : ContinuousAt f x := + hf.analyticAt.continuousAt + +protected theorem CPolynomialOn.continuousOn {s : Set E} (hf : CPolynomialOn 𝕜 f s) : + ContinuousOn f s := + hf.analyticOn.continuousOn + +/-- Continuously polynomial everywhere implies continuous -/ +theorem CPolynomialOn.continuous {f : E → F} (fa : CPolynomialOn 𝕜 f univ) : Continuous f := by + rw [continuous_iff_continuousOn_univ]; exact fa.continuousOn + +protected theorem FormalMultilinearSeries.sum_of_finite (p : FormalMultilinearSeries 𝕜 E F) + {n : ℕ} (hn : ∀ m, n ≤ m → p m = 0) (x : E) : + p.sum x = p.partialSum n x := + tsum_eq_sum fun m hm ↦ by rw [Finset.mem_range, not_lt] at hm; rw [hn m hm]; rfl + +/-- A finite formal multilinear series sums to its sum at every point.-/ +protected theorem FormalMultilinearSeries.hasSum_of_finite (p : FormalMultilinearSeries 𝕜 E F) + {n : ℕ} (hn : ∀ m, n ≤ m → p m = 0) (x : E) : + HasSum (fun n : ℕ => p n fun _ => x) (p.sum x) := + summable_of_ne_finset_zero (fun m hm ↦ by rw [Finset.mem_range, not_lt] at hm; rw [hn m hm]; rfl) + |>.hasSum + +/-- The sum of a finite power series `p` admits `p` as a power series.-/ +protected theorem FormalMultilinearSeries.hasFiniteFPowerSeriesOnBall_of_finite + (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (hn : ∀ m, n ≤ m → p m = 0) : + HasFiniteFPowerSeriesOnBall p.sum p 0 n ⊤ where + r_le := by rw [radius_eq_top_of_forall_image_add_eq_zero p n fun _ => hn _ (Nat.le_add_left _ _)] + r_pos := zero_lt_top + finite := hn + hasSum {y} _ := by rw [zero_add]; exact p.hasSum_of_finite hn y + +theorem HasFiniteFPowerSeriesOnBall.sum (h : HasFiniteFPowerSeriesOnBall f p x n r) {y : E} + (hy : y ∈ EMetric.ball (0 : E) r) : f (x + y) = p.sum y := + (h.hasSum hy).tsum_eq.symm + +/-- The sum of a finite power series is continuous. -/ +protected theorem FormalMultilinearSeries.continuousOn_of_finite + (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (hn : ∀ m, n ≤ m → p m = 0) : + Continuous p.sum := by + rw [continuous_iff_continuousOn_univ, ← Metric.emetric_ball_top] + exact (p.hasFiniteFPowerSeriesOnBall_of_finite hn).continuousOn + +end FiniteFPowerSeries + +namespace FormalMultilinearSeries + +section + +/-! We study what happens when we change the origin of a finite formal multilinear series `p`. The +main point is that the new series `p.changeOrigin x` is still finite, with the same bound.-/ + +variable (p : FormalMultilinearSeries 𝕜 E F) {x y : E} {r R : ℝ≥0} + +/-- If `p` is a formal multilinear series such that `p m = 0` for `n ≤ m`, then +`p.changeOriginSeriesTerm k l = 0` for `n ≤ k + l`. -/ +lemma changeOriginSeriesTerm_bound (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} + (hn : ∀ (m : ℕ), n ≤ m → p m = 0) (k l : ℕ) {s : Finset (Fin (k + l))} + (hs : s.card = l) (hkl : n ≤ k + l) : + p.changeOriginSeriesTerm k l s hs = 0 := by + rw [changeOriginSeriesTerm] + simp only [AddEquivClass.map_eq_zero_iff] + exact hn _ hkl + +/-- If `p` is a finite formal multilinear series, then so is `p.changeOriginSeries k` for every +`k` in `ℕ`. More precisely, if `p m = 0` for `n ≤ m`, then `p.changeOriginSeries k m = 0` for +`n ≤ k + m`. -/ +lemma changeOriginSeries_finite_of_finite (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} + (hn : ∀ (m : ℕ), n ≤ m → p m = 0) (k : ℕ) : ∀ {m : ℕ}, n ≤ k + m → + p.changeOriginSeries k m = 0 := by + intro m hm + rw [changeOriginSeries] + exact Finset.sum_eq_zero (fun _ _ => p.changeOriginSeriesTerm_bound hn _ _ _ hm) + +lemma changeOriginSeries_sum_eq_partialSum_of_finite (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} + (hn : ∀ (m : ℕ), n ≤ m → p m = 0) (k : ℕ) : + (p.changeOriginSeries k).sum = (p.changeOriginSeries k).partialSum (n - k) := by + ext x + rw [partialSum, FormalMultilinearSeries.sum, + tsum_eq_sum (f := fun m => p.changeOriginSeries k m (fun _ => x)) (s := Finset.range (n - k))] + intro m hm + rw [Finset.mem_range, not_lt] at hm + rw [p.changeOriginSeries_finite_of_finite hn k (by rw [add_comm]; exact Nat.le_add_of_sub_le hm), + ContinuousMultilinearMap.zero_apply] + +/-- If `p` is a formal multilinear series such that `p m = 0` for `n ≤ m`, then +`p.changeOrigin x k = 0` for `n ≤ k`. -/ +lemma changeOrigin_finite_of_finite (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} + (hn : ∀ (m : ℕ), n ≤ m → p m = 0) {k : ℕ} (hk : n ≤ k) : + p.changeOrigin x k = 0 := by + rw [changeOrigin, p.changeOriginSeries_sum_eq_partialSum_of_finite hn] + apply Finset.sum_eq_zero + intro m hm + rw [Finset.mem_range] at hm + rw [p.changeOriginSeries_finite_of_finite hn k (le_add_of_le_left hk), + ContinuousMultilinearMap.zero_apply] + +theorem hasFiniteFPowerSeriesOnBall_changeOrigin (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} + (k : ℕ) (hn : ∀ (m : ℕ), n + k ≤ m → p m = 0) : + HasFiniteFPowerSeriesOnBall (p.changeOrigin · k) (p.changeOriginSeries k) 0 n ⊤ := + (p.changeOriginSeries k).hasFiniteFPowerSeriesOnBall_of_finite + (fun _ hm => p.changeOriginSeries_finite_of_finite hn k + (by rw [add_comm n k]; apply add_le_add_left hm)) + +theorem changeOrigin_eval_of_finite (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} + (hn : ∀ (m : ℕ), n ≤ m → p m = 0) (x y : E) : + (p.changeOrigin x).sum y = p.sum (x + y) := by + let f (s : Σ k l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) : F := + p.changeOriginSeriesTerm s.1 s.2.1 s.2.2 s.2.2.2 (fun _ ↦ x) fun _ ↦ y + have finsupp : f.support.Finite + · apply Set.Finite.subset (s := changeOriginIndexEquiv ⁻¹' (Sigma.fst ⁻¹' {m | m < n})) + · apply Set.Finite.preimage ((Equiv.injective _).injOn _) + simp_rw [← {m | m < n}.iUnion_of_singleton_coe, preimage_iUnion, ← range_sigmaMk] + exact finite_iUnion fun _ ↦ finite_range _ + · refine fun s ↦ Not.imp_symm fun hs ↦ ?_ + simp only [preimage_setOf_eq, changeOriginIndexEquiv_apply_fst, mem_setOf, not_lt] at hs + dsimp only [f] + rw [changeOriginSeriesTerm_bound p hn _ _ _ hs, ContinuousMultilinearMap.zero_apply, + ContinuousMultilinearMap.zero_apply] + have hfkl k l : HasSum (f ⟨k, l, ·⟩) (changeOriginSeries p k l (fun _ ↦ x) fun _ ↦ y) + · simp_rw [changeOriginSeries, ContinuousMultilinearMap.sum_apply]; apply hasSum_fintype + have hfk k : HasSum (f ⟨k, ·⟩) (changeOrigin p x k fun _ ↦ y) + · have (m) (hm : m ∉ Finset.range n) : changeOriginSeries p k m (fun _ ↦ x) = 0 + · rw [Finset.mem_range, not_lt] at hm + rw [changeOriginSeries_finite_of_finite _ hn _ (le_add_of_le_right hm), + ContinuousMultilinearMap.zero_apply] + rw [changeOrigin, FormalMultilinearSeries.sum, + ContinuousMultilinearMap.tsum_eval (summable_of_ne_finset_zero this)] + refine (summable_of_ne_finset_zero (s := Finset.range n) fun m hm ↦ ?_).hasSum.sigma_of_hasSum + (hfkl k) (summable_of_finite_support <| finsupp.preimage <| sigma_mk_injective.injOn _) + rw [this m hm, ContinuousMultilinearMap.zero_apply] + have hf : HasSum f ((p.changeOrigin x).sum y) := + ((p.changeOrigin x).hasSum_of_finite (fun _ ↦ changeOrigin_finite_of_finite p hn) _) + |>.sigma_of_hasSum hfk (summable_of_finite_support finsupp) + refine hf.unique (changeOriginIndexEquiv.symm.hasSum_iff.1 ?_) + refine (p.hasSum_of_finite hn (x + y)).sigma_of_hasSum (fun n ↦ ?_) + (changeOriginIndexEquiv.symm.summable_iff.2 hf.summable) + rw [← Pi.add_def, (p n).map_add_univ (fun _ ↦ x) fun _ ↦ y] + simp_rw [← changeOriginSeriesTerm_changeOriginIndexEquiv_symm] + exact hasSum_fintype fun c ↦ f (changeOriginIndexEquiv.symm ⟨n, c⟩) + +/-- The terms of the formal multilinear series `p.changeOrigin` are continuously polynomial +as we vary the origin -/ +theorem cPolynomialAt_changeOrigin_of_finite (p : FormalMultilinearSeries 𝕜 E F) + {n : ℕ} (hn : ∀ (m : ℕ), n ≤ m → p m = 0) (k : ℕ) : + CPolynomialAt 𝕜 (p.changeOrigin · k) 0 := + (p.hasFiniteFPowerSeriesOnBall_changeOrigin k fun _ h ↦ hn _ (le_self_add.trans h)).cPolynomialAt + +end + +end FormalMultilinearSeries + +section + +variable {x y : E} + +theorem HasFiniteFPowerSeriesOnBall.changeOrigin (hf : HasFiniteFPowerSeriesOnBall f p x n r) + (h : (‖y‖₊ : ℝ≥0∞) < r) : + HasFiniteFPowerSeriesOnBall f (p.changeOrigin y) (x + y) n (r - ‖y‖₊) where + r_le := (tsub_le_tsub_right hf.r_le _).trans p.changeOrigin_radius + r_pos := by simp [h] + finite _ hm := p.changeOrigin_finite_of_finite hf.finite hm + hasSum {z} hz := by + have : f (x + y + z) = + FormalMultilinearSeries.sum (FormalMultilinearSeries.changeOrigin p y) z := by + rw [mem_emetric_ball_zero_iff, lt_tsub_iff_right, add_comm] at hz + rw [p.changeOrigin_eval_of_finite hf.finite, add_assoc, hf.sum] + refine' mem_emetric_ball_zero_iff.2 (lt_of_le_of_lt _ hz) + exact mod_cast nnnorm_add_le y z + rw [this] + apply (p.changeOrigin y).hasSum_of_finite fun _ => p.changeOrigin_finite_of_finite hf.finite + +/-- If a function admits a finite power series expansion `p` on an open ball `B (x, r)`, then +it is continuously polynomial at every point of this ball. -/ +theorem HasFiniteFPowerSeriesOnBall.cPolynomialAt_of_mem + (hf : HasFiniteFPowerSeriesOnBall f p x n r) (h : y ∈ EMetric.ball x r) : + CPolynomialAt 𝕜 f y := by + have : (‖y - x‖₊ : ℝ≥0∞) < r := by simpa [edist_eq_coe_nnnorm_sub] using h + have := hf.changeOrigin this + rw [add_sub_cancel'_right] at this + exact this.cPolynomialAt + +theorem HasFiniteFPowerSeriesOnBall.cPolynomialOn (hf : HasFiniteFPowerSeriesOnBall f p x n r) : + CPolynomialOn 𝕜 f (EMetric.ball x r) := + fun _y hy => hf.cPolynomialAt_of_mem hy + +variable (𝕜 f) + +/-- For any function `f` from a normed vector space to a normed vector space, the set of points +`x` such that `f` is continuously polynomial at `x` is open. -/ +theorem isOpen_cPolynomialAt : IsOpen { x | CPolynomialAt 𝕜 f x } := by + rw [isOpen_iff_mem_nhds] + rintro x ⟨p, n, r, hr⟩ + exact mem_of_superset (EMetric.ball_mem_nhds _ hr.r_pos) fun y hy => hr.cPolynomialAt_of_mem hy + +variable {𝕜} + +theorem CPolynomialAt.eventually_cPolynomialAt {f : E → F} {x : E} (h : CPolynomialAt 𝕜 f x) : + ∀ᶠ y in 𝓝 x, CPolynomialAt 𝕜 f y := + (isOpen_cPolynomialAt 𝕜 f).mem_nhds h + +theorem CPolynomialAt.exists_mem_nhds_cPolynomialOn {f : E → F} {x : E} (h : CPolynomialAt 𝕜 f x) : + ∃ s ∈ 𝓝 x, CPolynomialOn 𝕜 f s := + h.eventually_cPolynomialAt.exists_mem + +/-- If `f` is continuously polynomial at a point, then it is continuously polynomial in a +nonempty ball around that point.-/ +theorem CPolynomialAt.exists_ball_cPolynomialOn {f : E → F} {x : E} (h : CPolynomialAt 𝕜 f x) : + ∃ r : ℝ, 0 < r ∧ CPolynomialOn 𝕜 f (Metric.ball x r) := + Metric.isOpen_iff.mp (isOpen_cPolynomialAt _ _) _ h + +end diff --git a/Mathlib/Analysis/Analytic/Composition.lean b/Mathlib/Analysis/Analytic/Composition.lean index bdce464db1ce0..5ab5f2fb218ec 100644 --- a/Mathlib/Analysis/Analytic/Composition.lean +++ b/Mathlib/Analysis/Analytic/Composition.lean @@ -753,7 +753,7 @@ theorem HasFPowerSeriesAt.comp {g : F → G} {f : E → F} {q : FormalMultilinea `f (x + y)` is close enough to `f x` to be in the disk where `g` is well behaved. Let `min (r, rf, δ)` be this new radius.-/ obtain ⟨δ, δpos, hδ⟩ : - ∃ (δ : ℝ≥0∞) (_H : 0 < δ), ∀ {z : E}, z ∈ EMetric.ball x δ → f z ∈ EMetric.ball (f x) rg := by + ∃ δ : ℝ≥0∞, 0 < δ ∧ ∀ {z : E}, z ∈ EMetric.ball x δ → f z ∈ EMetric.ball (f x) rg := by have : EMetric.ball (f x) rg ∈ 𝓝 (f x) := EMetric.ball_mem_nhds _ Hg.r_pos rcases EMetric.mem_nhds_iff.1 (Hf.analyticAt.continuousAt this) with ⟨δ, δpos, Hδ⟩ exact ⟨δ, δpos, fun hz => Hδ hz⟩ @@ -1165,9 +1165,9 @@ def sigmaEquivSigmaPi (n : ℕ) : rw [get_of_eq (splitWrtComposition_join _ _ _)] · simp only [get_ofFn] rfl - · congr · simp only [map_ofFn] rfl + · congr #align composition.sigma_equiv_sigma_pi Composition.sigmaEquivSigmaPi end Composition diff --git a/Mathlib/Analysis/Analytic/IsolatedZeros.lean b/Mathlib/Analysis/Analytic/IsolatedZeros.lean index 5c78763dc8394..cad6906f1d944 100644 --- a/Mathlib/Analysis/Analytic/IsolatedZeros.lean +++ b/Mathlib/Analysis/Analytic/IsolatedZeros.lean @@ -3,10 +3,9 @@ Copyright (c) 2022 Vincent Beffara. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Vincent Beffara -/ -import Mathlib.Analysis.Analytic.Basic +import Mathlib.Analysis.Analytic.Constructions import Mathlib.Analysis.Calculus.Dslope import Mathlib.Analysis.Calculus.FDeriv.Analytic -import Mathlib.Analysis.Calculus.FormalMultilinearSeries import Mathlib.Analysis.Analytic.Uniqueness #align_import analysis.analytic.isolated_zeros from "leanprover-community/mathlib"@"a3209ddf94136d36e5e5c624b10b2a347cc9d090" @@ -154,6 +153,75 @@ theorem frequently_eq_iff_eventually_eq (hf : AnalyticAt 𝕜 f z₀) (hg : Anal simpa [sub_eq_zero] using frequently_zero_iff_eventually_zero (hf.sub hg) #align analytic_at.frequently_eq_iff_eventually_eq AnalyticAt.frequently_eq_iff_eventually_eq +/-- There exists at most one `n` such that locally around `z₀` we have `f z = (z - z₀) ^ n • g z`, +with `g` analytic and nonvanishing at `z₀`. -/ +lemma unique_eventuallyEq_pow_smul_nonzero {m n : ℕ} + (hm : ∃ g, AnalyticAt 𝕜 g z₀ ∧ g z₀ ≠ 0 ∧ ∀ᶠ z in 𝓝 z₀, f z = (z - z₀) ^ m • g z) + (hn : ∃ g, AnalyticAt 𝕜 g z₀ ∧ g z₀ ≠ 0 ∧ ∀ᶠ z in 𝓝 z₀, f z = (z - z₀) ^ n • g z) : + m = n := by + wlog h_le : n ≤ m generalizing m n + · exact ((this hn hm) (not_le.mp h_le).le).symm + let ⟨g, hg_an, _, hg_eq⟩ := hm + let ⟨j, hj_an, hj_ne, hj_eq⟩ := hn + contrapose! hj_ne + have : ∃ᶠ z in 𝓝[≠] z₀, j z = (z - z₀) ^ (m - n) • g z + · refine (eventually_nhdsWithin_iff.mpr ?_).frequently + filter_upwards [hg_eq, hj_eq] with z hfz hfz' hz + rwa [← Nat.add_sub_cancel' h_le, pow_add, mul_smul, hfz', smul_right_inj] at hfz + exact pow_ne_zero _ <| sub_ne_zero.mpr hz + rw [frequently_eq_iff_eventually_eq hj_an] at this + rw [EventuallyEq.eq_of_nhds this, sub_self, zero_pow, zero_smul] + · apply Nat.zero_lt_sub_of_lt (Nat.lt_of_le_of_ne h_le hj_ne.symm) + · exact (((analyticAt_id 𝕜 _).sub analyticAt_const).pow _).smul hg_an + +/-- If `f` is analytic at `z₀`, then exactly one of the following two possibilities occurs: either +`f` vanishes identically near `z₀`, or locally around `z₀` it has the form `z ↦ (z - z₀) ^ n • g z` +for some `n` and some `g` which is analytic and non-vanishing at `z₀`. -/ +theorem exists_eventuallyEq_pow_smul_nonzero_iff (hf : AnalyticAt 𝕜 f z₀) : + (∃ (n : ℕ), ∃ (g : 𝕜 → E), AnalyticAt 𝕜 g z₀ ∧ g z₀ ≠ 0 ∧ + ∀ᶠ z in 𝓝 z₀, f z = (z - z₀) ^ n • g z) ↔ (¬∀ᶠ z in 𝓝 z₀, f z = 0) := by + constructor + · rintro ⟨n, g, hg_an, hg_ne, hg_eq⟩ + contrapose! hg_ne + apply EventuallyEq.eq_of_nhds + rw [EventuallyEq, ← AnalyticAt.frequently_eq_iff_eventually_eq hg_an analyticAt_const] + refine (eventually_nhdsWithin_iff.mpr ?_).frequently + filter_upwards [hg_eq, hg_ne] with z hf_eq hf0 hz + rwa [hf0, eq_comm, smul_eq_zero_iff_right] at hf_eq + exact pow_ne_zero _ (sub_ne_zero.mpr hz) + · intro hf_ne + rcases hf with ⟨p, hp⟩ + exact ⟨p.order, _, ⟨_, hp.has_fpower_series_iterate_dslope_fslope p.order⟩, + hp.iterate_dslope_fslope_ne_zero (hf_ne.imp hp.locally_zero_iff.mpr), + hp.eq_pow_order_mul_iterate_dslope⟩ + +/-- The order of vanishing of `f` at `z₀`, as an element of `ℕ∞`. + +This is defined to be `∞` if `f` is identically 0 on a neighbourhood of `z₀`, and otherwise the +unique `n` such that `f z = (z - z₀) ^ n • g z` with `g` analytic and non-vanishing at `z₀`. See +`AnalyticAt.order_eq_top_iff` and `AnalyticAt.order_eq_nat_iff` for these equivalences. -/ +noncomputable def order (hf : AnalyticAt 𝕜 f z₀) : ENat := + if h : ∀ᶠ z in 𝓝 z₀, f z = 0 then ⊤ + else ↑(hf.exists_eventuallyEq_pow_smul_nonzero_iff.mpr h).choose + +lemma order_eq_top_iff (hf : AnalyticAt 𝕜 f z₀) : hf.order = ⊤ ↔ ∀ᶠ z in 𝓝 z₀, f z = 0 := by + unfold order + split_ifs with h + · rwa [eq_self, true_iff] + · simpa only [ne_eq, ENat.coe_ne_top, false_iff] using h + +lemma order_eq_nat_iff (hf : AnalyticAt 𝕜 f z₀) (n : ℕ) : hf.order = ↑n ↔ + ∃ (g : 𝕜 → E), AnalyticAt 𝕜 g z₀ ∧ g z₀ ≠ 0 ∧ ∀ᶠ z in 𝓝 z₀, f z = (z - z₀) ^ n • g z := by + unfold order + split_ifs with h + · simp only [ENat.top_ne_coe, false_iff] + contrapose! h + rw [← hf.exists_eventuallyEq_pow_smul_nonzero_iff] + exact ⟨n, h⟩ + · rw [← hf.exists_eventuallyEq_pow_smul_nonzero_iff] at h + refine ⟨fun hn ↦ (WithTop.coe_inj.mp hn : h.choose = n) ▸ h.choose_spec, fun h' ↦ ?_⟩ + rw [unique_eventuallyEq_pow_smul_nonzero h.choose_spec h'] + end AnalyticAt namespace AnalyticOn diff --git a/Mathlib/Analysis/Analytic/Linear.lean b/Mathlib/Analysis/Analytic/Linear.lean index d526f0a344cc4..b31816900a6f0 100644 --- a/Mathlib/Analysis/Analytic/Linear.lean +++ b/Mathlib/Analysis/Analytic/Linear.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yury G. Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury G. Kudryashov -/ -import Mathlib.Analysis.Analytic.Composition +import Mathlib.Analysis.Analytic.Basic #align_import analysis.analytic.linear from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Analysis/Analytic/Meromorphic.lean b/Mathlib/Analysis/Analytic/Meromorphic.lean new file mode 100644 index 0000000000000..dc33af45cce31 --- /dev/null +++ b/Mathlib/Analysis/Analytic/Meromorphic.lean @@ -0,0 +1,125 @@ +/- +Copyright (c) 2024 David Loeffler. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: David Loeffler +-/ +import Mathlib.Analysis.Analytic.IsolatedZeros + +/-! +# Meromorphic functions +-/ + +open scoped Topology + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + +/-- Meromorphy of `f` at `x` (more precisely, on a punctured neighbourhood of `x`; the value at +`x` itself is irrelevant). -/ +def MeromorphicAt (f : 𝕜 → E) (x : 𝕜) := + ∃ (n : ℕ), AnalyticAt 𝕜 (fun z ↦ (z - x) ^ n • f z) x + +lemma AnalyticAt.meromorphicAt {f : 𝕜 → E} {x : 𝕜} (hf : AnalyticAt 𝕜 f x) : + MeromorphicAt f x := + ⟨0, by simpa only [pow_zero, one_smul]⟩ + +lemma meromorphicAt_id (x : 𝕜) : MeromorphicAt id x := (analyticAt_id 𝕜 x).meromorphicAt + +lemma meromorphicAt_const (e : E) (x : 𝕜) : MeromorphicAt (fun _ ↦ e) x := + analyticAt_const.meromorphicAt + +namespace MeromorphicAt + +lemma add {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (f + g) x := by + rcases hf with ⟨m, hf⟩ + rcases hg with ⟨n, hg⟩ + refine ⟨max m n, ?_⟩ + have : (fun z ↦ (z - x) ^ max m n • (f + g) z) = fun z ↦ (z - x) ^ (max m n - m) • + ((z - x) ^ m • f z) + (z - x) ^ (max m n - n) • ((z - x) ^ n • g z) + · simp_rw [← mul_smul, ← pow_add, Nat.sub_add_cancel (Nat.le_max_left _ _), + Nat.sub_add_cancel (Nat.le_max_right _ _), Pi.add_apply, smul_add] + rw [this] + exact ((((analyticAt_id 𝕜 x).sub analyticAt_const).pow _).smul hf).add + ((((analyticAt_id 𝕜 x).sub analyticAt_const).pow _).smul hg) + +lemma smul {f : 𝕜 → 𝕜} {g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (f • g) x := by + rcases hf with ⟨m, hf⟩ + rcases hg with ⟨n, hg⟩ + refine ⟨m + n, ?_⟩ + convert hf.smul hg using 2 with z + rw [smul_eq_mul, ← mul_smul, mul_assoc, mul_comm (f z), ← mul_assoc, pow_add, + ← smul_eq_mul (a' := f z), smul_assoc, Pi.smul_apply'] + +lemma mul {f g : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (f * g) x := + hf.smul hg + +lemma neg {f : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) : MeromorphicAt (-f) x := by + convert (meromorphicAt_const (-1 : 𝕜) x).smul hf using 1 + ext1 z + simp only [Pi.neg_apply, Pi.smul_apply', neg_smul, one_smul] + +@[simp] +lemma neg_iff {f : 𝕜 → E} {x : 𝕜} : + MeromorphicAt (-f) x ↔ MeromorphicAt f x := + ⟨fun h ↦ by simpa only [neg_neg] using h.neg, MeromorphicAt.neg⟩ + +lemma sub {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (f - g) x := by + convert hf.add hg.neg using 1 + ext1 z + simp_rw [Pi.sub_apply, Pi.add_apply, Pi.neg_apply, sub_eq_add_neg] + +/-- With our definitions, `MeromorphicAt f x` depends only on the values of `f` on a punctured +neighbourhood of `x` (not on `f x`) -/ +lemma congr {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hfg : f =ᶠ[𝓝[≠] x] g) : + MeromorphicAt g x := by + rcases hf with ⟨m, hf⟩ + refine ⟨m + 1, ?_⟩ + have : AnalyticAt 𝕜 (fun z ↦ z - x) x := (analyticAt_id 𝕜 x).sub analyticAt_const + refine (this.smul hf).congr ?_ + rw [eventuallyEq_nhdsWithin_iff] at hfg + filter_upwards [hfg] with z hz + rcases eq_or_ne z x with rfl | hn + · simp + · rw [hz (Set.mem_compl_singleton_iff.mp hn), pow_succ, mul_smul] + +lemma inv {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) : MeromorphicAt f⁻¹ x := by + rcases hf with ⟨m, hf⟩ + by_cases h_eq : (fun z ↦ (z - x) ^ m • f z) =ᶠ[𝓝 x] 0 + · -- silly case: f locally 0 near x + apply (meromorphicAt_const 0 x).congr + rw [eventuallyEq_nhdsWithin_iff] + filter_upwards [h_eq] with z hfz hz + rw [Pi.inv_apply, (smul_eq_zero_iff_right <| pow_ne_zero _ (sub_ne_zero.mpr hz)).mp hfz, + inv_zero] + · -- interesting case: use local formula for `f` + obtain ⟨n, g, hg_an, hg_ne, hg_eq⟩ := hf.exists_eventuallyEq_pow_smul_nonzero_iff.mpr h_eq + have : AnalyticAt 𝕜 (fun z ↦ (z - x) ^ (m + 1)) x := + ((analyticAt_id 𝕜 x).sub analyticAt_const).pow _ + -- use `m + 1` rather than `m` to damp out any silly issues with the value at `z = x` + refine ⟨n + 1, (this.smul <| hg_an.inv hg_ne).congr ?_⟩ + filter_upwards [hg_eq, hg_an.continuousAt.eventually_ne hg_ne] with z hfg hg_ne' + rcases eq_or_ne z x with rfl | hz_ne + · simp only [sub_self, pow_succ, zero_mul, zero_smul] + · simp_rw [smul_eq_mul] at hfg ⊢ + have aux1 : f z ≠ 0 + · have : (z - x) ^ n * g z ≠ 0 := mul_ne_zero (pow_ne_zero _ (sub_ne_zero.mpr hz_ne)) hg_ne' + rw [← hfg, mul_ne_zero_iff] at this + exact this.2 + field_simp [sub_ne_zero.mpr hz_ne] + rw [pow_succ, mul_assoc, hfg] + ring + +@[simp] +lemma inv_iff {f : 𝕜 → 𝕜} {x : 𝕜} : + MeromorphicAt f⁻¹ x ↔ MeromorphicAt f x := + ⟨fun h ↦ by simpa only [inv_inv] using h.inv, MeromorphicAt.inv⟩ + +lemma div {f g : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (f / g) x := + (div_eq_mul_inv f g).symm ▸ (hf.mul hg.inv) + +end MeromorphicAt diff --git a/Mathlib/Analysis/BoundedVariation.lean b/Mathlib/Analysis/BoundedVariation.lean index 432611e0a648c..0722c9cdd9b25 100644 --- a/Mathlib/Analysis/BoundedVariation.lean +++ b/Mathlib/Analysis/BoundedVariation.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 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 Mathlib.Analysis.Calculus.Deriv.Add +import Mathlib.Analysis.Calculus.FDeriv.Add import Mathlib.Analysis.Calculus.FDeriv.Equiv import Mathlib.Analysis.Calculus.FDeriv.Prod import Mathlib.Analysis.Calculus.Monotone @@ -888,7 +888,7 @@ theorem ae_differentiableWithinAt_of_mem {f : ℝ → V} {s : Set ℝ} suffices H : ∀ᵐ x, x ∈ s → DifferentiableWithinAt ℝ (A ∘ f) s x · filter_upwards [H] with x hx xs have : f = (A.symm ∘ A) ∘ f := by - simp only [ContinuousLinearEquiv.symm_comp_self, Function.comp.left_id] + simp only [ContinuousLinearEquiv.symm_comp_self, Function.id_comp] rw [this] exact A.symm.differentiableAt.comp_differentiableWithinAt x (hx xs) apply ae_differentiableWithinAt_of_mem_pi diff --git a/Mathlib/Analysis/BoxIntegral/Basic.lean b/Mathlib/Analysis/BoxIntegral/Basic.lean index b1055deb96636..a891a13fd6b74 100644 --- a/Mathlib/Analysis/BoxIntegral/Basic.lean +++ b/Mathlib/Analysis/BoxIntegral/Basic.lean @@ -6,6 +6,7 @@ Authors: Yury Kudryashov import Mathlib.Analysis.BoxIntegral.Partition.Filter import Mathlib.Analysis.BoxIntegral.Partition.Measure import Mathlib.Topology.UniformSpace.Compact +import Mathlib.Init.Data.Bool.Lemmas #align_import analysis.box_integral.basic from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Analysis/BoxIntegral/Box/Basic.lean b/Mathlib/Analysis/BoxIntegral/Box/Basic.lean index da32ffc650d71..babffbe8d5c85 100644 --- a/Mathlib/Analysis/BoxIntegral/Box/Basic.lean +++ b/Mathlib/Analysis/BoxIntegral/Box/Basic.lean @@ -6,6 +6,7 @@ Authors: Yury Kudryashov import Mathlib.Data.Set.Intervals.Monotone import Mathlib.Topology.Algebra.Order.MonotoneConvergence import Mathlib.Topology.MetricSpace.Bounded +import Mathlib.Topology.MetricSpace.Basic #align_import analysis.box_integral.box.basic from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" /-! diff --git a/Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean b/Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean index d89e402b272dd..075d11d42fa88 100644 --- a/Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean +++ b/Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean @@ -5,10 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Analysis.BoxIntegral.Basic import Mathlib.Analysis.BoxIntegral.Partition.Additive -import Mathlib.Analysis.Calculus.FDeriv.Add -import Mathlib.Analysis.Calculus.FDeriv.Mul -import Mathlib.Analysis.Calculus.FDeriv.Equiv -import Mathlib.Analysis.Calculus.FDeriv.RestrictScalars +import Mathlib.Analysis.Calculus.FDeriv.Prod #align_import analysis.box_integral.divergence_theorem from "leanprover-community/mathlib"@"e3fb84046afd187b710170887195d50bada934ee" diff --git a/Mathlib/Analysis/BoxIntegral/Integrability.lean b/Mathlib/Analysis/BoxIntegral/Integrability.lean index 470892725e235..4f8b9e8654e96 100644 --- a/Mathlib/Analysis/BoxIntegral/Integrability.lean +++ b/Mathlib/Analysis/BoxIntegral/Integrability.lean @@ -252,7 +252,7 @@ theorem IntegrableOn.hasBoxIntegral [CompleteSpace E] {f : (ι → ℝ) → E} { (∑ J in π.boxes, ∫ x in J, f (Nx <| π.tag J) x ∂μ) _).trans _ rw [add_mul, add_mul, one_mul] refine' add_le_add_three _ _ _ - · /- Since each `f (Nx $ π.tag J)` is `ε`-close to `g (π.tag J)`, replacing the latter with + · /- Since each `f (Nx <| π.tag J)` is `ε`-close to `g (π.tag J)`, replacing the latter with the former in the formula for the integral sum changes the sum at most by `μ I * ε`. -/ rw [← hπp.iUnion_eq, π.measure_iUnion_toReal, sum_mul, integralSum] refine' dist_sum_sum_le_of_le _ fun J _ => _; dsimp diff --git a/Mathlib/Analysis/BoxIntegral/Partition/Additive.lean b/Mathlib/Analysis/BoxIntegral/Partition/Additive.lean index 9781e5d855bbe..f6eb63ffa11de 100644 --- a/Mathlib/Analysis/BoxIntegral/Partition/Additive.lean +++ b/Mathlib/Analysis/BoxIntegral/Partition/Additive.lean @@ -58,7 +58,7 @@ open Box Prepartition Finset variable {N : Type*} [AddCommMonoid M] [AddCommMonoid N] {I₀ : WithTop (Box ι)} {I J : Box ι} {i : ι} -instance : FunLike (ι →ᵇᵃ[I₀] M) (Box ι) (fun _ ↦ M) where +instance : FunLike (ι →ᵇᵃ[I₀] M) (Box ι) M where coe := toFun coe_injective' f g h := by cases f; cases g; congr @@ -71,11 +71,11 @@ theorem coe_mk (f h) : ⇑(mk f h : ι →ᵇᵃ[I₀] M) = f := rfl #align box_integral.box_additive_map.coe_mk BoxIntegral.BoxAdditiveMap.coe_mk theorem coe_injective : Injective fun (f : ι →ᵇᵃ[I₀] M) x => f x := - FunLike.coe_injective + DFunLike.coe_injective #align box_integral.box_additive_map.coe_injective BoxIntegral.BoxAdditiveMap.coe_injective -- porting note: was @[simp], now can be proved by `simp` -theorem coe_inj {f g : ι →ᵇᵃ[I₀] M} : (f : Box ι → M) = g ↔ f = g := FunLike.coe_fn_eq +theorem coe_inj {f g : ι →ᵇᵃ[I₀] M} : (f : Box ι → M) = g ↔ f = g := DFunLike.coe_fn_eq #align box_integral.box_additive_map.coe_inj BoxIntegral.BoxAdditiveMap.coe_inj theorem sum_partition_boxes (f : ι →ᵇᵃ[I₀] M) (hI : ↑I ≤ I₀) {π : Prepartition I} diff --git a/Mathlib/Analysis/BoxIntegral/Partition/Basic.lean b/Mathlib/Analysis/BoxIntegral/Partition/Basic.lean index 5505f02d69c65..79dbaf28d84dd 100644 --- a/Mathlib/Analysis/BoxIntegral/Partition/Basic.lean +++ b/Mathlib/Analysis/BoxIntegral/Partition/Basic.lean @@ -5,6 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Algebra.BigOperators.Option import Mathlib.Analysis.BoxIntegral.Box.Basic +import Mathlib.Data.Set.Pairwise.Lattice #align_import analysis.box_integral.partition.basic from "leanprover-community/mathlib"@"84dc0bd6619acaea625086d6f53cb35cdd554219" diff --git a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean index 8d18ddf3b6070..2a757812aaa38 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean @@ -4,11 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Analysis.Calculus.Series -import Mathlib.Analysis.Calculus.BumpFunction.Convolution import Mathlib.Analysis.Calculus.BumpFunction.InnerProduct +import Mathlib.Analysis.Convolution import Mathlib.Analysis.InnerProductSpace.EuclideanDist -import Mathlib.MeasureTheory.Measure.Haar.NormedSpace import Mathlib.Data.Set.Pointwise.Support +import Mathlib.MeasureTheory.Measure.Haar.NormedSpace +import Mathlib.MeasureTheory.Measure.Haar.Unique #align_import analysis.calculus.bump_function_findim from "leanprover-community/mathlib"@"fd5edc43dc4f10b85abfe544b88f82cf13c5f844" @@ -152,7 +153,7 @@ theorem IsOpen.exists_smooth_support_eq {s : Set E} (hs : IsOpen s) : ‖iteratedFDeriv ℝ i ((M⁻¹ * δ n) • g n) x‖ = ‖(M⁻¹ * δ n) • iteratedFDeriv ℝ i (g n) x‖ := by rw [iteratedFDeriv_const_smul_apply]; exact (g_smooth n).of_le le_top _ = M⁻¹ * δ n * ‖iteratedFDeriv ℝ i (g n) x‖ := by - rw [norm_smul, Real.norm_of_nonneg]; positivity + rw [norm_smul _ (iteratedFDeriv ℝ i (g n) x), Real.norm_of_nonneg]; positivity _ ≤ M⁻¹ * δ n * M := (mul_le_mul_of_nonneg_left ((hR i x).trans (IR i hi)) (by positivity)) _ = δ n := by field_simp choose r rpos hr using this @@ -551,8 +552,7 @@ instance (priority := 100) {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E simp only [norm_smul, inv_div, mem_closedBall_zero_iff, Real.norm_eq_abs, abs_div, abs_two, abs_of_nonneg A.le] calc - 2 / (R + 1) * ‖x‖ ≤ 2 / (R + 1) * 1 := - mul_le_mul_of_nonneg_left hx (div_nonneg zero_le_two A.le) + 2 / (R + 1) * ‖x‖ ≤ 2 / (R + 1) := mul_le_of_le_one_right (by positivity) hx _ = 1 - (R - 1) / (R + 1) := by field_simp; ring support := fun R hR => by have A : 0 < (R + 1) / 2 := by linarith diff --git a/Mathlib/Analysis/Calculus/Conformal/NormedSpace.lean b/Mathlib/Analysis/Calculus/Conformal/NormedSpace.lean index da176941af54e..d4e40f155639c 100644 --- a/Mathlib/Analysis/Calculus/Conformal/NormedSpace.lean +++ b/Mathlib/Analysis/Calculus/Conformal/NormedSpace.lean @@ -5,9 +5,6 @@ Authors: Yourong Zang -/ import Mathlib.Analysis.NormedSpace.ConformalLinearMap import Mathlib.Analysis.Calculus.FDeriv.Add -import Mathlib.Analysis.Calculus.FDeriv.Mul -import Mathlib.Analysis.Calculus.FDeriv.Equiv -import Mathlib.Analysis.Calculus.FDeriv.RestrictScalars #align_import analysis.calculus.conformal.normed_space from "leanprover-community/mathlib"@"e3fb84046afd187b710170887195d50bada934ee" diff --git a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean index 915132f0b7193..74eae95ddacdf 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean @@ -888,19 +888,19 @@ theorem iteratedFDerivWithin_one_apply (h : UniqueDiffWithinAt 𝕜 s x) (m : Fi rfl #align iterated_fderiv_within_one_apply iteratedFDerivWithin_one_apply -theorem Filter.EventuallyEq.iterated_fderiv_within' (h : f₁ =ᶠ[𝓝[s] x] f) (ht : t ⊆ s) (n : ℕ) : +theorem Filter.EventuallyEq.iteratedFDerivWithin' (h : f₁ =ᶠ[𝓝[s] x] f) (ht : t ⊆ s) (n : ℕ) : iteratedFDerivWithin 𝕜 n f₁ t =ᶠ[𝓝[s] x] iteratedFDerivWithin 𝕜 n f t := by induction' n with n ihn - · exact h.mono fun y hy => FunLike.ext _ _ fun _ => hy - · have : fderivWithin 𝕜 _ t =ᶠ[𝓝[s] x] fderivWithin 𝕜 _ t := ihn.fderiv_within' ht + · exact h.mono fun y hy => DFunLike.ext _ _ fun _ => hy + · have : fderivWithin 𝕜 _ t =ᶠ[𝓝[s] x] fderivWithin 𝕜 _ t := ihn.fderivWithin' ht apply this.mono intro y hy simp only [iteratedFDerivWithin_succ_eq_comp_left, hy, (· ∘ ·)] -#align filter.eventually_eq.iterated_fderiv_within' Filter.EventuallyEq.iterated_fderiv_within' +#align filter.eventually_eq.iterated_fderiv_within' Filter.EventuallyEq.iteratedFDerivWithin' protected theorem Filter.EventuallyEq.iteratedFDerivWithin (h : f₁ =ᶠ[𝓝[s] x] f) (n : ℕ) : iteratedFDerivWithin 𝕜 n f₁ s =ᶠ[𝓝[s] x] iteratedFDerivWithin 𝕜 n f s := - h.iterated_fderiv_within' Subset.rfl n + h.iteratedFDerivWithin' Subset.rfl n #align filter.eventually_eq.iterated_fderiv_within Filter.EventuallyEq.iteratedFDerivWithin /-- If two functions coincide in a neighborhood of `x` within a set `s` and at `x`, then their @@ -908,7 +908,7 @@ iterated differentials within this set at `x` coincide. -/ theorem Filter.EventuallyEq.iteratedFDerivWithin_eq (h : f₁ =ᶠ[𝓝[s] x] f) (hx : f₁ x = f x) (n : ℕ) : iteratedFDerivWithin 𝕜 n f₁ s x = iteratedFDerivWithin 𝕜 n f s x := have : f₁ =ᶠ[𝓝[insert x s] x] f := by simpa [EventuallyEq, hx] - (this.iterated_fderiv_within' (subset_insert _ _) n).self_of_nhdsWithin (mem_insert _ _) + (this.iteratedFDerivWithin' (subset_insert _ _) n).self_of_nhdsWithin (mem_insert _ _) #align filter.eventually_eq.iterated_fderiv_within_eq Filter.EventuallyEq.iteratedFDerivWithin_eq /-- If two functions coincide on a set `s`, then their iterated differentials within this set @@ -1147,7 +1147,7 @@ theorem contDiffOn_succ_iff_fderivWithin {n : ℕ} (hs : UniqueDiffOn 𝕜 s) : rwa [fderivWithin_inter (o_open.mem_nhds hy.2)] at A #align cont_diff_on_succ_iff_fderiv_within contDiffOn_succ_iff_fderivWithin -theorem contDiffOn_succ_iff_has_fderiv_within {n : ℕ} (hs : UniqueDiffOn 𝕜 s) : +theorem contDiffOn_succ_iff_hasFDerivWithin {n : ℕ} (hs : UniqueDiffOn 𝕜 s) : ContDiffOn 𝕜 (n + 1 : ℕ) f s ↔ ∃ f' : E → E →L[𝕜] F, ContDiffOn 𝕜 n f' s ∧ ∀ x, x ∈ s → HasFDerivWithinAt f (f' x) s x := by rw [contDiffOn_succ_iff_fderivWithin hs] @@ -1155,7 +1155,7 @@ theorem contDiffOn_succ_iff_has_fderiv_within {n : ℕ} (hs : UniqueDiffOn 𝕜 rcases h with ⟨f', h1, h2⟩ refine' ⟨fun x hx => (h2 x hx).differentiableWithinAt, fun x hx => _⟩ exact (h1 x hx).congr' (fun y hy => (h2 y hy).fderivWithin (hs y hy)) hx -#align cont_diff_on_succ_iff_has_fderiv_within contDiffOn_succ_iff_has_fderiv_within +#align cont_diff_on_succ_iff_has_fderiv_within contDiffOn_succ_iff_hasFDerivWithin /-- A function is `C^(n + 1)` on an open domain if and only if it is differentiable there, and its derivative (expressed with `fderiv`) is `C^n`. -/ @@ -1502,12 +1502,12 @@ theorem contDiff_iff_forall_nat_le : ContDiff 𝕜 n f ↔ ∀ m : ℕ, ↑m ≤ #align cont_diff_iff_forall_nat_le contDiff_iff_forall_nat_le /-- A function is `C^(n+1)` iff it has a `C^n` derivative. -/ -theorem contDiff_succ_iff_has_fderiv {n : ℕ} : +theorem contDiff_succ_iff_hasFDerivAt {n : ℕ} : ContDiff 𝕜 (n + 1 : ℕ) f ↔ ∃ f' : E → E →L[𝕜] F, ContDiff 𝕜 n f' ∧ ∀ x, HasFDerivAt f (f' x) x := by simp only [← contDiffOn_univ, ← hasFDerivWithinAt_univ, - contDiffOn_succ_iff_has_fderiv_within uniqueDiffOn_univ, Set.mem_univ, forall_true_left] -#align cont_diff_succ_iff_has_fderiv contDiff_succ_iff_has_fderiv + contDiffOn_succ_iff_hasFDerivWithin uniqueDiffOn_univ, Set.mem_univ, forall_true_left] +#align cont_diff_succ_iff_has_fderiv contDiff_succ_iff_hasFDerivAt /-! ### Iterated derivative -/ diff --git a/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean b/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean index dffe2df5e938a..af9976efcf432 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean @@ -39,7 +39,7 @@ theorem contDiffOn_clm_apply {n : ℕ∞} {f : E → F →L[𝕜] G} {s : Set E} have hd : d = finrank 𝕜 (Fin d → 𝕜) := (finrank_fin_fun 𝕜).symm let e₁ := ContinuousLinearEquiv.ofFinrankEq hd let e₂ := (e₁.arrowCongr (1 : G ≃L[𝕜] G)).trans (ContinuousLinearEquiv.piRing (Fin d)) - rw [← comp.left_id f, ← e₂.symm_comp_self] + rw [← id_comp f, ← e₂.symm_comp_self] exact e₂.symm.contDiff.comp_contDiffOn (contDiffOn_pi.mpr fun i => h _) #align cont_diff_on_clm_apply contDiffOn_clm_apply diff --git a/Mathlib/Analysis/Calculus/ContDiff/IsROrC.lean b/Mathlib/Analysis/Calculus/ContDiff/IsROrC.lean index cb9d81fbba0d0..ec5d9120159a1 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/IsROrC.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/IsROrC.lean @@ -3,7 +3,7 @@ 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, Floris van Doorn -/ -import Mathlib.Analysis.Calculus.ContDiff.Basic +import Mathlib.Analysis.Calculus.ContDiff.Defs import Mathlib.Analysis.Calculus.MeanValue #align_import analysis.calculus.cont_diff from "leanprover-community/mathlib"@"3bce8d800a6f2b8f63fe1e588fd76a9ff4adcebe" diff --git a/Mathlib/Analysis/Calculus/Deriv/Basic.lean b/Mathlib/Analysis/Calculus/Deriv/Basic.lean index 0a3df02e596b3..d04d442d1ec11 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Basic.lean @@ -535,6 +535,10 @@ theorem derivWithin_of_isOpen (hs : IsOpen s) (hx : x ∈ s) : derivWithin f s x derivWithin_of_mem_nhds (hs.mem_nhds hx) #align deriv_within_of_open derivWithin_of_isOpen +lemma deriv_eqOn {f' : 𝕜 → F} (hs : IsOpen s) (hf' : ∀ x ∈ s, HasDerivWithinAt f (f' x) s x) : + s.EqOn (deriv f) f' := fun x hx ↦ by + rw [← derivWithin_of_isOpen hs hx, (hf' _ hx).derivWithin <| hs.uniqueDiffWithinAt hx] + theorem deriv_mem_iff {f : 𝕜 → F} {s : Set F} {x : 𝕜} : deriv f x ∈ s ↔ DifferentiableAt 𝕜 f x ∧ deriv f x ∈ s ∨ ¬DifferentiableAt 𝕜 f x ∧ (0 : F) ∈ s := diff --git a/Mathlib/Analysis/Calculus/Deriv/Star.lean b/Mathlib/Analysis/Calculus/Deriv/Star.lean index 3aaeb9526a8eb..89f5da9f5a87a 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Star.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Star.lean @@ -16,9 +16,6 @@ operation. Note that these only apply when the field that the derivative is resp star operation; which as should be expected rules out `𝕜 = ℂ`. -/ -set_option autoImplicit true - - universe u v w variable {𝕜 : Type u} [NontriviallyNormedField 𝕜] @@ -32,7 +29,7 @@ variable {f : 𝕜 → F} variable [StarRing 𝕜] [TrivialStar 𝕜] [StarAddMonoid F] [ContinuousStar F] -variable [StarModule 𝕜 F] +variable [StarModule 𝕜 F] {f' : F} {s : Set 𝕜} {x : 𝕜} {L : Filter 𝕜} protected nonrec theorem HasDerivAtFilter.star (h : HasDerivAtFilter f f' x L) : HasDerivAtFilter (fun x => star (f x)) (star f') x L := by @@ -55,11 +52,11 @@ protected nonrec theorem HasStrictDerivAt.star (h : HasStrictDerivAt f f' x) : protected theorem derivWithin.star (hxs : UniqueDiffWithinAt 𝕜 s x) : derivWithin (fun y => star (f y)) s x = star (derivWithin f s x) := - FunLike.congr_fun (fderivWithin_star hxs) _ + DFunLike.congr_fun (fderivWithin_star hxs) _ #align deriv_within.star derivWithin.star protected theorem deriv.star : deriv (fun y => star (f y)) x = star (deriv f x) := - FunLike.congr_fun fderiv_star _ + DFunLike.congr_fun fderiv_star _ #align deriv.star deriv.star @[simp] diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index 8b78e9ec26002..60e8dabadecd3 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Analysis.Analytic.Basic +import Mathlib.Analysis.Analytic.CPolynomial import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.Analysis.Calculus.ContDiff.Defs @@ -87,32 +88,17 @@ theorem HasFPowerSeriesOnBall.fderiv_eq [CompleteSpace F] (h : HasFPowerSeriesOn /-- If a function has a power series on a ball, then so does its derivative. -/ theorem HasFPowerSeriesOnBall.fderiv [CompleteSpace F] (h : HasFPowerSeriesOnBall f p x r) : HasFPowerSeriesOnBall (fderiv 𝕜 f) - ((continuousMultilinearCurryFin1 𝕜 E F : - (E[×1]→L[𝕜] F) →L[𝕜] E →L[𝕜] F).compFormalMultilinearSeries - (p.changeOriginSeries 1)) - x r := by - suffices A : - HasFPowerSeriesOnBall - (fun z => continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin (z - x) 1)) - ((continuousMultilinearCurryFin1 𝕜 E F : - (E[×1]→L[𝕜] F) →L[𝕜] E →L[𝕜] F).compFormalMultilinearSeries - (p.changeOriginSeries 1)) - x r - · apply A.congr - intro z hz - dsimp - rw [← h.fderiv_eq, add_sub_cancel'_right] - simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz - suffices B : - HasFPowerSeriesOnBall (fun z => p.changeOrigin (z - x) 1) (p.changeOriginSeries 1) x r - exact - (continuousMultilinearCurryFin1 𝕜 E - F).toContinuousLinearEquiv.toContinuousLinearMap.comp_hasFPowerSeriesOnBall - B - simpa using - ((p.hasFPowerSeriesOnBall_changeOrigin 1 (h.r_pos.trans_le h.r_le)).mono h.r_pos - h.r_le).comp_sub - x + ((continuousMultilinearCurryFin1 𝕜 E F : (E[×1]→L[𝕜] F) →L[𝕜] E →L[𝕜] F) + |>.compFormalMultilinearSeries (p.changeOriginSeries 1)) x r := by + refine .congr (f := fun z ↦ continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin (z - x) 1)) ?_ + fun z hz ↦ ?_ + · refine continuousMultilinearCurryFin1 𝕜 E F + |>.toContinuousLinearEquiv.toContinuousLinearMap.comp_hasFPowerSeriesOnBall ?_ + simpa using ((p.hasFPowerSeriesOnBall_changeOrigin 1 + (h.r_pos.trans_le h.r_le)).mono h.r_pos h.r_le).comp_sub x + dsimp only + rw [← h.fderiv_eq, add_sub_cancel'_right] + simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz #align has_fpower_series_on_ball.fderiv HasFPowerSeriesOnBall.fderiv /-- If a function is analytic on a set `s`, so is its Fréchet derivative. -/ @@ -131,31 +117,23 @@ theorem AnalyticOn.iteratedFDeriv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) (n exact ((continuousMultilinearCurryFin0 𝕜 E F).symm : F →L[𝕜] E[×0]→L[𝕜] F).comp_analyticOn h · rw [iteratedFDeriv_succ_eq_comp_left] -- Porting note: for reasons that I do not understand at all, `?g` cannot be inlined. - convert @ContinuousLinearMap.comp_analyticOn 𝕜 E - ?_ (ContinuousMultilinearMap 𝕜 (fun _ : Fin (n + 1) ↦ E) F) - ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ - s ?g IH.fderiv - case g => - exact ↑(continuousMultilinearCurryLeftEquiv 𝕜 (fun _ : Fin (n + 1) => E) F) - rfl + convert ContinuousLinearMap.comp_analyticOn ?g IH.fderiv + case g => exact ↑(continuousMultilinearCurryLeftEquiv 𝕜 (fun _ : Fin (n + 1) ↦ E) F) + simp #align analytic_on.iterated_fderiv AnalyticOn.iteratedFDeriv /-- An analytic function is infinitely differentiable. -/ theorem AnalyticOn.contDiffOn [CompleteSpace F] (h : AnalyticOn 𝕜 f s) {n : ℕ∞} : - ContDiffOn 𝕜 n f s := by + ContDiffOn 𝕜 n f s := let t := { x | AnalyticAt 𝕜 f x } - suffices : ContDiffOn 𝕜 n f t; exact this.mono h - have H : AnalyticOn 𝕜 f t := fun x hx => hx + suffices ContDiffOn 𝕜 n f t from this.mono h + have H : AnalyticOn 𝕜 f t := fun _x hx ↦ hx have t_open : IsOpen t := isOpen_analyticAt 𝕜 f - apply contDiffOn_of_continuousOn_differentiableOn - · rintro m - - apply (H.iteratedFDeriv m).continuousOn.congr - intro x hx - exact iteratedFDerivWithin_of_isOpen _ t_open hx - · rintro m - - apply (H.iteratedFDeriv m).differentiableOn.congr - intro x hx - exact iteratedFDerivWithin_of_isOpen _ t_open hx + contDiffOn_of_continuousOn_differentiableOn + (fun m _ ↦ (H.iteratedFDeriv m).continuousOn.congr + fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) + (fun m _ ↦ (H.iteratedFDeriv m).differentiableOn.congr + fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) #align analytic_on.cont_diff_on AnalyticOn.contDiffOn theorem AnalyticAt.contDiffAt [CompleteSpace F] (h : AnalyticAt 𝕜 f x) {n : ℕ∞} : @@ -200,3 +178,119 @@ theorem AnalyticOn.iterated_deriv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) (n #align analytic_on.iterated_deriv AnalyticOn.iterated_deriv end deriv +section fderiv + +variable {p : FormalMultilinearSeries 𝕜 E F} {r : ℝ≥0∞} {n : ℕ} + +variable {f : E → F} {x : E} {s : Set E} + +/-! The case of continuously polynomial functions. We get the same differentiability +results as for analytic functions, but without the assumptions that `F` is complete.-/ + +theorem HasFiniteFPowerSeriesOnBall.differentiableOn + (h : HasFiniteFPowerSeriesOnBall f p x n r) : DifferentiableOn 𝕜 f (EMetric.ball x r) := + fun _ hy ↦ (h.cPolynomialAt_of_mem hy).analyticAt.differentiableWithinAt + +theorem HasFiniteFPowerSeriesOnBall.hasFDerivAt (h : HasFiniteFPowerSeriesOnBall f p x n r) + {y : E} (hy : (‖y‖₊ : ℝ≥0∞) < r) : + HasFDerivAt f (continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin y 1)) (x + y) := + (h.changeOrigin hy).toHasFPowerSeriesOnBall.hasFPowerSeriesAt.hasFDerivAt + +theorem HasFiniteFPowerSeriesOnBall.fderiv_eq (h : HasFiniteFPowerSeriesOnBall f p x n r) + {y : E} (hy : (‖y‖₊ : ℝ≥0∞) < r) : + fderiv 𝕜 f (x + y) = continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin y 1) := + (h.hasFDerivAt hy).fderiv + +/-- If a function has a finite power series on a ball, then so does its derivative. -/ +protected theorem HasFiniteFPowerSeriesOnBall.fderiv + (h : HasFiniteFPowerSeriesOnBall f p x (n + 1) r) : + HasFiniteFPowerSeriesOnBall (fderiv 𝕜 f) + ((continuousMultilinearCurryFin1 𝕜 E F : (E[×1]→L[𝕜] F) →L[𝕜] E →L[𝕜] F) + |>.compFormalMultilinearSeries (p.changeOriginSeries 1)) x n r := by + refine .congr (f := fun z ↦ continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin (z - x) 1)) ?_ + fun z hz ↦ ?_ + · refine continuousMultilinearCurryFin1 𝕜 E F + |>.toContinuousLinearEquiv.toContinuousLinearMap.comp_hasFiniteFPowerSeriesOnBall ?_ + simpa using + ((p.hasFiniteFPowerSeriesOnBall_changeOrigin 1 h.finite).mono h.r_pos le_top).comp_sub x + dsimp only + rw [← h.fderiv_eq, add_sub_cancel'_right] + simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz + +/-- If a function has a finite power series on a ball, then so does its derivative. +This is a variant of `HasFiniteFPowerSeriesOnBall.fderiv` where the degree of `f` is `< n` +and not `< n + 1`. -/ +theorem HasFiniteFPowerSeriesOnBall.fderiv' (h : HasFiniteFPowerSeriesOnBall f p x n r) : + HasFiniteFPowerSeriesOnBall (fderiv 𝕜 f) + ((continuousMultilinearCurryFin1 𝕜 E F : (E[×1]→L[𝕜] F) →L[𝕜] E →L[𝕜] F) + |>.compFormalMultilinearSeries (p.changeOriginSeries 1)) x (n - 1) r := by + obtain rfl | hn := eq_or_ne n 0 + · rw [zero_tsub] + refine HasFiniteFPowerSeriesOnBall.bound_zero_of_eq_zero (fun y hy ↦ ?_) h.r_pos fun n ↦ ?_ + · rw [Filter.EventuallyEq.fderiv_eq (f := fun _ ↦ 0)] + · rw [fderiv_const, Pi.zero_apply] + · exact Filter.eventuallyEq_iff_exists_mem.mpr ⟨EMetric.ball x r, + EMetric.isOpen_ball.mem_nhds hy, fun z hz ↦ by rw [h.eq_zero_of_bound_zero z hz]⟩ + · apply ContinuousMultilinearMap.ext; intro a + change (continuousMultilinearCurryFin1 𝕜 E F) (p.changeOriginSeries 1 n a) = 0 + rw [p.changeOriginSeries_finite_of_finite h.finite 1 (Nat.zero_le _)] + exact map_zero _ + · rw [← Nat.succ_pred hn] at h + exact h.fderiv + +/-- If a function is polynomial on a set `s`, so is its Fréchet derivative. -/ +theorem CPolynomialOn.fderiv (h : CPolynomialOn 𝕜 f s) : + CPolynomialOn 𝕜 (fderiv 𝕜 f) s := by + intro y hy + rcases h y hy with ⟨p, r, n, hp⟩ + exact hp.fderiv'.cPolynomialAt + +/-- If a function is polynomial on a set `s`, so are its successive Fréchet derivative. -/ +theorem CPolynomialOn.iteratedFDeriv (h : CPolynomialOn 𝕜 f s) (n : ℕ) : + CPolynomialOn 𝕜 (iteratedFDeriv 𝕜 n f) s := by + induction' n with n IH + · rw [iteratedFDeriv_zero_eq_comp] + exact ((continuousMultilinearCurryFin0 𝕜 E F).symm : F →L[𝕜] E[×0]→L[𝕜] F).comp_cPolynomialOn h + · rw [iteratedFDeriv_succ_eq_comp_left] + convert ContinuousLinearMap.comp_cPolynomialOn ?g IH.fderiv + case g => exact ↑(continuousMultilinearCurryLeftEquiv 𝕜 (fun _ : Fin (n + 1) ↦ E) F) + simp + +/-- A polynomial function is infinitely differentiable. -/ +theorem CPolynomialOn.contDiffOn (h : CPolynomialOn 𝕜 f s) {n : ℕ∞} : + ContDiffOn 𝕜 n f s := + let t := { x | CPolynomialAt 𝕜 f x } + suffices ContDiffOn 𝕜 n f t from this.mono h + have H : CPolynomialOn 𝕜 f t := fun _x hx ↦ hx + have t_open : IsOpen t := isOpen_cPolynomialAt 𝕜 f + contDiffOn_of_continuousOn_differentiableOn + (fun m _ ↦ (H.iteratedFDeriv m).continuousOn.congr + fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) + (fun m _ ↦ (H.iteratedFDeriv m).analyticOn.differentiableOn.congr + fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) + +theorem CPolynomialAt.contDiffAt (h : CPolynomialAt 𝕜 f x) {n : ℕ∞} : + ContDiffAt 𝕜 n f x := + let ⟨_, hs, hf⟩ := h.exists_mem_nhds_cPolynomialOn + hf.contDiffOn.contDiffAt hs + +end fderiv + +section deriv + +variable {p : FormalMultilinearSeries 𝕜 𝕜 F} {r : ℝ≥0∞} + +variable {f : 𝕜 → F} {x : 𝕜} {s : Set 𝕜} + +/-- If a function is polynomial on a set `s`, so is its derivative. -/ +protected theorem CPolynomialOn.deriv (h : CPolynomialOn 𝕜 f s) : CPolynomialOn 𝕜 (deriv f) s := + (ContinuousLinearMap.apply 𝕜 F (1 : 𝕜)).comp_cPolynomialOn h.fderiv + +/-- If a function is polynomial on a set `s`, so are its successive derivatives. -/ +theorem CPolynomialOn.iterated_deriv (h : CPolynomialOn 𝕜 f s) (n : ℕ) : + CPolynomialOn 𝕜 (deriv^[n] f) s := by + induction' n with n IH + · exact h + · simpa only [Function.iterate_succ', Function.comp_apply] using IH.deriv + +end deriv diff --git a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean index 00478ed34a603..07f0a64f66c6f 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2019 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Sébastien Gouëzel, Yury Kudryashov -/ -import Mathlib.Analysis.Asymptotics.AsymptoticEquivalent import Mathlib.Analysis.Calculus.TangentCone import Mathlib.Analysis.NormedSpace.OperatorNorm @@ -116,8 +115,6 @@ derivative, differentiable, Fréchet, calculus -/ -set_option autoImplicit true - open Filter Asymptotics ContinuousLinearMap Set Metric open Topology Classical NNReal Filter Asymptotics ENNReal @@ -1026,17 +1023,17 @@ theorem Filter.EventuallyEq.fderivWithin_eq (hs : f₁ =ᶠ[𝓝[s] x] f) (hx : simp only [fderivWithin, hs.hasFDerivWithinAt_iff hx] #align filter.eventually_eq.fderiv_within_eq Filter.EventuallyEq.fderivWithin_eq -theorem Filter.EventuallyEq.fderiv_within' (hs : f₁ =ᶠ[𝓝[s] x] f) (ht : t ⊆ s) : +theorem Filter.EventuallyEq.fderivWithin' (hs : f₁ =ᶠ[𝓝[s] x] f) (ht : t ⊆ s) : fderivWithin 𝕜 f₁ t =ᶠ[𝓝[s] x] fderivWithin 𝕜 f t := (eventually_nhdsWithin_nhdsWithin.2 hs).mp <| eventually_mem_nhdsWithin.mono fun _y hys hs => EventuallyEq.fderivWithin_eq (hs.filter_mono <| nhdsWithin_mono _ ht) (hs.self_of_nhdsWithin hys) -#align filter.eventually_eq.fderiv_within' Filter.EventuallyEq.fderiv_within' +#align filter.eventually_eq.fderiv_within' Filter.EventuallyEq.fderivWithin' protected theorem Filter.EventuallyEq.fderivWithin (hs : f₁ =ᶠ[𝓝[s] x] f) : fderivWithin 𝕜 f₁ s =ᶠ[𝓝[s] x] fderivWithin 𝕜 f s := - hs.fderiv_within' Subset.rfl + hs.fderivWithin' Subset.rfl #align filter.eventually_eq.fderiv_within Filter.EventuallyEq.fderivWithin theorem Filter.EventuallyEq.fderivWithin_eq_nhds (h : f₁ =ᶠ[𝓝 x] f) : @@ -1241,7 +1238,7 @@ theorem HasFDerivAt.of_nmem_tsupport (h : x ∉ tsupport f) : HasFDerivAt f (0 : E →L[𝕜] F) x := (HasStrictFDerivAt.of_nmem_tsupport 𝕜 h).hasFDerivAt -theorem HasFDerivWithinAt.of_not_mem_tsupport (h : x ∉ tsupport f) : +theorem HasFDerivWithinAt.of_not_mem_tsupport {s : Set E} {x : E} (h : x ∉ tsupport f) : HasFDerivWithinAt f (0 : E →L[𝕜] F) s x := (HasFDerivAt.of_nmem_tsupport 𝕜 h).hasFDerivWithinAt diff --git a/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean b/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean index 4bb25ce2831a8..3808c69940417 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean @@ -3,6 +3,7 @@ Copyright (c) 2019 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Sébastien Gouëzel, Yury Kudryashov -/ +import Mathlib.Analysis.Asymptotics.AsymptoticEquivalent import Mathlib.Analysis.Calculus.FDeriv.Linear import Mathlib.Analysis.Calculus.FDeriv.Comp diff --git a/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean b/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean index 6d204ec85a7c8..94596e32bcc75 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel, Yury Kudryashov -/ import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.Analysis.Calculus.Deriv.Slope +import Mathlib.Analysis.NormedSpace.FiniteDimension import Mathlib.MeasureTheory.Constructions.BorelSpace.ContinuousLinearMap import Mathlib.MeasureTheory.Function.StronglyMeasurable.Basic @@ -201,7 +202,7 @@ theorem norm_sub_le_of_mem_A {c : 𝕜} (hc : 1 < ‖c‖) {r ε : ℝ} (hε : 0 · simp only [le_of_lt (half_pos hr), mem_closedBall, dist_self] · simp only [dist_eq_norm, add_sub_cancel', mem_closedBall, ylt.le] _ = 2 * ε * r := by ring - _ ≤ 2 * ε * (2 * ‖c‖ * ‖y‖) := (mul_le_mul_of_nonneg_left ley (mul_nonneg (by norm_num) hε.le)) + _ ≤ 2 * ε * (2 * ‖c‖ * ‖y‖) := by gcongr _ = 4 * ‖c‖ * ε * ‖y‖ := by ring #align fderiv_measurable_aux.norm_sub_le_of_mem_A FDerivMeasurableAux.norm_sub_le_of_mem_A @@ -211,7 +212,7 @@ theorem differentiable_set_subset_D : intro x hx rw [D, mem_iInter] intro e - have : (0 : ℝ) < (1 / 2) ^ e := pow_pos (by norm_num) _ + have : (0 : ℝ) < (1 / 2) ^ e := by positivity rcases mem_A_of_differentiable this hx.1 with ⟨R, R_pos, hR⟩ obtain ⟨n, hn⟩ : ∃ n : ℕ, (1 / 2) ^ n < R := exists_pow_lt_of_lt_one R_pos (by norm_num : (1 : ℝ) / 2 < 1) @@ -226,7 +227,6 @@ theorem D_subset_differentiable_set {K : Set (E →L[𝕜] F)} (hK : IsComplete D f K ⊆ { x | DifferentiableAt 𝕜 f x ∧ fderiv 𝕜 f x ∈ K } := by have P : ∀ {n : ℕ}, (0 : ℝ) < (1 / 2) ^ n := fun {n} => pow_pos (by norm_num) n rcases NormedField.exists_one_lt_norm 𝕜 with ⟨c, hc⟩ - have cpos : 0 < ‖c‖ := lt_trans zero_lt_one hc intro x hx have : ∀ e : ℕ, ∃ n : ℕ, ∀ p q, n ≤ p → n ≤ q → @@ -285,13 +285,13 @@ theorem D_subset_differentiable_set {K : Set (E →L[𝕜] F)} (hK : IsComplete rw [Metric.cauchySeq_iff'] intro ε εpos obtain ⟨e, he⟩ : ∃ e : ℕ, (1 / 2) ^ e < ε / (12 * ‖c‖) := - exists_pow_lt_of_lt_one (div_pos εpos (mul_pos (by norm_num) cpos)) (by norm_num) + exists_pow_lt_of_lt_one (by positivity) (by norm_num) refine' ⟨e, fun e' he' => _⟩ rw [dist_comm, dist_eq_norm] calc ‖L0 e - L0 e'‖ ≤ 12 * ‖c‖ * (1 / 2) ^ e := M _ _ _ _ _ _ le_rfl le_rfl le_rfl le_rfl he' _ < 12 * ‖c‖ * (ε / (12 * ‖c‖)) := by gcongr - _ = ε := by field_simp [(by norm_num : (12 : ℝ) ≠ 0), ne_of_gt cpos]; ring + _ = ε := by field_simp; ring -- As it is Cauchy, the sequence `L0` converges, to a limit `f'` in `K`. obtain ⟨f', f'K, hf'⟩ : ∃ f' ∈ K, Tendsto L0 atTop (𝓝 f') := cauchySeq_tendsto_of_isComplete hK (fun e => (hn e (n e) (n e) le_rfl le_rfl).1) this @@ -338,7 +338,7 @@ theorem D_subset_differentiable_set {K : Set (E →L[𝕜] F)} (hK : IsComplete have J1 : ‖f (x + y) - f x - L e (n e) m (x + y - x)‖ ≤ (1 / 2) ^ e * (1 / 2) ^ m := by apply le_of_mem_A (hn e (n e) m le_rfl m_ge).2.2 · simp only [mem_closedBall, dist_self] - exact div_nonneg (le_of_lt P) zero_le_two + positivity · simpa only [dist_eq_norm, add_sub_cancel', mem_closedBall, pow_succ', mul_one_div] using h'k have J2 : ‖f (x + y) - f x - L e (n e) m y‖ ≤ 4 * (1 / 2) ^ e * ‖y‖ := @@ -346,15 +346,13 @@ theorem D_subset_differentiable_set {K : Set (E →L[𝕜] F)} (hK : IsComplete ‖f (x + y) - f x - L e (n e) m y‖ ≤ (1 / 2) ^ e * (1 / 2) ^ m := by simpa only [add_sub_cancel'] using J1 _ = 4 * (1 / 2) ^ e * (1 / 2) ^ (m + 2) := by field_simp; ring - _ ≤ 4 * (1 / 2) ^ e * ‖y‖ := - mul_le_mul_of_nonneg_left (le_of_lt hk) (mul_nonneg (by norm_num) (le_of_lt P)) + _ ≤ 4 * (1 / 2) ^ e * ‖y‖ := by gcongr -- use the previous estimates to see that `f (x + y) - f x - f' y` is small. calc ‖f (x + y) - f x - f' y‖ = ‖f (x + y) - f x - L e (n e) m y + (L e (n e) m - f') y‖ := congr_arg _ (by simp) _ ≤ 4 * (1 / 2) ^ e * ‖y‖ + 12 * ‖c‖ * (1 / 2) ^ e * ‖y‖ := - (norm_add_le_of_le J2 - ((le_op_norm _ _).trans (mul_le_mul_of_nonneg_right (Lf' _ _ m_ge) (norm_nonneg _)))) + norm_add_le_of_le J2 <| (le_op_norm _ _).trans <| by gcongr; exact Lf' _ _ m_ge _ = (4 + 12 * ‖c‖) * ‖y‖ * (1 / 2) ^ e := by ring _ ≤ (4 + 12 * ‖c‖) * ‖y‖ * (ε / (4 + 12 * ‖c‖)) := by gcongr _ = ε * ‖y‖ := by field_simp [ne_of_gt pos]; ring @@ -505,7 +503,7 @@ theorem measurableSet_B {K : Set F} {r s ε : ℝ} : MeasurableSet (B f K r s ε theorem A_mono (L : F) (r : ℝ) {ε δ : ℝ} (h : ε ≤ δ) : A f L r ε ⊆ A f L r δ := by rintro x ⟨r', r'r, hr'⟩ - refine' ⟨r', r'r, fun y hy z hz => (hr' y hy z hz).trans (mul_le_mul_of_nonneg_right h _)⟩ + refine ⟨r', r'r, fun y hy z hz => (hr' y hy z hz).trans (mul_le_mul_of_nonneg_right h ?_)⟩ linarith [hy.1, hy.2, r'r.2] #align right_deriv_measurable_aux.A_mono RightDerivMeasurableAux.A_mono @@ -554,10 +552,9 @@ theorem norm_sub_le_of_mem_A {r x : ℝ} (hr : 0 < r) (ε : ℝ) {L₁ L₂ : F} ‖f (x + r / 2) - f x - (x + r / 2 - x) • L₂ - (f (x + r / 2) - f x - (x + r / 2 - x) • L₁)‖ := by simp [smul_sub] - _ ≤ - ‖f (x + r / 2) - f x - (x + r / 2 - x) • L₂‖ + + _ ≤ ‖f (x + r / 2) - f x - (x + r / 2 - x) • L₂‖ + ‖f (x + r / 2) - f x - (x + r / 2 - x) • L₁‖ := - (norm_sub_le _ _) + norm_sub_le _ _ _ ≤ ε * r + ε * r := by apply add_le_add · apply le_of_mem_A h₂ <;> simp [(half_pos hr).le] @@ -701,24 +698,20 @@ theorem D_subset_differentiable_set {K : Set F} (hK : IsComplete K) : ‖f y - f x - (y - x) • L e (n e) m‖ ≤ (1 / 2) ^ e * (1 / 2) ^ m := by apply le_of_mem_A (hn e (n e) m le_rfl m_ge).2.2 · simp only [one_div, inv_pow, left_mem_Icc, le_add_iff_nonneg_right] - exact div_nonneg (inv_nonneg.2 (pow_nonneg zero_le_two _)) zero_le_two + positivity · simp only [pow_add, tsub_le_iff_left] at h'k simpa only [hy.1, mem_Icc, true_and_iff, one_div, pow_one] using h'k _ = 4 * (1 / 2) ^ e * (1 / 2) ^ (m + 2) := by field_simp; ring - _ ≤ 4 * (1 / 2) ^ e * (y - x) := - (mul_le_mul_of_nonneg_left (le_of_lt hk) (mul_nonneg (by norm_num) (le_of_lt P))) + _ ≤ 4 * (1 / 2) ^ e * (y - x) := by gcongr _ = 4 * (1 / 2) ^ e * ‖y - x‖ := by rw [Real.norm_of_nonneg yzero.le] - calc ‖f y - f x - (y - x) • f'‖ = ‖f y - f x - (y - x) • L e (n e) m + (y - x) • (L e (n e) m - f')‖ := by simp only [smul_sub, sub_add_sub_cancel] _ ≤ 4 * (1 / 2) ^ e * ‖y - x‖ + ‖y - x‖ * (12 * (1 / 2) ^ e) := - (norm_add_le_of_le J - (by rw [norm_smul]; exact mul_le_mul_of_nonneg_left (Lf' _ _ m_ge) (norm_nonneg _))) + norm_add_le_of_le J <| by rw [norm_smul]; gcongr; exact Lf' _ _ m_ge _ = 16 * ‖y - x‖ * (1 / 2) ^ e := by ring - _ ≤ 16 * ‖y - x‖ * (ε / 16) := - (mul_le_mul_of_nonneg_left he.le (mul_nonneg (by norm_num) (norm_nonneg _))) + _ ≤ 16 * ‖y - x‖ * (ε / 16) := by gcongr _ = ε * ‖y - x‖ := by ring rw [← this.derivWithin (uniqueDiffOn_Ici x x Set.left_mem_Ici)] at f'K diff --git a/Mathlib/Analysis/Calculus/FDeriv/Star.lean b/Mathlib/Analysis/Calculus/FDeriv/Star.lean index 04042518c575b..00512e90875ff 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Star.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Star.lean @@ -6,7 +6,7 @@ Authors: Eric Wieser import Mathlib.Analysis.Calculus.FDeriv.Linear import Mathlib.Analysis.Calculus.FDeriv.Comp import Mathlib.Analysis.Calculus.FDeriv.Equiv -import Mathlib.Analysis.NormedSpace.Star.Basic +import Mathlib.Topology.Algebra.Module.Star #align_import analysis.calculus.fderiv.star from "leanprover-community/mathlib"@"ad84a13c884fd19e286fb7abb36f4b9ba7e2f615" diff --git a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean index 5561a84ba4f0d..9c0d7d75a1cb5 100644 --- a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean +++ b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Heather Macbeth. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Heather Macbeth -/ +import Mathlib.Analysis.Calculus.ContDiff.Basic import Mathlib.Analysis.Calculus.ContDiff.IsROrC import Mathlib.Analysis.Calculus.InverseFunctionTheorem.FDeriv diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean similarity index 99% rename from Mathlib/Analysis/Calculus/IteratedDeriv.lean rename to Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean index 8c9de9cb4df2c..9acf9125275c4 100644 --- a/Mathlib/Analysis/Calculus/IteratedDeriv.lean +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 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 Mathlib.Analysis.Calculus.Deriv.Comp +import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.Analysis.Calculus.ContDiff.Defs #align_import analysis.calculus.iterated_deriv from "leanprover-community/mathlib"@"3bce8d800a6f2b8f63fe1e588fd76a9ff4adcebe" @@ -94,7 +94,7 @@ theorem iteratedFDerivWithin_eq_equiv_comp : iteratedFDerivWithin 𝕜 n f s = ContinuousMultilinearMap.piFieldEquiv 𝕜 (Fin n) F ∘ iteratedDerivWithin n f s := by rw [iteratedDerivWithin_eq_equiv_comp, ← Function.comp.assoc, LinearIsometryEquiv.self_comp_symm, - Function.left_id] + Function.id_comp] #align iterated_fderiv_within_eq_equiv_comp iteratedFDerivWithin_eq_equiv_comp /-- The `n`-th Fréchet derivative applied to a vector `(m 0, ..., m (n-1))` is the derivative @@ -230,7 +230,7 @@ iterated derivative. -/ theorem iteratedFDeriv_eq_equiv_comp : iteratedFDeriv 𝕜 n f = ContinuousMultilinearMap.piFieldEquiv 𝕜 (Fin n) F ∘ iteratedDeriv n f := by rw [iteratedDeriv_eq_equiv_comp, ← Function.comp.assoc, LinearIsometryEquiv.self_comp_symm, - Function.left_id] + Function.id_comp] #align iterated_fderiv_eq_equiv_comp iteratedFDeriv_eq_equiv_comp /-- The `n`-th Fréchet derivative applied to a vector `(m 0, ..., m (n-1))` is the derivative diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean new file mode 100644 index 0000000000000..d5b71e5b13fbb --- /dev/null +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean @@ -0,0 +1,80 @@ +/- +Copyright (c) 2023 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck, Ruben Van de Velde +-/ +import Mathlib.Analysis.Calculus.ContDiff.Basic +import Mathlib.Analysis.Calculus.Deriv.Add +import Mathlib.Analysis.Calculus.IteratedDeriv.Defs + +/-! +# One-dimensional iterated derivatives + +This file contains a number of further results on `iteratedDerivWithin` that need more imports +than are available in `Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean`. +-/ + +variable + {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + {R : Type*} [Semiring R] [Module R F] [SMulCommClass 𝕜 R F] [ContinuousConstSMul R F] + {n : ℕ} {x : 𝕜} {s : Set 𝕜} (hx : x ∈ s) (h : UniqueDiffOn 𝕜 s) {f g : 𝕜 → F} + +theorem iteratedDerivWithin_add (hf : ContDiffOn 𝕜 n f s) (hg : ContDiffOn 𝕜 n g s) : + iteratedDerivWithin n (f + g) s x = + iteratedDerivWithin n f s x + iteratedDerivWithin n g s x := by + simp_rw [iteratedDerivWithin, iteratedFDerivWithin_add_apply hf hg h hx, + ContinuousMultilinearMap.add_apply] + +theorem iteratedDerivWithin_congr (hfg : Set.EqOn f g s) : + Set.EqOn (iteratedDerivWithin n f s) (iteratedDerivWithin n g s) s := by + induction n generalizing f g with + | zero => rwa [iteratedDerivWithin_zero] + | succ n IH => + intro y hy + have : UniqueDiffWithinAt 𝕜 s y := h.uniqueDiffWithinAt hy + rw [iteratedDerivWithin_succ this, iteratedDerivWithin_succ this] + exact derivWithin_congr (IH hfg) (IH hfg hy) + +theorem iteratedDerivWithin_const_add (hn : 0 < n) (c : F) : + iteratedDerivWithin n (fun z => c + f z) s x = iteratedDerivWithin n f s x := by + obtain ⟨n, rfl⟩ := n.exists_eq_succ_of_ne_zero hn.ne' + rw [iteratedDerivWithin_succ' h hx, iteratedDerivWithin_succ' h hx] + refine iteratedDerivWithin_congr h ?_ hx + intro y hy + exact derivWithin_const_add (h.uniqueDiffWithinAt hy) _ + +theorem iteratedDerivWithin_const_neg (hn : 0 < n) (c : F) : + iteratedDerivWithin n (fun z => c - f z) s x = iteratedDerivWithin n (fun z => -f z) s x := by + obtain ⟨n, rfl⟩ := n.exists_eq_succ_of_ne_zero hn.ne' + rw [iteratedDerivWithin_succ' h hx, iteratedDerivWithin_succ' h hx] + refine iteratedDerivWithin_congr h ?_ hx + intro y hy + have : UniqueDiffWithinAt 𝕜 s y := h.uniqueDiffWithinAt hy + rw [derivWithin.neg this] + exact derivWithin_const_sub this _ + +theorem iteratedDerivWithin_const_smul (c : R) (hf : ContDiffOn 𝕜 n f s) : + iteratedDerivWithin n (c • f) s x = c • iteratedDerivWithin n f s x := by + simp_rw [iteratedDerivWithin] + rw [iteratedFDerivWithin_const_smul_apply hf h hx] + simp only [ContinuousMultilinearMap.smul_apply] + +theorem iteratedDerivWithin_const_mul (c : 𝕜) {f : 𝕜 → 𝕜} (hf : ContDiffOn 𝕜 n f s) : + iteratedDerivWithin n (fun z => c * f z) s x = c * iteratedDerivWithin n f s x := by + simpa using iteratedDerivWithin_const_smul (F := 𝕜) hx h c hf + +theorem iteratedDerivWithin_neg (hf : ContDiffOn 𝕜 n f s) : + iteratedDerivWithin n (-f) s x = -iteratedDerivWithin n f s x := by + have := iteratedDerivWithin_const_smul hx h (-1) hf + simpa only [neg_smul, one_smul] + +theorem iteratedDerivWithin_neg' (hf : ContDiffOn 𝕜 n f s) : + iteratedDerivWithin n (fun z => -f z) s x = -iteratedDerivWithin n f s x := + iteratedDerivWithin_neg hx h hf + +theorem iteratedDerivWithin_sub (hf : ContDiffOn 𝕜 n f s) (hg : ContDiffOn 𝕜 n g s) : + iteratedDerivWithin n (f - g) s x = + iteratedDerivWithin n f s x - iteratedDerivWithin n g s x := by + rw [sub_eq_add_neg, sub_eq_add_neg, Pi.neg_def, iteratedDerivWithin_add hx h hf hg.neg, + iteratedDerivWithin_neg' hx h hg] diff --git a/Mathlib/Analysis/Calculus/LocalExtr/Basic.lean b/Mathlib/Analysis/Calculus/LocalExtr/Basic.lean index 26a94d167e677..aa05a0bcad0a8 100644 --- a/Mathlib/Analysis/Calculus/LocalExtr/Basic.lean +++ b/Mathlib/Analysis/Calculus/LocalExtr/Basic.lean @@ -230,7 +230,7 @@ variable {f : ℝ → ℝ} {f' : ℝ} {a b : ℝ} /-- **Fermat's Theorem**: the derivative of a function at a local minimum equals zero. -/ theorem IsLocalMin.hasDerivAt_eq_zero (h : IsLocalMin f a) (hf : HasDerivAt f f' a) : f' = 0 := by - simpa using FunLike.congr_fun (h.hasFDerivAt_eq_zero (hasDerivAt_iff_hasFDerivAt.1 hf)) 1 + simpa using DFunLike.congr_fun (h.hasFDerivAt_eq_zero (hasDerivAt_iff_hasFDerivAt.1 hf)) 1 #align is_local_min.has_deriv_at_eq_zero IsLocalMin.hasDerivAt_eq_zero /-- **Fermat's Theorem**: the derivative of a function at a local minimum equals zero. -/ diff --git a/Mathlib/Analysis/Calculus/Monotone.lean b/Mathlib/Analysis/Calculus/Monotone.lean index f1e34d4e81b63..d1e11e1724096 100644 --- a/Mathlib/Analysis/Calculus/Monotone.lean +++ b/Mathlib/Analysis/Calculus/Monotone.lean @@ -168,15 +168,14 @@ theorem Monotone.ae_hasDerivAt {f : ℝ → ℝ} (hf : Monotone f) : norm_num; nlinarith -- apply the sandwiching argument, with the helper function and `g` apply tendsto_of_tendsto_of_tendsto_of_le_of_le' this hx.2 - · filter_upwards [self_mem_nhdsWithin] - rintro y (hy : x < y) - have : ↑0 < (y - x) ^ 2 := sq_pos_of_pos (sub_pos.2 hy) - apply div_le_div_of_le (sub_pos.2 hy).le - exact (sub_le_sub_iff_right _).2 (hf.rightLim_le (by norm_num; linarith)) - · filter_upwards [self_mem_nhdsWithin] - rintro y (hy : x < y) - apply div_le_div_of_le (sub_pos.2 hy).le - exact (sub_le_sub_iff_right _).2 (hf.le_rightLim (le_refl y)) + · filter_upwards [self_mem_nhdsWithin] with y hy + rw [mem_Ioi, ← sub_pos] at hy + gcongr + exact hf.rightLim_le (by nlinarith) + · filter_upwards [self_mem_nhdsWithin] with y hy + rw [mem_Ioi, ← sub_pos] at hy + gcongr + exact hf.le_rightLim le_rfl -- prove differentiability on the left, by sandwiching with values of `g` have L2 : Tendsto (fun y => (f y - f x) / (y - x)) (𝓝[<] x) (𝓝 (rnDeriv hf.stieltjesFunction.measure volume x).toReal) := by @@ -192,19 +191,22 @@ theorem Monotone.ae_hasDerivAt {f : ℝ → ℝ} (hf : Monotone f) : · have : Ioo (x - 1) x ∈ 𝓝[<] x := by apply Ioo_mem_nhdsWithin_Iio; exact ⟨by linarith, le_refl _⟩ filter_upwards [this] - rintro y ⟨hy : x - 1 < y, h'y : y < x⟩ + rintro y hy + rw [mem_Ioo] at hy rw [mem_Iio] norm_num; nlinarith -- apply the sandwiching argument, with `g` and the helper function apply tendsto_of_tendsto_of_tendsto_of_le_of_le' hx.1 this · filter_upwards [self_mem_nhdsWithin] - rintro y (hy : y < x) - apply div_le_div_of_nonpos_of_le (sub_neg.2 hy).le + rintro y hy + rw [mem_Iio, ← sub_neg] at hy + apply div_le_div_of_nonpos_of_le hy.le exact (sub_le_sub_iff_right _).2 (hf.le_rightLim (le_refl _)) · filter_upwards [self_mem_nhdsWithin] - rintro y (hy : y < x) - have : ↑0 < (y - x) ^ 2 := sq_pos_of_neg (sub_neg.2 hy) - apply div_le_div_of_nonpos_of_le (sub_neg.2 hy).le + rintro y hy + rw [mem_Iio, ← sub_neg] at hy + have : 0 < (y - x) ^ 2 := sq_pos_of_neg hy + apply div_le_div_of_nonpos_of_le hy.le exact (sub_le_sub_iff_right _).2 (hf.rightLim_le (by norm_num; linarith)) -- conclude global differentiability rw [hasDerivAt_iff_tendsto_slope, slope_fun_def_field, (nhds_left'_sup_nhds_right' x).symm, diff --git a/Mathlib/Analysis/Calculus/Rademacher.lean b/Mathlib/Analysis/Calculus/Rademacher.lean index 211f345769d31..115077edba698 100644 --- a/Mathlib/Analysis/Calculus/Rademacher.lean +++ b/Mathlib/Analysis/Calculus/Rademacher.lean @@ -357,7 +357,7 @@ theorem ae_differentiableWithinAt_of_mem {f : E → F} (hf : LipschitzOnWith C f suffices H : ∀ᵐ x ∂μ, x ∈ s → DifferentiableWithinAt ℝ (A ∘ f) s x by filter_upwards [H] with x hx xs have : f = (A.symm ∘ A) ∘ f := by - simp only [ContinuousLinearEquiv.symm_comp_self, Function.comp.left_id] + simp only [ContinuousLinearEquiv.symm_comp_self, Function.id_comp] rw [this] exact A.symm.differentiableAt.comp_differentiableWithinAt x (hx xs) apply ae_differentiableWithinAt_of_mem_pi diff --git a/Mathlib/Analysis/Calculus/Series.lean b/Mathlib/Analysis/Calculus/Series.lean index f16ed93d48e58..015f234c1d0cc 100644 --- a/Mathlib/Analysis/Calculus/Series.lean +++ b/Mathlib/Analysis/Calculus/Series.lean @@ -3,9 +3,11 @@ Copyright (c) 2022 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 Mathlib.Analysis.Calculus.ContDiff.Basic import Mathlib.Analysis.Calculus.UniformLimitsDeriv -import Mathlib.Analysis.Calculus.ContDiff.FiniteDimension import Mathlib.Data.Nat.Cast.WithTop +import Mathlib.RingTheory.Ideal.LocalRing +import Mathlib.Topology.Algebra.InfiniteSum.Module #align_import analysis.calculus.series from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Analysis/Calculus/Taylor.lean b/Mathlib/Analysis/Calculus/Taylor.lean index 78fe076ec705e..0e6261eb974b1 100644 --- a/Mathlib/Analysis/Calculus/Taylor.lean +++ b/Mathlib/Analysis/Calculus/Taylor.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Moritz Doll -/ import Mathlib.Analysis.Calculus.Deriv.Pow -import Mathlib.Analysis.Calculus.IteratedDeriv +import Mathlib.Analysis.Calculus.IteratedDeriv.Defs import Mathlib.Analysis.Calculus.MeanValue import Mathlib.Data.Polynomial.Module @@ -214,14 +214,14 @@ theorem taylorWithinEval_hasDerivAt_Ioo {f : ℝ → E} {a b t : ℝ} (x : ℝ) /-- Calculate the derivative of the Taylor polynomial with respect to `x₀`. Version for closed intervals -/ -theorem has_deriv_within_taylorWithinEval_at_Icc {f : ℝ → E} {a b t : ℝ} (x : ℝ) {n : ℕ} +theorem hasDerivWithinAt_taylorWithinEval_at_Icc {f : ℝ → E} {a b t : ℝ} (x : ℝ) {n : ℕ} (hx : a < b) (ht : t ∈ Icc a b) (hf : ContDiffOn ℝ n f (Icc a b)) (hf' : DifferentiableOn ℝ (iteratedDerivWithin n f (Icc a b)) (Icc a b)) : HasDerivWithinAt (fun y => taylorWithinEval f n (Icc a b) y x) (((n ! : ℝ)⁻¹ * (x - t) ^ n) • iteratedDerivWithin (n + 1) f (Icc a b) t) (Icc a b) t := hasDerivWithinAt_taylorWithinEval (uniqueDiffOn_Icc hx t ht) (uniqueDiffOn_Icc hx) self_mem_nhdsWithin ht rfl.subset hf (hf' t ht) -#align has_deriv_within_taylor_within_eval_at_Icc has_deriv_within_taylorWithinEval_at_Icc +#align has_deriv_within_taylor_within_eval_at_Icc hasDerivWithinAt_taylorWithinEval_at_Icc /-! ### Taylor's theorem with mean value type remainder estimate -/ @@ -343,7 +343,7 @@ theorem taylor_mean_remainder_bound {f : ℝ → E} {a b C x : ℝ} {n : ℕ} (h (((↑n !)⁻¹ * (x - t) ^ n) • iteratedDerivWithin (n + 1) f (Icc a b) t) (Icc a x) t := by intro t ht have I : Icc a x ⊆ Icc a b := Icc_subset_Icc_right hx.2 - exact (has_deriv_within_taylorWithinEval_at_Icc x h (I ht) hf.of_succ hf').mono I + exact (hasDerivWithinAt_taylorWithinEval_at_Icc x h (I ht) hf.of_succ hf').mono I have := norm_image_sub_le_of_norm_deriv_le_segment' A h' x (right_mem_Icc.2 hx.1) simp only [taylorWithinEval_self] at this refine' this.trans_eq _ diff --git a/Mathlib/Analysis/Complex/Basic.lean b/Mathlib/Analysis/Complex/Basic.lean index 076cf049ab763..794e7973c3724 100644 --- a/Mathlib/Analysis/Complex/Basic.lean +++ b/Mathlib/Analysis/Complex/Basic.lean @@ -41,6 +41,7 @@ assert_not_exists Absorbs noncomputable section namespace Complex +variable {z : ℂ} open ComplexConjugate Topology Filter @@ -52,6 +53,8 @@ theorem norm_eq_abs (z : ℂ) : ‖z‖ = abs z := rfl #align complex.norm_eq_abs Complex.norm_eq_abs +lemma norm_I : ‖I‖ = 1 := abs_I + theorem norm_exp_ofReal_mul_I (t : ℝ) : ‖exp (t * I)‖ = 1 := by simp only [norm_eq_abs, abs_exp_ofReal_mul_I] set_option linter.uppercaseLean3 false in @@ -169,6 +172,9 @@ theorem norm_int_of_nonneg {n : ℤ} (hn : 0 ≤ n) : ‖(n : ℂ)‖ = n := by rw [norm_int, ← Int.cast_abs, _root_.abs_of_nonneg hn] #align complex.norm_int_of_nonneg Complex.norm_int_of_nonneg +lemma normSq_eq_norm_sq (z : ℂ) : normSq z = ‖z‖ ^ 2 := by + rw [normSq_eq_abs, norm_eq_abs] + @[continuity] theorem continuous_abs : Continuous abs := continuous_norm @@ -195,7 +201,7 @@ theorem nnnorm_int (n : ℤ) : ‖(n : ℂ)‖₊ = ‖n‖₊ := #align complex.nnnorm_int Complex.nnnorm_int theorem nnnorm_eq_one_of_pow_eq_one {ζ : ℂ} {n : ℕ} (h : ζ ^ n = 1) (hn : n ≠ 0) : ‖ζ‖₊ = 1 := - (pow_left_inj zero_le' zero_le' hn).1 $ by rw [← nnnorm_pow, h, nnnorm_one, one_pow] + (pow_left_inj zero_le' zero_le' hn).1 <| by rw [← nnnorm_pow, h, nnnorm_one, one_pow] #align complex.nnnorm_eq_one_of_pow_eq_one Complex.nnnorm_eq_one_of_pow_eq_one theorem norm_eq_one_of_pow_eq_one {ζ : ℂ} {n : ℕ} (h : ζ ^ n = 1) (hn : n ≠ 0) : ‖ζ‖ = 1 := @@ -356,7 +362,7 @@ theorem continuous_conj : Continuous (conj : ℂ → ℂ) := conjugation. -/ theorem ringHom_eq_id_or_conj_of_continuous {f : ℂ →+* ℂ} (hf : Continuous f) : f = RingHom.id ℂ ∨ f = conj := by - simpa only [FunLike.ext_iff] using real_algHom_eq_id_or_conj (AlgHom.mk' f (map_real_smul f hf)) + simpa only [DFunLike.ext_iff] using real_algHom_eq_id_or_conj (AlgHom.mk' f (map_real_smul f hf)) #align complex.ring_hom_eq_id_or_conj_of_continuous Complex.ringHom_eq_id_or_conj_of_continuous /-- Continuous linear equiv version of the conj function, from `ℂ` to `ℂ`. -/ @@ -436,6 +442,46 @@ theorem _root_.IsROrC.im_eq_complex_im : ⇑(IsROrC.im : ℂ →+ ℝ) = Complex rfl #align is_R_or_C.im_eq_complex_im IsROrC.im_eq_complex_im +-- TODO: Replace `mul_conj` and `conj_mul` once `norm` has replaced `abs` +lemma mul_conj' (z : ℂ) : z * conj z = ‖z‖ ^ 2 := IsROrC.mul_conj z +lemma conj_mul' (z : ℂ) : conj z * z = ‖z‖ ^ 2 := IsROrC.conj_mul z + +lemma inv_eq_conj (hz : ‖z‖ = 1) : z⁻¹ = conj z := IsROrC.inv_eq_conj hz + +lemma exists_norm_eq_mul_self (z : ℂ) : ∃ c, ‖c‖ = 1 ∧ ‖z‖ = c * z := + IsROrC.exists_norm_eq_mul_self _ + +lemma exists_norm_mul_eq_self (z : ℂ) : ∃ c, ‖c‖ = 1 ∧ c * ‖z‖ = z := + IsROrC.exists_norm_mul_eq_self _ + +/-- The natural isomorphism between `𝕜` satisfying `IsROrC 𝕜` and `ℂ` when +`IsROrC.im IsROrC.I = 1`. -/ +@[simps] +def _root_.IsROrC.complexRingEquiv {𝕜 : Type*} [IsROrC 𝕜] (h : IsROrC.im (IsROrC.I : 𝕜) = 1) : + 𝕜 ≃+* ℂ where + toFun x := IsROrC.re x + IsROrC.im x * I + invFun x := re x + im x * IsROrC.I + left_inv x := by simp + right_inv x := by simp [h] + map_add' x y := by simp only [map_add, ofReal_add]; ring + map_mul' x y := by + simp only [IsROrC.mul_re, ofReal_sub, ofReal_mul, IsROrC.mul_im, ofReal_add] + ring_nf + rw [I_sq] + ring + +/-- The natural `ℝ`-linear isometry equivalence between `𝕜` satisfying `IsROrC 𝕜` and `ℂ` when +`IsROrC.im IsROrC.I = 1`. -/ +@[simps] +def _root_.IsROrC.complexLinearIsometryEquiv {𝕜 : Type*} [IsROrC 𝕜] + (h : IsROrC.im (IsROrC.I : 𝕜) = 1) : 𝕜 ≃ₗᵢ[ℝ] ℂ where + map_smul' _ _ := by simp [IsROrC.smul_re, IsROrC.smul_im, ofReal_mul]; ring + norm_map' _ := by + rw [← sq_eq_sq (by positivity) (by positivity), ← normSq_eq_norm_sq, ← IsROrC.normSq_eq_def', + IsROrC.normSq_apply] + simp [normSq_add] + __ := IsROrC.complexRingEquiv h + section ComplexOrder open ComplexOrder diff --git a/Mathlib/Analysis/Complex/CauchyIntegral.lean b/Mathlib/Analysis/Complex/CauchyIntegral.lean index 1a56cd60a1159..3179f0ac8030f 100644 --- a/Mathlib/Analysis/Complex/CauchyIntegral.lean +++ b/Mathlib/Analysis/Complex/CauchyIntegral.lean @@ -145,9 +145,6 @@ function is analytic on the open ball. Cauchy-Goursat theorem, Cauchy integral formula -/ -set_option autoImplicit true - - open TopologicalSpace Set MeasureTheory intervalIntegral Metric Filter Function open scoped Interval Real NNReal ENNReal Topology BigOperators @@ -607,7 +604,7 @@ theorem _root_.DifferentiableOn.analyticOn {s : Set ℂ} {f : ℂ → E} (hd : D /-- If `f : ℂ → E` is complex differentiable on some open set `s`, then it is continuously differentiable on `s`. -/ -protected theorem _root_.DifferentiableOn.contDiffOn {s : Set ℂ} {f : ℂ → E} +protected theorem _root_.DifferentiableOn.contDiffOn {s : Set ℂ} {f : ℂ → E} {n : ℕ} (hd : DifferentiableOn ℂ f s) (hs : IsOpen s) : ContDiffOn ℂ n f s := (hd.analyticOn hs).contDiffOn diff --git a/Mathlib/Analysis/Complex/PhragmenLindelof.lean b/Mathlib/Analysis/Complex/PhragmenLindelof.lean index 7bae38a3b8ecc..9f5735ac5d00a 100644 --- a/Mathlib/Analysis/Complex/PhragmenLindelof.lean +++ b/Mathlib/Analysis/Complex/PhragmenLindelof.lean @@ -113,8 +113,8 @@ Then `‖f z‖` is bounded by the same constant on the closed strip only for sufficiently large values of `|re z|`. -/ theorem horizontal_strip (hfd : DiffContOnCl ℂ f (im ⁻¹' Ioo a b)) - (hB : ∃ c < π / (b - a), ∃ B, - f =O[comap (Abs.abs ∘ re) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)] fun z ↦ expR (B * expR (c * |z.re|))) + (hB : ∃ c < π / (b - a), ∃ B, f =O[comap (_root_.abs ∘ re) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)] + fun z ↦ expR (B * expR (c * |z.re|))) (hle_a : ∀ z : ℂ, im z = a → ‖f z‖ ≤ C) (hle_b : ∀ z, im z = b → ‖f z‖ ≤ C) (hza : a ≤ im z) (hzb : im z ≤ b) : ‖f z‖ ≤ C := by -- If `im z = a` or `im z = b`, then we apply `hle_a` or `hle_b`, otherwise `im z ∈ Ioo a b`. @@ -160,9 +160,9 @@ theorem horizontal_strip (hfd : DiffContOnCl ℂ f (im ⁻¹' Ioo a b)) fun w hw => _⟩ replace hw : |im (aff w)| ≤ d * b · rw [← Real.closedBall_eq_Icc] at hw - rwa [ofReal_mul_im, sub_im, mul_I_im, ofReal_re, _root_.abs_mul, abs_of_pos hd₀, + rwa [im_ofReal_mul, sub_im, mul_I_im, ofReal_re, _root_.abs_mul, abs_of_pos hd₀, mul_le_mul_left hd₀] - simpa only [ofReal_mul_re, _root_.abs_mul, abs_of_pos hd₀, sub_re, mul_I_re, ofReal_im, + simpa only [re_ofReal_mul, _root_.abs_mul, abs_of_pos hd₀, sub_re, mul_I_re, ofReal_im, zero_mul, neg_zero, sub_zero] using abs_exp_mul_exp_add_exp_neg_le_of_abs_im_le ε₀.le hw hb'.le -- `abs (g ε w) ≤ 1` on the lines `w.im = a ± b` (actually, it holds everywhere in the strip) @@ -231,8 +231,8 @@ Let `f : ℂ → E` be a function such that Then `f` is equal to zero on the closed strip `{z : ℂ | a ≤ im z ≤ b}`. -/ theorem eq_zero_on_horizontal_strip (hd : DiffContOnCl ℂ f (im ⁻¹' Ioo a b)) - (hB : ∃ c < π / (b - a), ∃ B, - f =O[comap (Abs.abs ∘ re) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)] fun z ↦ expR (B * expR (c * |z.re|))) + (hB : ∃ c < π / (b - a), ∃ B, f =O[comap (_root_.abs ∘ re) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)] + fun z ↦ expR (B * expR (c * |z.re|))) (ha : ∀ z : ℂ, z.im = a → f z = 0) (hb : ∀ z : ℂ, z.im = b → f z = 0) : EqOn f 0 (im ⁻¹' Icc a b) := fun _z hz => norm_le_zero_iff.1 <| horizontal_strip hd hB (fun z hz => (ha z hz).symm ▸ norm_zero.le) @@ -250,11 +250,11 @@ Let `f g : ℂ → E` be functions such that Then `f` is equal to `g` on the closed strip `{z : ℂ | a ≤ im z ≤ b}`. -/ theorem eqOn_horizontal_strip {g : ℂ → E} (hdf : DiffContOnCl ℂ f (im ⁻¹' Ioo a b)) - (hBf : ∃ c < π / (b - a), ∃ B, - f =O[comap (Abs.abs ∘ re) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)] fun z ↦ expR (B * expR (c * |z.re|))) + (hBf : ∃ c < π / (b - a), ∃ B, f =O[comap (_root_.abs ∘ re) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)] + fun z ↦ expR (B * expR (c * |z.re|))) (hdg : DiffContOnCl ℂ g (im ⁻¹' Ioo a b)) - (hBg : ∃ c < π / (b - a), ∃ B, - g =O[comap (Abs.abs ∘ re) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)] fun z ↦ expR (B * expR (c * |z.re|))) + (hBg : ∃ c < π / (b - a), ∃ B, g =O[comap (_root_.abs ∘ re) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)] + fun z ↦ expR (B * expR (c * |z.re|))) (ha : ∀ z : ℂ, z.im = a → f z = g z) (hb : ∀ z : ℂ, z.im = b → f z = g z) : EqOn f g (im ⁻¹' Icc a b) := fun _z hz => sub_eq_zero.1 (eq_zero_on_horizontal_strip (hdf.sub hdg) (isBigO_sub_exp_exp hBf hBg) @@ -277,8 +277,8 @@ Then `‖f z‖` is bounded by the same constant on the closed strip only for sufficiently large values of `|im z|`. -/ theorem vertical_strip (hfd : DiffContOnCl ℂ f (re ⁻¹' Ioo a b)) - (hB : ∃ c < π / (b - a), ∃ B, - f =O[comap (Abs.abs ∘ im) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)] fun z ↦ expR (B * expR (c * |z.im|))) + (hB : ∃ c < π / (b - a), ∃ B, f =O[comap (_root_.abs ∘ im) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)] + fun z ↦ expR (B * expR (c * |z.im|))) (hle_a : ∀ z : ℂ, re z = a → ‖f z‖ ≤ C) (hle_b : ∀ z, re z = b → ‖f z‖ ≤ C) (hza : a ≤ re z) (hzb : re z ≤ b) : ‖f z‖ ≤ C := by suffices ‖f (z * I * -I)‖ ≤ C by simpa [mul_assoc] using this @@ -306,8 +306,8 @@ Let `f : ℂ → E` be a function such that Then `f` is equal to zero on the closed strip `{z : ℂ | a ≤ re z ≤ b}`. -/ theorem eq_zero_on_vertical_strip (hd : DiffContOnCl ℂ f (re ⁻¹' Ioo a b)) - (hB : ∃ c < π / (b - a), ∃ B, - f =O[comap (Abs.abs ∘ im) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)] fun z ↦ expR (B * expR (c * |z.im|))) + (hB : ∃ c < π / (b - a), ∃ B, f =O[comap (_root_.abs ∘ im) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)] + fun z ↦ expR (B * expR (c * |z.im|))) (ha : ∀ z : ℂ, re z = a → f z = 0) (hb : ∀ z : ℂ, re z = b → f z = 0) : EqOn f 0 (re ⁻¹' Icc a b) := fun _z hz => norm_le_zero_iff.1 <| vertical_strip hd hB (fun z hz => (ha z hz).symm ▸ norm_zero.le) @@ -325,11 +325,11 @@ Let `f g : ℂ → E` be functions such that Then `f` is equal to `g` on the closed strip `{z : ℂ | a ≤ re z ≤ b}`. -/ theorem eqOn_vertical_strip {g : ℂ → E} (hdf : DiffContOnCl ℂ f (re ⁻¹' Ioo a b)) - (hBf : ∃ c < π / (b - a), ∃ B, - f =O[comap (Abs.abs ∘ im) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)] fun z ↦ expR (B * expR (c * |z.im|))) + (hBf : ∃ c < π / (b - a), ∃ B, f =O[comap (_root_.abs ∘ im) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)] + fun z ↦ expR (B * expR (c * |z.im|))) (hdg : DiffContOnCl ℂ g (re ⁻¹' Ioo a b)) - (hBg : ∃ c < π / (b - a), ∃ B, - g =O[comap (Abs.abs ∘ im) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)] fun z ↦ expR (B * expR (c * |z.im|))) + (hBg : ∃ c < π / (b - a), ∃ B, g =O[comap (_root_.abs ∘ im) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)] + fun z ↦ expR (B * expR (c * |z.im|))) (ha : ∀ z : ℂ, re z = a → f z = g z) (hb : ∀ z : ℂ, re z = b → f z = g z) : EqOn f g (re ⁻¹' Icc a b) := fun _z hz => sub_eq_zero.1 (eq_zero_on_vertical_strip (hdf.sub hdg) (isBigO_sub_exp_exp hBf hBg) @@ -386,17 +386,16 @@ nonrec theorem quadrant_I (hd : DiffContOnCl ℂ f (Ioi 0 ×ℂ Ioi 0)) have hc : ContinuousWithinAt f (Ioi 0 ×ℂ Ioi 0) 0 := by refine' (hd.continuousOn _ _).mono subset_closure simp [closure_reProdIm, mem_reProdIm] - refine' - ((hc.tendsto.comp <| tendsto_exp_comap_re_atBot.inf H.tendsto).isBigO_one ℝ).trans - (isBigO_of_le _ fun w => _) + refine ((hc.tendsto.comp <| tendsto_exp_comap_re_atBot.inf H.tendsto).isBigO_one ℝ).trans + (isBigO_of_le _ fun w => ?_) rw [norm_one, Real.norm_of_nonneg (Real.exp_pos _).le, Real.one_le_exp_iff] - exact mul_nonneg (le_max_right _ _) (Real.exp_pos _).le + positivity · -- For the estimate as `ζ.re → ∞`, we reuse the upper estimate on `f` simp only [eventually_inf_principal, eventually_comap, comp_apply, one_mul, Real.norm_of_nonneg (Real.exp_pos _).le, abs_exp, ← Real.exp_mul, Real.exp_le_exp] refine' (eventually_ge_atTop 0).mono fun x hx z hz _ => _ rw [hz, _root_.abs_of_nonneg hx, mul_comm _ c] - exact mul_le_mul_of_nonneg_right (le_max_left _ _) (Real.exp_pos _).le + gcongr; apply le_max_left · -- If `ζ.im = 0`, then `Complex.exp ζ` is a positive real number intro ζ hζ; lift ζ to ℝ using hζ rw [comp_apply, ← ofReal_exp] @@ -767,7 +766,7 @@ theorem right_half_plane_of_bounded_on_real (hd : DiffContOnCl ℂ f {z | 0 < z. replace hd : DiffContOnCl ℂ g {z : ℂ | 0 < z.re} exact (differentiable_id.const_mul _).cexp.diffContOnCl.smul hd have hgn : ∀ z, ‖g z‖ = expR (ε * z.re) * ‖f z‖ := fun z ↦ by - rw [norm_smul, norm_eq_abs, abs_exp, ofReal_mul_re] + rw [norm_smul, norm_eq_abs, abs_exp, re_ofReal_mul] refine' right_half_plane_of_tendsto_zero_on_real hd _ _ (fun y => _) hz · rcases hexp with ⟨c, hc, B, hO⟩ refine ⟨c, hc, B, (IsBigO.of_bound 1 ?_).trans hO⟩ @@ -779,7 +778,7 @@ theorem right_half_plane_of_bounded_on_real (hd : DiffContOnCl ℂ f {z | 0 < z. have h₀ : Tendsto (fun x : ℝ => expR (ε * x)) atTop (𝓝 0) := Real.tendsto_exp_atBot.comp (tendsto_const_nhds.neg_mul_atTop ε₀ tendsto_id) exact h₀.zero_smul_isBoundedUnder_le hre - · rw [hgn, ofReal_mul_re, I_re, mul_zero, mul_zero, Real.exp_zero, + · rw [hgn, re_ofReal_mul, I_re, mul_zero, mul_zero, Real.exp_zero, one_mul] exact him y #align phragmen_lindelof.right_half_plane_of_bounded_on_real PhragmenLindelof.right_half_plane_of_bounded_on_real @@ -833,7 +832,7 @@ theorem eq_zero_on_right_half_plane_of_superexponential_decay (hd : DiffContOnCl exacts [le_max_left _ _, hz, le_max_left _ _] · rw [tendsto_zero_iff_norm_tendsto_zero]; simp only [hg] exact hre n - · rw [hg, ofReal_mul_re, I_re, mul_zero, Real.exp_zero, one_pow, one_mul] + · rw [hg, re_ofReal_mul, I_re, mul_zero, Real.exp_zero, one_pow, one_mul] exact hC y #align phragmen_lindelof.eq_zero_on_right_half_plane_of_superexponential_decay PhragmenLindelof.eq_zero_on_right_half_plane_of_superexponential_decay diff --git a/Mathlib/Analysis/Complex/Polynomial.lean b/Mathlib/Analysis/Complex/Polynomial.lean index 637bf597f822f..00d60bc9cfcc2 100644 --- a/Mathlib/Analysis/Complex/Polynomial.lean +++ b/Mathlib/Analysis/Complex/Polynomial.lean @@ -3,9 +3,10 @@ Copyright (c) 2019 Chris Hughes All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Junyan Xu -/ +import Mathlib.Algebra.CharZero.Infinite import Mathlib.Analysis.Complex.Liouville -import Mathlib.FieldTheory.IsAlgClosed.Basic import Mathlib.Analysis.Calculus.Deriv.Polynomial +import Mathlib.FieldTheory.IsAlgClosed.Basic import Mathlib.Topology.Algebra.Polynomial #align_import analysis.complex.polynomial from "leanprover-community/mathlib"@"17ef379e997badd73e5eabb4d38f11919ab3c4b3" diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean index 126c2f05890fe..3f3adbb0a7250 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ import Mathlib.Analysis.Complex.UpperHalfPlane.Topology -import Mathlib.Geometry.Manifold.MFDeriv +import Mathlib.Geometry.Manifold.MFDeriv.Basic #align_import analysis.complex.upper_half_plane.manifold from "leanprover-community/mathlib"@"57f9349f2fe19d2de7207e99b0341808d977cdcf" @@ -35,4 +35,3 @@ theorem mdifferentiable_coe : MDifferentiable 𝓘(ℂ) 𝓘(ℂ) ((↑) : ℍ #align upper_half_plane.mdifferentiable_coe UpperHalfPlane.mdifferentiable_coe end UpperHalfPlane - diff --git a/Mathlib/Analysis/Convex/Combination.lean b/Mathlib/Analysis/Convex/Combination.lean index cd227292d44ba..96785a999c6c9 100644 --- a/Mathlib/Analysis/Convex/Combination.lean +++ b/Mathlib/Analysis/Convex/Combination.lean @@ -106,7 +106,7 @@ theorem Finset.centerMass_segment (s : Finset ι) (w₁ w₂ : ι → R) (z : ι a • s.centerMass w₁ z + b • s.centerMass w₂ z = s.centerMass (fun i => a * w₁ i + b * w₂ i) z := by have hw : (∑ i in s, (a * w₁ i + b * w₂ i)) = 1 := by - simp only [mul_sum.symm, sum_add_distrib, mul_one, *] + simp only [← mul_sum, sum_add_distrib, mul_one, *] simp only [Finset.centerMass_eq_of_sum_1, Finset.centerMass_eq_of_sum_1 _ _ hw, smul_sum, sum_add_distrib, add_smul, mul_smul, *] #align finset.center_mass_segment Finset.centerMass_segment @@ -241,7 +241,7 @@ theorem Finset.centerMass_mem_convexHull (t : Finset ι) {w : ι → R} (hw₀ : lemma Finset.centerMass_mem_convexHull_of_nonpos (t : Finset ι) (hw₀ : ∀ i ∈ t, w i ≤ 0) (hws : ∑ i in t, w i < 0) (hz : ∀ i ∈ t, z i ∈ s) : t.centerMass w z ∈ convexHull R s := by rw [← centerMass_neg_left] - exact Finset.centerMass_mem_convexHull _ (λ _i hi ↦ neg_nonneg.2 $ hw₀ _ hi) (by simpa) hz + exact Finset.centerMass_mem_convexHull _ (λ _i hi ↦ neg_nonneg.2 <| hw₀ _ hi) (by simpa) hz /-- A refinement of `Finset.centerMass_mem_convexHull` when the indexed family is a `Finset` of the space. -/ @@ -341,7 +341,7 @@ theorem convexHull_eq (s : Set E) : convexHull R s = rw [Finset.mem_disjSum] at hi rcases hi with (⟨j, hj, rfl⟩ | ⟨j, hj, rfl⟩) <;> simp only [Sum.elim_inl, Sum.elim_inr] <;> apply_rules [mul_nonneg, hwx₀, hwy₀] - · simp [Finset.sum_sum_elim, Finset.mul_sum.symm, *] + · simp [Finset.sum_sum_elim, ← mul_sum, *] · intro i hi rw [Finset.mem_disjSum] at hi rcases hi with (⟨j, hj, rfl⟩ | ⟨j, hj, rfl⟩) <;> apply_rules [hzx, hzy] @@ -364,7 +364,7 @@ theorem Finset.convexHull_eq (s : Finset E) : convexHull R ↑s = refine' ⟨_, _, _, rfl⟩ · rintro i hi apply_rules [add_nonneg, mul_nonneg, hwx₀, hwy₀] - · simp only [Finset.sum_add_distrib, Finset.mul_sum.symm, mul_one, *] + · simp only [Finset.sum_add_distrib, ← mul_sum, mul_one, *] · rintro _ ⟨w, hw₀, hw₁, rfl⟩ exact s.centerMass_mem_convexHull (fun x hx => hw₀ _ hx) (hw₁.symm ▸ zero_lt_one) fun x hx => hx @@ -375,6 +375,14 @@ theorem Finset.mem_convexHull {s : Finset E} {x : E} : x ∈ convexHull R (s : S rw [Finset.convexHull_eq, Set.mem_setOf_eq] #align finset.mem_convex_hull Finset.mem_convexHull +/-- This is a version of `Finset.mem_convexHull` stated without `Finset.centerMass`. -/ +lemma Finset.mem_convexHull' {s : Finset E} {x : E} : + x ∈ convexHull R (s : Set E) ↔ + ∃ w : E → R, (∀ y ∈ s, 0 ≤ w y) ∧ ∑ y in s, w y = 1 ∧ ∑ y in s, w y • y = x := by + rw [mem_convexHull] + refine exists_congr fun w ↦ and_congr_right' $ and_congr_right fun hw ↦ ?_ + simp_rw [centerMass_eq_of_sum_1 _ _ hw, id_eq] + theorem Set.Finite.convexHull_eq {s : Set E} (hs : s.Finite) : convexHull R s = { x : E | ∃ w : E → R, (∀ y ∈ s, 0 ≤ w y) ∧ ∑ y in hs.toFinset, w y = 1 ∧ hs.toFinset.centerMass w id = x } := by @@ -513,15 +521,13 @@ to prove that this map is linear. -/ theorem Set.Finite.convexHull_eq_image {s : Set E} (hs : s.Finite) : convexHull R s = haveI := hs.fintype (⇑(∑ x : s, (@LinearMap.proj R s _ (fun _ => R) _ _ x).smulRight x.1)) '' stdSimplex R s := by - -- Porting note: Original proof didn't need to specify `hs.fintype` - rw [← @convexHull_basis_eq_stdSimplex _ _ _ hs.fintype, ← LinearMap.convexHull_image, - ← Set.range_comp] - simp_rw [Function.comp] + letI := hs.fintype + rw [← convexHull_basis_eq_stdSimplex, ← LinearMap.convexHull_image, ← Set.range_comp] apply congr_arg + simp_rw [Function.comp] convert Subtype.range_coe.symm - -- Porting note: Original proof didn't need to specify `hs.fintype` and `(1 : R)` - simp [LinearMap.sum_apply, ite_smul _ (1 : R), Finset.filter_eq, - @Finset.mem_univ _ hs.fintype _] + -- Porting note: Original proof didn't need to specify `(1 : R)` + simp [LinearMap.sum_apply, ite_smul _ _ (1 : R), Finset.filter_eq, Finset.mem_univ] #align set.finite.convex_hull_eq_image Set.Finite.convexHull_eq_image /-- All values of a function `f ∈ stdSimplex 𝕜 ι` belong to `[0, 1]`. -/ @@ -551,3 +557,37 @@ theorem AffineBasis.convexHull_eq_nonneg_coord {ι : Type*} (b : AffineBasis ι rw [b.coord_apply_combination_of_mem hi hw₁] at hx exact hx #align affine_basis.convex_hull_eq_nonneg_coord AffineBasis.convexHull_eq_nonneg_coord + +variable {s t t₁ t₂ : Finset E} + +/-- Two simplices glue nicely if the union of their vertices is affine independent. -/ +lemma AffineIndependent.convexHull_inter (hs : AffineIndependent R ((↑) : s → E)) + (ht₁ : t₁ ⊆ s) (ht₂ : t₂ ⊆ s) : + convexHull R (t₁ ∩ t₂ : Set E) = convexHull R t₁ ∩ convexHull R t₂ := by + refine (Set.subset_inter (convexHull_mono inf_le_left) $ + convexHull_mono inf_le_right).antisymm ?_ + simp_rw [Set.subset_def, mem_inter_iff, Set.inf_eq_inter, ← coe_inter, mem_convexHull'] + rintro x ⟨⟨w₁, h₁w₁, h₂w₁, h₃w₁⟩, w₂, -, h₂w₂, h₃w₂⟩ + let w (x : E) : R := (if x ∈ t₁ then w₁ x else 0) - if x ∈ t₂ then w₂ x else 0 + have h₁w : ∑ i in s, w i = 0 := by simp [Finset.inter_eq_right.2, *] + replace hs := hs.eq_zero_of_sum_eq_zero_subtype h₁w $ by + simp only [sub_smul, zero_smul, ite_smul, Finset.sum_sub_distrib, ← Finset.sum_filter, h₃w₁, + Finset.filter_mem_eq_inter, Finset.inter_eq_right.2 ht₁, Finset.inter_eq_right.2 ht₂, h₃w₂, + sub_self] + have ht (x) (hx₁ : x ∈ t₁) (hx₂ : x ∉ t₂) : w₁ x = 0 := by + simpa [hx₁, hx₂] using hs _ (ht₁ hx₁) + refine ⟨w₁, ?_, ?_, ?_⟩ + · simp only [and_imp, Finset.mem_inter] + exact fun y hy₁ _ ↦ h₁w₁ y hy₁ + all_goals + · rwa [sum_subset $ inter_subset_left _ _] + rintro x + simp_intro hx₁ hx₂ + simp [ht x hx₁ hx₂] + +/-- Two simplices glue nicely if the union of their vertices is affine independent. + +Note that `AffineIndependent.convexHull_inter` should be more versatile in most use cases. -/ +lemma AffineIndependent.convexHull_inter' (hs : AffineIndependent R ((↑) : ↑(t₁ ∪ t₂) → E)) : + convexHull R (t₁ ∩ t₂ : Set E) = convexHull R t₁ ∩ convexHull R t₂ := + hs.convexHull_inter (subset_union_left _ _) (subset_union_right _ _) diff --git a/Mathlib/Analysis/Convex/Cone/Closure.lean b/Mathlib/Analysis/Convex/Cone/Closure.lean new file mode 100644 index 0000000000000..f27c88547cd4b --- /dev/null +++ b/Mathlib/Analysis/Convex/Cone/Closure.lean @@ -0,0 +1,80 @@ +/- +Copyright (c) 2023 Apurva Nakade All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Apurva Nakade +-/ +import Mathlib.Analysis.Convex.Cone.Pointed + +/-! +# Closure of cones + +We define the closures of convex and pointed cones. This construction is primarily needed for +defining maps between proper cones. The current API is basic and should be extended as necessary. + +-/ + +namespace ConvexCone + +variable {𝕜 : Type*} [OrderedSemiring 𝕜] + +variable {E : Type*} [AddCommMonoid E] [TopologicalSpace E] [ContinuousAdd E] [SMul 𝕜 E] + [ContinuousConstSMul 𝕜 E] + +/-- The closure of a convex cone inside a topological space as a convex cone. This +construction is mainly used for defining maps between proper cones. -/ +protected def closure (K : ConvexCone 𝕜 E) : ConvexCone 𝕜 E where + carrier := closure ↑K + smul_mem' c hc _ h₁ := + map_mem_closure (continuous_id'.const_smul c) h₁ fun _ h₂ => K.smul_mem hc h₂ + add_mem' _ h₁ _ h₂ := map_mem_closure₂ continuous_add h₁ h₂ K.add_mem +#align convex_cone.closure ConvexCone.closure + +@[simp, norm_cast] +theorem coe_closure (K : ConvexCone 𝕜 E) : (K.closure : Set E) = closure K := + rfl +#align convex_cone.coe_closure ConvexCone.coe_closure + +@[simp] +protected theorem mem_closure {K : ConvexCone 𝕜 E} {a : E} : + a ∈ K.closure ↔ a ∈ closure (K : Set E) := + Iff.rfl +#align convex_cone.mem_closure ConvexCone.mem_closure + +@[simp] +theorem closure_eq {K L : ConvexCone 𝕜 E} : K.closure = L ↔ closure (K : Set E) = L := + SetLike.ext'_iff +#align convex_cone.closure_eq ConvexCone.closure_eq + +end ConvexCone + + + +namespace PointedCone + +variable {𝕜 : Type*} [OrderedSemiring 𝕜] + +variable {E : Type*} [AddCommMonoid E] [TopologicalSpace E] [ContinuousAdd E] [Module 𝕜 E] + [ContinuousConstSMul 𝕜 E] + +lemma toConvexCone_closure_pointed (K : PointedCone 𝕜 E) : (K : ConvexCone 𝕜 E).closure.Pointed := + subset_closure $ PointedCone.toConvexCone_pointed _ + +/-- The closure of a pointed cone inside a topological space as a pointed cone. This +construction is mainly used for defining maps between proper cones. -/ +protected def closure (K : PointedCone 𝕜 E) : PointedCone 𝕜 E := + ConvexCone.toPointedCone K.toConvexCone_closure_pointed + +@[simp, norm_cast] +theorem coe_closure (K : PointedCone 𝕜 E) : (K.closure : Set E) = closure K := + rfl + +@[simp] +protected theorem mem_closure {K : PointedCone 𝕜 E} {a : E} : + a ∈ K.closure ↔ a ∈ closure (K : Set E) := + Iff.rfl + +@[simp] +theorem closure_eq {K L : PointedCone 𝕜 E} : K.closure = L ↔ closure (K : Set E) = L := + SetLike.ext'_iff + +end PointedCone diff --git a/Mathlib/Analysis/Convex/Cone/Extension.lean b/Mathlib/Analysis/Convex/Cone/Extension.lean index 8e3163df7c9b3..d49fbe4ab191b 100644 --- a/Mathlib/Analysis/Convex/Cone/Extension.lean +++ b/Mathlib/Analysis/Convex/Cone/Extension.lean @@ -75,7 +75,7 @@ theorem step (nonneg : ∀ x : f.domain, (x : E) ∈ s → 0 ≤ f x) simpa only [Set.Nonempty, upperBounds, lowerBounds, ball_image_iff] using this refine' exists_between_of_forall_le (Nonempty.image f _) (Nonempty.image f (dense y)) _ · rcases dense (-y) with ⟨x, hx⟩ - rw [← neg_neg x, AddSubgroupClass.coe_neg, ← sub_eq_add_neg] at hx + rw [← neg_neg x, NegMemClass.coe_neg, ← sub_eq_add_neg] at hx exact ⟨_, hx⟩ rintro a ⟨xn, hxn, rfl⟩ b ⟨xp, hxp, rfl⟩ have := s.add_mem hxp hxn diff --git a/Mathlib/Analysis/Convex/Cone/Dual.lean b/Mathlib/Analysis/Convex/Cone/InnerDual.lean similarity index 100% rename from Mathlib/Analysis/Convex/Cone/Dual.lean rename to Mathlib/Analysis/Convex/Cone/InnerDual.lean diff --git a/Mathlib/Analysis/Convex/Cone/Pointed.lean b/Mathlib/Analysis/Convex/Cone/Pointed.lean index 8945c7ac499de..035ea28699643 100644 --- a/Mathlib/Analysis/Convex/Cone/Pointed.lean +++ b/Mathlib/Analysis/Convex/Cone/Pointed.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Apurva Nakade All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Apurva Nakade -/ -import Mathlib.Analysis.Convex.Cone.Dual +import Mathlib.Analysis.Convex.Cone.InnerDual import Mathlib.Algebra.Order.Nonneg.Module import Mathlib.Algebra.Module.Submodule.Basic @@ -15,16 +15,11 @@ nonnegative. This is equivalent to saying that as a set a pointed cone is convex contains `0`. This is a bundled version of `ConvexCone.Pointed`. We choose the submodule definition as it allows us to use the `Module` API to work with convex cones. -## TODO - -- Rewrite proper cones using pointed cones. - -/ variable {𝕜 E F G : Type*} --- TODO: remove `prettyPrint := false` once #6833 is merged -local notation3 (prettyPrint := false) "𝕜≥0" => {c : 𝕜 // 0 ≤ c} +local notation3 "𝕜≥0" => {c : 𝕜 // 0 ≤ c} /-- A pointed cone is a submodule of a module with scalars restricted to being nonnegative. -/ abbrev PointedCone (𝕜 E) [OrderedSemiring 𝕜] [AddCommMonoid E] [Module 𝕜 E] := diff --git a/Mathlib/Analysis/Convex/Cone/Proper.lean b/Mathlib/Analysis/Convex/Cone/Proper.lean index f870e73b293d3..9cd0463c917a9 100644 --- a/Mathlib/Analysis/Convex/Cone/Proper.lean +++ b/Mathlib/Analysis/Convex/Cone/Proper.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Apurva Nakade All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Apurva Nakade -/ -import Mathlib.Analysis.Convex.Cone.Dual +import Mathlib.Analysis.Convex.Cone.Closure import Mathlib.Analysis.InnerProductSpace.Adjoint #align_import analysis.convex.cone.proper from "leanprover-community/mathlib"@"147b294346843885f952c5171e9606616a8fd869" @@ -11,10 +11,10 @@ import Mathlib.Analysis.InnerProductSpace.Adjoint /-! # Proper cones -We define a proper cone as a nonempty, closed, convex cone. Proper cones are used in defining conic +We define a *proper cone* as a closed, pointed cone. Proper cones are used in defining conic programs which generalize linear programs. A linear program is a conic program for the positive cone. We then prove Farkas' lemma for conic programs following the proof in the reference below. -Farkas' lemma is equivalent to strong duality. So, once have the definitions of conic programs and +Farkas' lemma is equivalent to strong duality. So, once we have the definitions of conic and linear programs, the results from this file can be used to prove duality theorems. ## TODO @@ -25,7 +25,6 @@ The next steps are: - Prove regular and strong duality for cone programs using Farkas' lemma (see reference). - Define linear programs and prove LP duality as a special case of cone duality. - Find a better reference (textbook instead of lecture notes). -- Show submodules are (proper) cones. ## References @@ -35,61 +34,29 @@ The next steps are: open ContinuousLinearMap Filter Set -namespace ConvexCone - -variable {𝕜 : Type*} [OrderedSemiring 𝕜] - -variable {E : Type*} [AddCommMonoid E] [TopologicalSpace E] [ContinuousAdd E] [SMul 𝕜 E] - [ContinuousConstSMul 𝕜 E] - -/-- The closure of a convex cone inside a topological space as a convex cone. This -construction is mainly used for defining maps between proper cones. -/ -protected def closure (K : ConvexCone 𝕜 E) : ConvexCone 𝕜 E where - carrier := closure ↑K - smul_mem' c hc _ h₁ := - map_mem_closure (continuous_id'.const_smul c) h₁ fun _ h₂ => K.smul_mem hc h₂ - add_mem' _ h₁ _ h₂ := map_mem_closure₂ continuous_add h₁ h₂ K.add_mem -#align convex_cone.closure ConvexCone.closure - -@[simp, norm_cast] -theorem coe_closure (K : ConvexCone 𝕜 E) : (K.closure : Set E) = closure K := - rfl -#align convex_cone.coe_closure ConvexCone.coe_closure - -@[simp] -protected theorem mem_closure {K : ConvexCone 𝕜 E} {a : E} : - a ∈ K.closure ↔ a ∈ closure (K : Set E) := - Iff.rfl -#align convex_cone.mem_closure ConvexCone.mem_closure - -@[simp] -theorem closure_eq {K L : ConvexCone 𝕜 E} : K.closure = L ↔ closure (K : Set E) = L := - SetLike.ext'_iff -#align convex_cone.closure_eq ConvexCone.closure_eq - -end ConvexCone - -/-- A proper cone is a convex cone `K` that is nonempty and closed. Proper cones have the nice -property that the dual of the dual of a proper cone is itself. This makes them useful for defining -cone programs and proving duality theorems. -/ +/-- A proper cone is a pointed cone `K` that is closed. Proper cones have the nice property that +they are equal to their double dual, see `ProperCone.dual_dual`. +This makes them useful for defining cone programs and proving duality theorems. -/ structure ProperCone (𝕜 : Type*) (E : Type*) [OrderedSemiring 𝕜] [AddCommMonoid E] - [TopologicalSpace E] [SMul 𝕜 E] extends ConvexCone 𝕜 E where - nonempty' : (carrier : Set E).Nonempty + [TopologicalSpace E] [Module 𝕜 E] extends Submodule {c : 𝕜 // 0 ≤ c} E where isClosed' : IsClosed (carrier : Set E) #align proper_cone ProperCone namespace ProperCone - -section SMul +section Module variable {𝕜 : Type*} [OrderedSemiring 𝕜] -variable {E : Type*} [AddCommMonoid E] [TopologicalSpace E] [SMul 𝕜 E] +variable {E : Type*} [AddCommMonoid E] [TopologicalSpace E] [Module 𝕜 E] + +/-- A `PointedCone` is defined as an alias of submodule. We replicate the abbreviation here and +define `toPointedCone` as an alias of `toSubmodule`. -/ +abbrev toPointedCone (C : ProperCone 𝕜 E) := C.toSubmodule -attribute [coe] toConvexCone +attribute [coe] toPointedCone -instance : Coe (ProperCone 𝕜 E) (ConvexCone 𝕜 E) := - ⟨toConvexCone⟩ +instance : Coe (ProperCone 𝕜 E) (PointedCone 𝕜 E) := + ⟨toPointedCone⟩ -- Porting note: now a syntactic tautology -- @[simp] @@ -97,14 +64,14 @@ instance : Coe (ProperCone 𝕜 E) (ConvexCone 𝕜 E) := -- rfl #noalign proper_cone.to_convex_cone_eq_coe -theorem ext' : Function.Injective ((↑) : ProperCone 𝕜 E → ConvexCone 𝕜 E) := fun S T h => by - cases S; cases T; congr -#align proper_cone.ext' ProperCone.ext' +theorem toPointedCone_injective : Function.Injective ((↑) : ProperCone 𝕜 E → PointedCone 𝕜 E) := + fun S T h => by cases S; cases T; congr +#align proper_cone.ext' ProperCone.toPointedCone_injective -- TODO: add `ConvexConeClass` that extends `SetLike` and replace the below instance instance : SetLike (ProperCone 𝕜 E) E where coe K := K.carrier - coe_injective' _ _ h := ProperCone.ext' (SetLike.coe_injective h) + coe_injective' _ _ h := ProperCone.toPointedCone_injective (SetLike.coe_injective h) @[ext] theorem ext {S T : ProperCone 𝕜 E} (h : ∀ x, x ∈ S ↔ x ∈ T) : S = T := @@ -112,19 +79,21 @@ theorem ext {S T : ProperCone 𝕜 E} (h : ∀ x, x ∈ S ↔ x ∈ T) : S = T : #align proper_cone.ext ProperCone.ext @[simp] -theorem mem_coe {x : E} {K : ProperCone 𝕜 E} : x ∈ (K : ConvexCone 𝕜 E) ↔ x ∈ K := +theorem mem_coe {x : E} {K : ProperCone 𝕜 E} : x ∈ (K : PointedCone 𝕜 E) ↔ x ∈ K := Iff.rfl #align proper_cone.mem_coe ProperCone.mem_coe +instance instZero (K : ProperCone 𝕜 E) : Zero K := PointedCone.instZero (K.toSubmodule) + protected theorem nonempty (K : ProperCone 𝕜 E) : (K : Set E).Nonempty := - K.nonempty' + ⟨0, by { simp_rw [SetLike.mem_coe, ← ProperCone.mem_coe, Submodule.zero_mem] } ⟩ #align proper_cone.nonempty ProperCone.nonempty protected theorem isClosed (K : ProperCone 𝕜 E) : IsClosed (K : Set E) := K.isClosed' #align proper_cone.is_closed ProperCone.isClosed -end SMul +end Module section PositiveCone @@ -135,8 +104,7 @@ variable [OrderedSemiring 𝕜] [OrderedAddCommGroup E] [Module 𝕜 E] [Ordered /-- The positive cone is the proper cone formed by the set of nonnegative elements in an ordered module. -/ def positive : ProperCone 𝕜 E where - toConvexCone := ConvexCone.positive 𝕜 E - nonempty' := ⟨0, ConvexCone.pointed_positive _ _⟩ + toSubmodule := PointedCone.positive 𝕜 E isClosed' := isClosed_Ici @[simp] @@ -156,9 +124,8 @@ variable {𝕜 : Type*} [OrderedSemiring 𝕜] variable {E : Type*} [AddCommMonoid E] [TopologicalSpace E] [T1Space E] [Module 𝕜 E] instance : Zero (ProperCone 𝕜 E) := - ⟨{ toConvexCone := 0 - nonempty' := ⟨0, rfl⟩ - isClosed' := isClosed_singleton }⟩ + ⟨{ toSubmodule := 0 + isClosed' := isClosed_singleton }⟩ instance : Inhabited (ProperCone 𝕜 E) := ⟨0⟩ @@ -173,7 +140,8 @@ theorem coe_zero : ↑(0 : ProperCone 𝕜 E) = (0 : ConvexCone 𝕜 E) := rfl #align proper_cone.coe_zero ProperCone.coe_zero -theorem pointed_zero : (0 : ProperCone 𝕜 E).Pointed := by simp [ConvexCone.pointed_zero] +theorem pointed_zero : ((0 : ProperCone 𝕜 E) : ConvexCone 𝕜 E).Pointed := by + simp [ConvexCone.pointed_zero] #align proper_cone.pointed_zero ProperCone.pointed_zero end Module @@ -187,61 +155,54 @@ variable {F : Type*} [NormedAddCommGroup F] [InnerProductSpace ℝ F] variable {G : Type*} [NormedAddCommGroup G] [InnerProductSpace ℝ G] protected theorem pointed (K : ProperCone ℝ E) : (K : ConvexCone ℝ E).Pointed := - (K : ConvexCone ℝ E).pointed_of_nonempty_of_isClosed K.nonempty' K.isClosed + (K : ConvexCone ℝ E).pointed_of_nonempty_of_isClosed K.nonempty K.isClosed #align proper_cone.pointed ProperCone.pointed /-- The closure of image of a proper cone under a continuous `ℝ`-linear map is a proper cone. We use continuous maps here so that the comap of f is also a map between proper cones. -/ noncomputable def map (f : E →L[ℝ] F) (K : ProperCone ℝ E) : ProperCone ℝ F where - toConvexCone := ConvexCone.closure (ConvexCone.map (f : E →ₗ[ℝ] F) ↑K) - nonempty' := - ⟨0, subset_closure <| SetLike.mem_coe.2 <| ConvexCone.mem_map.2 ⟨0, K.pointed, map_zero _⟩⟩ + toSubmodule := PointedCone.closure (PointedCone.map (f : E →ₗ[ℝ] F) ↑K) isClosed' := isClosed_closure #align proper_cone.map ProperCone.map @[simp, norm_cast] theorem coe_map (f : E →L[ℝ] F) (K : ProperCone ℝ E) : - ↑(K.map f) = (ConvexCone.map (f : E →ₗ[ℝ] F) ↑K).closure := + ↑(K.map f) = (PointedCone.map (f : E →ₗ[ℝ] F) ↑K).closure := rfl #align proper_cone.coe_map ProperCone.coe_map @[simp] theorem mem_map {f : E →L[ℝ] F} {K : ProperCone ℝ E} {y : F} : - y ∈ K.map f ↔ y ∈ (ConvexCone.map (f : E →ₗ[ℝ] F) ↑K).closure := + y ∈ K.map f ↔ y ∈ (PointedCone.map (f : E →ₗ[ℝ] F) ↑K).closure := Iff.rfl #align proper_cone.mem_map ProperCone.mem_map @[simp] theorem map_id (K : ProperCone ℝ E) : K.map (ContinuousLinearMap.id ℝ E) = K := - ProperCone.ext' <| by simpa using IsClosed.closure_eq K.isClosed + ProperCone.toPointedCone_injective <| by simpa using IsClosed.closure_eq K.isClosed #align proper_cone.map_id ProperCone.map_id /-- The inner dual cone of a proper cone is a proper cone. -/ def dual (K : ProperCone ℝ E) : ProperCone ℝ E where - toConvexCone := (K : Set E).innerDualCone - nonempty' := ⟨0, pointed_innerDualCone _⟩ + toSubmodule := PointedCone.dual (K : PointedCone ℝ E) isClosed' := isClosed_innerDualCone _ #align proper_cone.dual ProperCone.dual @[simp, norm_cast] -theorem coe_dual (K : ProperCone ℝ E) : ↑(dual K) = (K : Set E).innerDualCone := +theorem coe_dual (K : ProperCone ℝ E) : K.dual = (K : Set E).innerDualCone := rfl #align proper_cone.coe_dual ProperCone.coe_dual @[simp] theorem mem_dual {K : ProperCone ℝ E} {y : E} : y ∈ dual K ↔ ∀ ⦃x⦄, x ∈ K → 0 ≤ ⟪x, y⟫_ℝ := by - rw [← mem_coe, coe_dual, mem_innerDualCone _ _]; rfl + aesop #align proper_cone.mem_dual ProperCone.mem_dual /-- The preimage of a proper cone under a continuous `ℝ`-linear map is a proper cone. -/ noncomputable def comap (f : E →L[ℝ] F) (S : ProperCone ℝ F) : ProperCone ℝ E where - toConvexCone := ConvexCone.comap (f : E →ₗ[ℝ] F) S - nonempty' := - ⟨0, by - simp only [ConvexCone.comap, mem_preimage, map_zero, SetLike.mem_coe, mem_coe] - apply ProperCone.pointed⟩ + toSubmodule := PointedCone.comap (f : E →ₗ[ℝ] F) S isClosed' := by - simp only [ConvexCone.comap, ContinuousLinearMap.coe_coe] + rw [PointedCone.comap] apply IsClosed.preimage f.2 S.isClosed #align proper_cone.comap ProperCone.comap @@ -276,23 +237,25 @@ variable {F : Type*} [NormedAddCommGroup F] [InnerProductSpace ℝ F] [CompleteS /-- The dual of the dual of a proper cone is itself. -/ @[simp] theorem dual_dual (K : ProperCone ℝ E) : K.dual.dual = K := - ProperCone.ext' <| - (K : ConvexCone ℝ E).innerDualCone_of_innerDualCone_eq_self K.nonempty' K.isClosed + ProperCone.toPointedCone_injective <| PointedCone.toConvexCone_injective <| + (K : ConvexCone ℝ E).innerDualCone_of_innerDualCone_eq_self K.nonempty K.isClosed #align proper_cone.dual_dual ProperCone.dual_dual /-- This is a relative version of `ConvexCone.hyperplane_separation_of_nonempty_of_isClosed_of_nmem`, which we recover by setting -`f` to be the identity map. This is a geometric interpretation of the Farkas' lemma +`f` to be the identity map. This is also a geometric interpretation of the Farkas' lemma stated using proper cones. -/ theorem hyperplane_separation (K : ProperCone ℝ E) {f : E →L[ℝ] F} {b : F} : b ∈ K.map f ↔ ∀ y : F, adjoint f y ∈ K.dual → 0 ≤ ⟪y, b⟫_ℝ := Iff.intro (by -- suppose `b ∈ K.map f` - simp only [ProperCone.mem_map, ProperCone.mem_dual, adjoint_inner_right, - ConvexCone.mem_closure, mem_closure_iff_seq_limit] + simp_rw [mem_map, PointedCone.mem_closure, PointedCone.coe_map, coe_coe, + mem_closure_iff_seq_limit, mem_image, SetLike.mem_coe, mem_coe, mem_dual, + adjoint_inner_right, forall_exists_index, and_imp] + -- there is a sequence `seq : ℕ → F` in the image of `f` that converges to `b` - rintro ⟨seq, hmem, htends⟩ y hinner + rintro seq hmem htends y hinner suffices h : ∀ n, 0 ≤ ⟪y, seq n⟫_ℝ from ge_of_tendsto' (Continuous.seqContinuous (Continuous.inner (@continuous_const _ _ _ _ y) continuous_id) @@ -306,19 +269,23 @@ theorem hyperplane_separation (K : ProperCone ℝ E) {f : E →L[ℝ] F} {b : F} -- suppose `b ∉ K.map f` intro h contrapose! h + -- as `b ∉ K.map f`, there is a hyperplane `y` separating `b` from `K.map f` + let C := @PointedCone.toConvexCone ℝ F _ _ _ (K.map f) obtain ⟨y, hxy, hyb⟩ := - ConvexCone.hyperplane_separation_of_nonempty_of_isClosed_of_nmem _ (K.map f).nonempty - (K.map f).isClosed h + @ConvexCone.hyperplane_separation_of_nonempty_of_isClosed_of_nmem + _ _ _ _ C (K.map f).nonempty (K.map f).isClosed b h + -- the rest of the proof is a straightforward algebraic manipulation refine' ⟨y, _, hyb⟩ simp_rw [ProperCone.mem_dual, adjoint_inner_right] intro x hxK apply hxy (f x) - rw [ProperCone.coe_map] + simp_rw [coe_map] apply subset_closure - rw [SetLike.mem_coe, ConvexCone.mem_map] - refine' ⟨x, hxK, by rw [coe_coe]⟩) + simp_rw [PointedCone.toConvexCone_map, ConvexCone.coe_map, coe_coe, mem_image, + SetLike.mem_coe] + exact ⟨x, hxK, rfl⟩) #align proper_cone.hyperplane_separation ProperCone.hyperplane_separation theorem hyperplane_separation_of_nmem (K : ProperCone ℝ E) {f : E →L[ℝ] F} {b : F} diff --git a/Mathlib/Analysis/Convex/Function.lean b/Mathlib/Analysis/Convex/Function.lean index 13deb1cbd7105..ee5f11cd31422 100644 --- a/Mathlib/Analysis/Convex/Function.lean +++ b/Mathlib/Analysis/Convex/Function.lean @@ -1142,10 +1142,10 @@ lemma StrictConvexOn.eq_of_isMinOn (hf : StrictConvexOn 𝕜 s f) (hfx : IsMinOn (hfy : IsMinOn f s y) (hx : x ∈ s) (hy : y ∈ s) : x = y := by by_contra hxy let z := (2 : 𝕜)⁻¹ • x + (2 : 𝕜)⁻¹ • y - have hz : z ∈ s := hf.1 hx hy (by norm_num) (by norm_num) $ by norm_num + have hz : z ∈ s := hf.1 hx hy (by norm_num) (by norm_num) <| by norm_num refine lt_irrefl (f z) ?_ calc - f z < _ := hf.2 hx hy hxy (by norm_num) (by norm_num) $ by norm_num + f z < _ := hf.2 hx hy hxy (by norm_num) (by norm_num) <| by norm_num _ ≤ (2 : 𝕜)⁻¹ • f z + (2 : 𝕜)⁻¹ • f z := by gcongr; exacts [hfx hz, hfy hz] _ = f z := by rw [← _root_.add_smul]; norm_num diff --git a/Mathlib/Analysis/Convex/Gauge.lean b/Mathlib/Analysis/Convex/Gauge.lean index 93cdb3761c0cf..204df83a13945 100644 --- a/Mathlib/Analysis/Convex/Gauge.lean +++ b/Mathlib/Analysis/Convex/Gauge.lean @@ -38,9 +38,6 @@ For a real vector space, Minkowski functional, gauge -/ -set_option autoImplicit true - - open NormedField Set open scoped Pointwise Topology NNReal @@ -58,7 +55,7 @@ def gauge (s : Set E) (x : E) : ℝ := sInf { r : ℝ | 0 < r ∧ x ∈ r • s } #align gauge gauge -variable {s t : Set E} {a : ℝ} +variable {s t : Set E} {x : E} {a : ℝ} theorem gauge_def : gauge s x = sInf ({ r ∈ Set.Ioi (0 : ℝ) | x ∈ r • s }) := rfl @@ -78,8 +75,8 @@ private theorem gauge_set_bddBelow : BddBelow { r : ℝ | 0 < r ∧ x ∈ r • which is useful for proving many properties about the gauge. -/ theorem Absorbent.gauge_set_nonempty (absorbs : Absorbent ℝ s) : { r : ℝ | 0 < r ∧ x ∈ r • s }.Nonempty := - let ⟨r, hr₁, hr₂⟩ := absorbs x - ⟨r, hr₁, hr₂ r (Real.norm_of_nonneg hr₁.le).ge⟩ + let ⟨r, hr₁, hr₂⟩ := (absorbs x).exists_pos + ⟨r, hr₁, hr₂ r (Real.norm_of_nonneg hr₁.le).ge rfl⟩ #align absorbent.gauge_set_nonempty Absorbent.gauge_set_nonempty theorem gauge_mono (hs : Absorbent ℝ s) (h : s ⊆ t) : gauge t ≤ gauge s := fun _ => @@ -236,7 +233,7 @@ theorem Balanced.starConvex (hs : Balanced ℝ s) : StarConvex ℝ 0 s := theorem le_gauge_of_not_mem (hs₀ : StarConvex ℝ 0 s) (hs₂ : Absorbs ℝ s {x}) (hx : x ∉ a • s) : a ≤ gauge s x := by rw [starConvex_zero_iff] at hs₀ - obtain ⟨r, hr, h⟩ := hs₂ + obtain ⟨r, hr, h⟩ := hs₂.exists_pos refine' le_csInf ⟨r, hr, singleton_subset_iff.1 <| h _ (Real.norm_of_nonneg hr.le).ge⟩ _ rintro b ⟨hb, x, hx', rfl⟩ refine' not_lt.1 fun hba => hx _ @@ -451,7 +448,7 @@ theorem gauge_eq_one_iff_mem_frontier (hc : Convex ℝ s) (hs₀ : s ∈ 𝓝 0) theorem gauge_eq_zero [T1Space E] (hs : Absorbent ℝ s) (hb : Bornology.IsVonNBounded ℝ s) : gauge s x = 0 ↔ x = 0 := by refine ⟨not_imp_not.1 fun (h : x ≠ 0) ↦ ne_of_gt ?_, fun h ↦ h.symm ▸ gauge_zero⟩ - rcases hb (isOpen_compl_singleton.mem_nhds h.symm) with ⟨c, hc₀, hc⟩ + rcases (hb (isOpen_compl_singleton.mem_nhds h.symm)).exists_pos with ⟨c, hc₀, hc⟩ refine (inv_pos.2 hc₀).trans_le <| le_csInf hs.gauge_set_nonempty ?_ rintro r ⟨hr₀, x, hx, rfl⟩ contrapose! hc @@ -522,7 +519,7 @@ protected theorem Seminorm.gauge_ball (p : Seminorm ℝ E) : gauge (p.ball 0 1) theorem Seminorm.gaugeSeminorm_ball (p : Seminorm ℝ E) : gaugeSeminorm (p.balanced_ball_zero 1) (p.convex_ball 0 1) (p.absorbent_ball_zero zero_lt_one) = p := - FunLike.coe_injective p.gauge_ball + DFunLike.coe_injective p.gauge_ball #align seminorm.gauge_seminorm_ball Seminorm.gaugeSeminorm_ball end AddCommGroup diff --git a/Mathlib/Analysis/Convex/Independent.lean b/Mathlib/Analysis/Convex/Independent.lean index 279b5d4de518c..72f4de7cdcff3 100644 --- a/Mathlib/Analysis/Convex/Independent.lean +++ b/Mathlib/Analysis/Convex/Independent.lean @@ -64,7 +64,7 @@ variable {𝕜} theorem Subsingleton.convexIndependent [Subsingleton ι] (p : ι → E) : ConvexIndependent 𝕜 p := by intro s x hx have : (convexHull 𝕜 (p '' s)).Nonempty := ⟨p x, hx⟩ - rw [convexHull_nonempty_iff, Set.nonempty_image_iff] at this + rw [convexHull_nonempty_iff, Set.image_nonempty] at this rwa [Subsingleton.mem_iff_nonempty] #align subsingleton.convex_independent Subsingleton.convexIndependent diff --git a/Mathlib/Analysis/Convex/Intrinsic.lean b/Mathlib/Analysis/Convex/Intrinsic.lean index aa04dcc12c895..b1229d49c9d18 100644 --- a/Mathlib/Analysis/Convex/Intrinsic.lean +++ b/Mathlib/Analysis/Convex/Intrinsic.lean @@ -260,7 +260,7 @@ theorem image_intrinsicInterior (φ : P →ᵃⁱ[𝕜] Q) (s : Set P) : rw [intrinsicInterior, intrinsicInterior, ← φ.coe_toAffineMap, ← map_span φ.toAffineMap s, ← this, ← Function.comp.assoc, image_comp, image_comp, f.symm.image_interior, f.image_symm, ← preimage_comp, Function.comp.assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, - Function.comp.right_id, preimage_comp, φ.injective.preimage_image] + Function.comp_id, preimage_comp, φ.injective.preimage_image] #align affine_isometry.image_intrinsic_interior AffineIsometry.image_intrinsicInterior @[simp] @@ -274,7 +274,7 @@ theorem image_intrinsicFrontier (φ : P →ᵃⁱ[𝕜] Q) (s : Set P) : rw [intrinsicFrontier, intrinsicFrontier, ← φ.coe_toAffineMap, ← map_span φ.toAffineMap s, ← this, ← Function.comp.assoc, image_comp, image_comp, f.symm.image_frontier, f.image_symm, ← preimage_comp, Function.comp.assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, - Function.comp.right_id, preimage_comp, φ.injective.preimage_image] + Function.comp_id, preimage_comp, φ.injective.preimage_image] #align affine_isometry.image_intrinsic_frontier AffineIsometry.image_intrinsicFrontier @[simp] @@ -288,7 +288,7 @@ theorem image_intrinsicClosure (φ : P →ᵃⁱ[𝕜] Q) (s : Set P) : rw [intrinsicClosure, intrinsicClosure, ← φ.coe_toAffineMap, ← map_span φ.toAffineMap s, ← this, ← Function.comp.assoc, image_comp, image_comp, f.symm.image_closure, f.image_symm, ← preimage_comp, Function.comp.assoc, f.symm_comp_self, AffineIsometry.coe_toAffineMap, - Function.comp.right_id, preimage_comp, φ.injective.preimage_image] + Function.comp_id, preimage_comp, φ.injective.preimage_image] #align affine_isometry.image_intrinsic_closure AffineIsometry.image_intrinsicClosure end AffineIsometry @@ -332,7 +332,7 @@ end NormedAddTorsor private theorem aux {α β : Type*} [TopologicalSpace α] [TopologicalSpace β] (φ : α ≃ₜ β) (s : Set β) : (interior s).Nonempty ↔ (interior (φ ⁻¹' s)).Nonempty := by - rw [← φ.image_symm, ← φ.symm.image_interior, nonempty_image_iff] + rw [← φ.image_symm, ← φ.symm.image_interior, image_nonempty] variable [NormedAddCommGroup V] [NormedSpace ℝ V] [FiniteDimensional ℝ V] {s : Set V} @@ -342,7 +342,7 @@ protected theorem Set.Nonempty.intrinsicInterior (hscv : Convex ℝ s) (hsne : s haveI := hsne.coe_sort obtain ⟨p, hp⟩ := hsne let p' : _root_.affineSpan ℝ s := ⟨p, subset_affineSpan _ _ hp⟩ - rw [intrinsicInterior, nonempty_image_iff, + rw [intrinsicInterior, image_nonempty, aux (AffineIsometryEquiv.constVSub ℝ p').symm.toHomeomorph, Convex.interior_nonempty_iff_affineSpan_eq_top, AffineIsometryEquiv.coe_toHomeomorph, ← AffineIsometryEquiv.coe_toAffineEquiv, ← comap_span, affineSpan_coe_preimage_eq_top, comap_top] diff --git a/Mathlib/Analysis/Convex/Jensen.lean b/Mathlib/Analysis/Convex/Jensen.lean index db52abaf227ef..e8f97381c10d7 100644 --- a/Mathlib/Analysis/Convex/Jensen.lean +++ b/Mathlib/Analysis/Convex/Jensen.lean @@ -113,13 +113,13 @@ lemma StrictConvexOn.map_sum_lt (hf : StrictConvexOn 𝕜 s f) (h₀ : ∀ i ∈ let u := (t.erase j).erase k have hj : j ∉ u := by simp have hk : k ∉ u := by simp - have ht : t = (u.cons k hk).cons j (mem_cons.not.2 $ not_or_intro (ne_of_apply_ne _ hjk) hj) + have ht : t = (u.cons k hk).cons j (mem_cons.not.2 <| not_or_intro (ne_of_apply_ne _ hjk) hj) · simp [insert_erase this, insert_erase ‹j ∈ t›, *] clear_value u subst ht simp only [sum_cons] - have := h₀ j $ by simp - have := h₀ k $ by simp + have := h₀ j <| by simp + have := h₀ k <| by simp let c := w j + w k have hc : w j / c + w k / c = 1 := by field_simp have hcj : c * (w j / c) = w j := by field_simp; ring @@ -130,13 +130,13 @@ lemma StrictConvexOn.map_sum_lt (hf : StrictConvexOn 𝕜 s f) (h₀ : ∀ i ∈ _ ≤ c • f ((w j / c) • p j + (w k / c) • p k) + ∑ x in u, w x • f (p x) := -- apply the usual Jensen's inequality wrt the weighted average of the two distinguished -- points and all the other points - hf.convexOn.map_add_sum_le (fun i hi ↦ (h₀ _ $ by simp [hi]).le) + hf.convexOn.map_add_sum_le (fun i hi ↦ (h₀ _ <| by simp [hi]).le) (by simpa [-cons_eq_insert, ← add_assoc] using h₁) - (forall_of_forall_cons $ forall_of_forall_cons hmem) (by positivity) $ by - refine hf.1 (hmem _ $ by simp) (hmem _ $ by simp) ?_ ?_ hc <;> positivity + (forall_of_forall_cons <| forall_of_forall_cons hmem) (by positivity) <| by + refine hf.1 (hmem _ <| by simp) (hmem _ <| by simp) ?_ ?_ hc <;> positivity _ < c • ((w j / c) • f (p j) + (w k / c) • f (p k)) + ∑ x in u, w x • f (p x) := by -- then apply the definition of strict convexity for the two distinguished points - gcongr; refine hf.2 (hmem _ $ by simp) (hmem _ $ by simp) hjk ?_ ?_ hc <;> positivity + gcongr; refine hf.2 (hmem _ <| by simp) (hmem _ <| by simp) hjk ?_ ?_ hc <;> positivity _ = (w j • f (p j) + w k • f (p k)) + ∑ x in u, w x • f (p x) := by rw [smul_add, ← mul_smul, ← mul_smul, hcj, hck] _ = w j • f (p j) + (w k • f (p k) + ∑ x in u, w x • f (p x)) := by abel_nf @@ -163,7 +163,7 @@ lemma StrictConvexOn.eq_of_le_map_sum (hf : StrictConvexOn 𝕜 s f) (h₀ : ∀ (h₁ : ∑ i in t, w i = 1) (hmem : ∀ i ∈ t, p i ∈ s) (h_eq : ∑ i in t, w i • f (p i) ≤ f (∑ i in t, w i • p i)) : ∀ ⦃j⦄, j ∈ t → ∀ ⦃k⦄, k ∈ t → p j = p k := by - by_contra!; exact h_eq.not_lt $ hf.map_sum_lt h₀ h₁ hmem this + by_contra!; exact h_eq.not_lt <| hf.map_sum_lt h₀ h₁ hmem this /-- A form of the **equality case of Jensen's equality**. @@ -175,7 +175,7 @@ lemma StrictConcaveOn.eq_of_map_sum_eq (hf : StrictConcaveOn 𝕜 s f) (h₀ : (h₁ : ∑ i in t, w i = 1) (hmem : ∀ i ∈ t, p i ∈ s) (h_eq : f (∑ i in t, w i • p i) ≤ ∑ i in t, w i • f (p i)) : ∀ ⦃j⦄, j ∈ t → ∀ ⦃k⦄, k ∈ t → p j = p k := by - by_contra!; exact h_eq.not_lt $ hf.lt_map_sum h₀ h₁ hmem this + by_contra!; exact h_eq.not_lt <| hf.lt_map_sum h₀ h₁ hmem this /-- Canonical form of the **equality case of Jensen's equality**. @@ -249,7 +249,7 @@ section MaximumPrinciple variable [LinearOrderedField 𝕜] [AddCommGroup E] [LinearOrderedAddCommGroup β] [Module 𝕜 E] [Module 𝕜 β] [OrderedSMul 𝕜 β] {s : Set E} {f : E → β} {t : Finset ι} {w : ι → 𝕜} {p : ι → E} - {x : E} + {x y z : E} theorem le_sup_of_mem_convexHull {s : Finset E} (hf : ConvexOn 𝕜 (convexHull 𝕜 (s : Set E)) f) (hx : x ∈ convexHull 𝕜 (s : Set E)) : @@ -289,8 +289,8 @@ theorem ConcaveOn.exists_le_of_centerMass (h : ConcaveOn 𝕜 s f) (hw₀ : ∀ ConvexOn.exists_ge_of_centerMass (β := βᵒᵈ) h hw₀ hw₁ hp #align concave_on.exists_le_of_center_mass ConcaveOn.exists_le_of_centerMass -/-- Maximum principle for convex functions. If a function `f` is convex on the convex hull of `s`, -then the eventual maximum of `f` on `convexHull 𝕜 s` lies in `s`. -/ +/-- **Maximum principle** for convex functions. If a function `f` is convex on the convex hull of +`s`, then the eventual maximum of `f` on `convexHull 𝕜 s` lies in `s`. -/ theorem ConvexOn.exists_ge_of_mem_convexHull (hf : ConvexOn 𝕜 (convexHull 𝕜 s) f) {x} (hx : x ∈ convexHull 𝕜 s) : ∃ y ∈ s, f x ≤ f y := by rw [_root_.convexHull_eq] at hx @@ -301,11 +301,35 @@ theorem ConvexOn.exists_ge_of_mem_convexHull (hf : ConvexOn 𝕜 (convexHull exact ⟨p i, hp i hit, Hi⟩ #align convex_on.exists_ge_of_mem_convex_hull ConvexOn.exists_ge_of_mem_convexHull -/-- Minimum principle for concave functions. If a function `f` is concave on the convex hull of `s`, -then the eventual minimum of `f` on `convexHull 𝕜 s` lies in `s`. -/ +/-- **Minimum principle** for concave functions. If a function `f` is concave on the convex hull of +`s`, then the eventual minimum of `f` on `convexHull 𝕜 s` lies in `s`. -/ theorem ConcaveOn.exists_le_of_mem_convexHull (hf : ConcaveOn 𝕜 (convexHull 𝕜 s) f) {x} (hx : x ∈ convexHull 𝕜 s) : ∃ y ∈ s, f y ≤ f x := ConvexOn.exists_ge_of_mem_convexHull (β := βᵒᵈ) hf hx #align concave_on.exists_le_of_mem_convex_hull ConcaveOn.exists_le_of_mem_convexHull +/-- **Maximum principle** for convex functions on a segment. If a function `f` is convex on the +segment `[x, y]`, then the eventual maximum of `f` on `[x, y]` is at `x` or `y`. -/ +lemma ConvexOn.le_max_of_mem_segment (hf : ConvexOn 𝕜 [x -[𝕜] y] f) (hz : z ∈ [x -[𝕜] y]) : + f z ≤ max (f x) (f y) := by + rw [← convexHull_pair] at hf hz; simpa using hf.exists_ge_of_mem_convexHull hz + +/-- **Minimum principle** for concave functions on a segment. If a function `f` is concave on the +segment `[x, y]`, then the eventual minimum of `f` on `[x, y]` is at `x` or `y`. -/ +lemma ConcaveOn.min_le_of_mem_segment (hf : ConcaveOn 𝕜 [x -[𝕜] y] f) (hz : z ∈ [x -[𝕜] y]) : + min (f x) (f y) ≤ f z := by + rw [← convexHull_pair] at hf hz; simpa using hf.exists_le_of_mem_convexHull hz + +/-- **Maximum principle** for convex functions on an interval. If a function `f` is convex on the +interval `[x, y]`, then the eventual maximum of `f` on `[x, y]` is at `x` or `y`. -/ +lemma ConvexOn.le_max_of_mem_Icc {f : 𝕜 → β} {x y z : 𝕜} (hf : ConvexOn 𝕜 (Icc x y) f) + (hz : z ∈ Icc x y) : f z ≤ max (f x) (f y) := by + rw [← segment_eq_Icc (hz.1.trans hz.2)] at hf hz; exact hf.le_max_of_mem_segment hz + +/-- **Minimum principle** for concave functions on an interval. If a function `f` is concave on the +interval `[x, y]`, then the eventual minimum of `f` on `[x, y]` is at `x` or `y`. -/ +lemma ConcaveOn.min_le_of_mem_Icc {f : 𝕜 → β} {x y z : 𝕜} (hf : ConcaveOn 𝕜 (Icc x y) f) + (hz : z ∈ Icc x y) : min (f x) (f y) ≤ f z := by + rw [← segment_eq_Icc (hz.1.trans hz.2)] at hf hz; exact hf.min_le_of_mem_segment hz + end MaximumPrinciple diff --git a/Mathlib/Analysis/Convex/Join.lean b/Mathlib/Analysis/Convex/Join.lean index cbbdb1e51994b..26f5d9532983e 100644 --- a/Mathlib/Analysis/Convex/Join.lean +++ b/Mathlib/Analysis/Convex/Join.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Analysis.Convex.Combination +import Mathlib.Analysis.Convex.Hull #align_import analysis.convex.join from "leanprover-community/mathlib"@"951bf1d9e98a2042979ced62c0620bcfb3587cf8" diff --git a/Mathlib/Analysis/Convex/KreinMilman.lean b/Mathlib/Analysis/Convex/KreinMilman.lean index 11da633722c85..ac1a5fd0161b6 100644 --- a/Mathlib/Analysis/Convex/KreinMilman.lean +++ b/Mathlib/Analysis/Convex/KreinMilman.lean @@ -112,13 +112,14 @@ lemma surjOn_extremePoints_image (f : E →A[ℝ] F) (hs : IsCompact s) : SurjOn f (extremePoints ℝ s) (extremePoints ℝ (f '' s)) := by rintro w hw -- The fiber of `w` is nonempty and compact - have ht : IsCompact {x ∈ s | f x = w} := hs.inter_right $ isClosed_singleton.preimage f.continuous + have ht : IsCompact {x ∈ s | f x = w} := + hs.inter_right <| isClosed_singleton.preimage f.continuous have ht₀ : {x ∈ s | f x = w}.Nonempty := by simpa using extremePoints_subset hw -- Hence by the Krein-Milman lemma it has an extreme point `x` obtain ⟨x, ⟨hx, rfl⟩, hyt⟩ := ht.extremePoints_nonempty ht₀ -- `f x = w` and `x` is an extreme point of `s`, so we're done refine mem_image_of_mem _ ⟨hx, fun y hy z hz hxyz ↦ ?_⟩ have := by simpa using image_openSegment _ f.toAffineMap y z - have := hw.2 (mem_image_of_mem _ hy) (mem_image_of_mem _ hz) $ by + have := hw.2 (mem_image_of_mem _ hy) (mem_image_of_mem _ hz) <| by rw [← this]; exact mem_image_of_mem _ hxyz exact hyt ⟨hy, this.1⟩ ⟨hz, this.2⟩ hxyz diff --git a/Mathlib/Analysis/Convex/Mul.lean b/Mathlib/Analysis/Convex/Mul.lean index d5749bfc15a75..70dcad63f29fb 100644 --- a/Mathlib/Analysis/Convex/Mul.lean +++ b/Mathlib/Analysis/Convex/Mul.lean @@ -31,8 +31,9 @@ lemma ConvexOn.smul' (hf : ConvexOn 𝕜 s f) (hg : ConvexOn 𝕜 s g) (hf₀ : (hg₀ : ∀ ⦃x⦄, x ∈ s → 0 ≤ g x) (hfg : MonovaryOn f g s) : ConvexOn 𝕜 s (f • g) := by refine ⟨hf.1, fun x hx y hy a b ha hb hab ↦ ?_⟩ dsimp - refine (smul_le_smul (hf.2 hx hy ha hb hab) (hg.2 hx hy ha hb hab) (hf₀ $ hf.1 hx hy ha hb hab) $ - add_nonneg (smul_nonneg ha $ hg₀ hx) $ smul_nonneg hb $ hg₀ hy).trans ?_ + refine + (smul_le_smul (hf.2 hx hy ha hb hab) (hg.2 hx hy ha hb hab) (hf₀ <| hf.1 hx hy ha hb hab) <| + add_nonneg (smul_nonneg ha <| hg₀ hx) <| smul_nonneg hb <| hg₀ hy).trans ?_ calc _ = (a * a) • (f x • g x) + (b * b) • (f y • g y) + (a * b) • (f x • g y + f y • g x) := ?_ _ ≤ (a * a) • (f x • g x) + (b * b) • (f y • g y) + (a * b) • (f x • g x + f y • g y) := by @@ -49,8 +50,9 @@ lemma ConcaveOn.smul' (hf : ConcaveOn 𝕜 s f) (hg : ConcaveOn 𝕜 s g) (hf₀ (hg₀ : ∀ ⦃x⦄, x ∈ s → 0 ≤ g x) (hfg : AntivaryOn f g s) : ConcaveOn 𝕜 s (f • g) := by refine ⟨hf.1, fun x hx y hy a b ha hb hab ↦ ?_⟩ dsimp - refine (smul_le_smul (hf.2 hx hy ha hb hab) (hg.2 hx hy ha hb hab) (add_nonneg - (smul_nonneg ha $ hf₀ hx) $ smul_nonneg hb $ hf₀ hy) $ hg₀ $ hf.1 hx hy ha hb hab).trans' ?_ + refine (smul_le_smul (hf.2 hx hy ha hb hab) (hg.2 hx hy ha hb hab) + (add_nonneg (smul_nonneg ha <| hf₀ hx) <| smul_nonneg hb <| hf₀ hy) + (hg₀ <| hf.1 hx hy ha hb hab)).trans' ?_ calc a • f x • g x + b • f y • g y = (a * (a + b)) • (f x • g x) + (b * (a + b)) • (f y • g y) := by simp_rw [hab, mul_one] _ = (a * a) • (f x • g x) + (b * b) • (f y • g y) + (a * b) • (f x • g x + f y • g y) := by @@ -91,13 +93,13 @@ lemma ConvexOn.smul_concaveOn' (hf : ConvexOn 𝕜 s f) (hg : ConcaveOn 𝕜 s g (hf₀ : ∀ ⦃x⦄, x ∈ s → f x ≤ 0) (hg₀ : ∀ ⦃x⦄, x ∈ s → 0 ≤ g x) (hfg : MonovaryOn f g s) : ConvexOn 𝕜 s (f • g) := by rw [← neg_concaveOn_iff, ← smul_neg] - exact hf.smul'' hg.neg hf₀ (fun x hx ↦ neg_nonpos.2 $ hg₀ hx) hfg.neg_right + exact hf.smul'' hg.neg hf₀ (fun x hx ↦ neg_nonpos.2 <| hg₀ hx) hfg.neg_right lemma ConcaveOn.smul_convexOn' (hf : ConcaveOn 𝕜 s f) (hg : ConvexOn 𝕜 s g) (hf₀ : ∀ ⦃x⦄, x ∈ s → f x ≤ 0) (hg₀ : ∀ ⦃x⦄, x ∈ s → 0 ≤ g x) (hfg : AntivaryOn f g s) : ConcaveOn 𝕜 s (f • g) := by rw [← neg_convexOn_iff, ← smul_neg] - exact hf.smul'' hg.neg hf₀ (fun x hx ↦ neg_nonpos.2 $ hg₀ hx) hfg.neg_right + exact hf.smul'' hg.neg hf₀ (fun x hx ↦ neg_nonpos.2 <| hg₀ hx) hfg.neg_right variable [IsScalarTower 𝕜 E E] [SMulCommClass 𝕜 E E] {f g : 𝕜 → E} @@ -142,6 +144,7 @@ lemma ConvexOn.pow (hf : ConvexOn 𝕜 s f) (hf₀ : ∀ ⦃x⦄, x ∈ s → 0 /-- `x^n`, `n : ℕ` is convex on `[0, +∞)` for all `n`. -/ lemma convexOn_pow : ∀ n, ConvexOn 𝕜 (Ici 0) fun x : 𝕜 ↦ x ^ n := (convexOn_id <| convex_Ici _).pow fun _ ↦ id +#align convex_on_pow convexOn_pow /-- `x^n`, `n : ℕ` is convex on the whole real line whenever `n` is even. -/ protected lemma Even.convexOn_pow {n : ℕ} (hn : Even n) : ConvexOn 𝕜 univ fun x : 𝕜 ↦ x ^ n := by @@ -152,6 +155,7 @@ protected lemma Even.convexOn_pow {n : ℕ} (hn : Even n) : ConvexOn 𝕜 univ f calc (0 : 𝕜) ≤ (a * b) * (x - y) ^ 2 := by positivity _ = _ := by obtain rfl := eq_sub_of_add_eq hab; simp only [smul_eq_mul]; ring +#align even.convex_on_pow Even.convexOn_pow end LinearOrderedCommRing @@ -174,3 +178,4 @@ lemma convexOn_zpow : ∀ n : ℤ, ConvexOn 𝕜 (Ioi 0) fun x : 𝕜 ↦ x ^ n 0 ≤ a * b * (x - y) ^ 2 := by positivity _ = _ := by obtain rfl := eq_sub_of_add_eq hab; ring all_goals positivity +#align convex_on_zpow convexOn_zpow diff --git a/Mathlib/Analysis/Convex/Normed.lean b/Mathlib/Analysis/Convex/Normed.lean index a5b0c23a1f99b..1be1ee7753f4e 100644 --- a/Mathlib/Analysis/Convex/Normed.lean +++ b/Mathlib/Analysis/Convex/Normed.lean @@ -8,7 +8,6 @@ import Mathlib.Analysis.Convex.Jensen import Mathlib.Analysis.Convex.Topology import Mathlib.Analysis.Normed.Group.Pointwise import Mathlib.Analysis.NormedSpace.AddTorsor -import Mathlib.Analysis.NormedSpace.Ray #align_import analysis.convex.normed from "leanprover-community/mathlib"@"a63928c34ec358b5edcda2bf7513c50052a5230f" diff --git a/Mathlib/Analysis/Convex/Radon.lean b/Mathlib/Analysis/Convex/Radon.lean index 274720066fb29..d53a4f8dff43e 100644 --- a/Mathlib/Analysis/Convex/Radon.lean +++ b/Mathlib/Analysis/Convex/Radon.lean @@ -39,7 +39,7 @@ theorem radon_partition (h : ¬ AffineIndependent 𝕜 f) : with ⟨pos_w_index, h1', h2'⟩ exact sum_pos' (λ _i hi ↦ (mem_filter.1 hi).2) ⟨pos_w_index, by simp only [mem_filter, h1', h2'.le, and_self, h2']⟩ - have hp : centerMass J w f = p := Finset.centerMass_of_sum_add_sum_eq_zero hJI $ by + have hp : centerMass J w f = p := Finset.centerMass_of_sum_add_sum_eq_zero hJI <| by simpa only [← h_vsum, not_lt] using sum_filter_add_sum_filter_not s (fun i ↦ w i < 0) _ refine ⟨I, p, ?_, ?_⟩ · exact centerMass_mem_convexHull _ (fun _i hi ↦ (mem_filter.mp hi).2) hI diff --git a/Mathlib/Analysis/Convex/SpecificFunctions/Basic.lean b/Mathlib/Analysis/Convex/SpecificFunctions/Basic.lean index 2cc4fc79a0f39..45f16125ae68d 100644 --- a/Mathlib/Analysis/Convex/SpecificFunctions/Basic.lean +++ b/Mathlib/Analysis/Convex/SpecificFunctions/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Sébastien Gouëzel, Heather Macbeth -/ -import Mathlib.Analysis.Convex.Mul import Mathlib.Analysis.Convex.Slope import Mathlib.Analysis.SpecialFunctions.Pow.Real import Mathlib.Tactic.LinearCombination @@ -69,10 +68,6 @@ theorem convexOn_exp : ConvexOn ℝ univ exp := strictConvexOn_exp.convexOn #align convex_on_exp convexOn_exp -#align convex_on_pow convexOn_pow -#align even.convex_on_pow Even.convexOn_pow -#align convex_on_zpow convexOn_zpow - /- `Real.log` is strictly concave on $(0, +∞)$. We give an elementary proof rather than using the second derivative test, since this lemma is @@ -225,7 +220,7 @@ lemma exp_mul_le_cosh_add_mul_sinh {t : ℝ} (ht : |t| ≤ 1) (x : ℝ) : calc _ = exp ((1 + t) / 2 * x + (1 - t) / 2 * (-x)) := by ring_nf _ ≤ (1 + t) / 2 * exp x + (1 - t) / 2 * exp (-x) := - convexOn_exp.2 (Set.mem_univ _) (Set.mem_univ _) (by linarith) (by linarith) $ by ring + convexOn_exp.2 (Set.mem_univ _) (Set.mem_univ _) (by linarith) (by linarith) <| by ring _ = _ := by rw [cosh_eq, sinh_eq]; ring end Real diff --git a/Mathlib/Analysis/Convex/SpecificFunctions/Deriv.lean b/Mathlib/Analysis/Convex/SpecificFunctions/Deriv.lean index 71d219b7bb727..a71bf04066af6 100644 --- a/Mathlib/Analysis/Convex/SpecificFunctions/Deriv.lean +++ b/Mathlib/Analysis/Convex/SpecificFunctions/Deriv.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Sébastien Gouëzel -/ import Mathlib.Analysis.Calculus.Deriv.ZPow -import Mathlib.Analysis.SpecialFunctions.Pow.Deriv import Mathlib.Analysis.SpecialFunctions.Sqrt +import Mathlib.Analysis.SpecialFunctions.Log.Deriv +import Mathlib.Analysis.SpecialFunctions.Trigonometric.Deriv #align_import analysis.convex.specific_functions.deriv from "leanprover-community/mathlib"@"a16665637b378379689c566204817ae792ac8b39" diff --git a/Mathlib/Analysis/Convex/Star.lean b/Mathlib/Analysis/Convex/Star.lean index de0bad248947f..f9b67ab2a6d87 100644 --- a/Mathlib/Analysis/Convex/Star.lean +++ b/Mathlib/Analysis/Convex/Star.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ +import Mathlib.Algebra.Order.Group.Instances import Mathlib.Analysis.Convex.Segment import Mathlib.Tactic.GCongr diff --git a/Mathlib/Analysis/Convex/StoneSeparation.lean b/Mathlib/Analysis/Convex/StoneSeparation.lean index 7f238e873e683..3124e78f7f2bb 100644 --- a/Mathlib/Analysis/Convex/StoneSeparation.lean +++ b/Mathlib/Analysis/Convex/StoneSeparation.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ +import Mathlib.Analysis.Convex.Combination import Mathlib.Analysis.Convex.Join #align_import analysis.convex.stone_separation from "leanprover-community/mathlib"@"6ca1a09bc9aa75824bf97388c9e3b441fc4ccf3f" @@ -41,15 +42,12 @@ theorem not_disjoint_segment_convexHull_triple {p q u v x y z : E} (hz : z ∈ s rw [zero_smul, zero_add, habv, one_smul] exact ⟨q, right_mem_segment _ _ _, subset_convexHull _ _ <| by simp⟩ obtain ⟨au, bu, hau, hbu, habu, rfl⟩ := hu - have hab : 0 < az * av + bz * au := - add_pos_of_pos_of_nonneg (mul_pos haz' hav') (mul_nonneg hbz hau) - refine' - ⟨(az * av / (az * av + bz * au)) • (au • x + bu • p) + - (bz * au / (az * av + bz * au)) • (av • y + bv • q), - ⟨_, _, _, _, _, rfl⟩, _⟩ - · exact div_nonneg (mul_nonneg haz hav) hab.le - · exact div_nonneg (mul_nonneg hbz hau) hab.le - · rw [← add_div, div_self hab.ne'] + have hab : 0 < az * av + bz * au := by positivity + refine ⟨(az * av / (az * av + bz * au)) • (au • x + bu • p) + + (bz * au / (az * av + bz * au)) • (av • y + bv • q), ⟨_, _, ?_, ?_, ?_, rfl⟩, ?_⟩ + · positivity + · positivity + · rw [← add_div, div_self]; positivity rw [smul_add, smul_add, add_add_add_comm, add_comm, ← mul_smul, ← mul_smul] classical let w : Fin 3 → 𝕜 := ![az * av * bu, bz * au * bv, au * av] diff --git a/Mathlib/Analysis/Convex/Strict.lean b/Mathlib/Analysis/Convex/Strict.lean index 9b05030853bbd..3cf63030d31ba 100644 --- a/Mathlib/Analysis/Convex/Strict.lean +++ b/Mathlib/Analysis/Convex/Strict.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Analysis.Convex.Basic -import Mathlib.Topology.Algebra.Order.Group +import Mathlib.Topology.Order.Basic +import Mathlib.Topology.Algebra.Group.Basic #align_import analysis.convex.strict from "leanprover-community/mathlib"@"84dc0bd6619acaea625086d6f53cb35cdd554219" diff --git a/Mathlib/Analysis/Convex/StrictConvexBetween.lean b/Mathlib/Analysis/Convex/StrictConvexBetween.lean index ff588ee9b2890..206923926301d 100644 --- a/Mathlib/Analysis/Convex/StrictConvexBetween.lean +++ b/Mathlib/Analysis/Convex/StrictConvexBetween.lean @@ -5,6 +5,7 @@ Authors: Joseph Myers -/ import Mathlib.Analysis.Convex.Between import Mathlib.Analysis.Convex.StrictConvexSpace +import Mathlib.Analysis.NormedSpace.AffineIsometry #align_import analysis.convex.strict_convex_between from "leanprover-community/mathlib"@"e1730698f86560a342271c0471e4cb72d021aabf" diff --git a/Mathlib/Analysis/Convex/StrictConvexSpace.lean b/Mathlib/Analysis/Convex/StrictConvexSpace.lean index 534f1354d8e76..3623a391d2dc8 100644 --- a/Mathlib/Analysis/Convex/StrictConvexSpace.lean +++ b/Mathlib/Analysis/Convex/StrictConvexSpace.lean @@ -8,7 +8,7 @@ import Mathlib.Analysis.Convex.Strict import Mathlib.Analysis.Normed.Order.Basic import Mathlib.Analysis.NormedSpace.AddTorsor import Mathlib.Analysis.NormedSpace.Pointwise -import Mathlib.Analysis.NormedSpace.AffineIsometry +import Mathlib.Analysis.NormedSpace.Ray #align_import analysis.convex.strict_convex_space from "leanprover-community/mathlib"@"a63928c34ec358b5edcda2bf7513c50052a5230f" @@ -57,12 +57,7 @@ formulated only for the case `𝕜 = ℝ`. convex, strictly convex -/ -set_option autoImplicit true - - -open Set Metric - -open Convex Pointwise +open Convex Pointwise Set Metric /-- A *strictly convex space* is a normed space where the closed balls are strictly convex. We only require balls of positive radius with center at the origin to be strictly convex in the definition, diff --git a/Mathlib/Analysis/Convex/Strong.lean b/Mathlib/Analysis/Convex/Strong.lean index dd0aa2e5f2834..5b4dadffcf5df 100644 --- a/Mathlib/Analysis/Convex/Strong.lean +++ b/Mathlib/Analysis/Convex/Strong.lean @@ -55,12 +55,12 @@ protected alias ⟨_, ConvexOn.uniformConvexOn_zero⟩ := uniformConvexOn_zero protected alias ⟨_, ConcaveOn.uniformConcaveOn_zero⟩ := uniformConcaveOn_zero lemma UniformConvexOn.mono (hψφ : ψ ≤ φ) (hf : UniformConvexOn s φ f) : UniformConvexOn s ψ f := - ⟨hf.1, fun x hx y hy a b ha hb hab ↦ (hf.2 hx hy ha hb hab).trans $ - sub_le_sub_left (mul_le_mul_of_nonneg_left (hψφ _) $ by positivity) _⟩ + ⟨hf.1, fun x hx y hy a b ha hb hab ↦ (hf.2 hx hy ha hb hab).trans <| + sub_le_sub_left (mul_le_mul_of_nonneg_left (hψφ _) <| by positivity) _⟩ lemma UniformConcaveOn.mono (hψφ : ψ ≤ φ) (hf : UniformConcaveOn s φ f) : UniformConcaveOn s ψ f := - ⟨hf.1, fun x hx y hy a b ha hb hab ↦ (hf.2 hx hy ha hb hab).trans' $ - add_le_add_left (mul_le_mul_of_nonneg_left (hψφ _) $ by positivity) _⟩ + ⟨hf.1, fun x hx y hy a b ha hb hab ↦ (hf.2 hx hy ha hb hab).trans' <| + add_le_add_left (mul_le_mul_of_nonneg_left (hψφ _) <| by positivity) _⟩ lemma UniformConvexOn.convexOn (hf : UniformConvexOn s φ f) (hφ : 0 ≤ φ) : ConvexOn ℝ s f := by simpa using hf.mono hφ @@ -70,7 +70,7 @@ lemma UniformConcaveOn.concaveOn (hf : UniformConcaveOn s φ f) (hφ : 0 ≤ φ) lemma UniformConvexOn.strictConvexOn (hf : UniformConvexOn s φ f) (hφ : ∀ r, r ≠ 0 → 0 < φ r) : StrictConvexOn ℝ s f := by - refine ⟨hf.1, fun x hx y hy hxy a b ha hb hab ↦ (hf.2 hx hy ha.le hb.le hab).trans_lt $ + refine ⟨hf.1, fun x hx y hy hxy a b ha hb hab ↦ (hf.2 hx hy ha.le hb.le hab).trans_lt <| sub_lt_self _ ?_⟩ rw [← sub_ne_zero, ← norm_pos_iff] at hxy have := hφ _ hxy.ne' @@ -78,7 +78,7 @@ lemma UniformConvexOn.strictConvexOn (hf : UniformConvexOn s φ f) (hφ : ∀ r, lemma UniformConcaveOn.strictConcaveOn (hf : UniformConcaveOn s φ f) (hφ : ∀ r, r ≠ 0 → 0 < φ r) : StrictConcaveOn ℝ s f := by - refine ⟨hf.1, fun x hx y hy hxy a b ha hb hab ↦ (hf.2 hx hy ha.le hb.le hab).trans_lt' $ + refine ⟨hf.1, fun x hx y hy hxy a b ha hb hab ↦ (hf.2 hx hy ha.le hb.le hab).trans_lt' <| lt_add_of_pos_right _ ?_⟩ rw [← sub_ne_zero, ← norm_pos_iff] at hxy have := hφ _ hxy.ne' @@ -127,11 +127,11 @@ def StrongConcaveOn (s : Set E) (m : ℝ) : (E → ℝ) → Prop := variable {s : Set E} {f : E → ℝ} {m n : ℝ} nonrec lemma StrongConvexOn.mono (hmn : m ≤ n) (hf : StrongConvexOn s n f) : StrongConvexOn s m f := - hf.mono fun r ↦ mul_le_mul_of_nonneg_right (div_le_div_of_le zero_le_two hmn) $ by positivity + hf.mono fun r ↦ mul_le_mul_of_nonneg_right (div_le_div_of_le zero_le_two hmn) <| by positivity nonrec lemma StrongConcaveOn.mono (hmn : m ≤ n) (hf : StrongConcaveOn s n f) : StrongConcaveOn s m f := - hf.mono fun r ↦ mul_le_mul_of_nonneg_right (div_le_div_of_le zero_le_two hmn) $ by positivity + hf.mono fun r ↦ mul_le_mul_of_nonneg_right (div_le_div_of_le zero_le_two hmn) <| by positivity @[simp] lemma strongConvexOn_zero : StrongConvexOn s 0 f ↔ ConvexOn ℝ s f := by simp [StrongConvexOn, ← Pi.zero_def] diff --git a/Mathlib/Analysis/Convex/Topology.lean b/Mathlib/Analysis/Convex/Topology.lean index 6b9685c597803..d91cf594e8960 100644 --- a/Mathlib/Analysis/Convex/Topology.lean +++ b/Mathlib/Analysis/Convex/Topology.lean @@ -70,7 +70,7 @@ theorem isCompact_stdSimplex : IsCompact (stdSimplex ℝ ι) := #align is_compact_std_simplex isCompact_stdSimplex instance stdSimplex.instCompactSpace_coe : CompactSpace ↥(stdSimplex ℝ ι) := - isCompact_iff_compactSpace.mp $ isCompact_stdSimplex _ + isCompact_iff_compactSpace.mp <| isCompact_stdSimplex _ end stdSimplex diff --git a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean index bb3a744055edd..d70c802ff8f07 100644 --- a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean +++ b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Geometry.Manifold.PartitionOfUnity import Mathlib.Geometry.Manifold.Metrizable +import Mathlib.MeasureTheory.Function.AEEqOfIntegral /-! # Functions which vanish as distributions vanish as functions diff --git a/Mathlib/Analysis/Distribution/SchwartzSpace.lean b/Mathlib/Analysis/Distribution/SchwartzSpace.lean index 6ae4730f62e0f..f2bfa70c476dc 100644 --- a/Mathlib/Analysis/Distribution/SchwartzSpace.lean +++ b/Mathlib/Analysis/Distribution/SchwartzSpace.lean @@ -6,11 +6,10 @@ Authors: Moritz Doll import Mathlib.Analysis.Calculus.Deriv.Add import Mathlib.Analysis.Calculus.Deriv.Mul import Mathlib.Analysis.Calculus.ContDiff.Bounds -import Mathlib.Analysis.Calculus.IteratedDeriv +import Mathlib.Analysis.Calculus.IteratedDeriv.Defs import Mathlib.Analysis.LocallyConvex.WithSeminorms import Mathlib.Topology.Algebra.UniformFilterBasis import Mathlib.Topology.ContinuousFunction.Bounded -import Mathlib.Tactic.Positivity import Mathlib.Analysis.SpecialFunctions.Pow.Real #align_import analysis.schwartz_space from "leanprover-community/mathlib"@"e137999b2c6f2be388f4cd3bbf8523de1910cd2b" @@ -92,14 +91,14 @@ open SchwartzSpace -- porting note: removed -- instance : Coe 𝓢(E, F) (E → F) := ⟨toFun⟩ -instance instFunLike : FunLike 𝓢(E, F) E fun _ => F where +instance instFunLike : FunLike 𝓢(E, F) E F where coe f := f.toFun coe_injective' f g h := by cases f; cases g; congr #align schwartz_map.fun_like SchwartzMap.instFunLike -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ instance instCoeFun : CoeFun 𝓢(E, F) fun _ => E → F := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun #align schwartz_map.has_coe_to_fun SchwartzMap.instCoeFun /-- All derivatives of a Schwartz function are rapidly decaying. -/ @@ -132,7 +131,7 @@ protected theorem differentiableAt (f : 𝓢(E, F)) {x : E} : DifferentiableAt @[ext] theorem ext {f g : 𝓢(E, F)} (h : ∀ x, (f : E → F) x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align schwartz_map.ext SchwartzMap.ext section IsBigO @@ -163,7 +162,7 @@ theorem isBigO_cocompact_rpow [ProperSpace E] (s : ℝ) : from this.comp_tendsto tendsto_norm_cocompact_atTop simp_rw [Asymptotics.IsBigO, Asymptotics.IsBigOWith] refine' ⟨1, (Filter.eventually_ge_atTop 1).mono fun x hx => _⟩ - rw [one_mul, Real.norm_of_nonneg (Real.rpow_nonneg_of_nonneg (zero_le_one.trans hx) _), + rw [one_mul, Real.norm_of_nonneg (Real.rpow_nonneg (zero_le_one.trans hx) _), Real.norm_of_nonneg (zpow_nonneg (zero_le_one.trans hx) _), ← Real.rpow_int_cast, Int.cast_neg, Int.cast_ofNat] exact Real.rpow_le_rpow_of_exponent_le hx hk @@ -210,7 +209,8 @@ variable [NormedField 𝕜] [NormedSpace 𝕜 F] [SMulCommClass ℝ 𝕜 F] theorem decay_smul_aux (k n : ℕ) (f : 𝓢(E, F)) (c : 𝕜) (x : E) : ‖x‖ ^ k * ‖iteratedFDeriv ℝ n (c • (f : E → F)) x‖ = ‖c‖ * ‖x‖ ^ k * ‖iteratedFDeriv ℝ n f x‖ := by - rw [mul_comm ‖c‖, mul_assoc, iteratedFDeriv_const_smul_apply (f.smooth _), norm_smul] + rw [mul_comm ‖c‖, mul_assoc, iteratedFDeriv_const_smul_apply (f.smooth _), + norm_smul c (iteratedFDeriv ℝ n (⇑f) x)] #align schwartz_map.decay_smul_aux SchwartzMap.decay_smul_aux end Aux @@ -323,7 +323,7 @@ instance instInhabited : Inhabited 𝓢(E, F) := ⟨0⟩ #align schwartz_map.inhabited SchwartzMap.instInhabited -theorem coe_zero : FunLike.coe (0 : 𝓢(E, F)) = (0 : E → F) := +theorem coe_zero : DFunLike.coe (0 : 𝓢(E, F)) = (0 : E → F) := rfl #align schwartz_map.coe_zero SchwartzMap.coe_zero @@ -403,7 +403,7 @@ end Sub section AddCommGroup instance instAddCommGroup : AddCommGroup 𝓢(E, F) := - FunLike.coe_injective.addCommGroup _ rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) + DFunLike.coe_injective.addCommGroup _ rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl #align schwartz_map.add_comm_group SchwartzMap.instAddCommGroup @@ -418,13 +418,13 @@ def coeHom : 𝓢(E, F) →+ E → F where variable {E F} -theorem coe_coeHom : (coeHom E F : 𝓢(E, F) → E → F) = FunLike.coe := +theorem coe_coeHom : (coeHom E F : 𝓢(E, F) → E → F) = DFunLike.coe := rfl #align schwartz_map.coe_coe_hom SchwartzMap.coe_coeHom theorem coeHom_injective : Function.Injective (coeHom E F) := by rw [coe_coeHom] - exact FunLike.coe_injective + exact DFunLike.coe_injective #align schwartz_map.coe_hom_injective SchwartzMap.coeHom_injective end AddCommGroup diff --git a/Mathlib/Analysis/Fourier/AddCircle.lean b/Mathlib/Analysis/Fourier/AddCircle.lean index 920eba649c205..7e2a331a19503 100644 --- a/Mathlib/Analysis/Fourier/AddCircle.lean +++ b/Mathlib/Analysis/Fourier/AddCircle.lean @@ -219,7 +219,7 @@ theorem fourier_norm [Fact (0 < T)] (n : ℤ) : ‖@fourier T n‖ = 1 := by rw [ContinuousMap.norm_eq_iSup_norm] have : ∀ x : AddCircle T, ‖fourier n x‖ = 1 := fun x => abs_coe_circle _ simp_rw [this] - exact @ciSup_const _ _ _ Zero.nonempty _ + exact @ciSup_const _ _ _ Zero.instNonempty _ #align fourier_norm fourier_norm /-- For `n ≠ 0`, a translation by `T / 2 / n` negates the function `fourier n`. -/ @@ -358,7 +358,8 @@ theorem fourierCoeff_eq_intervalIntegral (f : AddCircle T → E) (n : ℤ) (a : fourierCoeff f n = (1 / T) • ∫ x in a..a + T, @fourier T (-n) x • f x := by have : ∀ x : ℝ, @fourier T (-n) x • f x = (fun z : AddCircle T => @fourier T (-n) z • f z) x := by intro x; rfl - simp_rw [this] + -- After leanprover/lean4#3124, we need to add `singlePass := true` to avoid an infinite loop. + simp_rw (config := {singlePass := true}) [this] rw [fourierCoeff, AddCircle.intervalIntegral_preimage T a (fun z => _ • _), volume_eq_smul_haarAddCircle, integral_smul_measure, ENNReal.toReal_ofReal hT.out.le, ← smul_assoc, smul_eq_mul, one_div_mul_cancel hT.out.ne', one_smul] @@ -550,11 +551,7 @@ theorem has_antideriv_at_fourier_neg (hT : Fact (0 < T)) {n : ℤ} (hn : n ≠ 0 (fourier (-n) (x : AddCircle T)) x := by convert (hasDerivAt_fourier_neg T n x).div_const (-2 * π * I * n / T) using 1 · ext1 y; rw [div_div_eq_mul_div]; ring - · rw [mul_div_cancel_left] - simp only [Ne.def, div_eq_zero_iff, neg_eq_zero, mul_eq_zero, bit0_eq_zero, one_ne_zero, - ofReal_eq_zero, false_or_iff, Int.cast_eq_zero, not_or] - norm_num - exact ⟨⟨⟨Real.pi_ne_zero, I_ne_zero⟩, hn⟩, hT.out.ne'⟩ + · simp [mul_div_cancel_left, hn, (Fact.out : 0 < T).ne', Real.pi_pos.ne'] #align has_antideriv_at_fourier_neg has_antideriv_at_fourier_neg /-- Express Fourier coefficients of `f` on an interval in terms of those of its derivative. -/ diff --git a/Mathlib/Analysis/Fourier/PoissonSummation.lean b/Mathlib/Analysis/Fourier/PoissonSummation.lean index a877fcb07896f..9e60c8b79f2ad 100644 --- a/Mathlib/Analysis/Fourier/PoissonSummation.lean +++ b/Mathlib/Analysis/Fourier/PoissonSummation.lean @@ -109,19 +109,19 @@ theorem Real.fourierCoeff_tsum_comp_add {f : C(ℝ, ℂ)} theorem Real.tsum_eq_tsum_fourierIntegral {f : C(ℝ, ℂ)} (h_norm : ∀ K : Compacts ℝ, Summable fun n : ℤ => ‖(f.comp <| ContinuousMap.addRight n).restrict K‖) - (h_sum : Summable fun n : ℤ => 𝓕 f n) : ∑' n : ℤ, f n = (∑' n : ℤ, 𝓕 f n) := by + (h_sum : Summable fun n : ℤ => 𝓕 f n) (x : ℝ) : + ∑' n : ℤ, f (x + n) = ∑' n : ℤ, 𝓕 f n * fourier n (x : UnitAddCircle) := by let F : C(UnitAddCircle, ℂ) := ⟨(f.periodic_tsum_comp_add_zsmul 1).lift, continuous_coinduced_dom.mpr (map_continuous _)⟩ have : Summable (fourierCoeff F) := by convert h_sum exact Real.fourierCoeff_tsum_comp_add h_norm _ - convert (has_pointwise_sum_fourier_series_of_summable this 0).tsum_eq.symm using 1 - · have := (hasSum_apply (summable_of_locally_summable_norm h_norm).hasSum 0).tsum_eq - simpa only [coe_mk, ← QuotientAddGroup.mk_zero, Periodic.lift_coe, zsmul_one, comp_apply, - coe_addRight, zero_add] using this - · congr 1 with n : 1 - rw [← Real.fourierCoeff_tsum_comp_add h_norm n, fourier_eval_zero, smul_eq_mul, mul_one] - rfl + convert (has_pointwise_sum_fourier_series_of_summable this x).tsum_eq.symm using 1 + · simpa only [coe_mk, ← QuotientAddGroup.mk_zero, Periodic.lift_coe, zsmul_one, comp_apply, + coe_addRight, zero_add] + using (hasSum_apply (summable_of_locally_summable_norm h_norm).hasSum x).tsum_eq + · simp_rw [← Real.fourierCoeff_tsum_comp_add h_norm, smul_eq_mul, coe_mk] + #align real.tsum_eq_tsum_fourier_integral Real.tsum_eq_tsum_fourierIntegral section RpowDecay @@ -131,30 +131,17 @@ variable {E : Type*} [NormedAddCommGroup E] /-- If `f` is `O(x ^ (-b))` at infinity, then so is the function `λ x, ‖f.restrict (Icc (x + R) (x + S))‖` for any fixed `R` and `S`. -/ theorem isBigO_norm_Icc_restrict_atTop {f : C(ℝ, E)} {b : ℝ} (hb : 0 < b) - (hf : IsBigO atTop f fun x : ℝ => |x| ^ (-b)) (R S : ℝ) : - IsBigO atTop (fun x : ℝ => ‖f.restrict (Icc (x + R) (x + S))‖) fun x : ℝ => |x| ^ (-b) := by + (hf : f =O[atTop] fun x : ℝ => |x| ^ (-b)) (R S : ℝ) : + (fun x : ℝ => ‖f.restrict (Icc (x + R) (x + S))‖) =O[atTop] fun x : ℝ => |x| ^ (-b) := by -- First establish an explicit estimate on decay of inverse powers. -- This is logically independent of the rest of the proof, but of no mathematical interest in - -- itself, so it is proved using `async` rather than being formulated as a separate lemma. - have claim : - ∀ x : ℝ, max 0 (-2 * R) < x → ∀ y : ℝ, x + R ≤ y → y ^ (-b) ≤ (1 / 2) ^ (-b) * x ^ (-b) := by - intro x hx y hy + -- itself, so it is proved in-line rather than being formulated as a separate lemma. + have claim : ∀ x : ℝ, max 0 (-2 * R) < x → ∀ y : ℝ, x + R ≤ y → + y ^ (-b) ≤ (1 / 2) ^ (-b) * x ^ (-b) := fun x hx y hy ↦ by rw [max_lt_iff] at hx obtain ⟨hx1, hx2⟩ := hx - have hxR : 0 < x + R := by - rcases le_or_lt 0 R with (h | _) - · positivity - · linarith - have hy' : 0 < y := hxR.trans_le hy - have : y ^ (-b) ≤ (x + R) ^ (-b) := by - rw [rpow_neg, rpow_neg, inv_le_inv] - · gcongr - all_goals positivity - refine' this.trans _ - rw [← mul_rpow, rpow_neg, rpow_neg] - · gcongr - linarith - all_goals positivity + rw [← mul_rpow] <;> try positivity + apply rpow_le_rpow_of_nonpos <;> linarith -- Now the main proof. obtain ⟨c, hc, hc'⟩ := hf.exists_pos simp only [IsBigO, IsBigOWith, eventually_atTop] at hc' ⊢ @@ -163,9 +150,7 @@ theorem isBigO_norm_Icc_restrict_atTop {f : C(ℝ, E)} {b : ℝ} (hb : 0 < b) rw [ge_iff_le, max_le_iff] at hx have hx' : max 0 (-2 * R) < x := by linarith rw [max_lt_iff] at hx' - rw [norm_norm, - ContinuousMap.norm_le _ - (mul_nonneg (mul_nonneg hc.le <| rpow_nonneg_of_nonneg one_half_pos.le _) (norm_nonneg _))] + rw [norm_norm, ContinuousMap.norm_le _ (by positivity)] refine' fun y => (hd y.1 (by linarith [hx.1, y.2.1])).trans _ have A : ∀ x : ℝ, 0 ≤ |x| ^ (-b) := fun x => by positivity rw [mul_assoc, mul_le_mul_left hc, norm_of_nonneg (A _), norm_of_nonneg (A _)] @@ -176,9 +161,9 @@ set_option linter.uppercaseLean3 false in #align is_O_norm_Icc_restrict_at_top isBigO_norm_Icc_restrict_atTop theorem isBigO_norm_Icc_restrict_atBot {f : C(ℝ, E)} {b : ℝ} (hb : 0 < b) - (hf : IsBigO atBot f fun x : ℝ => |x| ^ (-b)) (R S : ℝ) : - IsBigO atBot (fun x : ℝ => ‖f.restrict (Icc (x + R) (x + S))‖) fun x : ℝ => |x| ^ (-b) := by - have h1 : IsBigO atTop (f.comp (ContinuousMap.mk _ continuous_neg)) fun x : ℝ => |x| ^ (-b) := by + (hf : f =O[atBot] fun x : ℝ => |x| ^ (-b)) (R S : ℝ) : + (fun x : ℝ => ‖f.restrict (Icc (x + R) (x + S))‖) =O[atBot] fun x : ℝ => |x| ^ (-b) := by + have h1 : (f.comp (ContinuousMap.mk _ continuous_neg)) =O[atTop] fun x : ℝ => |x| ^ (-b) := by convert hf.comp_tendsto tendsto_neg_atTop_atBot using 1 ext1 x; simp only [Function.comp_apply, abs_neg] have h2 := (isBigO_norm_Icc_restrict_atTop hb h1 (-S) (-R)).comp_tendsto tendsto_neg_atBot_atTop @@ -198,13 +183,11 @@ set_option linter.uppercaseLean3 false in #align is_O_norm_Icc_restrict_at_bot isBigO_norm_Icc_restrict_atBot theorem isBigO_norm_restrict_cocompact (f : C(ℝ, E)) {b : ℝ} (hb : 0 < b) - (hf : IsBigO (cocompact ℝ) f fun x : ℝ => |x| ^ (-b)) (K : Compacts ℝ) : - IsBigO (cocompact ℝ) (fun x => ‖(f.comp (ContinuousMap.addRight x)).restrict K‖) fun x => - |x| ^ (-b) := by + (hf : f =O[cocompact ℝ] fun x : ℝ => |x| ^ (-b)) (K : Compacts ℝ) : + (fun x => ‖(f.comp (ContinuousMap.addRight x)).restrict K‖) =O[cocompact ℝ] (|·| ^ (-b)) := by obtain ⟨r, hr⟩ := K.isCompact.isBounded.subset_closedBall 0 rw [closedBall_eq_Icc, zero_add, zero_sub] at hr - have : - ∀ x : ℝ, + have : ∀ x : ℝ, ‖(f.comp (ContinuousMap.addRight x)).restrict K‖ ≤ ‖f.restrict (Icc (x - r) (x + r))‖ := by intro x rw [ContinuousMap.norm_le _ (norm_nonneg _)] @@ -225,25 +208,22 @@ set_option linter.uppercaseLean3 false in `|x| ^ (-b)` for some `1 < b` and its Fourier transform is summable. -/ theorem Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay_of_summable {f : ℝ → ℂ} (hc : Continuous f) {b : ℝ} (hb : 1 < b) (hf : IsBigO (cocompact ℝ) f fun x : ℝ => |x| ^ (-b)) - (hFf : Summable fun n : ℤ => 𝓕 f n) : ∑' n : ℤ, f n = (∑' n : ℤ, 𝓕 f n) := - Real.tsum_eq_tsum_fourierIntegral - (fun K => - summable_of_isBigO (Real.summable_abs_int_rpow hb) - ((isBigO_norm_restrict_cocompact (ContinuousMap.mk _ hc) (zero_lt_one.trans hb) hf - K).comp_tendsto - Int.tendsto_coe_cofinite)) - hFf + (hFf : Summable fun n : ℤ => 𝓕 f n) (x : ℝ) : + ∑' n : ℤ, f (x + n) = ∑' n : ℤ, 𝓕 f n * fourier n (x : UnitAddCircle) := + Real.tsum_eq_tsum_fourierIntegral (fun K => summable_of_isBigO (Real.summable_abs_int_rpow hb) + ((isBigO_norm_restrict_cocompact ⟨_, hc⟩ (zero_lt_one.trans hb) hf K).comp_tendsto + Int.tendsto_coe_cofinite)) hFf x #align real.tsum_eq_tsum_fourier_integral_of_rpow_decay_of_summable Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay_of_summable /-- **Poisson's summation formula**, assuming that both `f` and its Fourier transform decay as `|x| ^ (-b)` for some `1 < b`. (This is the one-dimensional case of Corollary VII.2.6 of Stein and Weiss, *Introduction to Fourier analysis on Euclidean spaces*.) -/ theorem Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay {f : ℝ → ℂ} (hc : Continuous f) {b : ℝ} - (hb : 1 < b) (hf : IsBigO (cocompact ℝ) f fun x : ℝ => |x| ^ (-b)) - (hFf : IsBigO (cocompact ℝ) (𝓕 f) fun x : ℝ => |x| ^ (-b)) : - ∑' n : ℤ, f n = ∑' n : ℤ, 𝓕 f n := - Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay_of_summable hc hb hf - (summable_of_isBigO (Real.summable_abs_int_rpow hb) (hFf.comp_tendsto Int.tendsto_coe_cofinite)) + (hb : 1 < b) (hf : f =O[cocompact ℝ] (|·| ^ (-b))) + (hFf : (𝓕 f) =O[cocompact ℝ] (|·| ^ (-b))) (x : ℝ) : + ∑' n : ℤ, f (x + n) = ∑' n : ℤ, 𝓕 f n * fourier n (x : UnitAddCircle) := + Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay_of_summable hc hb hf (summable_of_isBigO + (Real.summable_abs_int_rpow hb) (hFf.comp_tendsto Int.tendsto_coe_cofinite)) x #align real.tsum_eq_tsum_fourier_integral_of_rpow_decay Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay end RpowDecay @@ -251,15 +231,13 @@ end RpowDecay section Schwartz /-- **Poisson's summation formula** for Schwartz functions. -/ -theorem SchwartzMap.tsum_eq_tsum_fourierIntegral (f g : SchwartzMap ℝ ℂ) (hfg : 𝓕 f = g) : - ∑' n : ℤ, f n = (∑' n : ℤ, g n) := by +theorem SchwartzMap.tsum_eq_tsum_fourierIntegral (f g : SchwartzMap ℝ ℂ) (hfg : 𝓕 ⇑f = ⇑g) (x : ℝ) : + ∑' n : ℤ, f (x + n) = (∑' n : ℤ, g n * fourier n (x : UnitAddCircle)) := by -- We know that Schwartz functions are `O(‖x ^ (-b)‖)` for *every* `b`; for this argument we take -- `b = 2` and work with that. - simp_rw [← hfg] - rw [Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay f.continuous one_lt_two - (f.isBigO_cocompact_rpow (-2))] - rw [hfg] - exact g.isBigO_cocompact_rpow (-2) + simp only [← hfg, Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay f.continuous one_lt_two + (f.isBigO_cocompact_rpow (-2)) (hfg ▸ g.isBigO_cocompact_rpow (-2))] + #align schwartz_map.tsum_eq_tsum_fourier_integral SchwartzMap.tsum_eq_tsum_fourierIntegral end Schwartz diff --git a/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean b/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean index 60b9996e7c838..484fe3d9a954b 100644 --- a/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean +++ b/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean @@ -23,7 +23,7 @@ spaces `V`: if `f` is a function on `V` (valued in a complete normed space `E`), Fourier transform of `f`, viewed as a function on the dual space of `V`, tends to 0 along the cocompact filter. Here the Fourier transform is defined by -`λ w : V →L[ℝ] ℝ, ∫ (v : V), exp (↑(2 * π * w v) * I) • f x`. +`fun w : V →L[ℝ] ℝ ↦ ∫ (v : V), exp (↑(2 * π * w v) * I) • f x`. This is true for arbitrary functions, but is only interesting for `L¹` functions (if `f` is not integrable then the integral is zero for all `w`). This is proved first for continuous @@ -260,10 +260,9 @@ via dual space. **Do not use** -- it is only a stepping stone to `tendsto_integral_exp_smul_cocompact` where the inner-product-space structure isn't required. -/ theorem tendsto_integral_exp_smul_cocompact_of_inner_product (μ : Measure V) [μ.IsAddHaarMeasure] : Tendsto (fun w : V →L[ℝ] ℝ => ∫ v, e[-w v] • f v ∂μ) (cocompact (V →L[ℝ] ℝ)) (𝓝 0) := by - obtain ⟨C, _, _, hC⟩ := μ.isAddHaarMeasure_eq_smul volume - rw [hC] - simp_rw [integral_smul_measure] - rw [← (smul_zero _ : C.toReal • (0 : E) = 0)] + rw [μ.isAddHaarMeasure_eq_smul volume] + simp_rw [integral_smul_nnreal_measure] + rw [← (smul_zero _ : Measure.addHaarScalarFactor μ volume • (0 : E) = 0)] apply Tendsto.const_smul let A := (InnerProductSpace.toDual ℝ V).symm have : (fun w : V →L[ℝ] ℝ => ∫ v, e[-w v] • f v) = (fun w : V => ∫ v, e[-⟪v, w⟫] • f v) ∘ A := by diff --git a/Mathlib/Analysis/Hofer.lean b/Mathlib/Analysis/Hofer.lean index 0b5364efcf5a9..d791299e3c91c 100644 --- a/Mathlib/Analysis/Hofer.lean +++ b/Mathlib/Analysis/Hofer.lean @@ -27,11 +27,7 @@ open Filter Finset local notation "d" => dist -@[simp] -theorem pos_div_pow_pos {α : Type*} [LinearOrderedSemifield α] {a b : α} (ha : 0 < a) (hb : 0 < b) - (k : ℕ) : 0 < a / b ^ k := - div_pos ha (pow_pos hb k) -#align pos_div_pow_pos pos_div_pow_pos +#noalign pos_div_pow_pos theorem hofer {X : Type*} [MetricSpace X] [CompleteSpace X] (x : X) (ε : ℝ) (ε_pos : 0 < ε) {ϕ : X → ℝ} (cont : Continuous ϕ) (nonneg : ∀ y, 0 ≤ ϕ y) : ∃ ε' > 0, ∃ x' : X, @@ -46,7 +42,7 @@ theorem hofer {X : Type*} [MetricSpace X] [CompleteSpace X] (x : X) (ε : ℝ) ( ∀ k : ℕ, ∀ x', d x' x ≤ 2 * ε ∧ 2 ^ k * ϕ x ≤ ϕ x' → ∃ y, d x' y ≤ ε / 2 ^ k ∧ 2 * ϕ x' < ϕ y · intro k x' push_neg at H - have := H (ε / 2 ^ k) (by simp [ε_pos]) x' (by simp [ε_pos.le, one_le_two]) + have := H (ε / 2 ^ k) (by positivity) x' (by simp [ε_pos.le, one_le_two]) simpa [reformulation] using this clear reformulation haveI : Nonempty X := ⟨x⟩ @@ -66,8 +62,7 @@ theorem hofer {X : Type*} [MetricSpace X] [CompleteSpace X] (x : X) (ε : ℝ) ( have key : ∀ n, d (u n) (u (n + 1)) ≤ ε / 2 ^ n ∧ 2 * ϕ (u n) < ϕ (u (n + 1)) := by intro n induction' n using Nat.case_strong_induction_on with n IH - · specialize hu 0 - simpa [mul_nonneg_iff, zero_le_one, ε_pos.le, le_refl] using hu + · simpa [ε_pos.le] using hu 0 have A : d (u (n + 1)) x ≤ 2 * ε := by rw [dist_comm] let r := range (n + 1) -- range (n+1) = {0, ..., n} @@ -75,10 +70,10 @@ theorem hofer {X : Type*} [MetricSpace X] [CompleteSpace X] (x : X) (ε : ℝ) ( d (u 0) (u (n + 1)) ≤ ∑ i in r, d (u i) (u <| i + 1) := dist_le_range_sum_dist u (n + 1) _ ≤ ∑ i in r, ε / 2 ^ i := (sum_le_sum fun i i_in => (IH i <| Nat.lt_succ_iff.mp <| Finset.mem_range.mp i_in).1) - _ = ∑ i in r, (1 / 2) ^ i * ε := by + _ = (∑ i in r, (1 / 2 : ℝ) ^ i) * ε := by + rw [Finset.sum_mul] congr with i field_simp - _ = (∑ i in r, ((1 : ℝ) / 2) ^ i) * ε := Finset.sum_mul.symm _ ≤ 2 * ε := by gcongr; apply sum_geometric_two_le have B : 2 ^ (n + 1) * ϕ x ≤ ϕ (u (n + 1)) := by refine' @geom_le (ϕ ∘ u) _ zero_le_two (n + 1) fun m hm => _ @@ -98,9 +93,8 @@ theorem hofer {X : Type*} [MetricSpace X] [CompleteSpace X] (x : X) (ε : ℝ) ( let v n := (ϕ ∘ u) (n + 1) suffices Tendsto v atTop atTop by rwa [tendsto_add_atTop_iff_nat] at this have hv₀ : 0 < v 0 := by - have : 0 ≤ ϕ (u 0) := nonneg x calc - 0 ≤ 2 * ϕ (u 0) := (mul_nonneg_iff_of_pos_left zero_lt_two).mpr this + 0 ≤ 2 * ϕ (u 0) := by specialize nonneg x; positivity _ < ϕ (u (0 + 1)) := key₂ 0 apply tendsto_atTop_of_geom_le hv₀ one_lt_two exact fun n => (key₂ (n + 1)).le diff --git a/Mathlib/Analysis/InnerProductSpace/Adjoint.lean b/Mathlib/Analysis/InnerProductSpace/Adjoint.lean index 1283a1f2401f9..7dfb6d8d5952a 100644 --- a/Mathlib/Analysis/InnerProductSpace/Adjoint.lean +++ b/Mathlib/Analysis/InnerProductSpace/Adjoint.lean @@ -143,25 +143,25 @@ theorem adjoint_comp (A : F →L[𝕜] G) (B : E →L[𝕜] F) : (A ∘L B)† = simp only [adjoint_inner_right, ContinuousLinearMap.coe_comp', Function.comp_apply] #align continuous_linear_map.adjoint_comp ContinuousLinearMap.adjoint_comp -theorem apply_norm_sq_eq_inner_adjoint_left (A : E →L[𝕜] E) (x : E) : - ‖A x‖ ^ 2 = re ⟪(A† * A) x, x⟫ := by - have h : ⟪(A† * A) x, x⟫ = ⟪A x, A x⟫ := by rw [← adjoint_inner_left]; rfl +theorem apply_norm_sq_eq_inner_adjoint_left (A : E →L[𝕜] F) (x : E) : + ‖A x‖ ^ 2 = re ⟪(A† ∘L A) x, x⟫ := by + have h : ⟪(A† ∘L A) x, x⟫ = ⟪A x, A x⟫ := by rw [← adjoint_inner_left]; rfl rw [h, ← inner_self_eq_norm_sq (𝕜 := 𝕜) _] #align continuous_linear_map.apply_norm_sq_eq_inner_adjoint_left ContinuousLinearMap.apply_norm_sq_eq_inner_adjoint_left -theorem apply_norm_eq_sqrt_inner_adjoint_left (A : E →L[𝕜] E) (x : E) : - ‖A x‖ = Real.sqrt (re ⟪(A† * A) x, x⟫) := by +theorem apply_norm_eq_sqrt_inner_adjoint_left (A : E →L[𝕜] F) (x : E) : + ‖A x‖ = Real.sqrt (re ⟪(A† ∘L A) x, x⟫) := by rw [← apply_norm_sq_eq_inner_adjoint_left, Real.sqrt_sq (norm_nonneg _)] #align continuous_linear_map.apply_norm_eq_sqrt_inner_adjoint_left ContinuousLinearMap.apply_norm_eq_sqrt_inner_adjoint_left -theorem apply_norm_sq_eq_inner_adjoint_right (A : E →L[𝕜] E) (x : E) : - ‖A x‖ ^ 2 = re ⟪x, (A† * A) x⟫ := by - have h : ⟪x, (A† * A) x⟫ = ⟪A x, A x⟫ := by rw [← adjoint_inner_right]; rfl +theorem apply_norm_sq_eq_inner_adjoint_right (A : E →L[𝕜] F) (x : E) : + ‖A x‖ ^ 2 = re ⟪x, (A† ∘L A) x⟫ := by + have h : ⟪x, (A† ∘L A) x⟫ = ⟪A x, A x⟫ := by rw [← adjoint_inner_right]; rfl rw [h, ← inner_self_eq_norm_sq (𝕜 := 𝕜) _] #align continuous_linear_map.apply_norm_sq_eq_inner_adjoint_right ContinuousLinearMap.apply_norm_sq_eq_inner_adjoint_right -theorem apply_norm_eq_sqrt_inner_adjoint_right (A : E →L[𝕜] E) (x : E) : - ‖A x‖ = Real.sqrt (re ⟪x, (A† * A) x⟫) := by +theorem apply_norm_eq_sqrt_inner_adjoint_right (A : E →L[𝕜] F) (x : E) : + ‖A x‖ = Real.sqrt (re ⟪x, (A† ∘L A) x⟫) := by rw [← apply_norm_sq_eq_inner_adjoint_right, Real.sqrt_sq (norm_nonneg _)] #align continuous_linear_map.apply_norm_eq_sqrt_inner_adjoint_right ContinuousLinearMap.apply_norm_eq_sqrt_inner_adjoint_right @@ -222,26 +222,27 @@ theorem isSelfAdjoint_iff' {A : E →L[𝕜] E} : IsSelfAdjoint A ↔ Continuous Iff.rfl #align continuous_linear_map.is_self_adjoint_iff' ContinuousLinearMap.isSelfAdjoint_iff' -instance : CstarRing (E →L[𝕜] E) := - ⟨by - intro A - rw [star_eq_adjoint] - refine' le_antisymm _ _ - · calc - ‖A† * A‖ ≤ ‖A†‖ * ‖A‖ := op_norm_comp_le _ _ - _ = ‖A‖ * ‖A‖ := by rw [LinearIsometryEquiv.norm_map] - · rw [← sq, ← Real.sqrt_le_sqrt_iff (norm_nonneg _), Real.sqrt_sq (norm_nonneg _)] - refine' op_norm_le_bound _ (Real.sqrt_nonneg _) fun x => _ - have := - calc - re ⟪(A† * A) x, x⟫ ≤ ‖(A† * A) x‖ * ‖x‖ := re_inner_le_norm _ _ - _ ≤ ‖A† * A‖ * ‖x‖ * ‖x‖ := mul_le_mul_of_nonneg_right (le_op_norm _ _) (norm_nonneg _) +theorem norm_adjoint_comp_self (A : E →L[𝕜] F) : + ‖ContinuousLinearMap.adjoint A ∘L A‖ = ‖A‖ * ‖A‖ := by + refine' le_antisymm _ _ + · calc + ‖A† ∘L A‖ ≤ ‖A†‖ * ‖A‖ := op_norm_comp_le _ _ + _ = ‖A‖ * ‖A‖ := by rw [LinearIsometryEquiv.norm_map] + · rw [← sq, ← Real.sqrt_le_sqrt_iff (norm_nonneg _), Real.sqrt_sq (norm_nonneg _)] + refine' op_norm_le_bound _ (Real.sqrt_nonneg _) fun x => _ + have := calc - ‖A x‖ = Real.sqrt (re ⟪(A† * A) x, x⟫) := by rw [apply_norm_eq_sqrt_inner_adjoint_left] - _ ≤ Real.sqrt (‖A† * A‖ * ‖x‖ * ‖x‖) := (Real.sqrt_le_sqrt this) - _ = Real.sqrt ‖A† * A‖ * ‖x‖ := by - simp_rw [mul_assoc, Real.sqrt_mul (norm_nonneg _) (‖x‖ * ‖x‖), - Real.sqrt_mul_self (norm_nonneg x)] ⟩ + re ⟪(A† ∘L A) x, x⟫ ≤ ‖(A† ∘L A) x‖ * ‖x‖ := re_inner_le_norm _ _ + _ ≤ ‖A† ∘L A‖ * ‖x‖ * ‖x‖ := mul_le_mul_of_nonneg_right (le_op_norm _ _) (norm_nonneg _) + calc + ‖A x‖ = Real.sqrt (re ⟪(A† ∘L A) x, x⟫) := by rw [apply_norm_eq_sqrt_inner_adjoint_left] + _ ≤ Real.sqrt (‖A† ∘L A‖ * ‖x‖ * ‖x‖) := (Real.sqrt_le_sqrt this) + _ = Real.sqrt ‖A† ∘L A‖ * ‖x‖ := by + simp_rw [mul_assoc, Real.sqrt_mul (norm_nonneg _) (‖x‖ * ‖x‖), + Real.sqrt_mul_self (norm_nonneg x)] + +instance : CstarRing (E →L[𝕜] E) where + norm_star_mul_self := norm_adjoint_comp_self _ theorem isAdjointPair_inner (A : E →L[𝕜] F) : LinearMap.IsAdjointPair (sesqFormOfInner : E →ₗ[𝕜] E →ₗ⋆[𝕜] 𝕜) @@ -505,20 +506,44 @@ theorem im_inner_adjoint_mul_self_eq_zero (T : E →ₗ[𝕜] E) (x : E) : end LinearMap -namespace Matrix +section Matrix + +open Matrix LinearMap variable {m n : Type*} [Fintype m] [DecidableEq m] [Fintype n] [DecidableEq n] +variable [FiniteDimensional 𝕜 E] [FiniteDimensional 𝕜 F] +variable (v₁ : OrthonormalBasis n 𝕜 E) (v₂ : OrthonormalBasis m 𝕜 F) + +/-- The linear map associated to the conjugate transpose of a matrix corresponding to two +orthonormal bases is the adjoint of the linear map associated to the matrix. -/ +lemma Matrix.toLin_conjTranspose (A : Matrix m n 𝕜) : + toLin v₂.toBasis v₁.toBasis Aᴴ = adjoint (toLin v₁.toBasis v₂.toBasis A) := by + refine eq_adjoint_iff_basis v₂.toBasis v₁.toBasis _ _ |>.mpr fun i j ↦ ?_ + simp_rw [toLin_self] + simp [sum_inner, inner_smul_left, inner_sum, inner_smul_right, + orthonormal_iff_ite.mp v₁.orthonormal, orthonormal_iff_ite.mp v₂.orthonormal] + +/-- The matrix associated to the adjoint of a linear map corresponding to two orthonormal bases +is the conjugate tranpose of the matrix associated to the linear map. -/ +lemma LinearMap.toMatrix_adjoint (f : E →ₗ[𝕜] F) : + toMatrix v₂.toBasis v₁.toBasis (adjoint f) = (toMatrix v₁.toBasis v₂.toBasis f)ᴴ := + toLin v₂.toBasis v₁.toBasis |>.injective <| by simp [toLin_conjTranspose] + +/-- The star algebra equivalence between the linear endomorphisms of finite-dimensional inner +product space and square matrices induced by the choice of an orthonormal basis. -/ +@[simps] +def LinearMap.toMatrixOrthonormal : (E →ₗ[𝕜] E) ≃⋆ₐ[𝕜] Matrix n n 𝕜 := + { LinearMap.toMatrix v₁.toBasis v₁.toBasis with + map_mul' := LinearMap.toMatrix_mul v₁.toBasis + map_star' := LinearMap.toMatrix_adjoint v₁ v₁ } open scoped ComplexConjugate /-- The adjoint of the linear map associated to a matrix is the linear map associated to the conjugate transpose of that matrix. -/ -theorem toEuclideanLin_conjTranspose_eq_adjoint (A : Matrix m n 𝕜) : - Matrix.toEuclideanLin A.conjTranspose = LinearMap.adjoint (Matrix.toEuclideanLin A) := by - rw [LinearMap.eq_adjoint_iff] - intro x y - simp_rw [EuclideanSpace.inner_eq_star_dotProduct, piLp_equiv_toEuclideanLin, toLin'_apply, - star_mulVec, conjTranspose_conjTranspose, dotProduct_mulVec] +theorem Matrix.toEuclideanLin_conjTranspose_eq_adjoint (A : Matrix m n 𝕜) : + Matrix.toEuclideanLin A.conjTranspose = LinearMap.adjoint (Matrix.toEuclideanLin A) := + A.toLin_conjTranspose (EuclideanSpace.basisFun n 𝕜) (EuclideanSpace.basisFun m 𝕜) #align matrix.to_euclidean_lin_conj_transpose_eq_adjoint Matrix.toEuclideanLin_conjTranspose_eq_adjoint end Matrix diff --git a/Mathlib/Analysis/InnerProductSpace/Basic.lean b/Mathlib/Analysis/InnerProductSpace/Basic.lean index 15dea535bc5e5..146c8d2f1e557 100644 --- a/Mathlib/Analysis/InnerProductSpace/Basic.lean +++ b/Mathlib/Analysis/InnerProductSpace/Basic.lean @@ -8,7 +8,7 @@ import Mathlib.Analysis.Complex.Basic import Mathlib.Analysis.Convex.Uniform import Mathlib.Analysis.NormedSpace.Completion import Mathlib.Analysis.NormedSpace.BoundedLinearMaps -import Mathlib.LinearAlgebra.BilinearForm.Orthogonal +import Mathlib.LinearAlgebra.BilinearForm.Basic #align_import analysis.inner_product_space.basic from "leanprover-community/mathlib"@"3f655f5297b030a87d641ad4e825af8d9679eb0b" @@ -81,11 +81,8 @@ class Inner (𝕜 E : Type*) where export Inner (inner) -/-- The inner product with values in `ℝ`. -/ -notation "⟪" x ", " y "⟫_ℝ" => @inner ℝ _ _ x y - -/-- The inner product with values in `ℂ`. -/ -notation "⟪" x ", " y "⟫_ℂ" => @inner ℂ _ _ x y +/-- The inner product with values in `𝕜`. -/ +notation3:max "⟪" x ", " y "⟫_" 𝕜:max => @inner 𝕜 _ _ x y section Notations @@ -317,8 +314,7 @@ theorem cauchy_schwarz_aux (x y : F) : rw [← @ofReal_inj 𝕜, ofReal_normSq_eq_inner_self] simp only [inner_sub_sub_self, inner_smul_left, inner_smul_right, conj_ofReal, mul_sub, ← ofReal_normSq_eq_inner_self x, ← ofReal_normSq_eq_inner_self y] - rw [← mul_assoc, mul_conj, IsROrC.conj_mul, normSq_eq_def', mul_left_comm, ← inner_conj_symm y, - mul_conj, normSq_eq_def'] + rw [← mul_assoc, mul_conj, IsROrC.conj_mul, mul_left_comm, ← inner_conj_symm y, mul_conj] push_cast ring #align inner_product_space.core.cauchy_schwarz_aux InnerProductSpace.Core.cauchy_schwarz_aux @@ -389,9 +385,10 @@ attribute [local instance] toNormedAddCommGroup def toNormedSpace : NormedSpace 𝕜 F where norm_smul_le r x := by rw [norm_eq_sqrt_inner, inner_smul_left, inner_smul_right, ← mul_assoc] - rw [IsROrC.conj_mul, ofReal_mul_re, sqrt_mul, ← ofReal_normSq_eq_inner_self, ofReal_re] + rw [IsROrC.conj_mul, ← ofReal_pow, re_ofReal_mul, sqrt_mul, ← ofReal_normSq_eq_inner_self, + ofReal_re] · simp [sqrt_normSq_eq_norm, IsROrC.sqrt_normSq_eq_norm] - · exact normSq_nonneg r + · positivity #align inner_product_space.core.to_normed_space InnerProductSpace.Core.toNormedSpace end InnerProductSpace.Core @@ -1175,17 +1172,15 @@ theorem dist_div_norm_sq_smul {x y : F} (hx : x ≠ 0) (hy : y ≠ 0) (R : ℝ) have hy' : ‖y‖ ≠ 0 := norm_ne_zero_iff.2 hy calc dist ((R / ‖x‖) ^ 2 • x) ((R / ‖y‖) ^ 2 • y) = - sqrt (‖(R / ‖x‖) ^ 2 • x - (R / ‖y‖) ^ 2 • y‖ ^ 2) := - by rw [dist_eq_norm, sqrt_sq (norm_nonneg _)] + sqrt (‖(R / ‖x‖) ^ 2 • x - (R / ‖y‖) ^ 2 • y‖ ^ 2) := by + rw [dist_eq_norm, sqrt_sq (norm_nonneg _)] _ = sqrt ((R ^ 2 / (‖x‖ * ‖y‖)) ^ 2 * ‖x - y‖ ^ 2) := - (congr_arg sqrt <| by + congr_arg sqrt <| by field_simp [sq, norm_sub_mul_self_real, norm_smul, real_inner_smul_left, inner_smul_right, Real.norm_of_nonneg (mul_self_nonneg _)] - ring) + ring _ = R ^ 2 / (‖x‖ * ‖y‖) * dist x y := by - rw [sqrt_mul (sq_nonneg _), sqrt_sq (norm_nonneg _), - sqrt_sq (div_nonneg (sq_nonneg _) (mul_nonneg (norm_nonneg _) (norm_nonneg _))), - dist_eq_norm] + rw [sqrt_mul, sqrt_sq, sqrt_sq, dist_eq_norm] <;> positivity #align dist_div_norm_sq_smul dist_div_norm_sq_smul @@ -1529,8 +1524,7 @@ theorem norm_sub_eq_norm_add {v w : E} (h : ⟪v, w⟫ = 0) : ‖w - v‖ = ‖w norms, has absolute value at most 1. -/ theorem abs_real_inner_div_norm_mul_norm_le_one (x y : F) : |⟪x, y⟫_ℝ / (‖x‖ * ‖y‖)| ≤ 1 := by rw [abs_div, abs_mul, abs_norm, abs_norm] - exact div_le_one_of_le (abs_real_inner_le_norm x y) (mul_nonneg (norm_nonneg _) (norm_nonneg _)) - -- porting note: was `(by positivity)` + exact div_le_one_of_le (abs_real_inner_le_norm x y) (by positivity) #align abs_real_inner_div_norm_mul_norm_le_one abs_real_inner_div_norm_mul_norm_le_one /-- The inner product of a vector with a multiple of itself. -/ @@ -1589,8 +1583,8 @@ theorem norm_inner_eq_norm_tfae (x y : E) : tfae_have 1 → 2 · refine' fun h => or_iff_not_imp_left.2 fun hx₀ => _ have : ‖x‖ ^ 2 ≠ 0 := pow_ne_zero _ (norm_ne_zero_iff.2 hx₀) - rw [← sq_eq_sq (norm_nonneg _) (mul_nonneg (norm_nonneg _) (norm_nonneg _)), mul_pow, ← - mul_right_inj' this, eq_comm, ← sub_eq_zero, ← mul_sub] at h + rw [← sq_eq_sq, mul_pow, ← mul_right_inj' this, eq_comm, ← sub_eq_zero, ← mul_sub] at h <;> + try positivity simp only [@norm_sq_eq_inner 𝕜] at h letI : InnerProductSpace.Core 𝕜 E := InnerProductSpace.toCore erw [← InnerProductSpace.Core.cauchy_schwarz_aux, InnerProductSpace.Core.normSq_eq_zero, @@ -1618,7 +1612,6 @@ theorem norm_inner_eq_norm_iff {x y : E} (hx₀ : x ≠ 0) (hy₀ : y ≠ 0) : _ ↔ ∃ r : 𝕜, r ≠ 0 ∧ y = r • x := ⟨fun ⟨r, h⟩ => ⟨r, fun hr₀ => hy₀ <| h.symm ▸ smul_eq_zero.2 <| Or.inl hr₀, h⟩, fun ⟨r, _hr₀, h⟩ => ⟨r, h⟩⟩ - #align norm_inner_eq_norm_iff norm_inner_eq_norm_iff /-- The inner product of two vectors, divided by the product of their @@ -1835,8 +1828,7 @@ theorem toSesqForm_apply_coe (f : E →L[𝕜] E') (x : E') : toSesqForm f x = ( #align continuous_linear_map.to_sesq_form_apply_coe ContinuousLinearMap.toSesqForm_apply_coe theorem toSesqForm_apply_norm_le {f : E →L[𝕜] E'} {v : E'} : ‖toSesqForm f v‖ ≤ ‖f‖ * ‖v‖ := by - refine' op_norm_le_bound _ (mul_nonneg (norm_nonneg _) (norm_nonneg _)) _ - intro x + refine op_norm_le_bound _ (by positivity) fun x ↦ ?_ have h₁ : ‖f x‖ ≤ ‖f‖ * ‖x‖ := le_op_norm _ _ have h₂ := @norm_inner_le_norm 𝕜 E' _ _ _ v (f x) calc @@ -1923,9 +1915,7 @@ end BesselsInequality /-- A field `𝕜` satisfying `IsROrC` is itself a `𝕜`-inner product space. -/ instance IsROrC.innerProductSpace : InnerProductSpace 𝕜 𝕜 where inner x y := conj x * y - norm_sq_eq_inner x := by - simp only [inner] - rw [mul_comm, mul_conj, ofReal_re, normSq_eq_def'] + norm_sq_eq_inner x := by simp only [inner, conj_mul, ← ofReal_pow, ofReal_re] conj_symm x y := by simp only [mul_comm, map_mul, starRingEnd_self_apply] add_left x y z := by simp only [add_mul, map_add] smul_left x y z := by simp only [mul_assoc, smul_eq_mul, map_mul] @@ -2208,7 +2198,7 @@ def InnerProductSpace.isROrCToReal : InnerProductSpace ℝ E := simp only [inner_add_left, map_add] smul_left := fun x y r => by change re ⟪(r : 𝕜) • x, y⟫ = r * re ⟪x, y⟫ - simp only [inner_smul_left, conj_ofReal, ofReal_mul_re] } + simp only [inner_smul_left, conj_ofReal, re_ofReal_mul] } #align inner_product_space.is_R_or_C_to_real InnerProductSpace.isROrCToReal variable {E} @@ -2305,7 +2295,7 @@ theorem ContinuousLinearMap.reApplyInnerSelf_continuous (T : E →L[𝕜] E) : theorem ContinuousLinearMap.reApplyInnerSelf_smul (T : E →L[𝕜] E) (x : E) {c : 𝕜} : T.reApplyInnerSelf (c • x) = ‖c‖ ^ 2 * T.reApplyInnerSelf x := by simp only [ContinuousLinearMap.map_smul, ContinuousLinearMap.reApplyInnerSelf_apply, - inner_smul_left, inner_smul_right, ← mul_assoc, mul_conj, normSq_eq_def', ← smul_re, + inner_smul_left, inner_smul_right, ← mul_assoc, mul_conj, ← ofReal_pow, ← smul_re, Algebra.smul_def (‖c‖ ^ 2) ⟪T x, x⟫, algebraMap_eq_ofReal] #align continuous_linear_map.re_apply_inner_self_smul ContinuousLinearMap.reApplyInnerSelf_smul diff --git a/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean b/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean index 2d46c65438741..1dc0281dde9a2 100644 --- a/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean +++ b/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean @@ -53,7 +53,7 @@ local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y and outputs a set of orthogonal vectors which have the same span. -/ noncomputable def gramSchmidt [IsWellOrder ι (· < ·)] (f : ι → E) (n : ι) : E := f n - ∑ i : Iio n, orthogonalProjection (𝕜 ∙ gramSchmidt f i) (f n) -termination_by _ n => n +termination_by n decreasing_by exact mem_Iio.1 i.2 #align gram_schmidt gramSchmidt @@ -152,7 +152,7 @@ theorem gramSchmidt_mem_span (f : ι → E) : let hkj : k < j := (Finset.mem_Iio.1 hk).trans_le hij exact smul_mem _ _ (span_mono (image_subset f <| Iic_subset_Iic.2 hkj.le) <| gramSchmidt_mem_span _ le_rfl) -termination_by _ => j +termination_by j => j decreasing_by exact hkj #align gram_schmidt_mem_span gramSchmidt_mem_span diff --git a/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean b/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean index 65671e3625264..31269923d7444 100644 --- a/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean +++ b/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean @@ -101,7 +101,7 @@ theorem range_eq_top (coercive : IsCoercive B) : range B♯ = ⊤ := by C * ‖w‖ * ‖w‖ ≤ B w w := coercivity w _ = ⟪B♯ w, w⟫_ℝ := (continuousLinearMapOfBilin_apply B w w).symm _ = 0 := mem_w_orthogonal _ ⟨w, rfl⟩ - · exact mul_nonneg (mul_nonneg C_pos.le (norm_nonneg w)) (norm_nonneg w) + · positivity exact inner_zero_left _ #align is_coercive.range_eq_top IsCoercive.range_eq_top diff --git a/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean b/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean index be45dcb7de0a1..1035d14eec1ee 100644 --- a/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean +++ b/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Moritz Doll -/ import Mathlib.Analysis.InnerProductSpace.Adjoint -import Mathlib.Topology.Algebra.Module.LinearPMap import Mathlib.Topology.Algebra.Module.Basic #align_import analysis.inner_product_space.linear_pmap from "leanprover-community/mathlib"@"8b981918a93bc45a8600de608cde7944a80d92b9" diff --git a/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean b/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean index b6cb618f07830..fb5ec636e58f4 100644 --- a/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean +++ b/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Zhouhang Zhou, Sébastien Gouëzel, Frédéric Dupuis -/ import Mathlib.Analysis.InnerProductSpace.Basic +import Mathlib.LinearAlgebra.BilinearForm.Orthogonal #align_import analysis.inner_product_space.orthogonal from "leanprover-community/mathlib"@"f0c8bf9245297a541f468be517f1bde6195105e9" diff --git a/Mathlib/Analysis/InnerProductSpace/PiL2.lean b/Mathlib/Analysis/InnerProductSpace/PiL2.lean index a2ad682841a9e..67f08bef29cd4 100644 --- a/Mathlib/Analysis/InnerProductSpace/PiL2.lean +++ b/Mathlib/Analysis/InnerProductSpace/PiL2.lean @@ -358,7 +358,7 @@ theorem repr_injective : -- Porting note: `CoeFun` → `FunLike` /-- `b i` is the `i`th basis vector. -/ -instance instFunLike : FunLike (OrthonormalBasis ι 𝕜 E) ι fun _ => E where +instance instFunLike : FunLike (OrthonormalBasis ι 𝕜 E) ι E where coe b i := by classical exact b.repr.symm (EuclideanSpace.single i (1 : 𝕜)) coe_injective' b b' h := repr_injective <| LinearIsometryEquiv.toLinearEquiv_injective <| LinearEquiv.symm_bijective.injective <| LinearEquiv.toLinearMap_injective <| by @@ -380,7 +380,7 @@ instance instFunLike : FunLike (OrthonormalBasis ι 𝕜 E) ι fun _ => E where theorem coe_ofRepr [DecidableEq ι] (e : E ≃ₗᵢ[𝕜] EuclideanSpace 𝕜 ι) : ⇑(OrthonormalBasis.ofRepr e) = fun i => e.symm (EuclideanSpace.single i (1 : 𝕜)) := by -- Porting note: simplified with `congr!` - dsimp only [FunLike.coe] + dsimp only [DFunLike.coe] funext congr! #align orthonormal_basis.coe_of_repr OrthonormalBasis.coe_ofRepr @@ -389,7 +389,7 @@ theorem coe_ofRepr [DecidableEq ι] (e : E ≃ₗᵢ[𝕜] EuclideanSpace 𝕜 protected theorem repr_symm_single [DecidableEq ι] (b : OrthonormalBasis ι 𝕜 E) (i : ι) : b.repr.symm (EuclideanSpace.single i (1 : 𝕜)) = b i := by -- Porting note: simplified with `congr!` - dsimp only [FunLike.coe] + dsimp only [DFunLike.coe] congr! #align orthonormal_basis.repr_symm_single OrthonormalBasis.repr_symm_single @@ -738,11 +738,10 @@ theorem OrthonormalBasis.toMatrix_orthonormalBasis_mem_unitary : unit length. -/ @[simp] theorem OrthonormalBasis.det_to_matrix_orthonormalBasis : ‖a.toBasis.det b‖ = 1 := by - have : (normSq (a.toBasis.det b) : 𝕜) = 1 := by - simpa [IsROrC.mul_conj] using - (Matrix.det_of_mem_unitary (a.toMatrix_orthonormalBasis_mem_unitary b)).2 + have := (Matrix.det_of_mem_unitary (a.toMatrix_orthonormalBasis_mem_unitary b)).2 + rw [star_def, IsROrC.mul_conj] at this norm_cast at this - rwa [← sqrt_normSq_eq_norm, sqrt_eq_one] + rwa [pow_eq_one_iff_of_nonneg (norm_nonneg _) two_ne_zero] at this #align orthonormal_basis.det_to_matrix_orthonormal_basis OrthonormalBasis.det_to_matrix_orthonormalBasis end @@ -1035,6 +1034,11 @@ theorem toEuclideanLin_eq_toLin : rfl #align matrix.to_euclidean_lin_eq_to_lin Matrix.toEuclideanLin_eq_toLin +open EuclideanSpace in +lemma toEuclideanLin_eq_toLin_orthonormal : + toEuclideanLin = toLin (basisFun n 𝕜).toBasis (basisFun m 𝕜).toBasis := + rfl + end Matrix local notation "⟪" x ", " y "⟫ₑ" => diff --git a/Mathlib/Analysis/InnerProductSpace/ProdL2.lean b/Mathlib/Analysis/InnerProductSpace/ProdL2.lean index 5d516f0c6577d..fa4917984c25b 100644 --- a/Mathlib/Analysis/InnerProductSpace/ProdL2.lean +++ b/Mathlib/Analysis/InnerProductSpace/ProdL2.lean @@ -3,8 +3,7 @@ Copyright (c) 2023 Moritz Doll. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Moritz Doll -/ - -import Mathlib.Analysis.InnerProductSpace.Projection +import Mathlib.Analysis.InnerProductSpace.Basic import Mathlib.Analysis.NormedSpace.ProdLp /-! diff --git a/Mathlib/Analysis/InnerProductSpace/Projection.lean b/Mathlib/Analysis/InnerProductSpace/Projection.lean index 9d301c71a6cf5..99a809497aa8e 100644 --- a/Mathlib/Analysis/InnerProductSpace/Projection.lean +++ b/Mathlib/Analysis/InnerProductSpace/Projection.lean @@ -60,7 +60,7 @@ variable [InnerProductSpace 𝕜 E] [InnerProductSpace ℝ F] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y -- mathport name: exprabsR -local notation "absR" => Abs.abs +local notation "absR" => abs /-! ### Orthogonal projection in inner product spaces -/ @@ -893,7 +893,7 @@ theorem orthogonalProjection_comp_subtypeL_eq_zero_iff {U V : Submodule 𝕜 E} [HasOrthogonalProjection U] : orthogonalProjection U ∘L V.subtypeL = 0 ↔ U ⟂ V := ⟨fun h u hu v hv => by convert orthogonalProjection_inner_eq_zero v u hu using 2 - have : orthogonalProjection U v = 0 := FunLike.congr_fun h (⟨_, hv⟩ : V) + have : orthogonalProjection U v = 0 := DFunLike.congr_fun h (⟨_, hv⟩ : V) rw [this, Submodule.coe_zero, sub_zero], Submodule.IsOrtho.orthogonalProjection_comp_subtypeL⟩ set_option linter.uppercaseLean3 false in #align orthogonal_projection_comp_subtypeL_eq_zero_iff orthogonalProjection_comp_subtypeL_eq_zero_iff diff --git a/Mathlib/Analysis/InnerProductSpace/Symmetric.lean b/Mathlib/Analysis/InnerProductSpace/Symmetric.lean index 68d8ca74fc847..d5b0182636b39 100644 --- a/Mathlib/Analysis/InnerProductSpace/Symmetric.lean +++ b/Mathlib/Analysis/InnerProductSpace/Symmetric.lean @@ -66,7 +66,7 @@ section Real /-- An operator `T` on an inner product space is symmetric if and only if it is `LinearMap.IsSelfAdjoint` with respect to the sesquilinear form given by the inner product. -/ theorem isSymmetric_iff_sesqForm (T : E →ₗ[𝕜] E) : - T.IsSymmetric ↔ @LinearMap.IsSelfAdjoint 𝕜 E _ _ _ (starRingEnd 𝕜) sesqFormOfInner T := + T.IsSymmetric ↔ LinearMap.IsSelfAdjoint (R := 𝕜) (M := E) sesqFormOfInner T := ⟨fun h x y => (h y x).symm, fun h x y => (h y x).symm⟩ #align linear_map.is_symmetric_iff_sesq_form LinearMap.isSymmetric_iff_sesqForm diff --git a/Mathlib/Analysis/InnerProductSpace/TwoDim.lean b/Mathlib/Analysis/InnerProductSpace/TwoDim.lean index 32a3c36a44303..088b2add56930 100644 --- a/Mathlib/Analysis/InnerProductSpace/TwoDim.lean +++ b/Mathlib/Analysis/InnerProductSpace/TwoDim.lean @@ -458,7 +458,7 @@ theorem nonneg_inner_and_areaForm_eq_zero_iff_sameRay (x y : E) : have hx' : 0 < ‖x‖ := by simpa using hx have ha' : 0 ≤ a := nonneg_of_mul_nonneg_left ha (by positivity) have hb' : b = 0 := eq_zero_of_ne_zero_of_mul_right_eq_zero (pow_ne_zero 2 hx'.ne') hb - simpa [hb'] using SameRay.sameRay_nonneg_smul_right x ha' + exact (SameRay.sameRay_nonneg_smul_right x ha').add_right $ by simp [hb'] · intro h obtain ⟨r, hr, rfl⟩ := h.exists_nonneg_left hx simp only [inner_smul_right, real_inner_self_eq_norm_sq, LinearMap.map_smulₛₗ, diff --git a/Mathlib/Analysis/InnerProductSpace/l2Space.lean b/Mathlib/Analysis/InnerProductSpace/l2Space.lean index 2b4a47b2e7dd9..2e721a0801bc0 100644 --- a/Mathlib/Analysis/InnerProductSpace/l2Space.lean +++ b/Mathlib/Analysis/InnerProductSpace/l2Space.lean @@ -415,16 +415,15 @@ instance {ι : Type*} : Inhabited (HilbertBasis ι 𝕜 ℓ²(ι, 𝕜)) := instance instCoeFun : CoeFun (HilbertBasis ι 𝕜 E) fun _ => ι → E where coe b i := b.repr.symm (lp.single 2 i (1 : 𝕜)) -@[simp] +-- This is a bad `@[simp]` lemma: the RHS is a coercion containing the LHS. protected theorem repr_symm_single (b : HilbertBasis ι 𝕜 E) (i : ι) : b.repr.symm (lp.single 2 i (1 : 𝕜)) = b i := rfl #align hilbert_basis.repr_symm_single HilbertBasis.repr_symm_single --- porting note: removed `@[simp]` because `simp` can prove this protected theorem repr_self (b : HilbertBasis ι 𝕜 E) (i : ι) : b.repr (b i) = lp.single 2 i (1 : 𝕜) := by - simp + simp only [LinearIsometryEquiv.apply_symm_apply] #align hilbert_basis.repr_self HilbertBasis.repr_self protected theorem repr_apply_apply (b : HilbertBasis ι 𝕜 E) (v : E) (i : ι) : diff --git a/Mathlib/Analysis/LocallyConvex/Basic.lean b/Mathlib/Analysis/LocallyConvex/Basic.lean index 0e34e934f5eb4..2b3631a7dcb31 100644 --- a/Mathlib/Analysis/LocallyConvex/Basic.lean +++ b/Mathlib/Analysis/LocallyConvex/Basic.lean @@ -6,6 +6,7 @@ Authors: Jean Lo, Bhavik Mehta, Yaël Dillies import Mathlib.Analysis.Convex.Basic import Mathlib.Analysis.Convex.Hull import Mathlib.Analysis.NormedSpace.Basic +import Mathlib.Topology.Bornology.Absorbs #align_import analysis.locally_convex.basic from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" @@ -51,106 +52,7 @@ variable [SeminormedRing 𝕜] section SMul -variable (𝕜) [SMul 𝕜 E] - -/-- A set `A` absorbs another set `B` if `B` is contained in all scalings of `A` by elements of -sufficiently large norm. -/ -def Absorbs (A B : Set E) := - ∃ r, 0 < r ∧ ∀ a : 𝕜, r ≤ ‖a‖ → B ⊆ a • A -#align absorbs Absorbs - -variable {𝕜} {s t u v A B : Set E} - -@[simp] -theorem absorbs_empty {s : Set E} : Absorbs 𝕜 s (∅ : Set E) := - ⟨1, one_pos, fun _a _ha => Set.empty_subset _⟩ -#align absorbs_empty absorbs_empty - -theorem Absorbs.mono (hs : Absorbs 𝕜 s u) (hst : s ⊆ t) (hvu : v ⊆ u) : Absorbs 𝕜 t v := - let ⟨r, hr, h⟩ := hs - ⟨r, hr, fun _a ha => hvu.trans <| (h _ ha).trans <| smul_set_mono hst⟩ -#align absorbs.mono Absorbs.mono - -theorem Absorbs.mono_left (hs : Absorbs 𝕜 s u) (h : s ⊆ t) : Absorbs 𝕜 t u := - hs.mono h Subset.rfl -#align absorbs.mono_left Absorbs.mono_left - -theorem Absorbs.mono_right (hs : Absorbs 𝕜 s u) (h : v ⊆ u) : Absorbs 𝕜 s v := - hs.mono Subset.rfl h -#align absorbs.mono_right Absorbs.mono_right - -theorem Absorbs.union (hu : Absorbs 𝕜 s u) (hv : Absorbs 𝕜 s v) : Absorbs 𝕜 s (u ∪ v) := by - obtain ⟨a, ha, hu⟩ := hu - obtain ⟨b, _hb, hv⟩ := hv - exact - ⟨max a b, lt_max_of_lt_left ha, fun c hc => - union_subset (hu _ <| le_of_max_le_left hc) (hv _ <| le_of_max_le_right hc)⟩ -#align absorbs.union Absorbs.union - -@[simp] -theorem absorbs_union : Absorbs 𝕜 s (u ∪ v) ↔ Absorbs 𝕜 s u ∧ Absorbs 𝕜 s v := - ⟨fun h => ⟨h.mono_right <| subset_union_left _ _, h.mono_right <| subset_union_right _ _⟩, - fun h => h.1.union h.2⟩ -#align absorbs_union absorbs_union - -theorem absorbs_iUnion_finset {ι : Type*} {t : Finset ι} {f : ι → Set E} : - Absorbs 𝕜 s (⋃ i ∈ t, f i) ↔ ∀ i ∈ t, Absorbs 𝕜 s (f i) := by - classical - induction' t using Finset.induction_on with i t _ht hi - · simp only [Finset.not_mem_empty, Set.iUnion_false, Set.iUnion_empty, absorbs_empty, - IsEmpty.forall_iff, imp_true_iff] - rw [Finset.set_biUnion_insert, absorbs_union, hi] - constructor <;> intro h - · refine' fun _ hi' => (Finset.mem_insert.mp hi').elim _ (h.2 _) - exact fun hi'' => by - rw [hi''] - exact h.1 - exact ⟨h i (Finset.mem_insert_self i t), fun i' hi' => h i' (Finset.mem_insert_of_mem hi')⟩ -#align absorbs_Union_finset absorbs_iUnion_finset - -theorem Set.Finite.absorbs_iUnion {ι : Type*} {s : Set E} {t : Set ι} {f : ι → Set E} - (hi : t.Finite) : Absorbs 𝕜 s (⋃ i ∈ t, f i) ↔ ∀ i ∈ t, Absorbs 𝕜 s (f i) := by - lift t to Finset ι using hi - simp only [Finset.mem_coe] - exact absorbs_iUnion_finset -#align set.finite.absorbs_Union Set.Finite.absorbs_iUnion - -variable (𝕜) - -/-- A set is absorbent if it absorbs every singleton. -/ -def Absorbent (A : Set E) := - ∀ x, ∃ r, 0 < r ∧ ∀ a : 𝕜, r ≤ ‖a‖ → x ∈ a • A -#align absorbent Absorbent - -variable {𝕜} - -theorem Absorbent.subset (hA : Absorbent 𝕜 A) (hAB : A ⊆ B) : Absorbent 𝕜 B := by - refine' forall_imp (fun x => _) hA - exact Exists.imp fun r => And.imp_right <| forall₂_imp fun a _ha hx => Set.smul_set_mono hAB hx -#align absorbent.subset Absorbent.subset - -theorem absorbent_iff_forall_absorbs_singleton : Absorbent 𝕜 A ↔ ∀ x, Absorbs 𝕜 A {x} := by - simp_rw [Absorbs, Absorbent, singleton_subset_iff] -#align absorbent_iff_forall_absorbs_singleton absorbent_iff_forall_absorbs_singleton - -theorem Absorbent.absorbs (hs : Absorbent 𝕜 s) {x : E} : Absorbs 𝕜 s {x} := - absorbent_iff_forall_absorbs_singleton.1 hs _ -#align absorbent.absorbs Absorbent.absorbs - -theorem absorbent_iff_nonneg_lt : - Absorbent 𝕜 A ↔ ∀ x, ∃ r, 0 ≤ r ∧ ∀ ⦃a : 𝕜⦄, r < ‖a‖ → x ∈ a • A := - forall_congr' fun _x => - ⟨fun ⟨r, hr, hx⟩ => ⟨r, hr.le, fun a ha => hx a ha.le⟩, fun ⟨r, hr, hx⟩ => - ⟨r + 1, add_pos_of_nonneg_of_pos hr zero_lt_one, fun _a ha => - hx ((lt_add_of_pos_right r zero_lt_one).trans_le ha)⟩⟩ -#align absorbent_iff_nonneg_lt absorbent_iff_nonneg_lt - -theorem Absorbent.absorbs_finite {s : Set E} (hs : Absorbent 𝕜 s) {v : Set E} (hv : v.Finite) : - Absorbs 𝕜 s v := by - rw [← Set.biUnion_of_singleton v] - exact hv.absorbs_iUnion.mpr fun _ _ => hs.absorbs -#align absorbent.absorbs_finite Absorbent.absorbs_finite - +variable [SMul 𝕜 E] {s t u v A B : Set E} variable (𝕜) /-- A set `A` is balanced if `a • A` is contained in `A` whenever `a` has norm at most `1`. -/ @@ -160,6 +62,15 @@ def Balanced (A : Set E) := variable {𝕜} +lemma absorbs_iff_norm : Absorbs 𝕜 A B ↔ ∃ r, ∀ c : 𝕜, r ≤ ‖c‖ → B ⊆ c • A := + Filter.atTop_basis.cobounded_of_norm.eventually_iff.trans <| by simp only [true_and]; rfl + +alias ⟨_, Absorbs.of_norm⟩ := absorbs_iff_norm + +lemma Absorbs.exists_pos (h : Absorbs 𝕜 A B) : ∃ r > 0, ∀ c : 𝕜, r ≤ ‖c‖ → B ⊆ c • A := + let ⟨r, hr₁, hr⟩ := (Filter.atTop_basis' 1).cobounded_of_norm.eventually_iff.1 h + ⟨r, one_pos.trans_le hr₁, hr⟩ + theorem balanced_iff_smul_mem : Balanced 𝕜 s ↔ ∀ ⦃a : 𝕜⦄, ‖a‖ ≤ 1 → ∀ ⦃x : E⦄, x ∈ s → a • x ∈ s := forall₂_congr fun _a _ha => smul_set_subset_iff #align balanced_iff_smul_mem balanced_iff_smul_mem @@ -213,32 +124,14 @@ section Module variable [AddCommGroup E] [Module 𝕜 E] {s s₁ s₂ t t₁ t₂ : Set E} -theorem Absorbs.neg : Absorbs 𝕜 s t → Absorbs 𝕜 (-s) (-t) := - Exists.imp fun _r => - And.imp_right <| forall₂_imp fun _ _ h => (neg_subset_neg.2 h).trans (smul_set_neg _ _).superset -#align absorbs.neg Absorbs.neg - theorem Balanced.neg : Balanced 𝕜 s → Balanced 𝕜 (-s) := forall₂_imp fun _ _ h => (smul_set_neg _ _).subset.trans <| neg_subset_neg.2 h #align balanced.neg Balanced.neg -theorem Absorbs.add : Absorbs 𝕜 s₁ t₁ → Absorbs 𝕜 s₂ t₂ → Absorbs 𝕜 (s₁ + s₂) (t₁ + t₂) := - fun ⟨r₁, hr₁, h₁⟩ ⟨r₂, _hr₂, h₂⟩ => - ⟨max r₁ r₂, lt_max_of_lt_left hr₁, fun _a ha => - (add_subset_add (h₁ _ <| le_of_max_le_left ha) <| h₂ _ <| le_of_max_le_right ha).trans - (smul_add _ _ _).superset⟩ -#align absorbs.add Absorbs.add - theorem Balanced.add (hs : Balanced 𝕜 s) (ht : Balanced 𝕜 t) : Balanced 𝕜 (s + t) := fun _a ha => (smul_add _ _ _).subset.trans <| add_subset_add (hs _ ha) <| ht _ ha #align balanced.add Balanced.add -theorem Absorbs.sub (h₁ : Absorbs 𝕜 s₁ t₁) (h₂ : Absorbs 𝕜 s₂ t₂) : - Absorbs 𝕜 (s₁ - s₂) (t₁ - t₂) := by - simp_rw [sub_eq_add_neg] - exact h₁.add h₂.neg -#align absorbs.sub Absorbs.sub - theorem Balanced.sub (hs : Balanced 𝕜 s) (ht : Balanced 𝕜 t) : Balanced 𝕜 (s - t) := by simp_rw [sub_eq_add_neg] exact hs.add ht.neg @@ -272,28 +165,19 @@ theorem Balanced.smul_mono (hs : Balanced 𝕝 s) {a : 𝕝} {b : 𝕜} (h : ‖ exact div_le_one_of_le h (norm_nonneg _) #align balanced.smul_mono Balanced.smul_mono -/-- A balanced set absorbs itself. -/ -theorem Balanced.absorbs_self (hA : Balanced 𝕜 A) : Absorbs 𝕜 A A := by - refine' ⟨1, zero_lt_one, fun a ha x hx => _⟩ - rw [mem_smul_set_iff_inv_smul_mem₀ (norm_pos_iff.1 <| zero_lt_one.trans_le ha)] - refine' hA a⁻¹ _ (smul_mem_smul_set hx) - rw [norm_inv] - exact inv_le_one ha -#align balanced.absorbs_self Balanced.absorbs_self - theorem Balanced.subset_smul (hA : Balanced 𝕜 A) (ha : 1 ≤ ‖a‖) : A ⊆ a • A := by - refine' (subset_set_smul_iff₀ _).2 (hA a⁻¹ _) - · rintro rfl - rw [norm_zero] at ha - exact zero_lt_one.not_le ha - · rw [norm_inv] - exact inv_le_one ha + rw [← @norm_one 𝕜] at ha; simpa using hA.smul_mono ha #align balanced.subset_smul Balanced.subset_smul theorem Balanced.smul_eq (hA : Balanced 𝕜 A) (ha : ‖a‖ = 1) : a • A = A := (hA _ ha.le).antisymm <| hA.subset_smul ha.ge #align balanced.smul_eq Balanced.smul_eq +/-- A balanced set absorbs itself. -/ +theorem Balanced.absorbs_self (hA : Balanced 𝕜 A) : Absorbs 𝕜 A A := + .of_norm ⟨1, fun _ => hA.subset_smul⟩ +#align balanced.absorbs_self Balanced.absorbs_self + theorem Balanced.mem_smul_iff (hs : Balanced 𝕜 s) (h : ‖a‖ = ‖b‖) : a • x ∈ s ↔ b • x ∈ s := by obtain rfl | hb := eq_or_ne b 0 · rw [norm_zero, norm_eq_zero] at h @@ -311,44 +195,12 @@ theorem Balanced.neg_mem_iff (hs : Balanced 𝕜 s) : -x ∈ s ↔ x ∈ s := by simp only [neg_smul, one_smul 𝕜 x] #align balanced.neg_mem_iff Balanced.neg_mem_iff -theorem Absorbs.inter (hs : Absorbs 𝕜 s u) (ht : Absorbs 𝕜 t u) : Absorbs 𝕜 (s ∩ t) u := by - obtain ⟨a, ha, hs⟩ := hs - obtain ⟨b, _hb, ht⟩ := ht - have h : 0 < max a b := lt_max_of_lt_left ha - refine' ⟨max a b, lt_max_of_lt_left ha, fun c hc => _⟩ - rw [smul_set_inter₀ (norm_pos_iff.1 <| h.trans_le hc)] - exact subset_inter (hs _ <| le_of_max_le_left hc) (ht _ <| le_of_max_le_right hc) -#align absorbs.inter Absorbs.inter - -@[simp] -theorem absorbs_inter : Absorbs 𝕜 (s ∩ t) u ↔ Absorbs 𝕜 s u ∧ Absorbs 𝕜 t u := - ⟨fun h => ⟨h.mono_left <| inter_subset_left _ _, h.mono_left <| inter_subset_right _ _⟩, fun h => - h.1.inter h.2⟩ -#align absorbs_inter absorbs_inter - -theorem absorbent_univ : Absorbent 𝕜 (univ : Set E) := by - refine' fun x => ⟨1, zero_lt_one, fun a ha => _⟩ - rw [smul_set_univ₀ (norm_pos_iff.1 <| zero_lt_one.trans_le ha)] - exact trivial -#align absorbent_univ absorbent_univ - variable [TopologicalSpace E] [ContinuousSMul 𝕜 E] /-- Every neighbourhood of the origin is absorbent. -/ -theorem absorbent_nhds_zero (hA : A ∈ 𝓝 (0 : E)) : Absorbent 𝕜 A := by - intro x - obtain ⟨w, hw₁, hw₂, hw₃⟩ := mem_nhds_iff.mp hA - have hc : Continuous fun t : 𝕜 => t • x := continuous_id.smul continuous_const - obtain ⟨r, hr₁, hr₂⟩ := - Metric.isOpen_iff.mp (hw₂.preimage hc) 0 (by rwa [mem_preimage, zero_smul]) - have hr₃ := inv_pos.mpr (half_pos hr₁) - refine' ⟨(r / 2)⁻¹, hr₃, fun a ha₁ => _⟩ - have ha₂ : 0 < ‖a‖ := hr₃.trans_le ha₁ - refine' (mem_smul_set_iff_inv_smul_mem₀ (norm_pos_iff.mp ha₂) _ _).2 (hw₁ <| hr₂ _) - rw [Metric.mem_ball, dist_zero_right, norm_inv] - calc - ‖a‖⁻¹ ≤ r / 2 := (inv_le (half_pos hr₁) ha₂).mp ha₁ - _ < r := half_lt_self hr₁ +theorem absorbent_nhds_zero (hA : A ∈ 𝓝 (0 : E)) : Absorbent 𝕜 A := + absorbent_iff_inv_smul.2 fun x ↦ Filter.tendsto_inv₀_cobounded.smul tendsto_const_nhds <| by + rwa [zero_smul] #align absorbent_nhds_zero absorbent_nhds_zero /-- The union of `{0}` with the interior of a balanced set is balanced. -/ @@ -385,18 +237,7 @@ section NontriviallyNormedField variable [NontriviallyNormedField 𝕜] [AddCommGroup E] [Module 𝕜 E] {s : Set E} -theorem absorbs_zero_iff : Absorbs 𝕜 s 0 ↔ (0 : E) ∈ s := by - refine' ⟨_, fun h => ⟨1, zero_lt_one, fun a _ => zero_subset.2 <| zero_mem_smul_set h⟩⟩ - rintro ⟨r, hr, h⟩ - obtain ⟨a, ha⟩ := NormedSpace.exists_lt_norm 𝕜 𝕜 r - have := h _ ha.le - rwa [zero_subset, zero_mem_smul_set_iff] at this - exact norm_ne_zero_iff.1 (hr.trans ha).ne' -#align absorbs_zero_iff absorbs_zero_iff - -theorem Absorbent.zero_mem (hs : Absorbent 𝕜 s) : (0 : E) ∈ s := - absorbs_zero_iff.1 <| absorbent_iff_forall_absorbs_singleton.1 hs _ -#align absorbent.zero_mem Absorbent.zero_mem +theorem Absorbent.zero_mem' (hs : Absorbent 𝕜 s) : (0 : E) ∈ s := hs.zero_mem variable [Module ℝ E] [SMulCommClass ℝ 𝕜 E] @@ -420,9 +261,8 @@ theorem balanced_iff_neg_mem (hs : Convex ℝ s) : Balanced ℝ s ↔ ∀ ⦃x refine' ⟨fun h x => h.neg_mem_iff.2, fun h a ha => smul_set_subset_iff.2 fun x hx => _⟩ rw [Real.norm_eq_abs, abs_le] at ha rw [show a = -((1 - a) / 2) + (a - -1) / 2 by ring, add_smul, neg_smul, ← smul_neg] - exact - hs (h hx) hx (div_nonneg (sub_nonneg_of_le ha.2) zero_le_two) - (div_nonneg (sub_nonneg_of_le ha.1) zero_le_two) (by ring) + exact hs (h hx) hx (div_nonneg (sub_nonneg_of_le ha.2) zero_le_two) + (div_nonneg (sub_nonneg_of_le ha.1) zero_le_two) (by ring) #align balanced_iff_neg_mem balanced_iff_neg_mem end Real diff --git a/Mathlib/Analysis/LocallyConvex/Bounded.lean b/Mathlib/Analysis/LocallyConvex/Bounded.lean index eaf0b967764dd..31e543399cd31 100644 --- a/Mathlib/Analysis/LocallyConvex/Bounded.lean +++ b/Mathlib/Analysis/LocallyConvex/Bounded.lean @@ -69,7 +69,7 @@ def IsVonNBounded (s : Set E) : Prop := variable (E) @[simp] -theorem isVonNBounded_empty : IsVonNBounded 𝕜 (∅ : Set E) := fun _ _ => absorbs_empty +theorem isVonNBounded_empty : IsVonNBounded 𝕜 (∅ : Set E) := fun _ _ => Absorbs.empty #align bornology.is_vonN_bounded_empty Bornology.isVonNBounded_empty variable {𝕜 E} @@ -78,12 +78,15 @@ theorem isVonNBounded_iff (s : Set E) : IsVonNBounded 𝕜 s ↔ ∀ V ∈ 𝓝 Iff.rfl #align bornology.is_vonN_bounded_iff Bornology.isVonNBounded_iff -theorem _root_.Filter.HasBasis.isVonNBounded_basis_iff {q : ι → Prop} {s : ι → Set E} {A : Set E} +theorem _root_.Filter.HasBasis.isVonNBounded_iff {q : ι → Prop} {s : ι → Set E} {A : Set E} (h : (𝓝 (0 : E)).HasBasis q s) : IsVonNBounded 𝕜 A ↔ ∀ i, q i → Absorbs 𝕜 (s i) A := by refine' ⟨fun hA i hi => hA (h.mem_of_mem hi), fun hA V hV => _⟩ rcases h.mem_iff.mp hV with ⟨i, hi, hV⟩ exact (hA i hi).mono_left hV -#align filter.has_basis.is_vonN_bounded_basis_iff Filter.HasBasis.isVonNBounded_basis_iff +#align filter.has_basis.is_vonN_bounded_basis_iff Filter.HasBasis.isVonNBounded_iff + +@[deprecated] -- since 12 January 2024 +alias _root_.Filter.HasBasis.isVonNBounded_basis_iff := Filter.HasBasis.isVonNBounded_iff /-- Subsets of bounded sets are bounded. -/ theorem IsVonNBounded.subset {s₁ s₂ : Set E} (h : s₁ ⊆ s₂) (hs₂ : IsVonNBounded 𝕜 s₂) : @@ -126,8 +129,8 @@ theorem IsVonNBounded.image {σ : 𝕜₁ →+* 𝕜₂} [RingHomSurjective σ] have f_tendsto_zero := f.continuous.tendsto 0 rw [map_zero] at f_tendsto_zero intro V hV - rcases hs (f_tendsto_zero hV) with ⟨r, hrpos, hr⟩ - refine' ⟨r, hrpos, fun a ha => _⟩ + rcases (hs (f_tendsto_zero hV)).exists_pos with ⟨r, hrpos, hr⟩ + refine' .of_norm ⟨r, fun a ha => _⟩ rw [← σ'.apply_symm_apply a] have hanz : a ≠ 0 := norm_pos_iff.mp (hrpos.trans_le ha) have : σ'.symm a ≠ 0 := (map_ne_zero σ'.symm.toRingHom).mpr hanz @@ -149,7 +152,7 @@ theorem IsVonNBounded.smul_tendsto_zero {S : Set E} {ε : ι → 𝕜} {x : ι Tendsto (ε • x) l (𝓝 0) := by rw [tendsto_def] at * intro V hV - rcases hS hV with ⟨r, r_pos, hrS⟩ + rcases (hS hV).exists_pos with ⟨r, r_pos, hrS⟩ filter_upwards [hxS, hε _ (Metric.ball_mem_nhds 0 <| inv_pos.mpr r_pos)] with n hnS hnr by_cases hε : ε n = 0 · simp [hε, mem_of_mem_nhds hV] @@ -161,14 +164,14 @@ theorem IsVonNBounded.smul_tendsto_zero {S : Set E} {ε : ι → 𝕜} {x : ι theorem isVonNBounded_of_smul_tendsto_zero {ε : ι → 𝕝} {l : Filter ι} [l.NeBot] (hε : ∀ᶠ n in l, ε n ≠ 0) {S : Set E} (H : ∀ x : ι → E, (∀ n, x n ∈ S) → Tendsto (ε • x) l (𝓝 0)) : IsVonNBounded 𝕝 S := by - rw [(nhds_basis_balanced 𝕝 E).isVonNBounded_basis_iff] + rw [(nhds_basis_balanced 𝕝 E).isVonNBounded_iff] by_contra! H' rcases H' with ⟨V, ⟨hV, hVb⟩, hVS⟩ have : ∀ᶠ n in l, ∃ x : S, ε n • (x : E) ∉ V := by filter_upwards [hε] with n hn - rw [Absorbs] at hVS + rw [absorbs_iff_norm] at hVS push_neg at hVS - rcases hVS _ (norm_pos_iff.mpr <| inv_ne_zero hn) with ⟨a, haε, haS⟩ + rcases hVS ‖(ε n)⁻¹‖ with ⟨a, haε, haS⟩ rcases Set.not_subset.mp haS with ⟨x, hxS, hx⟩ refine' ⟨⟨x, hxS⟩, fun hnx => _⟩ rw [← Set.mem_inv_smul_set_iff₀ hn] at hnx @@ -251,13 +254,13 @@ theorem TotallyBounded.isVonNBounded {s : Set E} (hs : TotallyBounded s) : simp_rw [← nhds_prod_eq, id.def] at h' rcases h.basis_left h' U hU with ⟨x, hx, h''⟩ rcases hs x.snd hx.2.1 with ⟨t, ht, hs⟩ - refine' Absorbs.mono_right _ hs - rw [ht.absorbs_iUnion] + refine Absorbs.mono_right ?_ hs + rw [ht.absorbs_biUnion] have hx_fstsnd : x.fst + x.snd ⊆ U := add_subset_iff.mpr fun z1 hz1 z2 hz2 ↦ h'' <| mk_mem_prod hz1 hz2 - refine' fun y _ => Absorbs.mono_left _ hx_fstsnd - rw [← Set.singleton_vadd, vadd_eq_add] - exact (absorbent_nhds_zero hx.1.1).absorbs.add hx.2.2.absorbs_self + refine fun y _ => Absorbs.mono_left ?_ hx_fstsnd + -- TODO: with dot notation, Lean timeouts on the next line. Why? + exact Absorbent.vadd_absorbs (absorbent_nhds_zero hx.1.1) hx.2.2.absorbs_self #align totally_bounded.is_vonN_bounded TotallyBounded.isVonNBounded end UniformAddGroup @@ -269,7 +272,7 @@ variable (𝕜 E) [NontriviallyNormedField 𝕜] [SeminormedAddCommGroup E] [Nor namespace NormedSpace theorem isVonNBounded_ball (r : ℝ) : Bornology.IsVonNBounded 𝕜 (Metric.ball (0 : E) r) := by - rw [Metric.nhds_basis_ball.isVonNBounded_basis_iff, ← ball_normSeminorm 𝕜 E] + rw [Metric.nhds_basis_ball.isVonNBounded_iff, ← ball_normSeminorm 𝕜 E] exact fun ε hε => (normSeminorm 𝕜 E).ball_zero_absorbs_ball_zero hε #align normed_space.is_vonN_bounded_ball NormedSpace.isVonNBounded_ball @@ -282,7 +285,7 @@ theorem isVonNBounded_iff (s : Set E) : Bornology.IsVonNBounded 𝕜 s ↔ Borno rw [Metric.isBounded_iff_subset_closedBall (0 : E)] constructor · intro h - rcases h (Metric.ball_mem_nhds 0 zero_lt_one) with ⟨ρ, hρ, hρball⟩ + rcases (h (Metric.ball_mem_nhds 0 zero_lt_one)).exists_pos with ⟨ρ, hρ, hρball⟩ rcases NormedField.exists_lt_norm 𝕜 ρ with ⟨a, ha⟩ specialize hρball a ha.le rw [← ball_normSeminorm 𝕜 E, Seminorm.smul_ball_zero (norm_pos_iff.1 <| hρ.trans ha), @@ -315,7 +318,7 @@ theorem isBounded_iff_subset_smul_ball {s : Set E} : rw [← isVonNBounded_iff 𝕜] constructor · intro h - rcases h (Metric.ball_mem_nhds 0 zero_lt_one) with ⟨ρ, _, hρball⟩ + rcases (h (Metric.ball_mem_nhds 0 zero_lt_one)).exists_pos with ⟨ρ, _, hρball⟩ rcases NormedField.exists_lt_norm 𝕜 ρ with ⟨a, ha⟩ exact ⟨a, hρball a ha.le⟩ · rintro ⟨a, ha⟩ diff --git a/Mathlib/Analysis/LocallyConvex/ContinuousOfBounded.lean b/Mathlib/Analysis/LocallyConvex/ContinuousOfBounded.lean index 307f82fe49f7c..0189e201f47c8 100644 --- a/Mathlib/Analysis/LocallyConvex/ContinuousOfBounded.lean +++ b/Mathlib/Analysis/LocallyConvex/ContinuousOfBounded.lean @@ -52,7 +52,7 @@ def LinearMap.clmOfExistsBoundedImage (f : E →ₗ[𝕜] F) intro U hU -- Continuity means that `U ∈ 𝓝 0` implies that `f ⁻¹' U ∈ 𝓝 0`. rcases h with ⟨V, hV, h⟩ - rcases h hU with ⟨r, hr, h⟩ + rcases (h hU).exists_pos with ⟨r, hr, h⟩ rcases NormedField.exists_lt_norm 𝕜 r with ⟨x, hx⟩ specialize h x hx.le -- After unfolding all the definitions, we know that `f '' V ⊆ x • U`. We use this to show the @@ -152,8 +152,8 @@ theorem LinearMap.continuousAt_zero_of_locally_bounded (f : E →ₛₗ[σ] F) -- The image `(fun n ↦ n • u n)` is von Neumann bounded: have h_bounded : IsVonNBounded 𝕜 (Set.range fun n : ℕ => (n : 𝕜) • u n) := h_tendsto.cauchySeq.totallyBounded_range.isVonNBounded 𝕜 - -- Since `range u` is bounded it absorbs `V` - rcases hf _ h_bounded hV with ⟨r, hr, h'⟩ + -- Since `range u` is bounded, `V` absorbs it + rcases (hf _ h_bounded hV).exists_pos with ⟨r, hr, h'⟩ cases' exists_nat_gt r with n hn -- We now find a contradiction between `f (u n) ∉ V` and the absorbing property have h1 : r ≤ ‖(n : 𝕜')‖ := by diff --git a/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean b/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean index 43d2de5b7bce1..3c1dddf95c9db 100644 --- a/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean +++ b/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean @@ -511,12 +511,12 @@ variable [TopologicalSpace E] theorem WithSeminorms.isVonNBounded_iff_finset_seminorm_bounded {s : Set E} (hp : WithSeminorms p) : Bornology.IsVonNBounded 𝕜 s ↔ ∀ I : Finset ι, ∃ r > 0, ∀ x ∈ s, I.sup p x < r := by - rw [hp.hasBasis.isVonNBounded_basis_iff] + rw [hp.hasBasis.isVonNBounded_iff] constructor · intro h I simp only [id.def] at h specialize h ((I.sup p).ball 0 1) (p.basisSets_mem I zero_lt_one) - rcases h with ⟨r, hr, h⟩ + rcases h.exists_pos with ⟨r, hr, h⟩ cases' NormedField.exists_lt_norm 𝕜 r with a ha specialize h a (le_of_lt ha) rw [Seminorm.smul_ball_zero (norm_pos_iff.1 <| hr.trans ha), mul_one] at h @@ -802,7 +802,7 @@ variable [NontriviallyNormedField 𝕜] [AddCommGroup E] [Module 𝕜 E] lemma map_eq_zero_of_norm_zero (q : Seminorm 𝕜 F) (hq : Continuous q) {x : F} (hx : ‖x‖ = 0) : q x = 0 := (map_zero q) ▸ - ((specializes_iff_mem_closure.mpr $ mem_closure_zero_iff_norm.mpr hx).map hq).eq.symm + ((specializes_iff_mem_closure.mpr <| mem_closure_zero_iff_norm.mpr hx).map hq).eq.symm /-- Let `F` be a semi-`NormedSpace` over a `NontriviallyNormedField`, and let `q` be a seminorm on `F`. If `q` is continuous, then it is uniformly controlled by the norm, that is there @@ -813,7 +813,7 @@ controlled image by `q`. The control of `q` at the original element follows by r lemma bound_of_continuous_normedSpace (q : Seminorm 𝕜 F) (hq : Continuous q) : ∃ C, 0 < C ∧ (∀ x : F, q x ≤ C * ‖x‖) := by have hq' : Tendsto q (𝓝 0) (𝓝 0) := map_zero q ▸ hq.tendsto 0 - rcases NormedAddCommGroup.nhds_zero_basis_norm_lt.mem_iff.mp (hq' $ Iio_mem_nhds one_pos) + rcases NormedAddCommGroup.nhds_zero_basis_norm_lt.mem_iff.mp (hq' <| Iio_mem_nhds one_pos) with ⟨ε, ε_pos, hε⟩ rcases NormedField.exists_one_lt_norm 𝕜 with ⟨c, hc⟩ have : 0 < ‖c‖ / ε := by positivity diff --git a/Mathlib/Analysis/Matrix.lean b/Mathlib/Analysis/Matrix.lean index 37ad8c40ca2be..7e60821737b2f 100644 --- a/Mathlib/Analysis/Matrix.lean +++ b/Mathlib/Analysis/Matrix.lean @@ -19,6 +19,7 @@ In this file we provide the following non-instances for norms on matrices: * `Matrix.seminormedAddCommGroup` * `Matrix.normedAddCommGroup` * `Matrix.normedSpace` + * `Matrix.boundedSMul` * The Frobenius norm: @@ -27,12 +28,14 @@ In this file we provide the following non-instances for norms on matrices: * `Matrix.frobeniusNormedSpace` * `Matrix.frobeniusNormedRing` * `Matrix.frobeniusNormedAlgebra` + * `Matrix.frobeniusBoundedSMul` * The $L^\infty$ operator norm: * `Matrix.linftyOpSeminormedAddCommGroup` * `Matrix.linftyOpNormedAddCommGroup` * `Matrix.linftyOpNormedSpace` + * `Matrix.linftyOpBoundedSMul` * `Matrix.linftyOpNonUnitalSemiNormedRing` * `Matrix.linftyOpSemiNormedRing` * `Matrix.linftyOpNonUnitalNormedRing` @@ -41,6 +44,10 @@ In this file we provide the following non-instances for norms on matrices: These are not declared as instances because there are several natural choices for defining the norm of a matrix. + +The norm induced by the identification of `Matrix m n 𝕜` with +`EuclideanSpace n 𝕜 →L[𝕜] EuclideanSpace m 𝕜` (i.e., the ℓ² operator norm) can be found in +`Analysis.NormedSpace.Star.Matrix`. It is separated to avoid extraneous imports in this file. -/ noncomputable section @@ -192,6 +199,11 @@ section NormedSpace attribute [local instance] Matrix.seminormedAddCommGroup +/-- This applies to the sup norm of sup norm. -/ +protected theorem boundedSMul [SeminormedRing R] [SeminormedAddCommGroup α] [Module R α] + [BoundedSMul R α] : BoundedSMul R (Matrix m n α) := + Pi.instBoundedSMul + variable [NormedField R] [SeminormedAddCommGroup α] [NormedSpace R α] /-- Normed space instance (using sup norm of sup norm) for matrices over a normed space. Not @@ -234,6 +246,13 @@ protected def linftyOpNormedAddCommGroup [NormedAddCommGroup α] : (by infer_instance : NormedAddCommGroup (m → PiLp 1 fun j : n => α)) #align matrix.linfty_op_normed_add_comm_group Matrix.linftyOpNormedAddCommGroup +/-- This applies to the sup norm of L1 norm. -/ +@[local instance] +protected theorem linftyOpBoundedSMul + [SeminormedRing R] [SeminormedAddCommGroup α] [Module R α] [BoundedSMul R α] : + BoundedSMul R (Matrix m n α) := + (by infer_instance : BoundedSMul R (m → PiLp 1 fun j : n => α)) + /-- Normed space instance (using sup norm of L1 norm) for matrices over a normed space. Not declared as an instance because there are several natural choices for defining the norm of a matrix. -/ @@ -386,6 +405,71 @@ protected def linftyOpNormedAlgebra [NormedField R] [SeminormedRing α] [NormedA { Matrix.linftyOpNormedSpace, Matrix.instAlgebra with } #align matrix.linfty_op_normed_algebra Matrix.linftyOpNormedAlgebra + +section +variable [NormedDivisionRing α] [NormedAlgebra ℝ α] [CompleteSpace α] + +/-- Auxiliary construction; an element of norm 1 such that `a * unitOf a = ‖a‖`. -/ +private def unitOf (a : α) : α := by classical exact if a = 0 then 1 else ‖a‖ • a⁻¹ + +private theorem norm_unitOf (a : α) : ‖unitOf a‖₊ = 1 := by + rw [unitOf] + split_ifs with h + · simp + · rw [← nnnorm_eq_zero] at h + rw [nnnorm_smul, nnnorm_inv, nnnorm_norm, mul_inv_cancel h] + +private theorem mul_unitOf (a : α) : a * unitOf a = algebraMap _ _ (‖a‖₊ : ℝ) := by + simp [unitOf] + split_ifs with h + · simp [h] + · rw [mul_smul_comm, mul_inv_cancel h, Algebra.algebraMap_eq_smul_one] + +end + +/-! +For a matrix over a field, the norm defined in this section agrees with the operator norm on +`ContinuousLinearMap`s between function types (which have the infinity norm). +-/ +section +variable [NontriviallyNormedField α] [NormedAlgebra ℝ α] + +lemma linfty_op_nnnorm_eq_op_nnnorm (A : Matrix m n α) : + ‖A‖₊ = ‖ContinuousLinearMap.mk (Matrix.mulVecLin A)‖₊ := by + rw [ContinuousLinearMap.op_nnnorm_eq_of_bounds _ (linfty_op_nnnorm_mulVec _) fun N hN => ?_] + rw [linfty_op_nnnorm_def] + refine Finset.sup_le fun i _ => ?_ + cases isEmpty_or_nonempty n + · simp + classical + let x : n → α := fun j => unitOf (A i j) + have hxn : ‖x‖₊ = 1 := by + simp_rw [Pi.nnnorm_def, norm_unitOf, Finset.sup_const Finset.univ_nonempty] + specialize hN x + rw [hxn, mul_one, Pi.nnnorm_def, Finset.sup_le_iff] at hN + replace hN := hN i (Finset.mem_univ _) + dsimp [mulVec, dotProduct] at hN + simp_rw [mul_unitOf, ← map_sum, nnnorm_algebraMap, ← NNReal.coe_sum, NNReal.nnnorm_eq, nnnorm_one, + mul_one] at hN + exact hN + +lemma linfty_op_norm_eq_op_norm (A : Matrix m n α) : + ‖A‖ = ‖ContinuousLinearMap.mk (Matrix.mulVecLin A)‖ := + congr_arg NNReal.toReal (linfty_op_nnnorm_eq_op_nnnorm A) + +variable [DecidableEq n] + +@[simp] lemma linfty_op_nnnorm_toMatrix (f : (n → α) →L[α] (m → α)) : + ‖LinearMap.toMatrix' (↑f : (n → α) →ₗ[α] (m → α))‖₊ = ‖f‖₊ := by + rw [linfty_op_nnnorm_eq_op_nnnorm] + simp only [← toLin'_apply', toLin'_toMatrix'] + +@[simp] lemma linfty_op_norm_toMatrix (f : (n → α) →L[α] (m → α)) : + ‖LinearMap.toMatrix' (↑f : (n → α) →ₗ[α] (m → α))‖ = ‖f‖ := + congr_arg NNReal.toReal (linfty_op_nnnorm_toMatrix f) + +end + end LinftyOp /-! ### The Frobenius norm @@ -416,6 +500,13 @@ def frobeniusNormedAddCommGroup [NormedAddCommGroup α] : NormedAddCommGroup (Ma (by infer_instance : NormedAddCommGroup (PiLp 2 fun i : m => PiLp 2 fun j : n => α)) #align matrix.frobenius_normed_add_comm_group Matrix.frobeniusNormedAddCommGroup +/-- This applies to the frobenius norm. -/ +@[local instance] +theorem frobeniusBoundedSMul [SeminormedRing R] [SeminormedAddCommGroup α] [Module R α] + [BoundedSMul R α] : + BoundedSMul R (Matrix m n α) := + (by infer_instance : BoundedSMul R (PiLp 2 fun i : m => PiLp 2 fun j : n => α)) + /-- Normed space instance (using frobenius norm) for matrices over a normed space. Not declared as an instance because there are several natural choices for defining the norm of a matrix. -/ @@ -542,11 +633,10 @@ variable [IsROrC α] theorem frobenius_nnnorm_mul (A : Matrix l m α) (B : Matrix m n α) : ‖A * B‖₊ ≤ ‖A‖₊ * ‖B‖₊ := by simp_rw [frobenius_nnnorm_def, Matrix.mul_apply] - rw [← NNReal.mul_rpow, @Finset.sum_comm _ n m, Finset.sum_mul_sum, Finset.sum_product] + rw [← NNReal.mul_rpow, @Finset.sum_comm _ n m, Finset.sum_mul_sum] gcongr with i _ j rw [← NNReal.rpow_le_rpow_iff one_half_pos, ← NNReal.rpow_mul, mul_div_cancel' (1 : ℝ) two_ne_zero, NNReal.rpow_one, NNReal.mul_rpow] - dsimp only have := @nnnorm_inner_le_nnnorm α _ _ _ _ ((WithLp.equiv 2 <| _ → α).symm fun j => star (A i j)) ((WithLp.equiv 2 <| _ → α).symm fun k => B k j) diff --git a/Mathlib/Analysis/MeanInequalities.lean b/Mathlib/Analysis/MeanInequalities.lean index 6b91aebbbf25f..183b2236b04c1 100644 --- a/Mathlib/Analysis/MeanInequalities.lean +++ b/Mathlib/Analysis/MeanInequalities.lean @@ -138,7 +138,7 @@ theorem geom_mean_le_arith_mean {ι : Type*} (s : Finset ι) (w : ι → ℝ) (z (hw : ∀ i ∈ s, 0 ≤ w i) (hw' : 0 < ∑ i in s, w i) (hz : ∀ i ∈ s, 0 ≤ z i) : (∏ i in s, z i ^ w i) ^ (∑ i in s, w i)⁻¹ ≤ (∑ i in s, w i * z i) / (∑ i in s, w i) := by convert geom_mean_le_arith_mean_weighted s (fun i => (w i) / ∑ i in s, w i) z ?_ ?_ hz using 2 - · rw [← finset_prod_rpow _ _ (fun i hi => rpow_nonneg_of_nonneg (hz _ hi) _) _] + · rw [← finset_prod_rpow _ _ (fun i hi => rpow_nonneg (hz _ hi) _) _] refine Finset.prod_congr rfl (fun _ ih => ?_) rw [div_eq_mul_inv, rpow_mul (hz _ ih)] · simp_rw [div_eq_mul_inv, mul_assoc, mul_comm, ← mul_assoc, ← Finset.sum_mul, mul_comm] @@ -264,7 +264,7 @@ theorem young_inequality_of_nonneg {a b p q : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hpq : p.IsConjugateExponent q) : a * b ≤ a ^ p / p + b ^ q / q := by simpa [← rpow_mul, ha, hb, hpq.ne_zero, hpq.symm.ne_zero, _root_.div_eq_inv_mul] using geom_mean_le_arith_mean2_weighted hpq.one_div_nonneg hpq.symm.one_div_nonneg - (rpow_nonneg_of_nonneg ha p) (rpow_nonneg_of_nonneg hb q) hpq.inv_add_inv_conj + (rpow_nonneg ha p) (rpow_nonneg hb q) hpq.inv_add_inv_conj #align real.young_inequality_of_nonneg Real.young_inequality_of_nonneg /-- Young's inequality, a version for arbitrary real numbers. -/ @@ -594,7 +594,7 @@ theorem Lp_add_le (hp : 1 ≤ p) : (NNReal.Lp_add_le s (fun i => ⟨_, abs_nonneg (f i)⟩) (fun i => ⟨_, abs_nonneg (g i)⟩) hp) push_cast at this refine' le_trans (rpow_le_rpow _ (sum_le_sum fun i _ => _) _) this <;> - simp [sum_nonneg, rpow_nonneg_of_nonneg, abs_nonneg, le_trans zero_le_one hp, abs_add, + simp [sum_nonneg, rpow_nonneg, abs_nonneg, le_trans zero_le_one hp, abs_add, rpow_le_rpow] #align real.Lp_add_le Real.Lp_add_le diff --git a/Mathlib/Analysis/MeanInequalitiesPow.lean b/Mathlib/Analysis/MeanInequalitiesPow.lean index 92bab49265059..b2f0e94a465ca 100644 --- a/Mathlib/Analysis/MeanInequalitiesPow.lean +++ b/Mathlib/Analysis/MeanInequalitiesPow.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Sébastien Gouëzel, Rémy Degenne -/ import Mathlib.Analysis.Convex.Jensen +import Mathlib.Analysis.Convex.Mul import Mathlib.Analysis.Convex.SpecificFunctions.Basic import Mathlib.Analysis.SpecialFunctions.Pow.NNReal -import Mathlib.Tactic.Positivity #align_import analysis.mean_inequalities_pow from "leanprover-community/mathlib"@"ccdbfb6e5614667af5aa3ab2d50885e0ef44a46f" @@ -104,9 +104,9 @@ theorem arith_mean_le_rpow_mean (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i) rw [← rpow_le_rpow_iff _ _ this, ← rpow_mul, one_div_mul_cancel (ne_of_gt this), rpow_one] exact rpow_arith_mean_le_arith_mean_rpow s w z hw hw' hz hp all_goals - apply_rules [sum_nonneg, rpow_nonneg_of_nonneg] + apply_rules [sum_nonneg, rpow_nonneg] intro i hi - apply_rules [mul_nonneg, rpow_nonneg_of_nonneg, hw i hi, hz i hi] + apply_rules [mul_nonneg, rpow_nonneg, hw i hi, hz i hi] #align real.arith_mean_le_rpow_mean Real.arith_mean_le_rpow_mean end Real diff --git a/Mathlib/Analysis/MellinTransform.lean b/Mathlib/Analysis/MellinTransform.lean index c9d67860f041b..0e6e4fdb3d4ba 100644 --- a/Mathlib/Analysis/MellinTransform.lean +++ b/Mathlib/Analysis/MellinTransform.lean @@ -226,8 +226,8 @@ theorem mellin_convergent_top_of_isBigO {f : ℝ → ℝ} ‖t ^ (s - 1) * f t‖ ≤ t ^ (s - 1 + -a) * d := by refine' (ae_restrict_mem measurableSet_Ioi).mono fun t ht => _ have ht' : 0 < t := he'.trans ht - rw [norm_mul, rpow_add ht', ← norm_of_nonneg (rpow_nonneg_of_nonneg ht'.le (-a)), mul_assoc, - mul_comm _ d, norm_of_nonneg (rpow_nonneg_of_nonneg ht'.le _)] + rw [norm_mul, rpow_add ht', ← norm_of_nonneg (rpow_nonneg ht'.le (-a)), mul_assoc, + mul_comm _ d, norm_of_nonneg (rpow_nonneg ht'.le _)] gcongr exact he t ((le_max_left e 1).trans_lt ht).le refine' (HasFiniteIntegral.mul_const _ _).mono' this @@ -261,7 +261,7 @@ theorem mellin_convergent_zero_of_isBigO {b : ℝ} {f : ℝ → ℝ} exact ht.2 · calc _ ≤ d * ‖t ^ (-b)‖ * ‖t ^ (s - 1)‖ := by gcongr _ = d * t ^ (s - b - 1) := ?_ - simp_rw [norm_of_nonneg (rpow_nonneg_of_nonneg (le_of_lt ht.1) _), mul_assoc] + simp_rw [norm_of_nonneg (rpow_nonneg (le_of_lt ht.1) _), mul_assoc] rw [← rpow_add ht.1] congr 2 abel @@ -375,7 +375,7 @@ theorem mellin_hasDerivAt_of_isBigO_rpow [CompleteSpace E] [NormedSpace ℂ E] { rw [Complex.norm_eq_abs, abs_cpow_eq_rpow_re_of_pos ht] rcases le_or_lt 1 t with h | h · refine' le_add_of_le_of_nonneg (rpow_le_rpow_of_exponent_le h _) - (rpow_nonneg_of_nonneg (zero_le_one.trans h) _) + (rpow_nonneg (zero_le_one.trans h) _) rw [sub_re, one_re, sub_le_sub_iff_right] rw [mem_ball_iff_norm, Complex.norm_eq_abs] at hz have hz' := (re_le_abs _).trans hz.le @@ -398,7 +398,7 @@ theorem mellin_hasDerivAt_of_isBigO_rpow [CompleteSpace E] [NormedSpace ℂ E] { refine' mellin_convergent_of_isBigO_scalar _ _ hw1' _ hw2 · simp_rw [mul_comm] refine' hfc.norm.mul_continuousOn _ isOpen_Ioi - refine' Continuous.comp_continuousOn continuous_abs (continuousOn_log.mono _) + refine' Continuous.comp_continuousOn _root_.continuous_abs (continuousOn_log.mono _) exact subset_compl_singleton_iff.mpr not_mem_Ioi_self · refine (isBigO_rpow_top_log_smul hw2' hf_top).norm_left.congr_left fun t ↦ ?_ simp only [norm_smul, Real.norm_eq_abs] diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index ee66ae3aeab78..596fdd9fba6d8 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -3,9 +3,11 @@ Copyright (c) 2018 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Johannes Hölzl -/ +import Mathlib.Algebra.Algebra.NonUnitalSubalgebra import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Analysis.Normed.Group.Basic -import Mathlib.Topology.Instances.ENNReal +import Mathlib.GroupTheory.OrderOfElement +import Mathlib.Topology.Instances.NNReal import Mathlib.Topology.MetricSpace.DilationEquiv #align_import analysis.normed.field.basic from "leanprover-community/mathlib"@"f06058e64b7e8397234455038f3f8aec83aaba5a" @@ -265,6 +267,21 @@ theorem mulRight_bound (x : α) : ∀ y : α, ‖AddMonoidHom.mulRight x y‖ exact norm_mul_le y x #align mul_right_bound mulRight_bound +/-- A non-unital subalgebra of a non-unital seminormed ring is also a non-unital seminormed ring, +with the restriction of the norm. -/ +instance NonUnitalSubalgebra.nonUnitalSeminormedRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} + [NonUnitalSeminormedRing E] [Module 𝕜 E] (s : NonUnitalSubalgebra 𝕜 E) : + NonUnitalSeminormedRing s := + { s.toSubmodule.seminormedAddCommGroup, s.toNonUnitalRing with + norm_mul := fun a b => norm_mul_le a.1 b.1 } + +/-- A non-unital subalgebra of a non-unital normed ring is also a non-unital normed ring, with the +restriction of the norm. -/ +instance NonUnitalSubalgebra.nonUnitalNormedRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} + [NonUnitalNormedRing E] [Module 𝕜 E] (s : NonUnitalSubalgebra 𝕜 E) : NonUnitalNormedRing s := + { s.nonUnitalSeminormedRing with + eq_of_dist_eq_zero := eq_of_dist_eq_zero } + instance ULift.nonUnitalSeminormedRing : NonUnitalSeminormedRing (ULift α) := { ULift.seminormedAddCommGroup, ULift.nonUnitalRing with norm_mul := fun x y => (norm_mul_le x.down y.down : _) } @@ -317,18 +334,15 @@ section SeminormedRing variable [SeminormedRing α] -/-- A subalgebra of a seminormed ring is also a seminormed ring, with the restriction of the norm. - -See note [implicit instance arguments]. -/ +/-- A subalgebra of a seminormed ring is also a seminormed ring, with the restriction of the +norm. -/ instance Subalgebra.seminormedRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [SeminormedRing E] [Algebra 𝕜 E] (s : Subalgebra 𝕜 E) : SeminormedRing s := { s.toSubmodule.seminormedAddCommGroup, s.toRing with norm_mul := fun a b => norm_mul_le a.1 b.1 } #align subalgebra.semi_normed_ring Subalgebra.seminormedRing -/-- A subalgebra of a normed ring is also a normed ring, with the restriction of the norm. - -See note [implicit instance arguments]. -/ +/-- A subalgebra of a normed ring is also a normed ring, with the restriction of the norm. -/ instance Subalgebra.normedRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [NormedRing E] [Algebra 𝕜 E] (s : Subalgebra 𝕜 E) : NormedRing s := { s.seminormedRing with @@ -521,10 +535,25 @@ instance MulOpposite.nonUnitalSeminormedCommRing : NonUnitalSeminormedCommRing { MulOpposite.nonUnitalSeminormedRing, MulOpposite.nonUnitalCommRing α with } end NonUnitalSeminormedCommRing + section NonUnitalNormedCommRing variable [NonUnitalNormedCommRing α] +/-- A non-unital subalgebra of a non-unital seminormed commutative ring is also a non-unital +seminormed commutative ring, with the restriction of the norm. -/ +instance NonUnitalSubalgebra.nonUnitalSeminormedCommRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} + [NonUnitalSeminormedCommRing E] [Module 𝕜 E] (s : NonUnitalSubalgebra 𝕜 E) : + NonUnitalSeminormedCommRing s := + { s.nonUnitalSeminormedRing, s.toNonUnitalCommRing with } + +/-- A non-unital subalgebra of a non-unital normed commutative ring is also a non-unital normed +commutative ring, with the restriction of the norm. -/ +instance NonUnitalSubalgebra.nonUnitalNormedCommRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} + [NonUnitalNormedCommRing E] [Module 𝕜 E] (s : NonUnitalSubalgebra 𝕜 E) : + NonUnitalNormedCommRing s := + { s.nonUnitalSeminormedCommRing, s.nonUnitalNormedRing with } + instance ULift.nonUnitalNormedCommRing : NonUnitalNormedCommRing (ULift α) := { ULift.nonUnitalSeminormedCommRing, ULift.normedAddCommGroup with } @@ -545,6 +574,64 @@ instance MulOpposite.nonUnitalNormedCommRing : NonUnitalNormedCommRing αᵐᵒ end NonUnitalNormedCommRing +section SeminormedCommRing + +variable [SeminormedCommRing α] + +instance ULift.seminormedCommRing : SeminormedCommRing (ULift α) := + { ULift.nonUnitalSeminormedRing, ULift.commRing with } + +/-- Seminormed commutative ring structure on the product of two seminormed commutative rings, + using the sup norm. -/ +instance Prod.seminormedCommRing [SeminormedCommRing β] : SeminormedCommRing (α × β) := + { Prod.nonUnitalSeminormedCommRing, instCommRing with } + +/-- Seminormed commutative ring structure on the product of finitely many seminormed commutative +rings, using the sup norm. -/ +instance Pi.seminormedCommRing {π : ι → Type*} [Fintype ι] [∀ i, SeminormedCommRing (π i)] : + SeminormedCommRing (∀ i, π i) := + { Pi.nonUnitalSeminormedCommRing, Pi.ring with } + +instance MulOpposite.seminormedCommRing : SeminormedCommRing αᵐᵒᵖ := + { MulOpposite.nonUnitalSeminormedCommRing, MulOpposite.ring α with } + +end SeminormedCommRing + +section NormedCommRing + +/-- A subalgebra of a seminormed commutative ring is also a seminormed commutative ring, with the +restriction of the norm. -/ +instance Subalgebra.seminormedCommRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [SeminormedCommRing E] + [Algebra 𝕜 E] (s : Subalgebra 𝕜 E) : SeminormedCommRing s := + { s.seminormedRing, s.toCommRing with } + +/-- A subalgebra of a normed commutative ring is also a normed commutative ring, with the +restriction of the norm. -/ +instance Subalgebra.normedCommRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [NormedCommRing E] + [Algebra 𝕜 E] (s : Subalgebra 𝕜 E) : NormedCommRing s := + { s.seminormedCommRing, s.normedRing with } + +variable [NormedCommRing α] + +instance ULift.normedCommRing : NormedCommRing (ULift α) := + { ULift.normedRing (α := α), ULift.seminormedCommRing with } + +/-- Normed commutative ring structure on the product of two normed commutative rings, using the sup +norm. -/ +instance Prod.normedCommRing [NormedCommRing β] : NormedCommRing (α × β) := + { nonUnitalNormedRing, instCommRing with } + +/-- Normed commutative ring structure on the product of finitely many normed commutative rings, +using the sup norm. -/ +instance Pi.normedCommutativeRing {π : ι → Type*} [Fintype ι] [∀ i, NormedCommRing (π i)] : + NormedCommRing (∀ i, π i) := + { Pi.seminormedCommRing, Pi.normedAddCommGroup with } + +instance MulOpposite.normedCommRing : NormedCommRing αᵐᵒᵖ := + { MulOpposite.seminormedCommRing, MulOpposite.normedAddCommGroup with } + +end NormedCommRing + -- see Note [lower instance priority] instance (priority := 100) semi_normed_ring_top_monoid [NonUnitalSeminormedRing α] : ContinuousMul α := @@ -579,7 +666,7 @@ instance (priority := 100) semi_normed_top_ring [NonUnitalSeminormedRing α] : T section NormedDivisionRing -variable [NormedDivisionRing α] +variable [NormedDivisionRing α] {a : α} @[simp] theorem norm_mul (a b : α) : ‖a * b‖ = ‖a‖ * ‖b‖ := @@ -786,15 +873,13 @@ instance (priority := 100) NormedDivisionRing.to_topologicalDivisionRing : Topol where #align normed_division_ring.to_topological_division_ring NormedDivisionRing.to_topologicalDivisionRing -theorem norm_map_one_of_pow_eq_one [Monoid β] (φ : β →* α) {x : β} {k : ℕ+} (h : x ^ (k : ℕ) = 1) : - ‖φ x‖ = 1 := by - rw [← pow_left_inj, ← norm_pow, ← map_pow, h, map_one, norm_one, one_pow] - exacts [norm_nonneg _, zero_le_one, k.ne_zero] -#align norm_map_one_of_pow_eq_one norm_map_one_of_pow_eq_one +protected lemma IsOfFinOrder.norm_eq_one (ha : IsOfFinOrder a) : ‖a‖ = 1 := + ((normHom : α →*₀ ℝ).toMonoidHom.isOfFinOrder ha).eq_one $ norm_nonneg _ +#align norm_one_of_pow_eq_one IsOfFinOrder.norm_eq_one -theorem norm_one_of_pow_eq_one {x : α} {k : ℕ+} (h : x ^ (k : ℕ) = 1) : ‖x‖ = 1 := - norm_map_one_of_pow_eq_one (MonoidHom.id α) h -#align norm_one_of_pow_eq_one norm_one_of_pow_eq_one +example [Monoid β] (φ : β →* α) {x : β} {k : ℕ+} (h : x ^ (k : ℕ) = 1) : + ‖φ x‖ = 1 := (φ.isOfFinOrder <| isOfFinOrder_iff_pow_eq_one.2 ⟨_, k.2, h⟩).norm_eq_one +#noalign norm_map_one_of_pow_eq_one end NormedDivisionRing diff --git a/Mathlib/Analysis/Normed/Field/InfiniteSum.lean b/Mathlib/Analysis/Normed/Field/InfiniteSum.lean index c7812051f74f9..d9ad30dc43f55 100644 --- a/Mathlib/Analysis/Normed/Field/InfiniteSum.lean +++ b/Mathlib/Analysis/Normed/Field/InfiniteSum.lean @@ -5,6 +5,7 @@ Authors: Anatole Dedecker -/ import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Analysis.Normed.Group.InfiniteSum +import Mathlib.Topology.Instances.ENNReal #align_import analysis.normed.field.infinite_sum from "leanprover-community/mathlib"@"008205aa645b3f194c1da47025c5f110c8406eab" diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index d6db12edc4426..592ac5daced5d 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -452,6 +452,7 @@ theorem norm_inv' (a : E) : ‖a⁻¹‖ = ‖a‖ := by simpa using norm_div_re #align norm_inv' norm_inv' #align norm_neg norm_neg +open scoped symmDiff in @[to_additive] theorem dist_mulIndicator (s t : Set α) (f : α → E) (x : α) : dist (s.mulIndicator f x) (t.mulIndicator f x) = ‖(s ∆ t).mulIndicator f x‖ := by @@ -511,6 +512,10 @@ theorem norm_mul₃_le (a b c : E) : ‖a * b * c‖ ≤ ‖a‖ + ‖b‖ + ‖ #align norm_mul₃_le norm_mul₃_le #align norm_add₃_le norm_add₃_le +@[to_additive] +lemma norm_div_le_norm_div_add_norm_div (a b c : E) : ‖a / c‖ ≤ ‖a / b‖ + ‖b / c‖ := by + simpa only [dist_eq_norm_div] using dist_triangle a b c + @[to_additive (attr := simp) norm_nonneg] theorem norm_nonneg' (a : E) : 0 ≤ ‖a‖ := by rw [← dist_one_right] @@ -969,6 +974,7 @@ theorem nnnorm_inv' (a : E) : ‖a⁻¹‖₊ = ‖a‖₊ := #align nnnorm_inv' nnnorm_inv' #align nnnorm_neg nnnorm_neg +open scoped symmDiff in @[to_additive] theorem nndist_mulIndicator (s t : Set α) (f : α → E) (x : α) : nndist (s.mulIndicator f x) (t.mulIndicator f x) = ‖(s ∆ t).mulIndicator f x‖₊ := @@ -1028,6 +1034,7 @@ theorem edist_eq_coe_nnnorm' (x : E) : edist x 1 = (‖x‖₊ : ℝ≥0∞) := #align edist_eq_coe_nnnorm' edist_eq_coe_nnnorm' #align edist_eq_coe_nnnorm edist_eq_coe_nnnorm +open scoped symmDiff in @[to_additive] theorem edist_mulIndicator (s t : Set α) (f : α → E) (x : α) : edist (s.mulIndicator f x) (t.mulIndicator f x) = ‖(s ∆ t).mulIndicator f x‖₊ := by diff --git a/Mathlib/Analysis/Normed/Group/Hom.lean b/Mathlib/Analysis/Normed/Group/Hom.lean index cea2d02f62e43..e21f46ed403d4 100644 --- a/Mathlib/Analysis/Normed/Group/Hom.lean +++ b/Mathlib/Analysis/Normed/Group/Hom.lean @@ -85,16 +85,18 @@ variable {f g : NormedAddGroupHom V₁ V₂} def ofLipschitz (f : V₁ →+ V₂) {K : ℝ≥0} (h : LipschitzWith K f) : NormedAddGroupHom V₁ V₂ := f.mkNormedAddGroupHom K fun x ↦ by simpa only [map_zero, dist_zero_right] using h.dist_le_mul x 0 --- porting note: moved this declaration up so we could get a `FunLike` instance sooner. +-- porting note: moved this declaration up so we could get a `DFunLike` instance sooner. instance toAddMonoidHomClass : AddMonoidHomClass (NormedAddGroupHom V₁ V₂) V₁ V₂ where coe := toFun coe_injective' := fun f g h => by cases f; cases g; congr map_add f := f.map_add' map_zero f := (AddMonoidHom.mk' f.toFun f.map_add').map_zero -/-- Helper instance for when there are too many metavariables to apply `FunLike.coeFun` directly. -/ +/-- +Helper instance for when there are too many metavariables to apply `DFunLike.coeFun` directly. +-/ instance coeFun : CoeFun (NormedAddGroupHom V₁ V₂) fun _ => V₁ → V₂ := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ initialize_simps_projections NormedAddGroupHom (toFun → apply) @@ -611,7 +613,7 @@ instance toNormedAddCommGroup {V₁ V₂ : Type*} [NormedAddCommGroup V₁] [Nor /-- Coercion of a `NormedAddGroupHom` is an `AddMonoidHom`. Similar to `AddMonoidHom.coeFn`. -/ @[simps] def coeAddHom : NormedAddGroupHom V₁ V₂ →+ V₁ → V₂ where - toFun := FunLike.coe + toFun := DFunLike.coe map_zero' := coe_zero map_add' := coe_add #align normed_add_group_hom.coe_fn_add_hom NormedAddGroupHom.coeAddHom diff --git a/Mathlib/Analysis/Normed/Group/Quotient.lean b/Mathlib/Analysis/Normed/Group/Quotient.lean index a9a571255b368..ead75701f1570 100644 --- a/Mathlib/Analysis/Normed/Group/Quotient.lean +++ b/Mathlib/Analysis/Normed/Group/Quotient.lean @@ -5,6 +5,7 @@ Authors: Patrick Massot, Riccardo Brasca -/ import Mathlib.Analysis.NormedSpace.Basic import Mathlib.Analysis.Normed.Group.Hom +import Mathlib.Data.Real.Sqrt import Mathlib.RingTheory.Ideal.QuotientOperations import Mathlib.Topology.MetricSpace.HausdorffDistance @@ -379,7 +380,7 @@ theorem IsQuotient.norm_lift {f : NormedAddGroupHom M N} (hquot : IsQuotient f) (n : N) : ∃ m : M, f m = n ∧ ‖m‖ < ‖n‖ + ε := by obtain ⟨m, rfl⟩ := hquot.surjective n have nonemp : ((fun m' => ‖m + m'‖) '' f.ker).Nonempty := by - rw [Set.nonempty_image_iff] + rw [Set.image_nonempty] exact ⟨0, f.ker.zero_mem⟩ rcases Real.lt_sInf_add_pos nonemp hε with ⟨_, ⟨⟨x, hx, rfl⟩, H : ‖m + x‖ < sInf ((fun m' : M => ‖m + m'‖) '' f.ker) + ε⟩⟩ diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGroupCat.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGroupCat.lean index 628a23e7cc11f..d01dca46bed46 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGroupCat.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGroupCat.lean @@ -68,7 +68,7 @@ instance toAddMonoidHomClass {V W : SemiNormedGroupCat} : AddMonoidHomClass (V -- Porting note: added to ease automation @[ext] lemma ext {M N : SemiNormedGroupCat} {f₁ f₂ : M ⟶ N} (h : ∀ (x : M), f₁ x = f₂ x) : f₁ = f₂ := - FunLike.ext _ _ h + DFunLike.ext _ _ h @[simp] theorem coe_of (V : Type u) [SeminormedAddCommGroup V] : (SemiNormedGroupCat.of V : Type u) = V := @@ -147,7 +147,7 @@ instance : LargeCategory.{u} SemiNormedGroupCat₁ where comp {X Y Z} f g := ⟨g.1.comp f.1, g.2.comp f.2⟩ -- Porting Note: Added -instance instFunLike (X Y : SemiNormedGroupCat₁) : FunLike (X ⟶ Y) X (fun _ => Y) where +instance instFunLike (X Y : SemiNormedGroupCat₁) : FunLike (X ⟶ Y) X Y where coe f := f.1.toFun coe_injective' _ _ h := Subtype.val_inj.mp (NormedAddGroupHom.coe_injective h) diff --git a/Mathlib/Analysis/Normed/Group/Seminorm.lean b/Mathlib/Analysis/Normed/Group/Seminorm.lean index 452e183e38454..3cfc13ff4c831 100644 --- a/Mathlib/Analysis/Normed/Group/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Group/Seminorm.lean @@ -3,9 +3,8 @@ Copyright (c) 2022 María Inés de Frutos-Fernández, Yaël Dillies. All rights Released under Apache 2.0 license as described in the file LICENSE. Authors: María Inés de Frutos-Fernández, Yaël Dillies -/ -import Mathlib.Tactic.Positivity import Mathlib.Data.Real.NNReal -import Mathlib.Tactic.GCongr +import Mathlib.Tactic.GCongr.Core #align_import analysis.normed.group.seminorm from "leanprover-community/mathlib"@"09079525fd01b3dda35e96adaa08d2f943e1648c" @@ -195,11 +194,11 @@ instance groupSeminormClass : GroupSeminormClass (GroupSeminorm E) E ℝ #align group_seminorm.group_seminorm_class GroupSeminorm.groupSeminormClass #align add_group_seminorm.add_group_seminorm_class AddGroupSeminorm.addGroupSeminormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ @[to_additive "Helper instance for when there's too many metavariables to apply -`FunLike.hasCoeToFun`. "] +`DFunLike.hasCoeToFun`. "] instance : CoeFun (GroupSeminorm E) fun _ => E → ℝ := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ @[to_additive (attr := simp)] theorem toFun_eq_coe : p.toFun = p := @@ -209,13 +208,13 @@ theorem toFun_eq_coe : p.toFun = p := @[to_additive (attr := ext)] theorem ext : (∀ x, p x = q x) → p = q := - FunLike.ext p q + DFunLike.ext p q #align group_seminorm.ext GroupSeminorm.ext #align add_group_seminorm.ext AddGroupSeminorm.ext @[to_additive] instance : PartialOrder (GroupSeminorm E) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective @[to_additive] theorem le_def : p ≤ q ↔ (p : E → ℝ) ≤ q := @@ -315,7 +314,7 @@ theorem sup_apply (x : E) : (p ⊔ q) x = p x ⊔ q x := @[to_additive] instance semilatticeSup : SemilatticeSup (GroupSeminorm E) := - FunLike.coe_injective.semilatticeSup _ coe_sup + DFunLike.coe_injective.semilatticeSup _ coe_sup /-- Composition of a group seminorm with a monoid homomorphism as a group seminorm. -/ @[to_additive "Composition of an additive group seminorm with an additive monoid homomorphism as an @@ -513,9 +512,9 @@ instance nonarchAddGroupSeminormClass : NonarchAddGroupSeminormClass (NonarchAdd map_neg_eq_map' f := f.neg' #align nonarch_add_group_seminorm.nonarch_add_group_seminorm_class NonarchAddGroupSeminorm.nonarchAddGroupSeminormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ instance : CoeFun (NonarchAddGroupSeminorm E) fun _ => E → ℝ := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ -- porting note: `simpNF` said the left hand side simplified to this @[simp] @@ -525,11 +524,11 @@ theorem toZeroHom_eq_coe : ⇑p.toZeroHom = p := by @[ext] theorem ext : (∀ x, p x = q x) → p = q := - FunLike.ext p q + DFunLike.ext p q #align nonarch_add_group_seminorm.ext NonarchAddGroupSeminorm.ext noncomputable instance : PartialOrder (NonarchAddGroupSeminorm E) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective theorem le_def : p ≤ q ↔ (p : E → ℝ) ≤ q := Iff.rfl @@ -592,7 +591,7 @@ theorem sup_apply (x : E) : (p ⊔ q) x = p x ⊔ q x := #align nonarch_add_group_seminorm.sup_apply NonarchAddGroupSeminorm.sup_apply noncomputable instance : SemilatticeSup (NonarchAddGroupSeminorm E) := - FunLike.coe_injective.semilatticeSup _ coe_sup + DFunLike.coe_injective.semilatticeSup _ coe_sup end AddGroup @@ -752,12 +751,12 @@ instance groupNormClass : GroupNormClass (GroupNorm E) E ℝ #align group_norm.group_norm_class GroupNorm.groupNormClass #align add_group_norm.add_group_norm_class AddGroupNorm.addGroupNormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ @[to_additive "Helper instance for when there's too many metavariables to apply -`FunLike.hasCoeToFun` directly. "] +`DFunLike.hasCoeToFun` directly. "] instance : CoeFun (GroupNorm E) fun _ => E → ℝ := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun -- porting note: `simpNF` told me the left-hand side simplified to this @[to_additive (attr := simp)] @@ -768,13 +767,13 @@ theorem toGroupSeminorm_eq_coe : ⇑p.toGroupSeminorm = p := @[to_additive (attr := ext)] theorem ext : (∀ x, p x = q x) → p = q := - FunLike.ext p q + DFunLike.ext p q #align group_norm.ext GroupNorm.ext #align add_group_norm.ext AddGroupNorm.ext @[to_additive] instance : PartialOrder (GroupNorm E) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective @[to_additive] theorem le_def : p ≤ q ↔ (p : E → ℝ) ≤ q := @@ -843,7 +842,7 @@ theorem sup_apply (x : E) : (p ⊔ q) x = p x ⊔ q x := @[to_additive] instance : SemilatticeSup (GroupNorm E) := - FunLike.coe_injective.semilatticeSup _ coe_sup + DFunLike.coe_injective.semilatticeSup _ coe_sup end Group @@ -906,9 +905,9 @@ instance nonarchAddGroupNormClass : NonarchAddGroupNormClass (NonarchAddGroupNor eq_zero_of_map_eq_zero f := f.eq_zero_of_map_eq_zero' _ #align nonarch_add_group_norm.nonarch_add_group_norm_class NonarchAddGroupNorm.nonarchAddGroupNormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ noncomputable instance : CoeFun (NonarchAddGroupNorm E) fun _ => E → ℝ := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun -- porting note: `simpNF` told me the left-hand side simplified to this @[simp] @@ -918,11 +917,11 @@ theorem toNonarchAddGroupSeminorm_eq_coe : ⇑p.toNonarchAddGroupSeminorm = p := @[ext] theorem ext : (∀ x, p x = q x) → p = q := - FunLike.ext p q + DFunLike.ext p q #align nonarch_add_group_norm.ext NonarchAddGroupNorm.ext noncomputable instance : PartialOrder (NonarchAddGroupNorm E) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective theorem le_def : p ≤ q ↔ (p : E → ℝ) ≤ q := Iff.rfl @@ -961,7 +960,7 @@ theorem sup_apply (x : E) : (p ⊔ q) x = p x ⊔ q x := #align nonarch_add_group_norm.sup_apply NonarchAddGroupNorm.sup_apply noncomputable instance : SemilatticeSup (NonarchAddGroupNorm E) := - FunLike.coe_injective.semilatticeSup _ coe_sup + DFunLike.coe_injective.semilatticeSup _ coe_sup instance [DecidableEq E] : One (NonarchAddGroupNorm E) := ⟨{ (1 : NonarchAddGroupSeminorm E) with diff --git a/Mathlib/Analysis/Normed/Group/Tannery.lean b/Mathlib/Analysis/Normed/Group/Tannery.lean new file mode 100644 index 0000000000000..93f60d10605d1 --- /dev/null +++ b/Mathlib/Analysis/Normed/Group/Tannery.lean @@ -0,0 +1,82 @@ +/- +Copyright (c) 2024 David Loeffler. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: David Loeffler +-/ + +import Mathlib.Data.IsROrC.Basic +import Mathlib.Analysis.Normed.Group.InfiniteSum + +/-! +# Tannery's theorem + +Tannery's theorem gives a sufficient criterion for the limit of an infinite sum (with respect to +an auxiliary parameter) to equal the sum of the pointwise limits. See +https://en.wikipedia.org/wiki/Tannery%27s_theorem. It is a special case of the dominated convergence +theorem (with the measure chosen to be the counting measure); but we give here a direct proof, in +order to avoid some unnecessary hypotheses that appear when specialising the general +measure-theoretic result. +-/ + +open Filter Topology + +open scoped BigOperators + +/-- **Tannery's theorem**: topological sums commute with termwise limits, when the norms of the +summands are uniformly bounded by a summable function. + +(This is the special case of the Lebesgue dominated convergence theorem for the counting measure +on a discrete set. However, we prove it under somewhat weaker assumptions than the general +measure-theoretic result, e.g. `G` is not assumed to be an `ℝ`-vector space or second countable, +and the limit is along an arbitrary filter rather than `atTop ℕ`.) + +See also: +* `MeasureTheory.tendsto_integral_of_dominated_convergence` (for general integrals, but + with more assumptions on `G`) +* `continuous_tsum` (continuity of infinite sums in a parameter) +-/ +lemma tendsto_tsum_of_dominated_convergence {α β G : Type*} {𝓕 : Filter α} + [DecidableEq β] [NormedAddCommGroup G] [CompleteSpace G] + {f : α → β → G} {g : β → G} {bound : β → ℝ} (h_sum : Summable bound) + (hab : ∀ k : β, Tendsto (f · k) 𝓕 (𝓝 (g k))) + (h_bound : ∀ n k, ‖f n k‖ ≤ bound k) : + Tendsto (∑' k, f · k) 𝓕 (𝓝 (∑' k, g k)) := by + -- WLOG β is nonempty + rcases isEmpty_or_nonempty β + · simpa only [tsum_empty] using tendsto_const_nhds + -- WLOG 𝓕 ≠ ⊥ + rcases 𝓕.eq_or_neBot with rfl | _ + · simp only [tendsto_bot] + -- Auxiliary lemmas + have h_g_le (k : β) : ‖g k‖ ≤ bound k := + le_of_tendsto (tendsto_norm.comp (hab k)) <| eventually_of_forall (h_bound · k) + have h_sumg : Summable (‖g ·‖) := + h_sum.of_norm_bounded _ (fun k ↦ (norm_norm (g k)).symm ▸ h_g_le k) + have h_suma (n : α) : Summable (‖f n ·‖) := + h_sum.of_norm_bounded _ <| by simpa only [norm_norm] using h_bound n + -- Now main proof, by an `ε / 3` argument + rw [Metric.tendsto_nhds] + intro ε hε + let ⟨S, hS⟩ := h_sum + obtain ⟨T, hT⟩ : ∃ (T : Finset β), dist (∑ b in T, bound b) S < ε / 3 := by + rw [HasSum, Metric.tendsto_nhds] at hS + exact (fun ⟨T, h⟩ ↦ ⟨T, h _ le_rfl⟩) <| eventually_atTop.mp (hS _ (by positivity)) + have h1 : ∑' (k : (Tᶜ : Set β)), bound k < ε / 3 := by + calc _ ≤ ‖∑' (k : (Tᶜ : Set β)), bound k‖ := Real.le_norm_self _ + _ = ‖S - ∑ b in T, bound b‖ := congrArg _ ?_ + _ < ε / 3 := by rwa [dist_eq_norm, norm_sub_rev] at hT + simpa only [sum_add_tsum_compl h_sum, eq_sub_iff_add_eq'] using hS.tsum_eq + have h2 : Tendsto (∑ k in T, f · k) 𝓕 (𝓝 (T.sum g)) := tendsto_finset_sum _ (fun i _ ↦ hab i) + rw [Metric.tendsto_nhds] at h2 + refine (h2 (ε / 3) (by positivity)).mp (eventually_of_forall (fun n hn ↦ ?_)) + rw [dist_eq_norm, ← tsum_sub (h_suma n).of_norm h_sumg.of_norm, + ← sum_add_tsum_compl (s := T) ((h_suma n).of_norm.sub h_sumg.of_norm), + (by ring : ε = ε / 3 + (ε / 3 + ε / 3))] + refine (norm_add_le _ _).trans_lt (add_lt_add ?_ ?_) + · simpa only [dist_eq_norm, Finset.sum_sub_distrib] using hn + · rw [tsum_sub ((h_suma n).subtype _).of_norm (h_sumg.subtype _).of_norm] + refine (norm_sub_le _ _).trans_lt (add_lt_add ?_ ?_) + · refine ((norm_tsum_le_tsum_norm ((h_suma n).subtype _)).trans ?_).trans_lt h1 + exact tsum_le_tsum (h_bound n ·) ((h_suma n).subtype _) (h_sum.subtype _) + · refine ((norm_tsum_le_tsum_norm <| h_sumg.subtype _).trans ?_).trans_lt h1 + exact tsum_le_tsum (h_g_le ·) (h_sumg.subtype _) (h_sum.subtype _) diff --git a/Mathlib/Analysis/Normed/MulAction.lean b/Mathlib/Analysis/Normed/MulAction.lean index 2bc16a30ed2a4..a0aa6365984b4 100644 --- a/Mathlib/Analysis/Normed/MulAction.lean +++ b/Mathlib/Analysis/Normed/MulAction.lean @@ -78,6 +78,9 @@ theorem BoundedSMul.of_norm_smul_le (h : ∀ (r : α) (x : β), ‖r • x‖ dist_pair_smul' := fun a₁ a₂ b => by simpa [sub_smul, dist_eq_norm] using h (a₁ - a₂) b } #align has_bounded_smul.of_norm_smul_le BoundedSMul.of_norm_smul_le +theorem BoundedSMul.of_nnnorm_smul_le (h : ∀ (r : α) (x : β), ‖r • x‖₊ ≤ ‖r‖₊ * ‖x‖₊) : + BoundedSMul α β := .of_norm_smul_le h + end SeminormedRing section NormedDivisionRing diff --git a/Mathlib/Analysis/Normed/Order/Basic.lean b/Mathlib/Analysis/Normed/Order/Basic.lean index a23db1d68de29..da41706915eca 100644 --- a/Mathlib/Analysis/Normed/Order/Basic.lean +++ b/Mathlib/Analysis/Normed/Order/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker, Yaël Dillies -/ import Mathlib.Algebra.Order.Group.TypeTags -import Mathlib.Analysis.NormedSpace.Basic +import Mathlib.Analysis.Normed.Field.Basic #align_import analysis.normed.order.basic from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Analysis/Normed/Order/Lattice.lean b/Mathlib/Analysis/Normed/Order/Lattice.lean index 935f0c8e132cb..b7dcc94b997fb 100644 --- a/Mathlib/Analysis/Normed/Order/Lattice.lean +++ b/Mathlib/Analysis/Normed/Order/Lattice.lean @@ -3,9 +3,9 @@ Copyright (c) 2021 Christopher Hoskin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Christopher Hoskin -/ -import Mathlib.Topology.Order.Lattice +import Mathlib.Algebra.Order.Group.PosPart import Mathlib.Analysis.Normed.Group.Basic -import Mathlib.Algebra.Order.LatticeGroup +import Mathlib.Topology.Order.Lattice #align_import analysis.normed.order.lattice from "leanprover-community/mathlib"@"5dc275ec639221ca4d5f56938eb966f6ad9bc89f" @@ -91,16 +91,16 @@ instance (priority := 100) NormedLatticeAddCommGroup.toOrderedAddCommGroup {α : variable {α : Type*} [NormedLatticeAddCommGroup α] -open LatticeOrderedGroup LatticeOrderedCommGroup HasSolidNorm +open HasSolidNorm theorem dual_solid (a b : α) (h : b ⊓ -b ≤ a ⊓ -a) : ‖a‖ ≤ ‖b‖ := by apply solid - rw [abs_eq_sup_neg] + rw [abs] nth_rw 1 [← neg_neg a] - rw [← neg_inf_eq_sup_neg] - rw [abs_eq_sup_neg] + rw [← neg_inf] + rw [abs] nth_rw 1 [← neg_neg b] - rwa [← neg_inf_eq_sup_neg, neg_le_neg_iff, @inf_comm _ _ _ b, @inf_comm _ _ _ a] + rwa [← neg_inf, neg_le_neg_iff, @inf_comm _ _ _ b, @inf_comm _ _ _ a] #align dual_solid dual_solid -- see Note [lower instance priority] @@ -118,7 +118,7 @@ theorem norm_abs_eq_norm (a : α) : ‖|a|‖ = ‖a‖ := theorem norm_inf_sub_inf_le_add_norm (a b c d : α) : ‖a ⊓ b - c ⊓ d‖ ≤ ‖a - c‖ + ‖b - d‖ := by rw [← norm_abs_eq_norm (a - c), ← norm_abs_eq_norm (b - d)] refine' le_trans (solid _) (norm_add_le |a - c| |b - d|) - rw [abs_of_nonneg (|a - c| + |b - d|) (add_nonneg (abs_nonneg (a - c)) (abs_nonneg (b - d)))] + rw [abs_of_nonneg (add_nonneg (abs_nonneg (a - c)) (abs_nonneg (b - d)))] calc |a ⊓ b - c ⊓ d| = |a ⊓ b - c ⊓ b + (c ⊓ b - c ⊓ d)| := by rw [sub_add_sub_cancel] _ ≤ |a ⊓ b - c ⊓ b| + |c ⊓ b - c ⊓ d| := (abs_add_le _ _) @@ -132,7 +132,7 @@ theorem norm_inf_sub_inf_le_add_norm (a b c d : α) : ‖a ⊓ b - c ⊓ d‖ theorem norm_sup_sub_sup_le_add_norm (a b c d : α) : ‖a ⊔ b - c ⊔ d‖ ≤ ‖a - c‖ + ‖b - d‖ := by rw [← norm_abs_eq_norm (a - c), ← norm_abs_eq_norm (b - d)] refine' le_trans (solid _) (norm_add_le |a - c| |b - d|) - rw [abs_of_nonneg (|a - c| + |b - d|) (add_nonneg (abs_nonneg (a - c)) (abs_nonneg (b - d)))] + rw [abs_of_nonneg (add_nonneg (abs_nonneg (a - c)) (abs_nonneg (b - d)))] calc |a ⊔ b - c ⊔ d| = |a ⊔ b - c ⊔ b + (c ⊔ b - c ⊔ d)| := by rw [sub_add_sub_cancel] _ ≤ |a ⊔ b - c ⊔ b| + |c ⊔ b - c ⊔ d| := (abs_add_le _ _) @@ -180,8 +180,7 @@ instance (priority := 100) NormedLatticeAddCommGroup.toTopologicalLattice : Topo TopologicalLattice.mk #align normed_lattice_add_comm_group_topological_lattice NormedLatticeAddCommGroup.toTopologicalLattice -theorem norm_abs_sub_abs (a b : α) : ‖|a| - |b|‖ ≤ ‖a - b‖ := - solid (LatticeOrderedCommGroup.abs_abs_sub_abs_le _ _) +theorem norm_abs_sub_abs (a b : α) : ‖|a| - |b|‖ ≤ ‖a - b‖ := solid (abs_abs_sub_abs_le _ _) #align norm_abs_sub_abs norm_abs_sub_abs theorem norm_sup_sub_sup_le_norm (x y z : α) : ‖x ⊔ z - y ⊔ z‖ ≤ ‖x - y‖ := @@ -198,28 +197,23 @@ theorem lipschitzWith_sup_right (z : α) : LipschitzWith 1 fun x => x ⊔ z := exact norm_sup_sub_sup_le_norm x y z #align lipschitz_with_sup_right lipschitzWith_sup_right -theorem lipschitzWith_pos : LipschitzWith 1 (PosPart.pos : α → α) := +lemma lipschitzWith_posPart : LipschitzWith 1 (posPart : α → α) := lipschitzWith_sup_right 0 -#align lipschitz_with_pos lipschitzWith_pos - -theorem continuous_pos : Continuous (PosPart.pos : α → α) := - LipschitzWith.continuous lipschitzWith_pos -#align continuous_pos continuous_pos - -theorem continuous_neg' : Continuous (NegPart.neg : α → α) := by - refine continuous_pos.comp <| @continuous_neg _ _ _ TopologicalAddGroup.toContinuousNeg - -- porting note: see the [Zulip thread](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/can't.20infer.20.60ContinuousNeg.60) -#align continuous_neg' continuous_neg' - -theorem isClosed_nonneg {E} [NormedLatticeAddCommGroup E] : IsClosed { x : E | 0 ≤ x } := by - suffices { x : E | 0 ≤ x } = NegPart.neg ⁻¹' {(0 : E)} by - rw [this] - exact IsClosed.preimage continuous_neg' isClosed_singleton - ext1 x - simp only [Set.mem_preimage, Set.mem_singleton_iff, Set.mem_setOf_eq, - @neg_eq_zero_iff E _ _ (OrderedAddCommGroup.to_covariantClass_left_le E)] - -- porting note: I'm not sure why Lean couldn't synthesize this instance because it works with - -- `have : CovariantClass E E (· + ·) (· ≤ ·) := inferInstance` +#align lipschitz_with_pos lipschitzWith_posPart + +lemma lipschitzWith_negPart : LipschitzWith 1 (negPart : α → α) := by + simpa [Function.comp] using lipschitzWith_posPart.comp LipschitzWith.id.neg + +lemma continuous_posPart : Continuous (posPart : α → α) := lipschitzWith_posPart.continuous +#align continuous_pos continuous_posPart + +lemma continuous_negPart : Continuous (negPart : α → α) := lipschitzWith_negPart.continuous +#align continuous_neg' continuous_negPart + +lemma isClosed_nonneg : IsClosed {x : α | 0 ≤ x} := by + have : {x : α | 0 ≤ x} = negPart ⁻¹' {0} := by ext; simp [negPart_eq_zero] + rw [this] + exact isClosed_singleton.preimage continuous_negPart #align is_closed_nonneg isClosed_nonneg theorem isClosed_le_of_isClosed_nonneg {G} [OrderedAddCommGroup G] [TopologicalSpace G] diff --git a/Mathlib/Analysis/Normed/Order/UpperLower.lean b/Mathlib/Analysis/Normed/Order/UpperLower.lean index 537a980a9abab..dad1c312e85bc 100644 --- a/Mathlib/Analysis/Normed/Order/UpperLower.lean +++ b/Mathlib/Analysis/Normed/Order/UpperLower.lean @@ -6,7 +6,8 @@ Authors: Yaël Dillies import Mathlib.Algebra.Order.Field.Pi import Mathlib.Analysis.Normed.Group.Pointwise import Mathlib.Analysis.Normed.Order.Basic -import Mathlib.Topology.Algebra.Order.UpperLower +import Mathlib.Algebra.Order.UpperLower +import Mathlib.Data.Real.Sqrt #align_import analysis.normed.order.upper_lower from "leanprover-community/mathlib"@"992efbda6f85a5c9074375d3c7cb9764c64d8f72" diff --git a/Mathlib/Analysis/Normed/Ring/Seminorm.lean b/Mathlib/Analysis/Normed/Ring/Seminorm.lean index 7f494e762968f..be2fc0244156d 100644 --- a/Mathlib/Analysis/Normed/Ring/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Ring/Seminorm.lean @@ -92,9 +92,9 @@ instance ringSeminormClass : RingSeminormClass (RingSeminorm R) R ℝ where map_neg_eq_map f := f.neg' #align ring_seminorm.ring_seminorm_class RingSeminorm.ringSeminormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ instance : CoeFun (RingSeminorm R) fun _ => R → ℝ := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[simp] theorem toFun_eq_coe (p : RingSeminorm R) : (p.toAddGroupSeminorm : R → ℝ) = p := @@ -103,7 +103,7 @@ theorem toFun_eq_coe (p : RingSeminorm R) : (p.toAddGroupSeminorm : R → ℝ) = @[ext] theorem ext {p q : RingSeminorm R} : (∀ x, p x = q x) → p = q := - FunLike.ext p q + DFunLike.ext p q #align ring_seminorm.ext RingSeminorm.ext instance : Zero (RingSeminorm R) := @@ -111,7 +111,7 @@ instance : Zero (RingSeminorm R) := fun _ _ => (zero_mul _).ge }⟩ theorem eq_zero_iff {p : RingSeminorm R} : p = 0 ↔ ∀ x, p x = 0 := - FunLike.ext_iff + DFunLike.ext_iff #align ring_seminorm.eq_zero_iff RingSeminorm.eq_zero_iff theorem ne_zero_iff {p : RingSeminorm R} : p ≠ 0 ↔ ∃ x, p x ≠ 0 := by simp [eq_zero_iff] @@ -191,7 +191,7 @@ instance ringNormClass : RingNormClass (RingNorm R) R ℝ where eq_zero_of_map_eq_zero f := f.eq_zero_of_map_eq_zero' _ #align ring_norm.ring_norm_class RingNorm.ringNormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ instance : CoeFun (RingNorm R) fun _ => R → ℝ := ⟨fun p => p.toFun⟩ @@ -202,7 +202,7 @@ instance : CoeFun (RingNorm R) fun _ => R → ℝ := @[ext] theorem ext {p q : RingNorm R} : (∀ x, p x = q x) → p = q := - FunLike.ext p q + DFunLike.ext p q #align ring_norm.ext RingNorm.ext variable (R) @@ -241,9 +241,9 @@ instance mulRingSeminormClass : MulRingSeminormClass (MulRingSeminorm R) R ℝ w map_neg_eq_map f := f.neg' #align mul_ring_seminorm.mul_ring_seminorm_class MulRingSeminorm.mulRingSeminormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ instance : CoeFun (MulRingSeminorm R) fun _ => R → ℝ := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[simp] theorem toFun_eq_coe (p : MulRingSeminorm R) : (p.toAddGroupSeminorm : R → ℝ) = p := @@ -252,7 +252,7 @@ theorem toFun_eq_coe (p : MulRingSeminorm R) : (p.toAddGroupSeminorm : R → ℝ @[ext] theorem ext {p q : MulRingSeminorm R} : (∀ x, p x = q x) → p = q := - FunLike.ext p q + DFunLike.ext p q #align mul_ring_seminorm.ext MulRingSeminorm.ext variable [DecidableEq R] [NoZeroDivisors R] [Nontrivial R] @@ -299,7 +299,7 @@ instance mulRingNormClass : MulRingNormClass (MulRingNorm R) R ℝ where eq_zero_of_map_eq_zero f := f.eq_zero_of_map_eq_zero' _ #align mul_ring_norm.mul_ring_norm_class MulRingNorm.mulRingNormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ instance : CoeFun (MulRingNorm R) fun _ => R → ℝ := ⟨fun p => p.toFun⟩ @@ -310,7 +310,7 @@ instance : CoeFun (MulRingNorm R) fun _ => R → ℝ := @[ext] theorem ext {p q : MulRingNorm R} : (∀ x, p x = q x) → p = q := - FunLike.ext p q + DFunLike.ext p q #align mul_ring_norm.ext MulRingNorm.ext variable (R) diff --git a/Mathlib/Analysis/NormedSpace/AddTorsor.lean b/Mathlib/Analysis/NormedSpace/AddTorsor.lean index d62a98fefaa43..807d962920c17 100644 --- a/Mathlib/Analysis/NormedSpace/AddTorsor.lean +++ b/Mathlib/Analysis/NormedSpace/AddTorsor.lean @@ -3,9 +3,9 @@ Copyright (c) 2020 Joseph Myers. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Myers, Yury Kudryashov -/ +import Mathlib.Algebra.CharP.Invertible import Mathlib.Analysis.NormedSpace.Basic import Mathlib.Analysis.Normed.Group.AddTorsor -import Mathlib.LinearAlgebra.AffineSpace.MidpointZero import Mathlib.LinearAlgebra.AffineSpace.AffineSubspace import Mathlib.Topology.Instances.RealVectorSpace diff --git a/Mathlib/Analysis/NormedSpace/AddTorsorBases.lean b/Mathlib/Analysis/NormedSpace/AddTorsorBases.lean index 1448306a2e444..20900bec64c75 100644 --- a/Mathlib/Analysis/NormedSpace/AddTorsorBases.lean +++ b/Mathlib/Analysis/NormedSpace/AddTorsorBases.lean @@ -116,8 +116,7 @@ theorem IsOpen.exists_between_affineIndependent_span_eq_top {s u : Set P} (hu : #align is_open.exists_between_affine_independent_span_eq_top IsOpen.exists_between_affineIndependent_span_eq_top theorem IsOpen.exists_subset_affineIndependent_span_eq_top {u : Set P} (hu : IsOpen u) - (hne : u.Nonempty) : - ∃ (s : _) (_ : s ⊆ u), AffineIndependent ℝ ((↑) : s → P) ∧ affineSpan ℝ s = ⊤ := by + (hne : u.Nonempty) : ∃ s ⊆ u, AffineIndependent ℝ ((↑) : s → P) ∧ affineSpan ℝ s = ⊤ := by rcases hne with ⟨x, hx⟩ rcases hu.exists_between_affineIndependent_span_eq_top (singleton_subset_iff.mpr hx) (singleton_nonempty _) (affineIndependent_of_subsingleton _ _) with ⟨s, -, hsu, hs⟩ diff --git a/Mathlib/Analysis/NormedSpace/AffineIsometry.lean b/Mathlib/Analysis/NormedSpace/AffineIsometry.lean index a07419f801902..6858cb0aa4a59 100644 --- a/Mathlib/Analysis/NormedSpace/AffineIsometry.lean +++ b/Mathlib/Analysis/NormedSpace/AffineIsometry.lean @@ -71,7 +71,7 @@ theorem linear_eq_linearIsometry : f.linear = f.linearIsometry.toLinearMap := by rfl #align affine_isometry.linear_eq_linear_isometry AffineIsometry.linear_eq_linearIsometry -instance : FunLike (P →ᵃⁱ[𝕜] P₂) P fun _ => P₂ := +instance : FunLike (P →ᵃⁱ[𝕜] P₂) P P₂ := { coe := fun f => f.toFun, coe_injective' := fun f g => by cases f; cases g; simp } @@ -337,7 +337,7 @@ instance : EquivLike (P ≃ᵃⁱ[𝕜] P₂) P P₂ := cases f cases g congr - simpa [FunLike.coe_injective.eq_iff] using h } + simpa [DFunLike.coe_injective.eq_iff] using h } @[simp] theorem coe_mk (e : P ≃ᵃ[𝕜] P₂) (he : ∀ x, ‖e.linear x‖ = ‖x‖) : ⇑(mk e he) = e := diff --git a/Mathlib/Analysis/NormedSpace/Banach.lean b/Mathlib/Analysis/NormedSpace/Banach.lean index 079f01e27c131..058f5113d77ea 100644 --- a/Mathlib/Analysis/NormedSpace/Banach.lean +++ b/Mathlib/Analysis/NormedSpace/Banach.lean @@ -94,72 +94,59 @@ theorem exists_approx_preimage_norm_le (surj : Surjective f) : simp only [mem_interior_iff_mem_nhds, Metric.mem_nhds_iff] at this rcases this with ⟨n, a, ε, ⟨εpos, H⟩⟩ rcases NormedField.exists_one_lt_norm 𝕜 with ⟨c, hc⟩ - refine' ⟨(ε / 2)⁻¹ * ‖c‖ * 2 * n, _, fun y => _⟩ - · refine' mul_nonneg (mul_nonneg (mul_nonneg _ (norm_nonneg _)) (by norm_num)) _ - exacts [inv_nonneg.2 (div_nonneg (le_of_lt εpos) (by norm_num)), n.cast_nonneg] - · by_cases hy : y = 0 - · use 0 - simp [hy] - · rcases rescale_to_shell hc (half_pos εpos) hy with ⟨d, hd, ydlt, -, dinv⟩ - let δ := ‖d‖ * ‖y‖ / 4 - have δpos : 0 < δ := div_pos (mul_pos (norm_pos_iff.2 hd) (norm_pos_iff.2 hy)) (by norm_num) - have : a + d • y ∈ ball a ε := by - simp [dist_eq_norm, lt_of_le_of_lt ydlt.le (half_lt_self εpos)] - rcases Metric.mem_closure_iff.1 (H this) _ δpos with ⟨z₁, z₁im, h₁⟩ - rcases (mem_image _ _ _).1 z₁im with ⟨x₁, hx₁, xz₁⟩ - rw [← xz₁] at h₁ - rw [mem_ball, dist_eq_norm, sub_zero] at hx₁ - have : a ∈ ball a ε := by - simp only [mem_ball, dist_self] - exact εpos - rcases Metric.mem_closure_iff.1 (H this) _ δpos with ⟨z₂, z₂im, h₂⟩ - rcases (mem_image _ _ _).1 z₂im with ⟨x₂, hx₂, xz₂⟩ - rw [← xz₂] at h₂ - rw [mem_ball, dist_eq_norm, sub_zero] at hx₂ - let x := x₁ - x₂ - have I : ‖f x - d • y‖ ≤ 2 * δ := - calc - ‖f x - d • y‖ = ‖f x₁ - (a + d • y) - (f x₂ - a)‖ := by - congr 1 - simp only [f.map_sub] - abel - _ ≤ ‖f x₁ - (a + d • y)‖ + ‖f x₂ - a‖ := (norm_sub_le _ _) - _ ≤ δ + δ := by - apply add_le_add - · rw [← dist_eq_norm, dist_comm] - exact le_of_lt h₁ - · rw [← dist_eq_norm, dist_comm] - exact le_of_lt h₂ - _ = 2 * δ := (two_mul _).symm - have J : ‖f (d⁻¹ • x) - y‖ ≤ 1 / 2 * ‖y‖ := - calc - ‖f (d⁻¹ • x) - y‖ = ‖d⁻¹ • f x - (d⁻¹ * d) • y‖ := by - rwa [f.map_smul _, inv_mul_cancel, one_smul] - _ = ‖d⁻¹ • (f x - d • y)‖ := by rw [mul_smul, smul_sub] - _ = ‖d‖⁻¹ * ‖f x - d • y‖ := by rw [norm_smul, norm_inv] - _ ≤ ‖d‖⁻¹ * (2 * δ) := by - apply mul_le_mul_of_nonneg_left I - rw [inv_nonneg] - exact norm_nonneg _ - _ = ‖d‖⁻¹ * ‖d‖ * ‖y‖ / 2 := by - simp only - ring - _ = ‖y‖ / 2 := by - rw [inv_mul_cancel, one_mul] - simp [norm_eq_zero, hd] - _ = 1 / 2 * ‖y‖ := by ring - rw [← dist_eq_norm] at J - have K : ‖d⁻¹ • x‖ ≤ (ε / 2)⁻¹ * ‖c‖ * 2 * ↑n * ‖y‖ := - calc - ‖d⁻¹ • x‖ = ‖d‖⁻¹ * ‖x₁ - x₂‖ := by rw [norm_smul, norm_inv] - _ ≤ (ε / 2)⁻¹ * ‖c‖ * ‖y‖ * (n + n) := by - refine' mul_le_mul dinv _ (norm_nonneg _) _ - · exact le_trans (norm_sub_le _ _) (add_le_add (le_of_lt hx₁) (le_of_lt hx₂)) - · apply mul_nonneg (mul_nonneg _ (norm_nonneg _)) (norm_nonneg _) - exact inv_nonneg.2 (le_of_lt (half_pos εpos)) - _ = (ε / 2)⁻¹ * ‖c‖ * 2 * ↑n * ‖y‖ := by ring - - exact ⟨d⁻¹ • x, J, K⟩ + refine ⟨(ε / 2)⁻¹ * ‖c‖ * 2 * n, by positivity, fun y => ?_⟩ + rcases eq_or_ne y 0 with rfl | hy + · use 0 + simp + · rcases rescale_to_shell hc (half_pos εpos) hy with ⟨d, hd, ydlt, -, dinv⟩ + let δ := ‖d‖ * ‖y‖ / 4 + have δpos : 0 < δ := div_pos (mul_pos (norm_pos_iff.2 hd) (norm_pos_iff.2 hy)) (by norm_num) + have : a + d • y ∈ ball a ε := by + simp [dist_eq_norm, lt_of_le_of_lt ydlt.le (half_lt_self εpos)] + rcases Metric.mem_closure_iff.1 (H this) _ δpos with ⟨z₁, z₁im, h₁⟩ + rcases (mem_image _ _ _).1 z₁im with ⟨x₁, hx₁, xz₁⟩ + rw [← xz₁] at h₁ + rw [mem_ball, dist_eq_norm, sub_zero] at hx₁ + have : a ∈ ball a ε := by + simp only [mem_ball, dist_self] + exact εpos + rcases Metric.mem_closure_iff.1 (H this) _ δpos with ⟨z₂, z₂im, h₂⟩ + rcases (mem_image _ _ _).1 z₂im with ⟨x₂, hx₂, xz₂⟩ + rw [← xz₂] at h₂ + rw [mem_ball, dist_eq_norm, sub_zero] at hx₂ + let x := x₁ - x₂ + have I : ‖f x - d • y‖ ≤ 2 * δ := + calc + ‖f x - d • y‖ = ‖f x₁ - (a + d • y) - (f x₂ - a)‖ := by + congr 1 + simp only [f.map_sub] + abel + _ ≤ ‖f x₁ - (a + d • y)‖ + ‖f x₂ - a‖ := (norm_sub_le _ _) + _ ≤ δ + δ := by rw [dist_eq_norm'] at h₁ h₂; gcongr + _ = 2 * δ := (two_mul _).symm + have J : ‖f (d⁻¹ • x) - y‖ ≤ 1 / 2 * ‖y‖ := + calc + ‖f (d⁻¹ • x) - y‖ = ‖d⁻¹ • f x - (d⁻¹ * d) • y‖ := by + rwa [f.map_smul _, inv_mul_cancel, one_smul] + _ = ‖d⁻¹ • (f x - d • y)‖ := by rw [mul_smul, smul_sub] + _ = ‖d‖⁻¹ * ‖f x - d • y‖ := by rw [norm_smul, norm_inv] + _ ≤ ‖d‖⁻¹ * (2 * δ) := by gcongr + _ = ‖d‖⁻¹ * ‖d‖ * ‖y‖ / 2 := by + simp only + ring + _ = ‖y‖ / 2 := by + rw [inv_mul_cancel, one_mul] + simp [norm_eq_zero, hd] + _ = 1 / 2 * ‖y‖ := by ring + rw [← dist_eq_norm] at J + have K : ‖d⁻¹ • x‖ ≤ (ε / 2)⁻¹ * ‖c‖ * 2 * ↑n * ‖y‖ := + calc + ‖d⁻¹ • x‖ = ‖d‖⁻¹ * ‖x₁ - x₂‖ := by rw [norm_smul, norm_inv] + _ ≤ (ε / 2)⁻¹ * ‖c‖ * ‖y‖ * (n + n) := by + gcongr + exact le_trans (norm_sub_le _ _) (by gcongr) + _ = (ε / 2)⁻¹ * ‖c‖ * 2 * ↑n * ‖y‖ := by ring + exact ⟨d⁻¹ • x, J, K⟩ #align continuous_linear_map.exists_approx_preimage_norm_le ContinuousLinearMap.exists_approx_preimage_norm_le variable [CompleteSpace E] @@ -189,12 +176,10 @@ theorem exists_preimage_norm_le (surj : Surjective f) : · rw [iterate_succ'] apply le_trans (hle _) _ rw [pow_succ, mul_assoc] - apply mul_le_mul_of_nonneg_left IH - norm_num + gcongr let u n := g (h^[n] y) - have ule : ∀ n, ‖u n‖ ≤ (1 / 2) ^ n * (C * ‖y‖) := by - intro n - apply le_trans (hg _).2 _ + have ule : ∀ n, ‖u n‖ ≤ (1 / 2) ^ n * (C * ‖y‖) := fun n ↦ by + apply le_trans (hg _).2 calc C * ‖h^[n] y‖ ≤ C * ((1 / 2) ^ n * ‖y‖) := mul_le_mul_of_nonneg_left (hnle n) C0 _ = (1 / 2) ^ n * (C * ‖y‖) := by ring @@ -353,6 +338,30 @@ theorem coeFn_toContinuousLinearEquivOfContinuous_symm (e : E ≃ₗ[𝕜] F) (h end LinearEquiv +namespace ContinuousLinearMap + +variable [CompleteSpace E] + +/-- An injective continuous linear map with a closed range defines a continuous linear equivalence +between its domain and its range. -/ +noncomputable def equivRange (f : E →L[𝕜] F) (hinj : Injective f) (hclo : IsClosed (range f)) : + E ≃L[𝕜] LinearMap.range f := + have : CompleteSpace (LinearMap.range f) := hclo.completeSpace_coe + LinearEquiv.toContinuousLinearEquivOfContinuous (LinearEquiv.ofInjective f.toLinearMap hinj) <| + (f.continuous.codRestrict fun x ↦ LinearMap.mem_range_self f x).congr fun _ ↦ rfl + +@[simp] +theorem coe_linearMap_equivRange (f : E →L[𝕜] F) (hinj : Injective f) (hclo : IsClosed (range f)) : + f.equivRange hinj hclo = f.rangeRestrict := + rfl + +@[simp] +theorem coe_equivRange (f : E →L[𝕜] F) (hinj : Injective f) (hclo : IsClosed (range f)) : + (f.equivRange hinj hclo : E → LinearMap.range f) = f.rangeRestrict := + rfl + +end ContinuousLinearMap + namespace ContinuousLinearEquiv variable [CompleteSpace E] diff --git a/Mathlib/Analysis/NormedSpace/Basic.lean b/Mathlib/Analysis/NormedSpace/Basic.lean index ecc9815a46f51..601f304da34cd 100644 --- a/Mathlib/Analysis/NormedSpace/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Basic.lean @@ -7,7 +7,6 @@ import Mathlib.Algebra.Algebra.Pi import Mathlib.Algebra.Algebra.RestrictScalars import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Analysis.Normed.MulAction -import Mathlib.Data.Real.Sqrt import Mathlib.Topology.Algebra.Module.Basic #align_import analysis.normed_space.basic from "leanprover-community/mathlib"@"bc91ed7093bf098d253401e69df601fc33dde156" diff --git a/Mathlib/Analysis/NormedSpace/CompactOperator.lean b/Mathlib/Analysis/NormedSpace/CompactOperator.lean index 97e90601a36ce..29fe55bc5ab36 100644 --- a/Mathlib/Analysis/NormedSpace/CompactOperator.lean +++ b/Mathlib/Analysis/NormedSpace/CompactOperator.lean @@ -101,7 +101,7 @@ theorem IsCompactOperator.image_subset_compact_of_isVonNBounded {f : M₁ →ₛ (hf : IsCompactOperator f) {S : Set M₁} (hS : IsVonNBounded 𝕜₁ S) : ∃ K : Set M₂, IsCompact K ∧ f '' S ⊆ K := let ⟨K, hK, hKf⟩ := hf - let ⟨r, hr, hrS⟩ := hS hKf + let ⟨r, hr, hrS⟩ := (hS hKf).exists_pos let ⟨c, hc⟩ := NormedField.exists_lt_norm 𝕜₁ r let this := ne_zero_of_norm_ne_zero (hr.trans hc).ne.symm ⟨σ₁₂ c • K, hK.image <| continuous_id.const_smul (σ₁₂ c), by @@ -346,7 +346,7 @@ theorem IsCompactOperator.continuous {f : M₁ →ₛₗ[σ₁₂] M₂} (hf : I rcases hf with ⟨K, hK, hKf⟩ -- But any compact set is totally bounded, hence Von-Neumann bounded. Thus, `K` absorbs `U`. -- This gives `r > 0` such that `∀ a : 𝕜₂, r ≤ ‖a‖ → K ⊆ a • U`. - rcases hK.totallyBounded.isVonNBounded 𝕜₂ hU with ⟨r, hr, hrU⟩ + rcases (hK.totallyBounded.isVonNBounded 𝕜₂ hU).exists_pos with ⟨r, hr, hrU⟩ -- Choose `c : 𝕜₂` with `r < ‖c‖`. rcases NormedField.exists_lt_norm 𝕜₁ r with ⟨c, hc⟩ have hcnz : c ≠ 0 := ne_zero_of_norm_ne_zero (hr.trans hc).ne.symm diff --git a/Mathlib/Analysis/NormedSpace/Complemented.lean b/Mathlib/Analysis/NormedSpace/Complemented.lean index 62efcfe659b47..0403a68c6de83 100644 --- a/Mathlib/Analysis/NormedSpace/Complemented.lean +++ b/Mathlib/Analysis/NormedSpace/Complemented.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Analysis.NormedSpace.Banach -import Mathlib.Analysis.NormedSpace.FiniteDimension +import Mathlib.Topology.Algebra.Module.FiniteDimension #align_import analysis.normed_space.complemented from "leanprover-community/mathlib"@"3397560e65278e5f31acefcdea63138bd53d1cd4" diff --git a/Mathlib/Analysis/NormedSpace/ConformalLinearMap.lean b/Mathlib/Analysis/NormedSpace/ConformalLinearMap.lean index 32cd7977c5952..0103e7f332bd0 100644 --- a/Mathlib/Analysis/NormedSpace/ConformalLinearMap.lean +++ b/Mathlib/Analysis/NormedSpace/ConformalLinearMap.lean @@ -48,7 +48,7 @@ open Function LinearIsometry ContinuousLinearMap a nonzero multiple of a linear isometry. -/ def IsConformalMap {R : Type*} {X Y : Type*} [NormedField R] [SeminormedAddCommGroup X] [SeminormedAddCommGroup Y] [NormedSpace R X] [NormedSpace R Y] (f' : X →L[R] Y) := - ∃ (c : R) (_ : c ≠ 0) (li : X →ₗᵢ[R] Y), f' = c • li.toContinuousLinearMap + ∃ c ≠ (0 : R), ∃ li : X →ₗᵢ[R] Y, f' = c • li.toContinuousLinearMap #align is_conformal_map IsConformalMap variable {R M N G M' : Type*} [NormedField R] [SeminormedAddCommGroup M] [SeminormedAddCommGroup N] diff --git a/Mathlib/Analysis/NormedSpace/Extend.lean b/Mathlib/Analysis/NormedSpace/Extend.lean index e71c718e8ecc6..eba7ed8ae9366 100644 --- a/Mathlib/Analysis/NormedSpace/Extend.lean +++ b/Mathlib/Analysis/NormedSpace/Extend.lean @@ -94,7 +94,7 @@ theorem norm_extendTo𝕜'_apply_sq (fr : F →ₗ[ℝ] ℝ) (x : F) : ‖(fr.extendTo𝕜' x : 𝕜)‖ ^ 2 = fr (conj (fr.extendTo𝕜' x : 𝕜) • x) := calc ‖(fr.extendTo𝕜' x : 𝕜)‖ ^ 2 = re (conj (fr.extendTo𝕜' x) * fr.extendTo𝕜' x : 𝕜) := by - rw [IsROrC.conj_mul, normSq_eq_def', ofReal_re] + rw [IsROrC.conj_mul, ← ofReal_pow, ofReal_re] _ = fr (conj (fr.extendTo𝕜' x : 𝕜) • x) := by rw [← smul_eq_mul, ← map_smul, extendTo𝕜'_apply_re] #align linear_map.norm_extend_to_𝕜'_apply_sq LinearMap.norm_extendTo𝕜'_apply_sq diff --git a/Mathlib/Analysis/NormedSpace/FiniteDimension.lean b/Mathlib/Analysis/NormedSpace/FiniteDimension.lean index e759852b0180e..140f8cf54dbba 100644 --- a/Mathlib/Analysis/NormedSpace/FiniteDimension.lean +++ b/Mathlib/Analysis/NormedSpace/FiniteDimension.lean @@ -278,7 +278,7 @@ theorem Basis.op_nnnorm_le {ι : Type*} [Fintype ι] (v : Basis ι 𝕜 E) {u : _ ≤ ∑ i, ‖v.equivFun e i • (u <| v i)‖₊ := (nnnorm_sum_le _ _) _ = ∑ i, ‖v.equivFun e i‖₊ * ‖u (v i)‖₊ := by simp only [nnnorm_smul] _ ≤ ∑ i, ‖v.equivFun e i‖₊ * M := by gcongr; apply hu - _ = (∑ i, ‖v.equivFun e i‖₊) * M := Finset.sum_mul.symm + _ = (∑ i, ‖v.equivFun e i‖₊) * M := by rw [Finset.sum_mul] _ ≤ Fintype.card ι • (‖φ‖₊ * ‖e‖₊) * M := by gcongr calc @@ -568,7 +568,7 @@ theorem continuousOn_clm_apply {X : Type*} [TopologicalSpace X] [FiniteDimension let e₁ : E ≃L[𝕜] Fin d → 𝕜 := ContinuousLinearEquiv.ofFinrankEq hd let e₂ : (E →L[𝕜] F) ≃L[𝕜] Fin d → F := (e₁.arrowCongr (1 : F ≃L[𝕜] F)).trans (ContinuousLinearEquiv.piRing (Fin d)) - rw [← Function.comp.left_id f, ← e₂.symm_comp_self] + rw [← f.id_comp, ← e₂.symm_comp_self] exact e₂.symm.continuous.comp_continuousOn (continuousOn_pi.mpr fun i => h _) #align continuous_on_clm_apply continuousOn_clm_apply diff --git a/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean b/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean index 6dfa6ca5bab72..a4dbeb4070a11 100644 --- a/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean +++ b/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean @@ -134,7 +134,7 @@ lemma ContinuousLinearMap.exist_extension_of_finiteDimensional_range {p : Submod lemma Submodule.ClosedComplemented.of_finiteDimensional (p : Submodule 𝕜 F) [FiniteDimensional 𝕜 p] : p.ClosedComplemented := let ⟨g, hg⟩ := (ContinuousLinearMap.id 𝕜 p).exist_extension_of_finiteDimensional_range - ⟨g, FunLike.congr_fun hg.symm⟩ + ⟨g, DFunLike.congr_fun hg.symm⟩ end IsROrC diff --git a/Mathlib/Analysis/NormedSpace/HomeomorphBall.lean b/Mathlib/Analysis/NormedSpace/HomeomorphBall.lean index 96a84b8da3d83..e7e68c251b3a0 100644 --- a/Mathlib/Analysis/NormedSpace/HomeomorphBall.lean +++ b/Mathlib/Analysis/NormedSpace/HomeomorphBall.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Oliver Nash -/ import Mathlib.Topology.PartialHomeomorph -import Mathlib.Analysis.NormedSpace.AddTorsor +import Mathlib.Analysis.Normed.Group.AddTorsor import Mathlib.Analysis.NormedSpace.Pointwise +import Mathlib.Data.Real.Sqrt #align_import analysis.normed_space.basic from "leanprover-community/mathlib"@"bc91ed7093bf098d253401e69df601fc33dde156" diff --git a/Mathlib/Analysis/NormedSpace/LinearIsometry.lean b/Mathlib/Analysis/NormedSpace/LinearIsometry.lean index 64815cc752a59..c844dcebf214b 100644 --- a/Mathlib/Analysis/NormedSpace/LinearIsometry.lean +++ b/Mathlib/Analysis/NormedSpace/LinearIsometry.lean @@ -144,13 +144,13 @@ theorem toLinearMap_inj {f g : E →ₛₗᵢ[σ₁₂] E₂} : f.toLinearMap = instance : SemilinearIsometryClass (E →ₛₗᵢ[σ₁₂] E₂) σ₁₂ E E₂ where coe f := f.toFun - coe_injective' _ _ h := toLinearMap_injective (FunLike.coe_injective h) + coe_injective' _ _ h := toLinearMap_injective (DFunLike.coe_injective h) map_add f := map_add f.toLinearMap map_smulₛₗ f := map_smulₛₗ f.toLinearMap norm_map f := f.norm_map' -- porting note: These helper instances are unhelpful in Lean 4, so omitting: --- /-- Helper instance for when there's too many metavariables to apply `FunLike.has_coe_to_fun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.has_coe_to_fun` -- directly. -- -/ -- instance : CoeFun (E →ₛₗᵢ[σ₁₂] E₂) fun _ => E → E₂ := @@ -526,7 +526,7 @@ instance (priority := 100) [s : SemilinearIsometryEquivClass 𝓕 σ₁₂ E E SemilinearIsometryClass 𝓕 σ₁₂ E E₂ := { s with coe := ((↑) : 𝓕 → E → E₂) - coe_injective' := @FunLike.coe_injective 𝓕 _ _ _ } + coe_injective' := @DFunLike.coe_injective 𝓕 _ _ _ } end SemilinearIsometryEquivClass @@ -551,7 +551,7 @@ instance : SemilinearIsometryEquivClass (E ≃ₛₗᵢ[σ₁₂] E₂) σ₁₂ cases' g with g' _ cases f' cases g' - simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, FunLike.coe_fn_eq] at h₁ + simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, DFunLike.coe_fn_eq] at h₁ congr left_inv e := e.left_inv right_inv e := e.right_inv @@ -559,14 +559,14 @@ instance : SemilinearIsometryEquivClass (E ≃ₛₗᵢ[σ₁₂] E₂) σ₁₂ map_smulₛₗ e := map_smulₛₗ e.toLinearEquiv norm_map e := e.norm_map' -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (E ≃ₛₗᵢ[σ₁₂] E₂) fun _ => E → E₂ := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ theorem coe_injective : @Function.Injective (E ≃ₛₗᵢ[σ₁₂] E₂) (E → E₂) (↑) := - FunLike.coe_injective + DFunLike.coe_injective #align linear_isometry_equiv.coe_injective LinearIsometryEquiv.coe_injective @[simp] diff --git a/Mathlib/Analysis/NormedSpace/MStructure.lean b/Mathlib/Analysis/NormedSpace/MStructure.lean index a1edf05ce370c..9250843d1198e 100644 --- a/Mathlib/Analysis/NormedSpace/MStructure.lean +++ b/Mathlib/Analysis/NormedSpace/MStructure.lean @@ -5,6 +5,7 @@ Authors: Christopher Hoskin -/ import Mathlib.Algebra.Ring.Idempotents import Mathlib.Analysis.Normed.Group.Basic +import Mathlib.Order.Basic import Mathlib.Tactic.NoncommRing #align_import analysis.normed_space.M_structure from "leanprover-community/mathlib"@"d11893b411025250c8e61ff2f12ccbd7ee35ab15" diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean index 508e3a1bdf050..750baf3b15b28 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean @@ -48,9 +48,8 @@ suppress_compilation noncomputable section -open BigOperators NNReal - -open Finset Metric +open scoped BigOperators NNReal Topology +open Finset Metric Function Filter /- Porting note: These lines are not required in Mathlib4. @@ -76,13 +75,15 @@ We use the following type variables in this file: universe u v v' wE wE₁ wE' wEi wG wG' +section Seminorm + variable {𝕜 : Type u} {ι : Type v} {ι' : Type v'} {n : ℕ} {E : ι → Type wE} {E₁ : ι → Type wE₁} {E' : ι' → Type wE'} {Ei : Fin n.succ → Type wEi} {G : Type wG} {G' : Type wG'} [Fintype ι] - [Fintype ι'] [NontriviallyNormedField 𝕜] [∀ i, NormedAddCommGroup (E i)] - [∀ i, NormedSpace 𝕜 (E i)] [∀ i, NormedAddCommGroup (E₁ i)] [∀ i, NormedSpace 𝕜 (E₁ i)] - [∀ i, NormedAddCommGroup (E' i)] [∀ i, NormedSpace 𝕜 (E' i)] [∀ i, NormedAddCommGroup (Ei i)] - [∀ i, NormedSpace 𝕜 (Ei i)] [NormedAddCommGroup G] [NormedSpace 𝕜 G] [NormedAddCommGroup G'] - [NormedSpace 𝕜 G'] + [Fintype ι'] [NontriviallyNormedField 𝕜] [∀ i, SeminormedAddCommGroup (E i)] + [∀ i, NormedSpace 𝕜 (E i)] [∀ i, SeminormedAddCommGroup (E₁ i)] [∀ i, NormedSpace 𝕜 (E₁ i)] + [∀ i, SeminormedAddCommGroup (E' i)] [∀ i, NormedSpace 𝕜 (E' i)] + [∀ i, SeminormedAddCommGroup (Ei i)] [∀ i, NormedSpace 𝕜 (Ei i)] + [SeminormedAddCommGroup G] [NormedSpace 𝕜 G] [SeminormedAddCommGroup G'] [NormedSpace 𝕜 G'] /-! ### Continuity properties of multilinear maps @@ -91,25 +92,54 @@ We relate continuity of multilinear maps to the inequality `‖f m‖ ≤ C * both directions. Along the way, we prove useful bounds on the difference `‖f m₁ - f m₂‖`. -/ - namespace MultilinearMap variable (f : MultilinearMap 𝕜 E G) -/-- If a multilinear map in finitely many variables on normed spaces satisfies the inequality -`‖f m‖ ≤ C * ∏ i, ‖m i‖` on a shell `ε i / ‖c i‖ < ‖m i‖ < ε i` for some positive numbers `ε i` -and elements `c i : 𝕜`, `1 < ‖c i‖`, then it satisfies this inequality for all `m`. -/ -theorem bound_of_shell {ε : ι → ℝ} {C : ℝ} (hε : ∀ i, 0 < ε i) {c : ι → 𝕜} (hc : ∀ i, 1 < ‖c i‖) +/-- If `f` is a continuous multilinear map in finitely many variables on `E` and `m` is an element +of `∀ i, E i` such that one of the `m i` has norm `0`, then `f m` has norm `0`. + +Note that we cannot drop the continuity assumption because `f (m : Unit → E) = f (m ())`, +where the domain has zero norm and the codomain has a nonzero norm +does not satisfy this condition. -/ +lemma norm_map_coord_zero (hf : Continuous f) {m : ∀ i, E i} {i : ι} (hi : ‖m i‖ = 0) : + ‖f m‖ = 0 := by + classical + have : Nonempty ι := ⟨i⟩ + set m' : 𝕜 → ∀ i, E i := fun ε : 𝕜 ↦ update (ε • m) i (ε⁻¹ ^ (Fintype.card ι) • ((ε • m) i)) + have A : Tendsto m' (𝓝[≠] 0) (𝓝 0) := by + rw [← update_eq_self i (0 : ∀ i, E i)] + refine (Tendsto.mono_left ?_ inf_le_left).update i ?_ + · exact (continuous_id.smul continuous_const).tendsto' _ _ (zero_smul _ m) + · refine NormedAddCommGroup.tendsto_nhds_zero.2 fun r hr ↦ eventually_mem_nhdsWithin.mono ?_ + simp [norm_smul, *] + have B : Tendsto (‖f <| m' ·‖) (𝓝[≠] 0) (𝓝 0) := by + simpa only [f.map_zero, norm_zero] using ((hf.tendsto 0).comp A).norm + refine tendsto_nhds_unique (tendsto_const_nhds.congr' ?_) B + refine eventually_mem_nhdsWithin.mono fun ε (hε : ε ≠ 0) ↦ ?_ + simp_rw [f.map_smul, Pi.smul_def, update_eq_self, f.map_smul_univ, prod_const, smul_smul, + Fintype.card, ← mul_pow, inv_mul_cancel hε, one_pow, one_smul] + +theorem bound_of_shell_of_norm_map_coord_zero (hf₀ : ∀ {m i}, ‖m i‖ = 0 → ‖f m‖ = 0) + {ε : ι → ℝ} {C : ℝ} (hε : ∀ i, 0 < ε i) {c : ι → 𝕜} (hc : ∀ i, 1 < ‖c i‖) (hf : ∀ m : ∀ i, E i, (∀ i, ε i / ‖c i‖ ≤ ‖m i‖) → (∀ i, ‖m i‖ < ε i) → ‖f m‖ ≤ C * ∏ i, ‖m i‖) (m : ∀ i, E i) : ‖f m‖ ≤ C * ∏ i, ‖m i‖ := by - rcases em (∃ i, m i = 0) with (⟨i, hi⟩ | hm) - · simp [f.map_coord_zero i hi, prod_eq_zero (mem_univ i), hi] + rcases em (∃ i, ‖m i‖ = 0) with (⟨i, hi⟩ | hm) + · rw [hf₀ hi, prod_eq_zero (mem_univ i) hi, mul_zero] push_neg at hm - choose δ hδ0 hδm_lt hle_δm _ using fun i => rescale_to_shell (hc i) (hε i) (hm i) + choose δ hδ0 hδm_lt hle_δm _ using fun i => rescale_to_shell_semi_normed (hc i) (hε i) (hm i) have hδ0 : 0 < ∏ i, ‖δ i‖ := prod_pos fun i _ => norm_pos_iff.2 (hδ0 i) simpa [map_smul_univ, norm_smul, prod_mul_distrib, mul_left_comm C, mul_le_mul_left hδ0] using hf (fun i => δ i • m i) hle_δm hδm_lt -#align multilinear_map.bound_of_shell MultilinearMap.bound_of_shell + +/-- If a continuous multilinear map in finitely many variables on normed spaces satisfies +the inequality `‖f m‖ ≤ C * ∏ i, ‖m i‖` on a shell `ε i / ‖c i‖ < ‖m i‖ < ε i` for some positive +numbers `ε i` and elements `c i : 𝕜`, `1 < ‖c i‖`, then it satisfies this inequality for all `m`. -/ +theorem bound_of_shell_of_continuous (hfc : Continuous f) + {ε : ι → ℝ} {C : ℝ} (hε : ∀ i, 0 < ε i) {c : ι → 𝕜} (hc : ∀ i, 1 < ‖c i‖) + (hf : ∀ m : ∀ i, E i, (∀ i, ε i / ‖c i‖ ≤ ‖m i‖) → (∀ i, ‖m i‖ < ε i) → ‖f m‖ ≤ C * ∏ i, ‖m i‖) + (m : ∀ i, E i) : ‖f m‖ ≤ C * ∏ i, ‖m i‖ := + bound_of_shell_of_norm_map_coord_zero f (norm_map_coord_zero f hfc) hε hc hf m /-- If a multilinear map in finitely many variables on normed spaces is continuous, then it satisfies the inequality `‖f m‖ ≤ C * ∏ i, ‖m i‖`, for some `C` which can be chosen to be @@ -127,7 +157,7 @@ theorem exists_bound_of_continuous (hf : Continuous f) : rcases NormedField.exists_one_lt_norm 𝕜 with ⟨c, hc⟩ have : 0 < (‖c‖ / ε) ^ Fintype.card ι := pow_pos (div_pos (zero_lt_one.trans hc) ε0) _ refine' ⟨_, this, _⟩ - refine' f.bound_of_shell (fun _ => ε0) (fun _ => hc) fun m hcm hm => _ + refine' f.bound_of_shell_of_continuous hf (fun _ => ε0) (fun _ => hc) fun m hcm hm => _ refine' (hε m ((pi_norm_lt_iff ε0).2 hm)).le.trans _ rw [← div_le_iff' this, one_div, ← inv_pow, inv_div, Fintype.card, ← prod_const] exact prod_le_prod (fun _ _ => div_nonneg ε0.le (norm_nonneg _)) fun i _ => hcm i @@ -200,7 +230,7 @@ theorem norm_image_sub_le_of_bound {C : ℝ} (hC : 0 ≤ C) (H : ∀ m, ‖f m calc ∏ j, (if j = i then ‖m₁ i - m₂ i‖ else max ‖m₁ j‖ ‖m₂ j‖) ≤ ∏ j : ι, Function.update (fun _ => max ‖m₁‖ ‖m₂‖) i ‖m₁ - m₂‖ j := by - apply prod_le_prod + apply Finset.prod_le_prod · intro j _ by_cases h : j = i <;> simp [h, norm_nonneg] · intro j _ @@ -397,11 +427,6 @@ theorem op_norm_zero : ‖(0 : ContinuousMultilinearMap 𝕜 E G)‖ = 0 := (op_norm_nonneg _).antisymm' <| op_norm_le_bound 0 le_rfl fun m => by simp #align continuous_multilinear_map.op_norm_zero ContinuousMultilinearMap.op_norm_zero -/-- A continuous linear map is zero iff its norm vanishes. -/ -theorem op_norm_zero_iff : ‖f‖ = 0 ↔ f = 0 := by - simp [← (op_norm_nonneg f).le_iff_eq, op_norm_le_iff f le_rfl, ext_iff] -#align continuous_multilinear_map.op_norm_zero_iff ContinuousMultilinearMap.op_norm_zero_iff - section variable {𝕜' : Type*} [NormedField 𝕜'] [NormedSpace 𝕜' G] [SMulCommClass 𝕜 𝕜' G] @@ -419,23 +444,21 @@ theorem op_norm_neg : ‖-f‖ = ‖f‖ := by simp #align continuous_multilinear_map.op_norm_neg ContinuousMultilinearMap.op_norm_neg -/-- Continuous multilinear maps themselves form a normed space with respect to +/-- Continuous multilinear maps themselves form a seminormed space with respect to the operator norm. -/ -instance normedAddCommGroup : NormedAddCommGroup (ContinuousMultilinearMap 𝕜 E G) := - AddGroupNorm.toNormedAddCommGroup +instance seminormedAddCommGroup : + SeminormedAddCommGroup (ContinuousMultilinearMap 𝕜 E G) := + AddGroupSeminorm.toSeminormedAddCommGroup { toFun := norm map_zero' := op_norm_zero neg' := op_norm_neg - add_le' := op_norm_add_le - eq_zero_of_map_eq_zero' := fun f => f.op_norm_zero_iff.1 } -#align continuous_multilinear_map.normed_add_comm_group ContinuousMultilinearMap.normedAddCommGroup + add_le' := fun f g ↦ op_norm_add_le f g} -/-- An alias of `ContinuousMultilinearMap.normedAddCommGroup` with non-dependent types to help +/-- An alias of `ContinuousMultilinearMap.seminormedAddCommGroup` with non-dependent types to help typeclass search. -/ -instance normedAddCommGroup' : - NormedAddCommGroup (ContinuousMultilinearMap 𝕜 (fun _ : ι => G) G') := - ContinuousMultilinearMap.normedAddCommGroup -#align continuous_multilinear_map.normed_add_comm_group' ContinuousMultilinearMap.normedAddCommGroup' +instance seminormedAddCommGroup' : + SeminormedAddCommGroup (ContinuousMultilinearMap 𝕜 (fun _ : ι => G) G') := + ContinuousMultilinearMap.seminormedAddCommGroup instance normedSpace : NormedSpace 𝕜' (ContinuousMultilinearMap 𝕜 E G) := ⟨fun c f => f.op_norm_smul_le c⟩ @@ -476,14 +499,13 @@ theorem op_norm_prod (f : ContinuousMultilinearMap 𝕜 E G) (g : ContinuousMult #align continuous_multilinear_map.op_norm_prod ContinuousMultilinearMap.op_norm_prod theorem op_nnnorm_pi - {ι' : Type v'} [Fintype ι'] {E' : ι' → Type wE'} [∀ i', NormedAddCommGroup (E' i')] - [∀ i', NormedSpace 𝕜 (E' i')] (f : ∀ i', ContinuousMultilinearMap 𝕜 E (E' i')) : - ‖pi f‖₊ = ‖f‖₊ := + [∀ i', SeminormedAddCommGroup (E' i')] [∀ i', NormedSpace 𝕜 (E' i')] + (f : ∀ i', ContinuousMultilinearMap 𝕜 E (E' i')) : ‖pi f‖₊ = ‖f‖₊ := eq_of_forall_ge_iff fun _ ↦ by simpa [op_nnnorm_le_iff, pi_nnnorm_le_iff] using forall_swap theorem op_norm_pi {ι' : Type v'} [Fintype ι'] {E' : ι' → Type wE'} - [∀ i', NormedAddCommGroup (E' i')] - [∀ i', NormedSpace 𝕜 (E' i')] (f : ∀ i', ContinuousMultilinearMap 𝕜 E (E' i')) : + [∀ i', SeminormedAddCommGroup (E' i')] [∀ i', NormedSpace 𝕜 (E' i')] + (f : ∀ i', ContinuousMultilinearMap 𝕜 E (E' i')) : ‖pi f‖ = ‖f‖ := congr_arg NNReal.toReal (op_nnnorm_pi f) #align continuous_multilinear_map.norm_pi ContinuousMultilinearMap.op_norm_pi @@ -519,20 +541,11 @@ theorem norm_ofSubsingleton_id_le [Subsingleton ι] (i : ι) : apply ContinuousLinearMap.norm_id_le #align continuous_multilinear_map.norm_of_subsingleton_le ContinuousMultilinearMap.norm_ofSubsingleton_id_le -theorem norm_ofSubsingleton_id [Subsingleton ι] [Nontrivial G] (i : ι) : - ‖ofSubsingleton 𝕜 G G i (.id _ _)‖ = 1 := by simp -#align continuous_multilinear_map.norm_of_subsingleton ContinuousMultilinearMap.norm_ofSubsingleton_id - theorem nnnorm_ofSubsingleton_id_le [Subsingleton ι] (i : ι) : ‖ofSubsingleton 𝕜 G G i (.id _ _)‖₊ ≤ 1 := norm_ofSubsingleton_id_le _ _ _ #align continuous_multilinear_map.nnnorm_of_subsingleton_le ContinuousMultilinearMap.nnnorm_ofSubsingleton_id_le -theorem nnnorm_ofSubsingleton_id [Subsingleton ι] [Nontrivial G] (i : ι) : - ‖ofSubsingleton 𝕜 G G i (.id _ _)‖₊ = 1 := - NNReal.eq <| norm_ofSubsingleton_id _ _ _ -#align continuous_multilinear_map.nnnorm_of_subsingleton ContinuousMultilinearMap.nnnorm_ofSubsingleton_id - variable {G} (E) @[simp] @@ -684,87 +697,6 @@ theorem hasSum_eval {α : Type*} {p : α → ContinuousMultilinearMap 𝕜 E G} simp #align continuous_multilinear_map.has_sum_eval ContinuousMultilinearMap.hasSum_eval -theorem tsum_eval {α : Type*} {p : α → ContinuousMultilinearMap 𝕜 E G} (hp : Summable p) - (m : ∀ i, E i) : (∑' a, p a) m = ∑' a, p a m := - (hasSum_eval hp.hasSum m).tsum_eq.symm -#align continuous_multilinear_map.tsum_eval ContinuousMultilinearMap.tsum_eval - -open Topology Filter - -/-- If the target space is complete, the space of continuous multilinear maps with its norm is also -complete. The proof is essentially the same as for the space of continuous linear maps (modulo the -addition of `Finset.prod` where needed. The duplication could be avoided by deducing the linear -case from the multilinear case via a currying isomorphism. However, this would mess up imports, -and it is more satisfactory to have the simplest case as a standalone proof. -/ -instance completeSpace [CompleteSpace G] : CompleteSpace (ContinuousMultilinearMap 𝕜 E G) := by - have nonneg : ∀ v : ∀ i, E i, 0 ≤ ∏ i, ‖v i‖ := fun v => - Finset.prod_nonneg fun i _ => norm_nonneg _ - -- We show that every Cauchy sequence converges. - refine' Metric.complete_of_cauchySeq_tendsto fun f hf => _ - -- We now expand out the definition of a Cauchy sequence, - rcases cauchySeq_iff_le_tendsto_0.1 hf with ⟨b, b0, b_bound, b_lim⟩ - -- and establish that the evaluation at any point `v : Π i, E i` is Cauchy. - have cau : ∀ v, CauchySeq fun n => f n v := by - intro v - apply cauchySeq_iff_le_tendsto_0.2 ⟨fun n => b n * ∏ i, ‖v i‖, _, _, _⟩ - · intro - exact mul_nonneg (b0 _) (nonneg v) - · intro n m N hn hm - rw [dist_eq_norm] - apply le_trans ((f n - f m).le_op_norm v) _ - exact mul_le_mul_of_nonneg_right (b_bound n m N hn hm) (nonneg v) - · simpa using b_lim.mul tendsto_const_nhds - -- We assemble the limits points of those Cauchy sequences - -- (which exist as `G` is complete) - -- into a function which we call `F`. - choose F hF using fun v => cauchySeq_tendsto_of_complete (cau v) - -- Next, we show that this `F` is multilinear, - let Fmult : MultilinearMap 𝕜 E G := - { toFun := F - map_add' := fun v i x y => by - skip - have A := hF (Function.update v i (x + y)) - have B := (hF (Function.update v i x)).add (hF (Function.update v i y)) - simp? at A B says simp only [map_add] at A B - exact tendsto_nhds_unique A B - map_smul' := fun v i c x => by - skip - have A := hF (Function.update v i (c • x)) - have B := Filter.Tendsto.smul (@tendsto_const_nhds _ ℕ _ c _) (hF (Function.update v i x)) - simp? at A B says simp only [map_smul] at A B - exact tendsto_nhds_unique A B } - -- and that `F` has norm at most `(b 0 + ‖f 0‖)`. - have Fnorm : ∀ v, ‖F v‖ ≤ (b 0 + ‖f 0‖) * ∏ i, ‖v i‖ := by - intro v - have A : ∀ n, ‖f n v‖ ≤ (b 0 + ‖f 0‖) * ∏ i, ‖v i‖ := by - intro n - apply le_trans ((f n).le_op_norm _) _ - apply mul_le_mul_of_nonneg_right _ (nonneg v) - calc - ‖f n‖ = ‖f n - f 0 + f 0‖ := by - congr 1 - abel - _ ≤ ‖f n - f 0‖ + ‖f 0‖ := (norm_add_le _ _) - _ ≤ b 0 + ‖f 0‖ := by - apply add_le_add_right - simpa [dist_eq_norm] using b_bound n 0 0 (zero_le _) (zero_le _) - exact le_of_tendsto (hF v).norm (eventually_of_forall A) - -- Thus `F` is continuous, and we propose that as the limit point of our original Cauchy sequence. - let Fcont := Fmult.mkContinuous _ Fnorm - use Fcont - -- Our last task is to establish convergence to `F` in norm. - have : ∀ n, ‖f n - Fcont‖ ≤ b n := by - intro n - apply op_norm_le_bound _ (b0 n) fun v => ?_ - have A : ∀ᶠ m in atTop, ‖(f n - f m) v‖ ≤ b n * ∏ i, ‖v i‖ := by - refine' eventually_atTop.2 ⟨n, fun m hm => _⟩ - apply le_trans ((f n - f m).le_op_norm _) _ - exact mul_le_mul_of_nonneg_right (b_bound n m n le_rfl hm) (nonneg v) - have B : Tendsto (fun m => ‖(f n - f m) v‖) atTop (𝓝 ‖(f n - Fcont) v‖) := - Tendsto.norm (tendsto_const_nhds.sub (hF v)) - exact le_of_tendsto B A - rw [tendsto_iff_norm_sub_tendsto_zero] - exact squeeze_zero (fun n => norm_nonneg _) this b_lim end ContinuousMultilinearMap /-- If a continuous multilinear map is constructed from a multilinear map via the constructor @@ -1228,7 +1160,7 @@ noncomputable def compContinuousLinearMapContinuousMultilinear : ((ContinuousMultilinearMap 𝕜 E₁ G) →L[𝕜] ContinuousMultilinearMap 𝕜 E G) := @MultilinearMap.mkContinuous 𝕜 ι (fun i ↦ E i →L[𝕜] E₁ i) ((ContinuousMultilinearMap 𝕜 E₁ G) →L[𝕜] ContinuousMultilinearMap 𝕜 E G) _ _ - (fun _ ↦ ContinuousLinearMap.toNormedAddCommGroup) + (fun _ ↦ ContinuousLinearMap.toSeminormedAddCommGroup) (fun _ ↦ ContinuousLinearMap.toNormedSpace) _ _ (compContinuousLinearMapMultilinear 𝕜 E E₁ G) 1 fun f ↦ by simpa using norm_compContinuousLinearMapL_le G f @@ -1286,3 +1218,162 @@ instance continuousConstSMul : ContinuousConstSMul R (ContinuousMultilinearMap (ContinuousLinearMap.compContinuousMultilinearMapL 𝕜 _ G G (c • ContinuousLinearMap.id 𝕜 G)).2⟩ end SMul + +end Seminorm + +section Norm + +namespace ContinuousMultilinearMap + +/-! Results that are only true if the target space is a `NormedAddCommGroup` (and not just a +`SeminormedAddCommGroup`).-/ + +variable {𝕜 : Type u} {ι : Type v} {E : ι → Type wE} {G : Type wG} {G' : Type wG'} [Fintype ι] + [NontriviallyNormedField 𝕜] [∀ i, SeminormedAddCommGroup (E i)] [∀ i, NormedSpace 𝕜 (E i)] + [NormedAddCommGroup G] [NormedSpace 𝕜 G] [SeminormedAddCommGroup G'] [NormedSpace 𝕜 G'] + +variable (f : ContinuousMultilinearMap 𝕜 E G) + +/-- A continuous linear map is zero iff its norm vanishes. -/ +theorem op_norm_zero_iff : ‖f‖ = 0 ↔ f = 0 := by + simp [← (op_norm_nonneg f).le_iff_eq, op_norm_le_iff f le_rfl, ext_iff] +#align continuous_multilinear_map.op_norm_zero_iff ContinuousMultilinearMap.op_norm_zero_iff + +/-- Continuous multilinear maps themselves form a normed group with respect to + the operator norm. -/ +instance normedAddCommGroup : NormedAddCommGroup (ContinuousMultilinearMap 𝕜 E G) := + NormedAddCommGroup.ofSeparation (fun f ↦ (op_norm_zero_iff f).mp) +#align continuous_multilinear_map.normed_add_comm_group ContinuousMultilinearMap.normedAddCommGroup + +/-- An alias of `ContinuousMultilinearMap.normedAddCommGroup` with non-dependent types to help +typeclass search. -/ +instance normedAddCommGroup' : + NormedAddCommGroup (ContinuousMultilinearMap 𝕜 (fun _ : ι => G') G) := + ContinuousMultilinearMap.normedAddCommGroup +#align continuous_multilinear_map.normed_add_comm_group' ContinuousMultilinearMap.normedAddCommGroup' + +variable (𝕜 G) + +theorem norm_ofSubsingleton_id [Subsingleton ι] [Nontrivial G] (i : ι) : + ‖ofSubsingleton 𝕜 G G i (.id _ _)‖ = 1 := by simp +#align continuous_multilinear_map.norm_of_subsingleton ContinuousMultilinearMap.norm_ofSubsingleton_id + +theorem nnnorm_ofSubsingleton_id [Subsingleton ι] [Nontrivial G] (i : ι) : + ‖ofSubsingleton 𝕜 G G i (.id _ _)‖₊ = 1 := + NNReal.eq <| norm_ofSubsingleton_id _ _ _ +#align continuous_multilinear_map.nnnorm_of_subsingleton ContinuousMultilinearMap.nnnorm_ofSubsingleton_id + +variable {𝕜 G} + +theorem tsum_eval {α : Type*} {p : α → ContinuousMultilinearMap 𝕜 E G} (hp : Summable p) + (m : ∀ i, E i) : (∑' a, p a) m = ∑' a, p a m := + (hasSum_eval hp.hasSum m).tsum_eq.symm +#align continuous_multilinear_map.tsum_eval ContinuousMultilinearMap.tsum_eval + +open Topology Filter + +/-- If the target space is complete, the space of continuous multilinear maps with its norm is also +complete. The proof is essentially the same as for the space of continuous linear maps (modulo the +addition of `Finset.prod` where needed. The duplication could be avoided by deducing the linear +case from the multilinear case via a currying isomorphism. However, this would mess up imports, +and it is more satisfactory to have the simplest case as a standalone proof. -/ +instance completeSpace [CompleteSpace G] : CompleteSpace (ContinuousMultilinearMap 𝕜 E G) := by + have nonneg : ∀ v : ∀ i, E i, 0 ≤ ∏ i, ‖v i‖ := fun v => + Finset.prod_nonneg fun i _ => norm_nonneg _ + -- We show that every Cauchy sequence converges. + refine' Metric.complete_of_cauchySeq_tendsto fun f hf => _ + -- We now expand out the definition of a Cauchy sequence, + rcases cauchySeq_iff_le_tendsto_0.1 hf with ⟨b, b0, b_bound, b_lim⟩ + -- and establish that the evaluation at any point `v : Π i, E i` is Cauchy. + have cau : ∀ v, CauchySeq fun n => f n v := by + intro v + apply cauchySeq_iff_le_tendsto_0.2 ⟨fun n => b n * ∏ i, ‖v i‖, _, _, _⟩ + · intro + exact mul_nonneg (b0 _) (nonneg v) + · intro n m N hn hm + rw [dist_eq_norm] + apply le_trans ((f n - f m).le_op_norm v) _ + exact mul_le_mul_of_nonneg_right (b_bound n m N hn hm) (nonneg v) + · simpa using b_lim.mul tendsto_const_nhds + -- We assemble the limits points of those Cauchy sequences + -- (which exist as `G` is complete) + -- into a function which we call `F`. + choose F hF using fun v => cauchySeq_tendsto_of_complete (cau v) + -- Next, we show that this `F` is multilinear, + let Fmult : MultilinearMap 𝕜 E G := + { toFun := F + map_add' := fun v i x y => by + skip + have A := hF (Function.update v i (x + y)) + have B := (hF (Function.update v i x)).add (hF (Function.update v i y)) + simp? at A B says simp only [map_add] at A B + exact tendsto_nhds_unique A B + map_smul' := fun v i c x => by + skip + have A := hF (Function.update v i (c • x)) + have B := Filter.Tendsto.smul (@tendsto_const_nhds _ ℕ _ c _) (hF (Function.update v i x)) + simp? at A B says simp only [map_smul] at A B + exact tendsto_nhds_unique A B } + -- and that `F` has norm at most `(b 0 + ‖f 0‖)`. + have Fnorm : ∀ v, ‖F v‖ ≤ (b 0 + ‖f 0‖) * ∏ i, ‖v i‖ := by + intro v + have A : ∀ n, ‖f n v‖ ≤ (b 0 + ‖f 0‖) * ∏ i, ‖v i‖ := by + intro n + apply le_trans ((f n).le_op_norm _) _ + apply mul_le_mul_of_nonneg_right _ (nonneg v) + calc + ‖f n‖ = ‖f n - f 0 + f 0‖ := by + congr 1 + abel + _ ≤ ‖f n - f 0‖ + ‖f 0‖ := (norm_add_le _ _) + _ ≤ b 0 + ‖f 0‖ := by + apply add_le_add_right + simpa [dist_eq_norm] using b_bound n 0 0 (zero_le _) (zero_le _) + exact le_of_tendsto (hF v).norm (eventually_of_forall A) + -- Thus `F` is continuous, and we propose that as the limit point of our original Cauchy sequence. + let Fcont := Fmult.mkContinuous _ Fnorm + use Fcont + -- Our last task is to establish convergence to `F` in norm. + have : ∀ n, ‖f n - Fcont‖ ≤ b n := by + intro n + apply op_norm_le_bound _ (b0 n) fun v => ?_ + have A : ∀ᶠ m in atTop, ‖(f n - f m) v‖ ≤ b n * ∏ i, ‖v i‖ := by + refine' eventually_atTop.2 ⟨n, fun m hm => _⟩ + apply le_trans ((f n - f m).le_op_norm _) _ + exact mul_le_mul_of_nonneg_right (b_bound n m n le_rfl hm) (nonneg v) + have B : Tendsto (fun m => ‖(f n - f m) v‖) atTop (𝓝 ‖(f n - Fcont) v‖) := + Tendsto.norm (tendsto_const_nhds.sub (hF v)) + exact le_of_tendsto B A + rw [tendsto_iff_norm_sub_tendsto_zero] + exact squeeze_zero (fun n => norm_nonneg _) this b_lim + +end ContinuousMultilinearMap + +end Norm + +section Norm + +/-! Results that are only true if the source is a `NormedAddCommGroup` (and not just a +`SeminormedAddCommGroup`).-/ + +variable {𝕜 : Type u} {ι : Type v} {E : ι → Type wE} {G : Type wG} [Fintype ι] + [NontriviallyNormedField 𝕜] [∀ i, NormedAddCommGroup (E i)] [∀ i, NormedSpace 𝕜 (E i)] + [SeminormedAddCommGroup G] [NormedSpace 𝕜 G] + +namespace MultilinearMap + +variable (f : MultilinearMap 𝕜 E G) + +/-- If a multilinear map in finitely many variables on normed spaces satisfies the inequality +`‖f m‖ ≤ C * ∏ i, ‖m i‖` on a shell `ε i / ‖c i‖ < ‖m i‖ < ε i` for some positive numbers `ε i` +and elements `c i : 𝕜`, `1 < ‖c i‖`, then it satisfies this inequality for all `m`. -/ +theorem bound_of_shell {ε : ι → ℝ} {C : ℝ} (hε : ∀ i, 0 < ε i) {c : ι → 𝕜} (hc : ∀ i, 1 < ‖c i‖) + (hf : ∀ m : ∀ i, E i, (∀ i, ε i / ‖c i‖ ≤ ‖m i‖) → (∀ i, ‖m i‖ < ε i) → ‖f m‖ ≤ C * ∏ i, ‖m i‖) + (m : ∀ i, E i) : ‖f m‖ ≤ C * ∏ i, ‖m i‖ := + bound_of_shell_of_norm_map_coord_zero f + (fun h ↦ by rw [map_coord_zero f _ (norm_eq_zero.1 h), norm_zero]) hε hc hf m +#align multilinear_map.bound_of_shell MultilinearMap.bound_of_shell + +end MultilinearMap + +end Norm diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Curry.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Curry.lean index a2b6e5e3e47d3..89ee1050152ce 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Curry.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Curry.lean @@ -534,7 +534,7 @@ theorem norm_domDomCongr (σ : ι ≃ ι') (f : ContinuousMultilinearMap 𝕜 (f ‖domDomCongr σ f‖ = ‖f‖ := by simp only [norm_def, LinearEquiv.coe_mk, ← σ.prod_comp, (σ.arrowCongr (Equiv.refl G)).surjective.forall, domDomCongr_apply, Equiv.arrowCongr_apply, - Equiv.coe_refl, comp.left_id, comp_apply, Equiv.symm_apply_apply, id] + Equiv.coe_refl, id_comp, comp_apply, Equiv.symm_apply_apply, id] #align continuous_multilinear_map.norm_dom_dom_congr ContinuousMultilinearMap.norm_domDomCongr /-- An equivalence of the index set defines a linear isometric equivalence between the spaces diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm.lean index 72eae739234a7..bd2947b2c63cc 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm.lean @@ -869,11 +869,11 @@ def compSL : (F →SL[σ₂₃] G) →L[𝕜₃] (E →SL[σ₁₂] F) →SL[σ 1 fun f g => by simpa only [one_mul] using op_norm_comp_le f g #align continuous_linear_map.compSL ContinuousLinearMap.compSL -/-- Porting note: Local instance for `norm_compSL_le`. -Should be by `inferInstance`, and indeed not be needed. -/ -local instance : Norm ((F →SL[σ₂₃] G) →L[𝕜₃] (E →SL[σ₁₂] F) →SL[σ₂₃] E →SL[σ₁₃] G) := - hasOpNorm (E := F →SL[σ₂₃] G) (F := (E →SL[σ₁₂] F) →SL[σ₂₃] E →SL[σ₁₃] G) in -theorem norm_compSL_le : ‖compSL E F G σ₁₂ σ₂₃‖ ≤ 1 := +theorem norm_compSL_le : + -- porting note: added + letI : Norm ((F →SL[σ₂₃] G) →L[𝕜₃] (E →SL[σ₁₂] F) →SL[σ₂₃] E →SL[σ₁₃] G) := + hasOpNorm (E := F →SL[σ₂₃] G) (F := (E →SL[σ₁₂] F) →SL[σ₂₃] E →SL[σ₁₃] G) + ‖compSL E F G σ₁₂ σ₂₃‖ ≤ 1 := LinearMap.mkContinuous₂_norm_le _ zero_le_one _ #align continuous_linear_map.norm_compSL_le ContinuousLinearMap.norm_compSL_le @@ -905,11 +905,10 @@ def compL : (Fₗ →L[𝕜] Gₗ) →L[𝕜] (E →L[𝕜] Fₗ) →L[𝕜] E compSL E Fₗ Gₗ (RingHom.id 𝕜) (RingHom.id 𝕜) #align continuous_linear_map.compL ContinuousLinearMap.compL -/-- Porting note: Local instance for `norm_compL_le`. -Should be by `inferInstance`, and indeed not be needed. -/ -local instance : Norm ((Fₗ →L[𝕜] Gₗ) →L[𝕜] (E →L[𝕜] Fₗ) →L[𝕜] E →L[𝕜] Gₗ) := - hasOpNorm (E := Fₗ →L[𝕜] Gₗ) (F := (E →L[𝕜] Fₗ) →L[𝕜] E →L[𝕜] Gₗ) in -theorem norm_compL_le : ‖compL 𝕜 E Fₗ Gₗ‖ ≤ 1 := +theorem norm_compL_le : + letI : Norm ((Fₗ →L[𝕜] Gₗ) →L[𝕜] (E →L[𝕜] Fₗ) →L[𝕜] E →L[𝕜] Gₗ) := + hasOpNorm (E := Fₗ →L[𝕜] Gₗ) (F := (E →L[𝕜] Fₗ) →L[𝕜] E →L[𝕜] Gₗ) + ‖compL 𝕜 E Fₗ Gₗ‖ ≤ 1 := norm_compSL_le _ _ _ _ _ #align continuous_linear_map.norm_compL_le ContinuousLinearMap.norm_compL_le @@ -931,22 +930,22 @@ def precompL (L : E →L[𝕜] Fₗ →L[𝕜] Gₗ) : (Eₗ →L[𝕜] E) →L[ (precompR Eₗ (flip L)).flip #align continuous_linear_map.precompL ContinuousLinearMap.precompL -/-- Porting note: Local instances for `norm_precompR_le`. -Should be by `inferInstance`, and indeed not be needed. -/ -local instance : SeminormedAddCommGroup ((Eₗ →L[𝕜] Fₗ) →L[𝕜] Eₗ →L[𝕜] Gₗ) := inferInstance in -local instance : NormedSpace 𝕜 ((Eₗ →L[𝕜] Fₗ) →L[𝕜] Eₗ →L[𝕜] Gₗ) := inferInstance in -theorem norm_precompR_le (L : E →L[𝕜] Fₗ →L[𝕜] Gₗ) : ‖precompR Eₗ L‖ ≤ ‖L‖ := +theorem norm_precompR_le (L : E →L[𝕜] Fₗ →L[𝕜] Gₗ) : + -- porting note: added + letI : SeminormedAddCommGroup ((Eₗ →L[𝕜] Fₗ) →L[𝕜] Eₗ →L[𝕜] Gₗ) := inferInstance + letI : NormedSpace 𝕜 ((Eₗ →L[𝕜] Fₗ) →L[𝕜] Eₗ →L[𝕜] Gₗ) := inferInstance + ‖precompR Eₗ L‖ ≤ ‖L‖ := calc ‖precompR Eₗ L‖ ≤ ‖compL 𝕜 Eₗ Fₗ Gₗ‖ * ‖L‖ := op_norm_comp_le _ _ _ ≤ 1 * ‖L‖ := (mul_le_mul_of_nonneg_right (norm_compL_le _ _ _ _) (norm_nonneg _)) _ = ‖L‖ := by rw [one_mul] #align continuous_linear_map.norm_precompR_le ContinuousLinearMap.norm_precompR_le -/-- Porting note: Local instance for `norm_precompL_le`. -Should be by `inferInstance`, and indeed not be needed. -/ -local instance : Norm ((Eₗ →L[𝕜] E) →L[𝕜] Fₗ →L[𝕜] Eₗ →L[𝕜] Gₗ) := - hasOpNorm (E := Eₗ →L[𝕜] E) (F := Fₗ →L[𝕜] Eₗ →L[𝕜] Gₗ) in -theorem norm_precompL_le (L : E →L[𝕜] Fₗ →L[𝕜] Gₗ) : ‖precompL Eₗ L‖ ≤ ‖L‖ := by +theorem norm_precompL_le (L : E →L[𝕜] Fₗ →L[𝕜] Gₗ) : + -- porting note: added + letI : Norm ((Eₗ →L[𝕜] E) →L[𝕜] Fₗ →L[𝕜] Eₗ →L[𝕜] Gₗ) := + hasOpNorm (E := Eₗ →L[𝕜] E) (F := Fₗ →L[𝕜] Eₗ →L[𝕜] Gₗ) + ‖precompL Eₗ L‖ ≤ ‖L‖ := by rw [precompL, op_norm_flip, ← op_norm_flip L] exact norm_precompR_le _ L.flip #align continuous_linear_map.norm_precompL_le ContinuousLinearMap.norm_precompL_le @@ -1105,11 +1104,9 @@ theorem op_norm_mulLeftRight_apply_le (x : 𝕜') : ‖mulLeftRight 𝕜 𝕜' x op_norm_le_bound _ (norm_nonneg x) (op_norm_mulLeftRight_apply_apply_le 𝕜 𝕜' x) #align continuous_linear_map.op_norm_mul_left_right_apply_le ContinuousLinearMap.op_norm_mulLeftRight_apply_le -/-- Porting note: Local instance for `op_norm_mulLeftRight_le`. -Should be by `inferInstance`, and indeed not be needed. -/ -local instance : Norm (𝕜' →L[𝕜] 𝕜' →L[𝕜] 𝕜' →L[𝕜] 𝕜') := - hasOpNorm (E := 𝕜') (F := 𝕜' →L[𝕜] 𝕜' →L[𝕜] 𝕜') in -theorem op_norm_mulLeftRight_le : ‖mulLeftRight 𝕜 𝕜'‖ ≤ 1 := +theorem op_norm_mulLeftRight_le : + letI : Norm (𝕜' →L[𝕜] 𝕜' →L[𝕜] 𝕜' →L[𝕜] 𝕜') := hasOpNorm (E := 𝕜') (F := 𝕜' →L[𝕜] 𝕜' →L[𝕜] 𝕜') + ‖mulLeftRight 𝕜 𝕜'‖ ≤ 1 := op_norm_le_bound _ zero_le_one fun x => (one_mul ‖x‖).symm ▸ op_norm_mulLeftRight_apply_le 𝕜 𝕜' x #align continuous_linear_map.op_norm_mul_left_right_le ContinuousLinearMap.op_norm_mulLeftRight_le @@ -1624,7 +1621,7 @@ weak-* topology in `mathlib`, so we use an equivalent condition (see `isClosed_i theorem is_weak_closed_closedBall (f₀ : E' →SL[σ₁₂] F) (r : ℝ) ⦃f : E' →SL[σ₁₂] F⦄ (hf : ⇑f ∈ closure (((↑) : (E' →SL[σ₁₂] F) → E' → F) '' closedBall f₀ r)) : f ∈ closedBall f₀ r := by - have hr : 0 ≤ r := nonempty_closedBall.1 (nonempty_image_iff.1 (closure_nonempty_iff.1 ⟨_, hf⟩)) + have hr : 0 ≤ r := nonempty_closedBall.1 (closure_nonempty_iff.1 ⟨_, hf⟩).of_image refine' mem_closedBall_iff_norm.2 (op_norm_le_bound _ hr fun x => _) have : IsClosed { g : E' → F | ‖g x - f₀ x‖ ≤ r * ‖x‖ } := isClosed_Iic.preimage ((@continuous_apply E' (fun _ => F) _ x).sub continuous_const).norm diff --git a/Mathlib/Analysis/NormedSpace/PiLp.lean b/Mathlib/Analysis/NormedSpace/PiLp.lean index c9835ce73c4db..25d38f3c856cd 100644 --- a/Mathlib/Analysis/NormedSpace/PiLp.lean +++ b/Mathlib/Analysis/NormedSpace/PiLp.lean @@ -85,7 +85,41 @@ protected theorem PiLp.ext {p : ℝ≥0∞} {ι : Type*} {α : ι → Type*} {x namespace PiLp -variable (p : ℝ≥0∞) (𝕜 𝕜' : Type*) {ι : Type*} (α : ι → Type*) (β : ι → Type*) +variable (p : ℝ≥0∞) (𝕜 : Type*) {ι : Type*} (α : ι → Type*) (β : ι → Type*) +section +/- Register simplification lemmas for the applications of `PiLp` elements, as the usual lemmas +for Pi types will not trigger. -/ +variable {𝕜 p α} +variable [SeminormedRing 𝕜] [∀ i, SeminormedAddCommGroup (β i)] +variable [∀ i, Module 𝕜 (β i)] [∀ i, BoundedSMul 𝕜 (β i)] (c : 𝕜) + +variable (x y : PiLp p β) (i : ι) + +@[simp] +theorem zero_apply : (0 : PiLp p β) i = 0 := + rfl +#align pi_Lp.zero_apply PiLp.zero_apply + +@[simp] +theorem add_apply : (x + y) i = x i + y i := + rfl +#align pi_Lp.add_apply PiLp.add_apply + +@[simp] +theorem sub_apply : (x - y) i = x i - y i := + rfl +#align pi_Lp.sub_apply PiLp.sub_apply + +@[simp] +theorem smul_apply : (c • x) i = c • x i := + rfl +#align pi_Lp.smul_apply PiLp.smul_apply + +@[simp] +theorem neg_apply : (-x) i = -x i := + rfl +#align pi_Lp.neg_apply PiLp.neg_apply +end /-! Note that the unapplied versions of these lemmas are deliberately omitted, as they break the use of the type synonym. -/ @@ -223,11 +257,11 @@ separate from `PiLp.seminormedAddCommGroup` since the latter requires the type c Registering this separately allows for a future norm-like structure on `PiLp p β` for `p < 1` satisfying a relaxed triangle inequality. These are called *quasi-norms*. -/ -instance hasNorm : Norm (PiLp p β) where +instance instNorm : Norm (PiLp p β) where norm f := if p = 0 then {i | ‖f i‖ ≠ 0}.toFinite.toFinset.card else if p = ∞ then ⨆ i, ‖f i‖ else (∑ i, ‖f i‖ ^ p.toReal) ^ (1 / p.toReal) -#align pi_Lp.has_norm PiLp.hasNorm +#align pi_Lp.has_norm PiLp.instNorm variable {p β} @@ -299,7 +333,6 @@ def pseudoEmetricAux : PseudoEMetricSpace (PiLp p β) where (∑ i, edist (f i) (g i) ^ p.toReal) ^ (1 / p.toReal) + (∑ i, edist (g i) (h i) ^ p.toReal) ^ (1 / p.toReal) := ENNReal.Lp_add_le _ _ _ hp - #align pi_Lp.pseudo_emetric_aux PiLp.pseudoEmetricAux attribute [local instance] PiLp.pseudoEmetricAux @@ -309,7 +342,7 @@ use outside this file. -/ theorem iSup_edist_ne_top_aux {ι : Type*} [Finite ι] {α : ι → Type*} [∀ i, PseudoMetricSpace (α i)] (f g : PiLp ∞ α) : (⨆ i, edist (f i) (g i)) ≠ ⊤ := by cases nonempty_fintype ι - obtain ⟨M, hM⟩ := Fintype.exists_le fun i => (⟨dist (f i) (g i), dist_nonneg⟩ : ℝ≥0) + obtain ⟨M, hM⟩ := Finite.exists_le fun i => (⟨dist (f i) (g i), dist_nonneg⟩ : ℝ≥0) refine' ne_of_lt ((iSup_le fun i => _).trans_lt (@ENNReal.coe_lt_top M)) simp only [edist, PseudoMetricSpace.edist_dist, ENNReal.ofReal_eq_coe_nnreal dist_nonneg] exact mod_cast hM i @@ -353,7 +386,7 @@ def pseudoMetricAux : PseudoMetricSpace (PiLp p α) := rw [PseudoMetricSpace.edist_dist] -- Porting note: `le_ciSup` needed some help exact ENNReal.ofReal_le_ofReal - (le_ciSup (Fintype.bddAbove_range (fun k => dist (f k) (g k))) i) + (le_ciSup (Finite.bddAbove_range (fun k => dist (f k) (g k))) i) · have A : ∀ i, edist (f i) (g i) ^ p.toReal ≠ ⊤ := fun i => ENNReal.rpow_ne_top_of_nonneg (zero_le_one.trans h) (edist_ne_top _ _) simp only [edist_eq_sum (zero_lt_one.trans_le h), dist_edist, ENNReal.toReal_rpow, @@ -528,17 +561,13 @@ instance seminormedAddCommGroup [∀ i, SeminormedAddCommGroup (β i)] : { Pi.addCommGroup with dist_eq := fun x y => by rcases p.dichotomy with (rfl | h) - · simp only [dist_eq_iSup, norm_eq_ciSup, dist_eq_norm] - -- Porting note: added - congr + · simp only [dist_eq_iSup, norm_eq_ciSup, dist_eq_norm, sub_apply] · have : p ≠ ∞ := by intro hp rw [hp, ENNReal.top_toReal] at h linarith simp only [dist_eq_sum (zero_lt_one.trans_le h), norm_eq_sum (zero_lt_one.trans_le h), - dist_eq_norm] - -- Porting note: added - congr } + dist_eq_norm, sub_apply] } #align pi_Lp.seminormed_add_comm_group PiLp.seminormedAddCommGroup /-- normed group instance on the product of finitely many normed groups, using the `L^p` norm. -/ @@ -554,12 +583,30 @@ theorem nnnorm_eq_sum {p : ℝ≥0∞} [Fact (1 ≤ p)] {β : ι → Type*} (hp simp [NNReal.coe_sum, norm_eq_sum (p.toReal_pos_iff_ne_top.mpr hp)] #align pi_Lp.nnnorm_eq_sum PiLp.nnnorm_eq_sum -theorem nnnorm_eq_ciSup {β : ι → Type*} [∀ i, SeminormedAddCommGroup (β i)] (f : PiLp ∞ β) : - ‖f‖₊ = ⨆ i, ‖f i‖₊ := by +section Linfty +variable {β} +variable [∀ i, SeminormedAddCommGroup (β i)] + +theorem nnnorm_eq_ciSup (f : PiLp ∞ β) : ‖f‖₊ = ⨆ i, ‖f i‖₊ := by ext simp [NNReal.coe_iSup, norm_eq_ciSup] #align pi_Lp.nnnorm_eq_csupr PiLp.nnnorm_eq_ciSup +@[simp] theorem nnnorm_equiv (f : PiLp ∞ β) : ‖WithLp.equiv ⊤ _ f‖₊ = ‖f‖₊ := by + rw [nnnorm_eq_ciSup, Pi.nnnorm_def, Finset.sup_univ_eq_ciSup] + dsimp only [WithLp.equiv_pi_apply] + +@[simp] theorem nnnorm_equiv_symm (f : ∀ i, β i) : ‖(WithLp.equiv ⊤ _).symm f‖₊ = ‖f‖₊ := + (nnnorm_equiv _).symm + +@[simp] theorem norm_equiv (f : PiLp ∞ β) : ‖WithLp.equiv ⊤ _ f‖ = ‖f‖ := + congr_arg NNReal.toReal <| nnnorm_equiv f + +@[simp] theorem norm_equiv_symm (f : ∀ i, β i) : ‖(WithLp.equiv ⊤ _).symm f‖ = ‖f‖ := + (norm_equiv _).symm + +end Linfty + theorem norm_eq_of_nat {p : ℝ≥0∞} [Fact (1 ≤ p)] {β : ι → Type*} [∀ i, SeminormedAddCommGroup (β i)] (n : ℕ) (h : p = n) (f : PiLp p β) : ‖f‖ = (∑ i, ‖f i‖ ^ n) ^ (1 / (n : ℝ)) := by @@ -592,8 +639,7 @@ theorem norm_sq_eq_of_L2 (β : ι → Type*) [∀ i, SeminormedAddCommGroup (β theorem dist_eq_of_L2 {β : ι → Type*} [∀ i, SeminormedAddCommGroup (β i)] (x y : PiLp 2 β) : dist x y = (∑ i, dist (x i) (y i) ^ 2).sqrt := by - simp_rw [dist_eq_norm, norm_eq_of_L2] - rfl + simp_rw [dist_eq_norm, norm_eq_of_L2, sub_apply] #align pi_Lp.dist_eq_of_L2 PiLp.dist_eq_of_L2 theorem nndist_eq_of_L2 {β : ι → Type*} [∀ i, SeminormedAddCommGroup (β i)] (x y : PiLp 2 β) : @@ -608,75 +654,37 @@ theorem edist_eq_of_L2 {β : ι → Type*} [∀ i, SeminormedAddCommGroup (β i) edist x y = (∑ i, edist (x i) (y i) ^ 2) ^ (1 / 2 : ℝ) := by simp [PiLp.edist_eq_sum] #align pi_Lp.edist_eq_of_L2 PiLp.edist_eq_of_L2 -variable [NormedField 𝕜] [NormedField 𝕜'] +instance instBoundedSMul [SeminormedRing 𝕜] [∀ i, SeminormedAddCommGroup (β i)] + [∀ i, Module 𝕜 (β i)] [∀ i, BoundedSMul 𝕜 (β i)] : + BoundedSMul 𝕜 (PiLp p β) := + .of_nnnorm_smul_le fun c f => by + rcases p.dichotomy with (rfl | hp) + · rw [← nnnorm_equiv, ← nnnorm_equiv, WithLp.equiv_smul] + exact nnnorm_smul_le c (WithLp.equiv ∞ (∀ i, β i) f) + · have hp0 : 0 < p.toReal := zero_lt_one.trans_le hp + have hpt : p ≠ ⊤ := p.toReal_pos_iff_ne_top.mp hp0 + rw [nnnorm_eq_sum hpt, nnnorm_eq_sum hpt, NNReal.rpow_one_div_le_iff hp0, NNReal.mul_rpow, + ← NNReal.rpow_mul, div_mul_cancel 1 hp0.ne', NNReal.rpow_one, Finset.mul_sum] + simp_rw [← NNReal.mul_rpow, smul_apply] + exact Finset.sum_le_sum fun i _ => NNReal.rpow_le_rpow (nnnorm_smul_le _ _) hp0.le /-- The product of finitely many normed spaces is a normed space, with the `L^p` norm. -/ -instance normedSpace [∀ i, SeminormedAddCommGroup (β i)] [∀ i, NormedSpace 𝕜 (β i)] : - NormedSpace 𝕜 (PiLp p β) := - { norm_smul_le := fun c f => by - rcases p.dichotomy with (rfl | hp) - · letI : Module 𝕜 (PiLp ∞ β) := Pi.module ι β 𝕜 - suffices ‖c • f‖₊ = ‖c‖₊ * ‖f‖₊ from mod_cast NNReal.coe_mono this.le - simp only [nnnorm_eq_ciSup, NNReal.mul_iSup, ← nnnorm_smul] - -- Porting note: added - congr - · have : p.toReal * (1 / p.toReal) = 1 := mul_div_cancel' 1 (zero_lt_one.trans_le hp).ne' - -- Porting note: added to replace Pi.smul_apply - have smul_apply : ∀ i : ι, (c • f) i = c • (f i) := fun i => rfl - simp only [norm_eq_sum (zero_lt_one.trans_le hp), norm_smul, Real.mul_rpow, norm_nonneg, ← - Finset.mul_sum, smul_apply] - rw [mul_rpow (rpow_nonneg_of_nonneg (norm_nonneg _) _), ← rpow_mul (norm_nonneg _), this, - Real.rpow_one] - exact Finset.sum_nonneg fun i _ => rpow_nonneg_of_nonneg (norm_nonneg _) _ } +instance normedSpace [NormedField 𝕜] [∀ i, SeminormedAddCommGroup (β i)] + [∀ i, NormedSpace 𝕜 (β i)] : NormedSpace 𝕜 (PiLp p β) where + norm_smul_le := norm_smul_le #align pi_Lp.normed_space PiLp.normedSpace -/- Register simplification lemmas for the applications of `PiLp` elements, as the usual lemmas -for Pi types will not trigger. -/ -variable {𝕜 𝕜' p α} -variable [∀ i, SeminormedAddCommGroup (β i)] [∀ i, NormedSpace 𝕜 (β i)] (c : 𝕜) - -variable (x y : PiLp p β) (x' y' : ∀ i, β i) (i : ι) - -@[simp] -theorem zero_apply : (0 : PiLp p β) i = 0 := - rfl -#align pi_Lp.zero_apply PiLp.zero_apply - -@[simp] -theorem add_apply : (x + y) i = x i + y i := - rfl -#align pi_Lp.add_apply PiLp.add_apply - -@[simp] -theorem sub_apply : (x - y) i = x i - y i := - rfl -#align pi_Lp.sub_apply PiLp.sub_apply - -@[simp] -theorem smul_apply : (c • x) i = c • x i := - rfl -#align pi_Lp.smul_apply PiLp.smul_apply - -@[simp] -theorem neg_apply : (-x) i = -x i := - rfl -#align pi_Lp.neg_apply PiLp.neg_apply +variable {𝕜 p α} +variable [SeminormedRing 𝕜] [∀ i, SeminormedAddCommGroup (β i)] +variable [∀ i, Module 𝕜 (β i)] [∀ i, BoundedSMul 𝕜 (β i)] (c : 𝕜) /-- The canonical map `WithLp.equiv` between `PiLp ∞ β` and `Π i, β i` as a linear isometric equivalence. -/ def equivₗᵢ : PiLp ∞ β ≃ₗᵢ[𝕜] ∀ i, β i := { WithLp.equiv ∞ (∀ i, β i) with - map_add' := fun f g => rfl - map_smul' := fun c f => rfl - norm_map' := fun f => by - suffices (Finset.univ.sup fun i => ‖f i‖₊) = ⨆ i, ‖f i‖₊ by - simpa only [NNReal.coe_iSup] using congr_arg ((↑) : ℝ≥0 → ℝ) this - refine' - antisymm (Finset.sup_le fun i _ => le_ciSup (Fintype.bddAbove_range fun i => ‖f i‖₊) _) _ - cases isEmpty_or_nonempty ι - · simp only [ciSup_of_empty, Finset.univ_eq_empty, Finset.sup_empty, le_rfl] - · -- Porting note: `Finset.le_sup` needed some helps - exact ciSup_le fun i => Finset.le_sup (f := fun k => ‖f k‖₊) (Finset.mem_univ i) } + map_add' := fun _f _g => rfl + map_smul' := fun _c _f => rfl + norm_map' := norm_equiv } #align pi_Lp.equivₗᵢ PiLp.equivₗᵢ variable {ι' : Type*} @@ -684,7 +692,7 @@ variable {ι' : Type*} variable [Fintype ι'] variable (p 𝕜) -variable (E : Type*) [NormedAddCommGroup E] [NormedSpace 𝕜 E] +variable (E : Type*) [NormedAddCommGroup E] [Module 𝕜 E] [BoundedSMul 𝕜 E] /-- An equivalence of finite domains induces a linearly isometric equivalence of finitely supported functions-/ @@ -692,8 +700,6 @@ def _root_.LinearIsometryEquiv.piLpCongrLeft (e : ι ≃ ι') : (PiLp p fun _ : ι => E) ≃ₗᵢ[𝕜] PiLp p fun _ : ι' => E where toLinearEquiv := LinearEquiv.piCongrLeft' 𝕜 (fun _ : ι => E) e norm_map' x' := by - -- Porting note: this avoids spurious `x` and `y` arguments - clear x y rcases p.dichotomy with (rfl | h) · simp_rw [norm_eq_ciSup] exact e.symm.iSup_congr fun _ => rfl @@ -743,7 +749,6 @@ variable [DecidableEq ι] @[simp] theorem nnnorm_equiv_symm_single [hp : Fact (1 ≤ p)] (i : ι) (b : β i) : ‖(WithLp.equiv p (∀ i, β i)).symm (Pi.single i b)‖₊ = ‖b‖₊ := by - clear x y -- Porting note: added haveI : Nonempty ι := ⟨i⟩ induction p using ENNReal.recTopCoe generalizing hp with | top => @@ -823,7 +828,6 @@ for `p ≠ ∞`. -/ theorem nnnorm_equiv_symm_const' {β} [SeminormedAddCommGroup β] [Nonempty ι] (b : β) : ‖(WithLp.equiv p (ι → β)).symm (Function.const _ b)‖₊ = (Fintype.card ι : ℝ≥0) ^ (1 / p).toReal * ‖b‖₊ := by - clear x y -- Porting note: added to avoid spurious arguments rcases em <| p = ∞ with (rfl | hp) · simp only [WithLp.equiv_symm_pi_apply, ENNReal.div_top, ENNReal.zero_toReal, NNReal.rpow_zero, one_mul, nnnorm_eq_ciSup, Function.const_apply, ciSup_const] @@ -909,7 +913,8 @@ theorem basisFun_map : open Matrix -nonrec theorem basis_toMatrix_basisFun_mul (b : Basis ι 𝕜 (PiLp p fun _ : ι => 𝕜)) +nonrec theorem basis_toMatrix_basisFun_mul + {𝕜} [SeminormedCommRing 𝕜] (b : Basis ι 𝕜 (PiLp p fun _ : ι => 𝕜)) (A : Matrix ι ι 𝕜) : b.toMatrix (PiLp.basisFun _ _ _) * A = Matrix.of fun i j => b.repr ((WithLp.equiv _ _).symm (Aᵀ j)) i := by diff --git a/Mathlib/Analysis/NormedSpace/ProdLp.lean b/Mathlib/Analysis/NormedSpace/ProdLp.lean index efcfef4076544..5b037305b0562 100644 --- a/Mathlib/Analysis/NormedSpace/ProdLp.lean +++ b/Mathlib/Analysis/NormedSpace/ProdLp.lean @@ -624,6 +624,18 @@ theorem prod_nnnorm_eq_sup (f : WithLp ∞ (α × β)) : ‖f‖₊ = ‖f.fst ext norm_cast +@[simp] theorem prod_nnnorm_equiv (f : WithLp ∞ (α × β)) : ‖WithLp.equiv ⊤ _ f‖₊ = ‖f‖₊ := by + rw [prod_nnnorm_eq_sup, Prod.nnnorm_def', _root_.sup_eq_max, equiv_fst, equiv_snd] + +@[simp] theorem prod_nnnorm_equiv_symm (f : α × β) : ‖(WithLp.equiv ⊤ _).symm f‖₊ = ‖f‖₊ := + (prod_nnnorm_equiv _).symm + +@[simp] theorem prod_norm_equiv (f : WithLp ∞ (α × β)) : ‖WithLp.equiv ⊤ _ f‖ = ‖f‖ := + congr_arg NNReal.toReal <| prod_nnnorm_equiv f + +@[simp] theorem prod_norm_equiv_symm (f : α × β) : ‖(WithLp.equiv ⊤ _).symm f‖ = ‖f‖ := + (prod_norm_equiv _).symm + theorem prod_norm_eq_of_L2 (x : WithLp 2 (α × β)) : ‖x‖ = Real.sqrt (‖x.fst‖ ^ 2 + ‖x.snd‖ ^ 2) := by rw [prod_norm_eq_of_nat 2 (by norm_cast) _, Real.sqrt_eq_rpow] @@ -729,25 +741,22 @@ theorem edist_equiv_symm_snd (y₁ y₂ : β) : end Single -section NormedSpace - -variable [NormedField 𝕜] [NormedSpace 𝕜 α] [NormedSpace 𝕜 β] +section BoundedSMul +variable [SeminormedRing 𝕜] [Module 𝕜 α] [Module 𝕜 β] [BoundedSMul 𝕜 α] [BoundedSMul 𝕜 β] -/-- The product of two normed spaces is a normed space, with the `L^p` norm. -/ -instance instProdNormedSpace : NormedSpace 𝕜 (WithLp p (α × β)) where - norm_smul_le c f := by +instance instProdBoundedSMul : BoundedSMul 𝕜 (WithLp p (α × β)) := + .of_nnnorm_smul_le fun c f => by rcases p.dichotomy with (rfl | hp) - · suffices ‖c • f‖₊ = ‖c‖₊ * ‖f‖₊ from mod_cast NNReal.coe_mono this.le - simp only [prod_nnnorm_eq_sup, NNReal.mul_sup, ← nnnorm_smul] - rfl - · have : p.toReal * (1 / p.toReal) = 1 := mul_div_cancel' 1 (zero_lt_one.trans_le hp).ne' - have smul_fst : (c • f).fst = c • f.fst := rfl - have smul_snd : (c • f).snd = c • f.snd := rfl - simp only [prod_norm_eq_add (zero_lt_one.trans_le hp), norm_smul, Real.mul_rpow, - norm_nonneg, smul_fst, smul_snd] - rw [← mul_add, mul_rpow (rpow_nonneg_of_nonneg (norm_nonneg _) _), - ← rpow_mul (norm_nonneg _), this, Real.rpow_one] - positivity + · simp only [← prod_nnnorm_equiv, WithLp.equiv_smul] + exact norm_smul_le _ _ + · have hp0 : 0 < p.toReal := zero_lt_one.trans_le hp + have hpt : p ≠ ⊤ := p.toReal_pos_iff_ne_top.mp hp0 + rw [prod_nnnorm_eq_add hpt, prod_nnnorm_eq_add hpt, NNReal.rpow_one_div_le_iff hp0, + NNReal.mul_rpow, ← NNReal.rpow_mul, div_mul_cancel 1 hp0.ne', NNReal.rpow_one, mul_add, + ← NNReal.mul_rpow, ← NNReal.mul_rpow] + exact add_le_add + (NNReal.rpow_le_rpow (nnnorm_smul_le _ _) hp0.le) + (NNReal.rpow_le_rpow (nnnorm_smul_le _ _) hp0.le) variable {𝕜 p α β} @@ -755,9 +764,18 @@ variable {𝕜 p α β} equivalence. -/ def prodEquivₗᵢ : WithLp ∞ (α × β) ≃ₗᵢ[𝕜] α × β where __ := WithLp.equiv ∞ (α × β) - map_add' f g := rfl - map_smul' c f := rfl - norm_map' f := by simp [Norm.norm] + map_add' _f _g := rfl + map_smul' _c _f := rfl + norm_map' := prod_norm_equiv + +end BoundedSMul + +section NormedSpace + +/-- The product of two normed spaces is a normed space, with the `L^p` norm. -/ +instance instProdNormedSpace [NormedField 𝕜] [NormedSpace 𝕜 α] [NormedSpace 𝕜 β] : + NormedSpace 𝕜 (WithLp p (α × β)) where + norm_smul_le := norm_smul_le end NormedSpace diff --git a/Mathlib/Analysis/NormedSpace/QuaternionExponential.lean b/Mathlib/Analysis/NormedSpace/QuaternionExponential.lean index d6c86be752826..b5f22ffa29a08 100644 --- a/Mathlib/Analysis/NormedSpace/QuaternionExponential.lean +++ b/Mathlib/Analysis/NormedSpace/QuaternionExponential.lean @@ -35,6 +35,48 @@ theorem exp_coe (r : ℝ) : exp ℝ (r : ℍ[ℝ]) = ↑(exp ℝ r) := (map_exp ℝ (algebraMap ℝ ℍ[ℝ]) (continuous_algebraMap _ _) _).symm #align quaternion.exp_coe Quaternion.exp_coe +/-- The even terms of `expSeries` are real, and correspond to the series for $\cos ‖q‖$. -/ +theorem expSeries_even_of_imaginary {q : Quaternion ℝ} (hq : q.re = 0) (n : ℕ) : + expSeries ℝ (Quaternion ℝ) (2 * n) (fun _ => q) = + ↑((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n) / (2 * n)!) := by + rw [expSeries_apply_eq] + have hq2 : q ^ 2 = -normSq q := sq_eq_neg_normSq.mpr hq + letI k : ℝ := ↑(2 * n)! + calc + k⁻¹ • q ^ (2 * n) = k⁻¹ • (-normSq q) ^ n := by rw [pow_mul, hq2] + _ = k⁻¹ • ↑((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n)) := ?_ + _ = ↑((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n) / k) := ?_ + · congr 1 + rw [neg_pow, normSq_eq_norm_mul_self, pow_mul, sq] + push_cast + rfl + · rw [← coe_mul_eq_smul, div_eq_mul_inv] + norm_cast + ring_nf + +/-- The odd terms of `expSeries` are real, and correspond to the series for +$\frac{q}{‖q‖} \sin ‖q‖$. -/ +theorem expSeries_odd_of_imaginary {q : Quaternion ℝ} (hq : q.re = 0) (n : ℕ) : + expSeries ℝ (Quaternion ℝ) (2 * n + 1) (fun _ => q) = + (((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n + 1) / (2 * n + 1)!) / ‖q‖) • q := by + rw [expSeries_apply_eq] + obtain rfl | hq0 := eq_or_ne q 0 + · simp + have hq2 : q ^ 2 = -normSq q := sq_eq_neg_normSq.mpr hq + have hqn := norm_ne_zero_iff.mpr hq0 + let k : ℝ := ↑(2 * n + 1)! + calc + k⁻¹ • q ^ (2 * n + 1) = k⁻¹ • ((-normSq q) ^ n * q) := by rw [pow_succ', pow_mul, hq2] + _ = k⁻¹ • ((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n)) • q := ?_ + _ = ((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n + 1) / k / ‖q‖) • q := ?_ + · congr 1 + rw [neg_pow, normSq_eq_norm_mul_self, pow_mul, sq, ← coe_mul_eq_smul] + norm_cast + · rw [smul_smul] + congr 1 + simp_rw [pow_succ', mul_div_assoc, div_div_cancel_left' hqn] + ring + /-- Auxiliary result; if the power series corresponding to `Real.cos` and `Real.sin` evaluated at `‖q‖` tend to `c` and `s`, then the exponential series tends to `c + (s / ‖q‖)`. -/ theorem hasSum_expSeries_of_imaginary {q : Quaternion ℝ} (hq : q.re = 0) {c s : ℝ} @@ -43,48 +85,13 @@ theorem hasSum_expSeries_of_imaginary {q : Quaternion ℝ} (hq : q.re = 0) {c s HasSum (fun n => expSeries ℝ (Quaternion ℝ) n fun _ => q) (↑c + (s / ‖q‖) • q) := by replace hc := hasSum_coe.mpr hc replace hs := (hs.div_const ‖q‖).smul_const q - obtain rfl | hq0 := eq_or_ne q 0 - · simp_rw [expSeries_apply_zero, norm_zero, div_zero, zero_smul, add_zero] - simp_rw [norm_zero] at hc - convert hc using 1 - ext (_ | n) : 1 - · rw [pow_zero, Nat.zero_eq, mul_zero, pow_zero, Nat.factorial_zero, Nat.cast_one, - div_one, one_mul, Pi.single_eq_same, coe_one] - · rw [zero_pow (mul_pos two_pos (Nat.succ_pos _)), mul_zero, zero_div, - Pi.single_eq_of_ne n.succ_ne_zero, coe_zero] - simp_rw [expSeries_apply_eq] - have hq2 : q ^ 2 = -normSq q := sq_eq_neg_normSq.mpr hq - have hqn := norm_ne_zero_iff.mpr hq0 - refine' HasSum.even_add_odd _ _ + refine HasSum.even_add_odd ?_ ?_ · convert hc using 1 ext n : 1 - letI k : ℝ := ↑(2 * n)! - calc - k⁻¹ • q ^ (2 * n) = k⁻¹ • (-normSq q) ^ n := by rw [pow_mul, hq2] - _ = k⁻¹ • ↑((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n)) := ?_ - _ = ↑((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n) / k) := ?_ - · congr 1 - rw [neg_pow, normSq_eq_norm_mul_self, pow_mul, sq] - push_cast - rfl - · rw [← coe_mul_eq_smul, div_eq_mul_inv] - norm_cast - ring_nf + rw [expSeries_even_of_imaginary hq] · convert hs using 1 ext n : 1 - let k : ℝ := ↑(2 * n + 1)! - calc - k⁻¹ • q ^ (2 * n + 1) = k⁻¹ • ((-normSq q) ^ n * q) := by - rw [pow_succ', pow_mul, hq2] - _ = k⁻¹ • ((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n)) • q := ?_ - _ = ((-1 : ℝ) ^ n * ‖q‖ ^ (2 * n + 1) / k / ‖q‖) • q := ?_ - · congr 1 - rw [neg_pow, normSq_eq_norm_mul_self, pow_mul, sq, ← coe_mul_eq_smul] - norm_cast - · rw [smul_smul] - congr 1 - simp_rw [pow_succ', mul_div_assoc, div_div_cancel_left' hqn] - ring + rw [expSeries_odd_of_imaginary hq] #align quaternion.has_sum_exp_series_of_imaginary Quaternion.hasSum_expSeries_of_imaginary /-- The closed form for the quaternion exponential on imaginary quaternions. -/ diff --git a/Mathlib/Analysis/NormedSpace/SphereNormEquiv.lean b/Mathlib/Analysis/NormedSpace/SphereNormEquiv.lean index a259dbaa0ee8b..df9214b167caf 100644 --- a/Mathlib/Analysis/NormedSpace/SphereNormEquiv.lean +++ b/Mathlib/Analysis/NormedSpace/SphereNormEquiv.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Analysis.NormedSpace.Basic -import Mathlib.Topology.PartialHomeomorph /-! # Homeomorphism between a normed space and sphere times `(0, +∞)` diff --git a/Mathlib/Analysis/NormedSpace/Star/Basic.lean b/Mathlib/Analysis/NormedSpace/Star/Basic.lean index cdb579d99aa64..49e82419cd394 100644 --- a/Mathlib/Analysis/NormedSpace/Star/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Star/Basic.lean @@ -7,8 +7,8 @@ import Mathlib.Analysis.Normed.Group.Hom import Mathlib.Analysis.NormedSpace.Basic import Mathlib.Analysis.NormedSpace.LinearIsometry import Mathlib.Algebra.Star.SelfAdjoint +import Mathlib.Algebra.Star.Subalgebra import Mathlib.Algebra.Star.Unitary -import Mathlib.Topology.Algebra.StarSubalgebra import Mathlib.Topology.Algebra.Module.Star #align_import analysis.normed_space.star.basic from "leanprover-community/mathlib"@"aa6669832974f87406a3d9d70fc5707a60546207" diff --git a/Mathlib/Analysis/NormedSpace/Star/GelfandDuality.lean b/Mathlib/Analysis/NormedSpace/Star/GelfandDuality.lean index 0ff228a39b066..0449e32fd8484 100644 --- a/Mathlib/Analysis/NormedSpace/Star/GelfandDuality.lean +++ b/Mathlib/Analysis/NormedSpace/Star/GelfandDuality.lean @@ -9,6 +9,7 @@ import Mathlib.Analysis.NormedSpace.Algebra import Mathlib.Topology.ContinuousFunction.Units import Mathlib.Topology.ContinuousFunction.Compact import Mathlib.Topology.Algebra.Algebra +import Mathlib.Topology.ContinuousFunction.Ideals import Mathlib.Topology.ContinuousFunction.StoneWeierstrass #align_import analysis.normed_space.star.gelfand_duality from "leanprover-community/mathlib"@"e65771194f9e923a70dfb49b6ca7be6e400d8b6f" @@ -22,12 +23,21 @@ the Gelfand transform is actually spectrum-preserving (`spectrum.gelfandTransfor when `A` is a commutative C⋆-algebra over `ℂ`, then the Gelfand transform is a surjective isometry, and even an equivalence between C⋆-algebras. +Consider the contravariant functors between compact Hausdorff spaces and commutative unital +C⋆algebras `F : Cpct → CommCStarAlg := X ↦ C(X, ℂ)` and +`G : CommCStarAlg → Cpct := A → characterSpace ℂ A` whose actions on morphisms are given by +`WeakDual.CharacterSpace.compContinuousMap` and `ContinuousMap.compStarAlgHom'`, respectively. + +Then `η₁ : id → F ∘ G := gelfandStarTransform` and +`η₂ : id → G ∘ F := WeakDual.CharacterSpace.homeoEval` are the natural isomorphisms implementing +**Gelfand Duality**, i.e., the (contravariant) equivalence of these categories. + ## Main definitions * `Ideal.toCharacterSpace` : constructs an element of the character space from a maximal ideal in a commutative complex Banach algebra -* `WeakDual.CharacterSpace.compContinuousMap`: The functorial map taking `ψ : A →⋆ₐ[ℂ] B` to a - continuous function `characterSpace ℂ B → characterSpace ℂ A` given by pre-composition with `ψ`. +* `WeakDual.CharacterSpace.compContinuousMap`: The functorial map taking `ψ : A →⋆ₐ[𝕜] B` to a + continuous function `characterSpace 𝕜 B → characterSpace 𝕜 A` given by pre-composition with `ψ`. ## Main statements @@ -37,6 +47,8 @@ and even an equivalence between C⋆-algebras. commutative (unital) C⋆-algebra over `ℂ`. * `gelfandTransform_bijective` : the Gelfand transform is bijective when the algebra is a commutative (unital) C⋆-algebra over `ℂ`. +* `gelfandStarTransform_naturality`: The `gelfandStarTransform` is a natural isomorphism +* `WeakDual.CharacterSpace.homeoEval_naturality`: This map implements a natural isomorphism ## TODO @@ -206,23 +218,20 @@ namespace WeakDual namespace CharacterSpace -variable {A B C : Type*} - -variable [NormedRing A] [NormedAlgebra ℂ A] [CompleteSpace A] [StarRing A] - -variable [NormedRing B] [NormedAlgebra ℂ B] [CompleteSpace B] [StarRing B] - -variable [NormedRing C] [NormedAlgebra ℂ C] [CompleteSpace C] [StarRing C] +variable {A B C 𝕜 : Type*} [NontriviallyNormedField 𝕜] +variable [NormedRing A] [NormedAlgebra 𝕜 A] [CompleteSpace A] [StarRing A] +variable [NormedRing B] [NormedAlgebra 𝕜 B] [CompleteSpace B] [StarRing B] +variable [NormedRing C] [NormedAlgebra 𝕜 C] [CompleteSpace C] [StarRing C] /-- The functorial map taking `ψ : A →⋆ₐ[ℂ] B` to a continuous function `characterSpace ℂ B → characterSpace ℂ A` obtained by pre-composition with `ψ`. -/ @[simps] -noncomputable def compContinuousMap (ψ : A →⋆ₐ[ℂ] B) : C(characterSpace ℂ B, characterSpace ℂ A) +noncomputable def compContinuousMap (ψ : A →⋆ₐ[𝕜] B) : C(characterSpace 𝕜 B, characterSpace 𝕜 A) where toFun φ := equivAlgHom.symm ((equivAlgHom φ).comp ψ.toAlgHom) continuous_toFun := Continuous.subtype_mk - (continuous_of_continuous_eval fun a => map_continuous <| gelfandTransform ℂ B (ψ a)) _ + (continuous_of_continuous_eval fun a => map_continuous <| gelfandTransform 𝕜 B (ψ a)) _ #align weak_dual.character_space.comp_continuous_map WeakDual.CharacterSpace.compContinuousMap variable (A) @@ -230,7 +239,7 @@ variable (A) /-- `WeakDual.CharacterSpace.compContinuousMap` sends the identity to the identity. -/ @[simp] theorem compContinuousMap_id : - compContinuousMap (StarAlgHom.id ℂ A) = ContinuousMap.id (characterSpace ℂ A) := + compContinuousMap (StarAlgHom.id 𝕜 A) = ContinuousMap.id (characterSpace 𝕜 A) := ContinuousMap.ext fun _a => ext fun _x => rfl #align weak_dual.character_space.comp_continuous_map_id WeakDual.CharacterSpace.compContinuousMap_id @@ -238,7 +247,7 @@ variable {A} /-- `WeakDual.CharacterSpace.compContinuousMap` is functorial. -/ @[simp] -theorem compContinuousMap_comp (ψ₂ : B →⋆ₐ[ℂ] C) (ψ₁ : A →⋆ₐ[ℂ] B) : +theorem compContinuousMap_comp (ψ₂ : B →⋆ₐ[𝕜] C) (ψ₁ : A →⋆ₐ[𝕜] B) : compContinuousMap (ψ₂.comp ψ₁) = (compContinuousMap ψ₁).comp (compContinuousMap ψ₂) := ContinuousMap.ext fun _a => ext fun _x => rfl #align weak_dual.character_space.comp_continuous_map_comp WeakDual.CharacterSpace.compContinuousMap_comp @@ -248,3 +257,64 @@ end CharacterSpace end WeakDual end Functoriality + +open CharacterSpace in +/-- +Consider the contravariant functors between compact Hausdorff spaces and commutative unital +C⋆algebras `F : Cpct → CommCStarAlg := X ↦ C(X, ℂ)` and +`G : CommCStarAlg → Cpct := A → characterSpace ℂ A` whose actions on morphisms are given by +`WeakDual.CharacterSpace.compContinuousMap` and `ContinuousMap.compStarAlgHom'`, respectively. + +Then `η : id → F ∘ G := gelfandStarTransform` is a natural isomorphism implementing (half of) +the duality between these categories. That is, for commutative unital C⋆-algebras `A` and `B` and +`φ : A →⋆ₐ[ℂ] B` the following diagram commutes: + +``` +A --- η A ---> C(characterSpace ℂ A, ℂ) + +| | + +φ (F ∘ G) φ + +| | +V V + +B --- η B ---> C(characterSpace ℂ B, ℂ) +``` +-/ +theorem gelfandStarTransform_naturality {A B : Type*} [NormedCommRing A] [NormedAlgebra ℂ A] + [CompleteSpace A] [StarRing A] [CstarRing A] [StarModule ℂ A] [NormedCommRing B] + [NormedAlgebra ℂ B] [CompleteSpace B] [StarRing B] [CstarRing B] [StarModule ℂ B] + (φ : A →⋆ₐ[ℂ] B) : + (gelfandStarTransform B : _ →⋆ₐ[ℂ] _).comp φ = + (compContinuousMap φ |>.compStarAlgHom' ℂ ℂ).comp (gelfandStarTransform A : _ →⋆ₐ[ℂ] _) := by + rfl + +/-- +Consider the contravariant functors between compact Hausdorff spaces and commutative unital +C⋆algebras `F : Cpct → CommCStarAlg := X ↦ C(X, ℂ)` and +`G : CommCStarAlg → Cpct := A → characterSpace ℂ A` whose actions on morphisms are given by +`WeakDual.CharacterSpace.compContinuousMap` and `ContinuousMap.compStarAlgHom'`, respectively. + +Then `η : id → G ∘ F := WeakDual.CharacterSpace.homeoEval` is a natural isomorphism implementing +(half of) the duality between these categories. That is, for compact Hausdorff spaces `X` and `Y`, +`f : C(X, Y)` the following diagram commutes: + +``` +X --- η X ---> characterSpace ℂ C(X, ℂ) + +| | + +f (G ∘ F) f + +| | +V V + +Y --- η Y ---> characterSpace ℂ C(Y, ℂ) +``` +-/ +lemma WeakDual.CharacterSpace.homeoEval_naturality {X Y 𝕜 : Type*} [IsROrC 𝕜] [TopologicalSpace X] + [CompactSpace X] [T2Space X] [TopologicalSpace Y] [CompactSpace Y] [T2Space Y] (f : C(X, Y)) : + (homeoEval Y 𝕜 : C(_, _)).comp f = + (f.compStarAlgHom' 𝕜 𝕜 |> compContinuousMap).comp (homeoEval X 𝕜 : C(_, _)) := + rfl diff --git a/Mathlib/Analysis/NormedSpace/Star/Matrix.lean b/Mathlib/Analysis/NormedSpace/Star/Matrix.lean index 5480cdcb90ba5..b467089e9d137 100644 --- a/Mathlib/Analysis/NormedSpace/Star/Matrix.lean +++ b/Mathlib/Analysis/NormedSpace/Star/Matrix.lean @@ -3,23 +3,45 @@ Copyright (c) 2022 Hans Parshall. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Hans Parshall -/ +import Mathlib.Analysis.InnerProductSpace.Adjoint import Mathlib.Analysis.Matrix import Mathlib.Analysis.NormedSpace.Basic import Mathlib.Data.IsROrC.Basic import Mathlib.LinearAlgebra.UnitaryGroup +import Mathlib.Topology.UniformSpace.Matrix #align_import analysis.normed_space.star.matrix from "leanprover-community/mathlib"@"468b141b14016d54b479eb7a0fff1e360b7e3cf6" /-! -# Unitary matrices +# Analytic properties of the `star` operation on matrices + +This transports the operator norm on `EuclideanSpace 𝕜 n →L[𝕜] EuclideanSpace 𝕜 m` to +`Matrix m n 𝕜`. See the file `Analysis.Matrix` for many other matrix norms. + +## Main definitions + +* `Matrix.instNormedRingL2Op`: the (necessarily unique) normed ring structure on `Matrix n n 𝕜` + which ensure it is a `CstarRing` in `Matrix.instCstarRing`. This is a scoped instance in the + namespace `Matrix.L2OpNorm` in order to avoid choosing a global norm for `Matrix`. + +## Main statements + +* `entry_norm_bound_of_unitary`: the entries of a unitary matrix are uniformly boundd by `1`. + +## Implementation details + +We take care to ensure the topology and uniformity induced by `Matrix.instMetricSpaceL2Op` +coincide with the existing topology and uniformity on matrices. + +## TODO + +* Show that `‖diagonal (v : n → 𝕜)‖ = ‖v‖`. -This file collects facts about the unitary matrices over `𝕜` (either `ℝ` or `ℂ`). -/ open scoped BigOperators Matrix - -variable {𝕜 m n E : Type*} +variable {𝕜 m n l E : Type*} section EntrywiseSupNorm @@ -70,3 +92,168 @@ theorem entrywise_sup_norm_bound_of_unitary {U : Matrix n n 𝕜} (hU : U ∈ Ma #align entrywise_sup_norm_bound_of_unitary entrywise_sup_norm_bound_of_unitary end EntrywiseSupNorm + +noncomputable section L2OpNorm + +namespace Matrix +open LinearMap + +variable [IsROrC 𝕜] +variable [Fintype m] [DecidableEq m] [Fintype n] [DecidableEq n] [Fintype l] [DecidableEq l] + +/-- The natural star algebra equivalence between matrices and continuous linear endomoporphisms +of Euclidean space induced by the orthonormal basis `EuclideanSpace.basisFun`. + +This is a more-bundled version of `Matrix.toEuclideanLin`, for the special case of square matrices, +followed by a more-bundled version of `LinearMap.toContinuousLinearMap`. -/ +def toEuclideanClm : + Matrix n n 𝕜 ≃⋆ₐ[𝕜] (EuclideanSpace 𝕜 n →L[𝕜] EuclideanSpace 𝕜 n) := + toMatrixOrthonormal (EuclideanSpace.basisFun n 𝕜) |>.symm.trans <| + { toContinuousLinearMap with + map_mul' := fun _ _ ↦ rfl + map_star' := adjoint_toContinuousLinearMap } + +lemma coe_toEuclideanClm_eq_toEuclideanLin (A : Matrix n n 𝕜) : + (toEuclideanClm (n := n) (𝕜 := 𝕜) A : _ →ₗ[𝕜] _) = toEuclideanLin A := + rfl + +@[simp] +lemma toEuclideanClm_piLp_equiv_symm (A : Matrix n n 𝕜) (x : n → 𝕜) : + toEuclideanClm (n := n) (𝕜 := 𝕜) A ((WithLp.equiv _ _).symm x) = + (WithLp.equiv _ _).symm (toLin' A x) := + rfl + +@[simp] +lemma piLp_equiv_toEuclideanClm (A : Matrix n n 𝕜) (x : EuclideanSpace 𝕜 n) : + WithLp.equiv _ _ (toEuclideanClm (n := n) (𝕜 := 𝕜) A x) = + toLin' A (WithLp.equiv _ _ x) := + rfl + +/-- An auxiliary definition used only to construct the true `NormedAddCommGroup` (and `Metric`) +structure provided by `Matrix.instMetricSpaceL2Op` and `Matrix.instNormedAddCommGroupL2Op`. -/ +def l2OpNormedAddCommGroupAux : NormedAddCommGroup (Matrix m n 𝕜) := + @NormedAddCommGroup.induced ((Matrix m n 𝕜) ≃ₗ[𝕜] (EuclideanSpace 𝕜 n →L[𝕜] EuclideanSpace 𝕜 m)) + _ _ _ ContinuousLinearMap.toNormedAddCommGroup.toNormedAddGroup _ _ <| + (toEuclideanLin.trans toContinuousLinearMap).injective + +/-- An auxiliary definition used only to construct the true `NormedRing` (and `Metric`) structure +provided by `Matrix.instMetricSpaceL2Op` and `Matrix.instNormedRingL2Op`. -/ +def l2OpNormedRingAux : NormedRing (Matrix n n 𝕜) := + @NormedRing.induced ((Matrix n n 𝕜) ≃⋆ₐ[𝕜] (EuclideanSpace 𝕜 n →L[𝕜] EuclideanSpace 𝕜 n)) + _ _ _ ContinuousLinearMap.toNormedRing _ _ toEuclideanClm.injective + +open Bornology Filter +open scoped Topology Uniformity + +/-- The metric on `Matrix m n 𝕜` arising from the operator norm given by the identification with +(continuous) linear maps of `EuclideanSpace`. -/ +def instL2OpMetricSpace : MetricSpace (Matrix m n 𝕜) := by + /- We first replace the topology so that we can automatically replace the uniformity using + `UniformAddGroup.toUniformSpace_eq`. -/ + letI normed_add_comm_group : NormedAddCommGroup (Matrix m n 𝕜) := + { l2OpNormedAddCommGroupAux.replaceTopology <| + (toEuclideanLin (𝕜 := 𝕜) (m := m) (n := n)).trans toContinuousLinearMap + |>.toContinuousLinearEquiv.toHomeomorph.inducing.induced with + norm := l2OpNormedAddCommGroupAux.norm + dist_eq := l2OpNormedAddCommGroupAux.dist_eq } + exact normed_add_comm_group.replaceUniformity <| by + congr + rw [← @UniformAddGroup.toUniformSpace_eq _ (instUniformSpaceMatrix m n 𝕜) _ _] + rw [@UniformAddGroup.toUniformSpace_eq _ PseudoEMetricSpace.toUniformSpace _ _] + +scoped[Matrix.L2OpNorm] attribute [instance] Matrix.instL2OpMetricSpace + +open scoped Matrix.L2OpNorm + +/-- The norm structure on `Matrix m n 𝕜` arising from the operator norm given by the identification +with (continuous) linear maps of `EuclideanSpace`. -/ +def instL2OpNormedAddCommGroup : NormedAddCommGroup (Matrix m n 𝕜) where + norm := l2OpNormedAddCommGroupAux.norm + dist_eq := l2OpNormedAddCommGroupAux.dist_eq + +scoped[Matrix.L2OpNorm] attribute [instance] Matrix.instL2OpNormedAddCommGroup + +lemma l2_op_norm_def (A : Matrix m n 𝕜) : + ‖A‖ = ‖(toEuclideanLin (𝕜 := 𝕜) (m := m) (n := n)).trans toContinuousLinearMap A‖ := rfl + +lemma l2_op_nnnorm_def (A : Matrix m n 𝕜) : + ‖A‖₊ = ‖(toEuclideanLin (𝕜 := 𝕜) (m := m) (n := n)).trans toContinuousLinearMap A‖₊ := rfl + +lemma l2_op_norm_conjTranspose (A : Matrix m n 𝕜) : ‖Aᴴ‖ = ‖A‖ := by + rw [l2_op_norm_def, toEuclideanLin_eq_toLin_orthonormal, LinearEquiv.trans_apply, + toLin_conjTranspose, adjoint_toContinuousLinearMap] + exact ContinuousLinearMap.adjoint.norm_map _ + +lemma l2_op_nnnorm_conjTranspose (A : Matrix m n 𝕜) : ‖Aᴴ‖₊ = ‖A‖₊ := + Subtype.ext <| l2_op_norm_conjTranspose _ + +lemma l2_op_norm_conjTranspose_mul_self (A : Matrix m n 𝕜) : ‖Aᴴ * A‖ = ‖A‖ * ‖A‖ := by + rw [l2_op_norm_def, toEuclideanLin_eq_toLin_orthonormal, LinearEquiv.trans_apply, + Matrix.toLin_mul (v₂ := (EuclideanSpace.basisFun m 𝕜).toBasis), toLin_conjTranspose] + exact ContinuousLinearMap.norm_adjoint_comp_self _ + +lemma l2_op_nnnorm_conjTranspose_mul_self (A : Matrix m n 𝕜) : ‖Aᴴ * A‖₊ = ‖A‖₊ * ‖A‖₊ := + Subtype.ext <| l2_op_norm_conjTranspose_mul_self _ + +-- note: with only a type ascription in the left-hand side, Lean picks the wrong norm. +lemma l2_op_norm_mulVec (A : Matrix m n 𝕜) (x : EuclideanSpace 𝕜 n) : + ‖(EuclideanSpace.equiv m 𝕜).symm <| A.mulVec x‖ ≤ ‖A‖ * ‖x‖ := + toEuclideanLin (n := n) (m := m) (𝕜 := 𝕜) |>.trans toContinuousLinearMap A |>.le_op_norm x + +lemma l2_op_nnnorm_mulVec (A : Matrix m n 𝕜) (x : EuclideanSpace 𝕜 n) : + ‖(EuclideanSpace.equiv m 𝕜).symm <| A.mulVec x‖₊ ≤ ‖A‖₊ * ‖x‖₊ := + A.l2_op_norm_mulVec x + +lemma l2_op_norm_mul (A : Matrix m n 𝕜) (B : Matrix n l 𝕜) : + ‖A * B‖ ≤ ‖A‖ * ‖B‖ := by + simp only [l2_op_norm_def] + have := (toEuclideanLin (n := n) (m := m) (𝕜 := 𝕜) ≪≫ₗ toContinuousLinearMap) A + |>.op_norm_comp_le <| (toEuclideanLin (n := l) (m := n) (𝕜 := 𝕜) ≪≫ₗ toContinuousLinearMap) B + convert this + ext1 x + exact congr($(Matrix.toLin'_mul A B) x) + +lemma l2_op_nnnorm_mul (A : Matrix m n 𝕜) (B : Matrix n l 𝕜) : ‖A * B‖₊ ≤ ‖A‖₊ * ‖B‖₊ := + l2_op_norm_mul A B + +/-- The normed algebra structure on `Matrix n n 𝕜` arising from the operator norm given by the +identification with (continuous) linear endmorphisms of `EuclideanSpace 𝕜 n`. -/ +def instL2OpNormedSpace : NormedSpace 𝕜 (Matrix m n 𝕜) where + norm_smul_le r x := by + rw [l2_op_norm_def, LinearEquiv.map_smul] + exact norm_smul_le r ((toEuclideanLin (𝕜 := 𝕜) (m := m) (n := n)).trans toContinuousLinearMap x) + +scoped[Matrix.L2OpNorm] attribute [instance] Matrix.instL2OpNormedSpace + +/-- The normed ring structure on `Matrix n n 𝕜` arising from the operator norm given by the +identification with (continuous) linear endmorphisms of `EuclideanSpace 𝕜 n`. -/ +def instL2OpNormedRing : NormedRing (Matrix n n 𝕜) where + dist_eq := l2OpNormedRingAux.dist_eq + norm_mul := l2OpNormedRingAux.norm_mul + +scoped[Matrix.L2OpNorm] attribute [instance] Matrix.instL2OpNormedRing + +/-- This is the same as `Matrix.l2_op_norm_def`, but with a more bundled RHS for square matrices. -/ +lemma cstar_norm_def (A : Matrix n n 𝕜) : ‖A‖ = ‖toEuclideanClm (n := n) (𝕜 := 𝕜) A‖ := rfl + +/-- This is the same as `Matrix.l2_op_nnnorm_def`, but with a more bundled RHS for square +matrices. -/ +lemma cstar_nnnorm_def (A : Matrix n n 𝕜) : ‖A‖₊ = ‖toEuclideanClm (n := n) (𝕜 := 𝕜) A‖₊ := rfl + +/-- The normed algebra structure on `Matrix n n 𝕜` arising from the operator norm given by the +identification with (continuous) linear endmorphisms of `EuclideanSpace 𝕜 n`. -/ +def instL2OpNormedAlgebra : NormedAlgebra 𝕜 (Matrix n n 𝕜) where + norm_smul_le := norm_smul_le + +scoped[Matrix.L2OpNorm] attribute [instance] Matrix.instL2OpNormedAlgebra + +/-- The operator norm on `Matrix n n 𝕜` given by the identification with (continuous) linear +endmorphisms of `EuclideanSpace 𝕜 n` makes it into a `L2OpRing`. -/ +lemma instCstarRing : CstarRing (Matrix n n 𝕜) where + norm_star_mul_self := l2_op_norm_conjTranspose_mul_self _ + +scoped[Matrix.L2OpNorm] attribute [instance] Matrix.instCstarRing + +end Matrix + +end L2OpNorm diff --git a/Mathlib/Analysis/NormedSpace/Star/Multiplier.lean b/Mathlib/Analysis/NormedSpace/Star/Multiplier.lean index 7a790033364cb..2e37c6256fa86 100644 --- a/Mathlib/Analysis/NormedSpace/Star/Multiplier.lean +++ b/Mathlib/Analysis/NormedSpace/Star/Multiplier.lean @@ -519,7 +519,7 @@ noncomputable def coeHom [StarRing 𝕜] [StarRing A] [StarModule 𝕜 A] [Norme map_smul' _ _ := ext _ _ _ _ <| Prod.ext (map_smul _ _ _) (map_smul _ _ _) map_zero' := ext _ _ _ _ <| Prod.ext (map_zero _) (map_zero _) map_add' _ _ := ext _ _ _ _ <| Prod.ext (map_add _ _ _) (map_add _ _ _) - map_mul' _ _ := ext _ _ _ _ <| Prod.ext + map_mul' _ _ := ext _ _ _ _ <| Prod.ext (ContinuousLinearMap.ext fun _ => (mul_assoc _ _ _)) (ContinuousLinearMap.ext fun _ => (mul_assoc _ _ _).symm) map_star' _ := ext _ _ _ _ <| Prod.ext diff --git a/Mathlib/Analysis/NormedSpace/Star/Spectrum.lean b/Mathlib/Analysis/NormedSpace/Star/Spectrum.lean index bf6ecd79726a3..4b121f31c605d 100644 --- a/Mathlib/Analysis/NormedSpace/Star/Spectrum.lean +++ b/Mathlib/Analysis/NormedSpace/Star/Spectrum.lean @@ -170,7 +170,7 @@ variable {F A : Type*} [NormedRing A] [NormedAlgebra ℂ A] [CompleteSpace A] [S See note [lower instance priority] -/ noncomputable instance (priority := 100) Complex.instStarHomClass : StarHomClass F A ℂ where coe φ := φ - coe_injective' := FunLike.coe_injective' + coe_injective' := DFunLike.coe_injective' map_star φ a := by suffices hsa : ∀ s : selfAdjoint A, (φ s)⋆ = φ s · rw [← realPart_add_I_smul_imaginaryPart a] diff --git a/Mathlib/Analysis/NormedSpace/TrivSqZeroExt.lean b/Mathlib/Analysis/NormedSpace/TrivSqZeroExt.lean index 25135fad86b70..d94daf4f5e07f 100644 --- a/Mathlib/Analysis/NormedSpace/TrivSqZeroExt.lean +++ b/Mathlib/Analysis/NormedSpace/TrivSqZeroExt.lean @@ -5,6 +5,7 @@ Authors: Eric Wieser -/ import Mathlib.Analysis.NormedSpace.Basic import Mathlib.Analysis.NormedSpace.Exponential +import Mathlib.Analysis.NormedSpace.ProdLp import Mathlib.Topology.Instances.TrivSqZeroExt #align_import analysis.normed_space.triv_sq_zero_ext from "leanprover-community/mathlib"@"88a563b158f59f2983cfad685664da95502e8cdd" @@ -12,7 +13,15 @@ import Mathlib.Topology.Instances.TrivSqZeroExt /-! # Results on `TrivSqZeroExt R M` related to the norm -For now, this file contains results about `exp` for this type. +This file contains results about `NormedSpace.exp` for `TrivSqZeroExt`. + +It also contains a definition of the $ℓ^1$ norm, +which defines $\|r + m\| \coloneqq \|r\| + \|m\|$. +This is not a particularly canonical choice of definition, +but it is sufficient to provide a `NormedAlgebra` instance, +and thus enables `NormedSpace.exp_add_of_commute` to be used on `TrivSqZeroExt`. +If the non-canonicity becomes problematic in future, +we could keep the collection of instances behind an `open scoped`. ## Main results @@ -20,21 +29,29 @@ For now, this file contains results about `exp` for this type. * `TrivSqZeroExt.snd_exp` * `TrivSqZeroExt.exp_inl` * `TrivSqZeroExt.exp_inr` +* The $ℓ^1$ norm on `TrivSqZeroExt`: + * `TrivSqZeroExt.instL1SeminormedAddCommGroup` + * `TrivSqZeroExt.instL1SeminormedRing` + * `TrivSqZeroExt.instL1SeminormedCommRing` + * `TrivSqZeroExt.instL1BoundedSMul` + * `TrivSqZeroExt.instL1NormedAddCommGroup` + * `TrivSqZeroExt.instL1NormedRing` + * `TrivSqZeroExt.instL1NormedCommRing` + * `TrivSqZeroExt.instL1NormedSpace` + * `TrivSqZeroExt.instL1NormedAlgebra` ## TODO -* Actually define a sensible norm on `TrivSqZeroExt R M`, so that we have access to lemmas - like `exp_add`. * Generalize more of these results to non-commutative `R`. In principle, under sufficient conditions we should expect - `(exp 𝕜 x).snd = ∫ t in 0..1, exp 𝕜 (t • x.fst) • op (exp 𝕜 ((1 - t) • x.fst)) • x.snd` + `(exp 𝕜 x).snd = ∫ t in 0..1, exp 𝕜 (t • x.fst) • op (exp 𝕜 ((1 - t) • x.fst)) • x.snd` ([Physics.SE](https://physics.stackexchange.com/a/41671/185147), and https://link.springer.com/chapter/10.1007/978-3-540-44953-9_2). -/ -variable (𝕜 : Type*) {R M : Type*} +variable (𝕜 : Type*) {S R M : Type*} local notation "tsze" => TrivSqZeroExt @@ -44,76 +61,70 @@ namespace TrivSqZeroExt section Topology -variable [TopologicalSpace R] [TopologicalSpace M] - -/-- If `exp R x.fst` converges to `e` then `(exp R x).fst` converges to `e`. -/ -theorem hasSum_fst_expSeries [Field 𝕜] [Ring R] [AddCommGroup M] [Algebra 𝕜 R] [Module R M] - [Module Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] [Module 𝕜 M] [IsScalarTower 𝕜 R M] - [IsScalarTower 𝕜 Rᵐᵒᵖ M] [TopologicalRing R] [TopologicalAddGroup M] [ContinuousSMul R M] - [ContinuousSMul Rᵐᵒᵖ M] (x : tsze R M) {e : R} - (h : HasSum (fun n => expSeries 𝕜 R n fun _ => x.fst) e) : - HasSum (fun n => fst (expSeries 𝕜 (tsze R M) n fun _ => x)) e := by - simpa [expSeries_apply_eq] using h -#align triv_sq_zero_ext.has_sum_fst_exp_series TrivSqZeroExt.hasSum_fst_expSeries +section not_charZero +variable [Field 𝕜] [Ring R] [AddCommGroup M] + [Algebra 𝕜 R] [Module 𝕜 M] [Module R M] [Module Rᵐᵒᵖ M] + [SMulCommClass R Rᵐᵒᵖ M] [IsScalarTower 𝕜 R M] [IsScalarTower 𝕜 Rᵐᵒᵖ M] + [TopologicalSpace R] [TopologicalSpace M] + [TopologicalRing R] [TopologicalAddGroup M] [ContinuousSMul R M] [ContinuousSMul Rᵐᵒᵖ M] + +@[simp] theorem fst_expSeries (x : tsze R M) (n : ℕ) : + fst (expSeries 𝕜 (tsze R M) n fun _ => x) = expSeries 𝕜 R n fun _ => x.fst := by + simp [expSeries_apply_eq] + +end not_charZero + +section Ring +variable [Field 𝕜] [CharZero 𝕜] [Ring R] [AddCommGroup M] + [Algebra 𝕜 R] [Module 𝕜 M] [Module R M] [Module Rᵐᵒᵖ M] + [SMulCommClass R Rᵐᵒᵖ M] [IsScalarTower 𝕜 R M] [IsScalarTower 𝕜 Rᵐᵒᵖ M] + [TopologicalSpace R] [TopologicalSpace M] + [TopologicalRing R] [TopologicalAddGroup M] [ContinuousSMul R M] [ContinuousSMul Rᵐᵒᵖ M] + +theorem snd_expSeries_of_smul_comm + (x : tsze R M) (hx : MulOpposite.op x.fst • x.snd = x.fst • x.snd) (n : ℕ) : + snd (expSeries 𝕜 (tsze R M) (n + 1) fun _ => x) = (expSeries 𝕜 R n fun _ => x.fst) • x.snd := by + simp_rw [expSeries_apply_eq, snd_smul, snd_pow_of_smul_comm _ _ hx, nsmul_eq_smul_cast 𝕜 (n + 1), + smul_smul, smul_assoc, Nat.factorial_succ, Nat.pred_succ, Nat.cast_mul, mul_inv_rev, + inv_mul_cancel_right₀ ((Nat.cast_ne_zero (R := 𝕜)).mpr <| Nat.succ_ne_zero n)] /-- If `exp R x.fst` converges to `e` then `(exp R x).snd` converges to `e • x.snd`. -/ -theorem hasSum_snd_expSeries_of_smul_comm [Field 𝕜] [CharZero 𝕜] [Ring R] [AddCommGroup M] - [Algebra 𝕜 R] [Module R M] [Module Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] [Module 𝕜 M] - [IsScalarTower 𝕜 R M] [IsScalarTower 𝕜 Rᵐᵒᵖ M] [TopologicalRing R] [TopologicalAddGroup M] - [ContinuousSMul R M] [ContinuousSMul Rᵐᵒᵖ M] (x : tsze R M) +theorem hasSum_snd_expSeries_of_smul_comm (x : tsze R M) (hx : MulOpposite.op x.fst • x.snd = x.fst • x.snd) {e : R} (h : HasSum (fun n => expSeries 𝕜 R n fun _ => x.fst) e) : HasSum (fun n => snd (expSeries 𝕜 (tsze R M) n fun _ => x)) (e • x.snd) := by - simp_rw [expSeries_apply_eq] at * - conv => - congr - ext n - rw [snd_smul, snd_pow_of_smul_comm _ _ hx, nsmul_eq_smul_cast 𝕜 n, smul_smul, inv_mul_eq_div, ← - inv_div, ← smul_assoc] - apply HasSum.smul_const rw [← hasSum_nat_add_iff' 1] - rw [Finset.range_one, Finset.sum_singleton, Nat.cast_zero, div_zero, inv_zero, zero_smul, - sub_zero] - simp_rw [← Nat.succ_eq_add_one, Nat.pred_succ, Nat.factorial_succ, Nat.cast_mul, ← - Nat.succ_eq_add_one, - mul_div_cancel_left _ ((@Nat.cast_ne_zero 𝕜 _ _ _).mpr <| Nat.succ_ne_zero _)] - exact h + simp_rw [snd_expSeries_of_smul_comm _ _ hx] + simp_rw [expSeries_apply_eq] at * + rw [Finset.range_one, Finset.sum_singleton, Nat.factorial_zero, Nat.cast_one, pow_zero, + inv_one, one_smul, snd_one, sub_zero] + exact h.smul_const _ #align triv_sq_zero_ext.has_sum_snd_exp_series_of_smul_comm TrivSqZeroExt.hasSum_snd_expSeries_of_smul_comm /-- If `exp R x.fst` converges to `e` then `exp R x` converges to `inl e + inr (e • x.snd)`. -/ -theorem hasSum_expSeries_of_smul_comm [Field 𝕜] [CharZero 𝕜] [Ring R] [AddCommGroup M] [Algebra 𝕜 R] - [Module R M] [Module Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] [Module 𝕜 M] [IsScalarTower 𝕜 R M] - [IsScalarTower 𝕜 Rᵐᵒᵖ M] [TopologicalRing R] [TopologicalAddGroup M] [ContinuousSMul R M] - [ContinuousSMul Rᵐᵒᵖ M] (x : tsze R M) (hx : MulOpposite.op x.fst • x.snd = x.fst • x.snd) +theorem hasSum_expSeries_of_smul_comm + (x : tsze R M) (hx : MulOpposite.op x.fst • x.snd = x.fst • x.snd) {e : R} (h : HasSum (fun n => expSeries 𝕜 R n fun _ => x.fst) e) : HasSum (fun n => expSeries 𝕜 (tsze R M) n fun _ => x) (inl e + inr (e • x.snd)) := by + have : HasSum (fun n => fst (expSeries 𝕜 (tsze R M) n fun _ => x)) e := by + simpa [fst_expSeries] using h simpa only [inl_fst_add_inr_snd_eq] using - (hasSum_inl _ <| hasSum_fst_expSeries 𝕜 x h).add - (hasSum_inr _ <| hasSum_snd_expSeries_of_smul_comm 𝕜 x hx h) + (hasSum_inl _ <| this).add (hasSum_inr _ <| hasSum_snd_expSeries_of_smul_comm 𝕜 x hx h) #align triv_sq_zero_ext.has_sum_exp_series_of_smul_comm TrivSqZeroExt.hasSum_expSeries_of_smul_comm -end Topology - -section NormedRing - -variable [IsROrC 𝕜] [NormedRing R] [AddCommGroup M] - -variable [NormedAlgebra 𝕜 R] [Module R M] [Module Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] - -variable [Module 𝕜 M] [IsScalarTower 𝕜 R M] [IsScalarTower 𝕜 Rᵐᵒᵖ M] - -variable [TopologicalSpace M] [TopologicalRing R] - -variable [TopologicalAddGroup M] [ContinuousSMul R M] [ContinuousSMul Rᵐᵒᵖ M] - -variable [CompleteSpace R] [T2Space R] [T2Space M] +variable [T2Space R] [T2Space M] theorem exp_def_of_smul_comm (x : tsze R M) (hx : MulOpposite.op x.fst • x.snd = x.fst • x.snd) : exp 𝕜 x = inl (exp 𝕜 x.fst) + inr (exp 𝕜 x.fst • x.snd) := by simp_rw [exp, FormalMultilinearSeries.sum] - refine' (hasSum_expSeries_of_smul_comm 𝕜 x hx _).tsum_eq - exact expSeries_hasSum_exp _ -#align triv_sq_zero_ext.exp_def_of_smul_comm TrivSqZeroExt.exp_def_of_smul_comm + by_cases h : Summable (fun (n : ℕ) => (expSeries 𝕜 R n) fun x_1 ↦ fst x) + · refine (hasSum_expSeries_of_smul_comm 𝕜 x hx ?_).tsum_eq + exact h.hasSum + · rw [tsum_eq_zero_of_not_summable h, zero_smul, inr_zero, inl_zero, zero_add, + tsum_eq_zero_of_not_summable] + simp_rw [← fst_expSeries] at h + refine mt ?_ h + exact (Summable.map · (TrivSqZeroExt.fstHom 𝕜 R M).toLinearMap continuous_fst) @[simp] theorem exp_inl (x : R) : exp 𝕜 (inl x : tsze R M) = inl (exp 𝕜 x) := by @@ -127,21 +138,16 @@ theorem exp_inr (m : M) : exp 𝕜 (inr m : tsze R M) = 1 + inr m := by · rw [snd_inr, fst_inr, MulOpposite.op_zero, zero_smul, zero_smul] #align triv_sq_zero_ext.exp_inr TrivSqZeroExt.exp_inr -end NormedRing - -section NormedCommRing - -variable [IsROrC 𝕜] [NormedCommRing R] [AddCommGroup M] - -variable [NormedAlgebra 𝕜 R] [Module R M] [Module Rᵐᵒᵖ M] [IsCentralScalar R M] - -variable [Module 𝕜 M] [IsScalarTower 𝕜 R M] +end Ring -variable [TopologicalSpace M] [TopologicalRing R] +section CommRing +variable [Field 𝕜] [CharZero 𝕜] [CommRing R] [AddCommGroup M] + [Algebra 𝕜 R] [Module 𝕜 M] [Module R M] [Module Rᵐᵒᵖ M] + [IsCentralScalar R M] [IsScalarTower 𝕜 R M] + [TopologicalSpace R] [TopologicalSpace M] + [TopologicalRing R] [TopologicalAddGroup M] [ContinuousSMul R M] [ContinuousSMul Rᵐᵒᵖ M] -variable [TopologicalAddGroup M] [ContinuousSMul R M] - -variable [CompleteSpace R] [T2Space R] [T2Space M] +variable [T2Space R] [T2Space M] theorem exp_def (x : tsze R M) : exp 𝕜 x = inl (exp 𝕜 x.fst) + inr (exp 𝕜 x.fst • x.snd) := exp_def_of_smul_comm 𝕜 x (op_smul_eq_smul _ _) @@ -164,21 +170,16 @@ theorem eq_smul_exp_of_invertible (x : tsze R M) [Invertible x.fst] : smul_smul, mul_invOf_self, one_smul, inl_fst_add_inr_snd_eq] #align triv_sq_zero_ext.eq_smul_exp_of_invertible TrivSqZeroExt.eq_smul_exp_of_invertible -end NormedCommRing - -section NormedField - -variable [IsROrC 𝕜] [NormedField R] [AddCommGroup M] - -variable [NormedAlgebra 𝕜 R] [Module R M] [Module Rᵐᵒᵖ M] [IsCentralScalar R M] - -variable [Module 𝕜 M] [IsScalarTower 𝕜 R M] +end CommRing -variable [TopologicalSpace M] [TopologicalRing R] +section Field +variable [Field 𝕜] [CharZero 𝕜] [Field R] [AddCommGroup M] + [Algebra 𝕜 R] [Module 𝕜 M] [Module R M] [Module Rᵐᵒᵖ M] + [IsCentralScalar R M] [IsScalarTower 𝕜 R M] + [TopologicalSpace R] [TopologicalSpace M] + [TopologicalRing R] [TopologicalAddGroup M] [ContinuousSMul R M] [ContinuousSMul Rᵐᵒᵖ M] -variable [TopologicalAddGroup M] [ContinuousSMul R M] - -variable [CompleteSpace R] [T2Space R] [T2Space M] +variable [T2Space R] [T2Space M] /-- More convenient version of `TrivSqZeroExt.eq_smul_exp_of_invertible` for when `R` is a field. -/ @@ -188,6 +189,144 @@ theorem eq_smul_exp_of_ne_zero (x : tsze R M) (hx : x.fst ≠ 0) : eq_smul_exp_of_invertible _ _ #align triv_sq_zero_ext.eq_smul_exp_of_ne_zero TrivSqZeroExt.eq_smul_exp_of_ne_zero -end NormedField +end Field + +end Topology + +/-! +### The $ℓ^1$ norm on the trivial square zero extension +-/ + +noncomputable section Seminormed + +section Ring +variable [SeminormedCommRing S] [SeminormedRing R] [SeminormedAddCommGroup M] +variable [Algebra S R] [Module S M] [Module R M] [Module Rᵐᵒᵖ M] +variable [BoundedSMul S R] [BoundedSMul S M] [BoundedSMul R M] [BoundedSMul Rᵐᵒᵖ M] +variable [SMulCommClass R Rᵐᵒᵖ M] [IsScalarTower S R M] [IsScalarTower S Rᵐᵒᵖ M] + +instance instL1SeminormedAddCommGroup : SeminormedAddCommGroup (tsze R M) := + inferInstanceAs <| SeminormedAddCommGroup (WithLp 1 <| R × M) + +example : + (TrivSqZeroExt.instUniformSpace : UniformSpace (tsze R M)) = + PseudoMetricSpace.toUniformSpace := rfl + +theorem norm_def (x : tsze R M) : ‖x‖ = ‖fst x‖ + ‖snd x‖ := by + rw [WithLp.prod_norm_eq_add (by norm_num)] + simp only [ENNReal.one_toReal, Real.rpow_one, div_one] + rfl + +theorem nnnorm_def (x : tsze R M) : ‖x‖₊ = ‖fst x‖₊ + ‖snd x‖₊ := by + ext; simp [norm_def] + +@[simp] theorem norm_inl (r : R) : ‖(inl r : tsze R M)‖ = ‖r‖ := by simp [norm_def] +@[simp] theorem norm_inr (m : M) : ‖(inr m : tsze R M)‖ = ‖m‖ := by simp [norm_def] + +@[simp] theorem nnnorm_inl (r : R) : ‖(inl r : tsze R M)‖₊ = ‖r‖₊ := by simp [nnnorm_def] +@[simp] theorem nnnorm_inr (m : M) : ‖(inr m : tsze R M)‖₊ = ‖m‖₊ := by simp [nnnorm_def] + +instance instL1SeminormedRing : SeminormedRing (tsze R M) where + norm_mul + | ⟨r₁, m₁⟩, ⟨r₂, m₂⟩ => by + dsimp + rw [norm_def, norm_def, norm_def, add_mul, mul_add, mul_add, snd_mul, fst_mul] + dsimp [fst, snd] + rw [add_assoc] + gcongr + · exact norm_mul_le _ _ + refine (norm_add_le _ _).trans ?_ + gcongr + · exact norm_smul_le _ _ + refine (_root_.norm_smul_le _ _).trans ?_ + rw [mul_comm, MulOpposite.norm_op] + exact le_add_of_nonneg_right <| by positivity + __ : SeminormedAddCommGroup (tsze R M) := inferInstance + __ : Ring (tsze R M) := inferInstance + +instance instL1BoundedSMul : BoundedSMul S (tsze R M) := + inferInstanceAs <| BoundedSMul S (WithLp 1 <| R × M) + +instance [NormOneClass R] : NormOneClass (tsze R M) where + norm_one := by rw [norm_def, fst_one, snd_one, norm_zero, norm_one, add_zero] + + +end Ring + +section CommRing + +variable [SeminormedCommRing R] [SeminormedAddCommGroup M] +variable [Module R M] [Module Rᵐᵒᵖ M] [IsCentralScalar R M] +variable [BoundedSMul R M] + +instance instL1SeminormedCommRing : SeminormedCommRing (tsze R M) where + __ : CommRing (tsze R M) := inferInstance + __ : SeminormedRing (tsze R M) := inferInstance + +end CommRing + +end Seminormed + +noncomputable section Normed + +section Ring + +variable [NormedCommRing S] [NormedRing R] [NormedAddCommGroup M] +variable [Algebra S R] [Module S M] [Module R M] [Module Rᵐᵒᵖ M] +variable [BoundedSMul S R] [BoundedSMul S M] [BoundedSMul R M] [BoundedSMul Rᵐᵒᵖ M] +variable [SMulCommClass R Rᵐᵒᵖ M] [IsScalarTower S R M] [IsScalarTower S Rᵐᵒᵖ M] + +instance instL1NormedAddCommGroup : NormedAddCommGroup (tsze R M) := + inferInstanceAs <| NormedAddCommGroup (WithLp 1 <| R × M) + +instance instL1NormedRing : NormedRing (tsze R M) where + __ : NormedAddCommGroup (tsze R M) := inferInstance + __ : SeminormedRing (tsze R M) := inferInstance + +end Ring + +section CommRing + +variable [NormedCommRing R] [NormedAddCommGroup M] +variable [Module R M] [Module Rᵐᵒᵖ M] [IsCentralScalar R M] +variable [BoundedSMul R M] + +instance instL1NormedCommRing : NormedCommRing (tsze R M) where + __ : CommRing (tsze R M) := inferInstance + __ : NormedRing (tsze R M) := inferInstance + +end CommRing + +section Algebra + +variable [NormedField 𝕜] [NormedRing R] [NormedAddCommGroup M] +variable [NormedAlgebra 𝕜 R] [NormedSpace 𝕜 M] [Module R M] [Module Rᵐᵒᵖ M] +variable [BoundedSMul R M] [BoundedSMul Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] +variable [IsScalarTower 𝕜 R M] [IsScalarTower 𝕜 Rᵐᵒᵖ M] + +instance instL1NormedSpace : NormedSpace 𝕜 (tsze R M) := + inferInstanceAs <| NormedSpace 𝕜 (WithLp 1 <| R × M) + +instance instL1NormedAlgebra : NormedAlgebra 𝕜 (tsze R M) where + norm_smul_le := _root_.norm_smul_le + +end Algebra + + +end Normed + +section + +variable [IsROrC 𝕜] [NormedRing R] [NormedAddCommGroup M] +variable [NormedAlgebra 𝕜 R] [NormedSpace 𝕜 M] [Module R M] [Module Rᵐᵒᵖ M] +variable [BoundedSMul R M] [BoundedSMul Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] +variable [IsScalarTower 𝕜 R M] [IsScalarTower 𝕜 Rᵐᵒᵖ M] +variable [CompleteSpace R] [CompleteSpace M] + +-- Evidence that we have sufficient instances on `tsze R N` to make `exp_add_of_commute` usable +example (a b : tsze R M) (h : Commute a b) : exp 𝕜 (a + b) = exp 𝕜 a * exp 𝕜 b := + exp_add_of_commute h + +end end TrivSqZeroExt diff --git a/Mathlib/Analysis/NormedSpace/Unitization.lean b/Mathlib/Analysis/NormedSpace/Unitization.lean index 551eacfa12069..a66eadea2c5e8 100644 --- a/Mathlib/Analysis/NormedSpace/Unitization.lean +++ b/Mathlib/Analysis/NormedSpace/Unitization.lean @@ -6,6 +6,7 @@ Authors: Jireh Loreaux import Mathlib.Algebra.Algebra.Unitization import Mathlib.Analysis.NormedSpace.OperatorNorm +import Mathlib.Topology.Bornology.Constructions /-! # Unitization norms diff --git a/Mathlib/Analysis/NormedSpace/WeakDual.lean b/Mathlib/Analysis/NormedSpace/WeakDual.lean index fe9b86030683d..76698a8b364f7 100644 --- a/Mathlib/Analysis/NormedSpace/WeakDual.lean +++ b/Mathlib/Analysis/NormedSpace/WeakDual.lean @@ -216,7 +216,7 @@ theorem isClosed_image_coe_of_bounded_of_closed {s : Set (WeakDual 𝕜 E)} theorem isCompact_of_bounded_of_closed [ProperSpace 𝕜] {s : Set (WeakDual 𝕜 E)} (hb : IsBounded (Dual.toWeakDual ⁻¹' s)) (hc : IsClosed s) : IsCompact s := - (Embedding.isCompact_iff FunLike.coe_injective.embedding_induced).mpr <| + (Embedding.isCompact_iff DFunLike.coe_injective.embedding_induced).mpr <| ContinuousLinearMap.isCompact_image_coe_of_bounded_of_closed_image hb <| isClosed_image_coe_of_bounded_of_closed hb hc #align weak_dual.is_compact_of_bounded_of_closed WeakDual.isCompact_of_bounded_of_closed diff --git a/Mathlib/Analysis/NormedSpace/WithLp.lean b/Mathlib/Analysis/NormedSpace/WithLp.lean index 2d1ef7218b003..373a27d90c3d4 100644 --- a/Mathlib/Analysis/NormedSpace/WithLp.lean +++ b/Mathlib/Analysis/NormedSpace/WithLp.lean @@ -3,8 +3,8 @@ Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Data.Real.ENNReal -import Mathlib.LinearAlgebra.FiniteDimensional +import Mathlib.Data.ENNReal.Basic +import Mathlib.RingTheory.Finiteness /-! # The `WithLp` type synonym diff --git a/Mathlib/Analysis/NormedSpace/lpSpace.lean b/Mathlib/Analysis/NormedSpace/lpSpace.lean index cf39125f6e249..a9e4d7809ed16 100644 --- a/Mathlib/Analysis/NormedSpace/lpSpace.lean +++ b/Mathlib/Analysis/NormedSpace/lpSpace.lean @@ -6,6 +6,7 @@ Authors: Heather Macbeth import Mathlib.Analysis.MeanInequalities import Mathlib.Analysis.MeanInequalitiesPow import Mathlib.Analysis.SpecialFunctions.Pow.Continuity +import Mathlib.Data.Set.Image import Mathlib.Topology.Algebra.Order.LiminfLimsup #align_import analysis.normed_space.lp_space from "leanprover-community/mathlib"@"de83b43717abe353f425855fcf0cedf9ea0fe8a4" @@ -55,8 +56,6 @@ say that `‖-f‖ = ‖f‖`, instead of the non-working `f.norm_neg`. -/ -set_option autoImplicit true - noncomputable section open scoped NNReal ENNReal BigOperators Function @@ -121,7 +120,7 @@ theorem memℓp_gen' {C : ℝ} {f : ∀ i, E i} (hf : ∀ s : Finset α, ∑ i i use ⨆ s : Finset α, ∑ i in s, ‖f i‖ ^ p.toReal apply hasSum_of_isLUB_of_nonneg · intro b - exact Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + exact Real.rpow_nonneg (norm_nonneg _) _ apply isLUB_ciSup use C rintro - ⟨s, rfl⟩ @@ -206,7 +205,7 @@ theorem of_exponent_ge {p q : ℝ≥0∞} {f : ∀ i, E i} (hfq : Memℓp f q) ( exact H.subset fun i hi => Real.one_le_rpow hi hq.le · show ∀ i, ¬|‖f i‖ ^ p.toReal| ≤ ‖f i‖ ^ q.toReal → 1 ≤ ‖f i‖ intro i hi - have : 0 ≤ ‖f i‖ ^ p.toReal := Real.rpow_nonneg_of_nonneg (norm_nonneg _) p.toReal + have : 0 ≤ ‖f i‖ ^ p.toReal := Real.rpow_nonneg (norm_nonneg _) p.toReal simp only [abs_of_nonneg, this] at hi contrapose! hi exact Real.rpow_le_rpow_of_exponent_ge' (norm_nonneg _) hi.le hq.le hpq' @@ -438,8 +437,8 @@ theorem norm_nonneg' (f : lp E p) : 0 ≤ ‖f‖ := by inhabit α exact (norm_nonneg (f default)).trans ((lp.isLUB_norm f).1 ⟨default, rfl⟩) · rw [lp.norm_eq_tsum_rpow hp f] - refine' Real.rpow_nonneg_of_nonneg (tsum_nonneg _) _ - exact fun i => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + refine' Real.rpow_nonneg (tsum_nonneg _) _ + exact fun i => Real.rpow_nonneg (norm_nonneg _) _ #align lp.norm_nonneg' lp.norm_nonneg' @[simp] @@ -468,7 +467,7 @@ theorem norm_eq_zero_iff {f : lp E p} : ‖f‖ = 0 ↔ f = 0 := by · have hf : HasSum (fun i : α => ‖f i‖ ^ p.toReal) 0 := by have := lp.hasSum_norm hp f rwa [h, Real.zero_rpow hp.ne'] at this - have : ∀ i, 0 ≤ ‖f i‖ ^ p.toReal := fun i => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + have : ∀ i, 0 ≤ ‖f i‖ ^ p.toReal := fun i => Real.rpow_nonneg (norm_nonneg _) _ rw [hasSum_zero_iff_of_nonneg this] at hf ext i have : f i = 0 ∧ p.toReal ≠ 0 := by @@ -560,7 +559,7 @@ theorem norm_apply_le_norm (hp : p ≠ 0) (f : lp E p) (i : α) : ‖f i‖ ≤ · haveI : Nonempty α := ⟨i⟩ exact (isLUB_norm f).1 ⟨i, rfl⟩ have hp'' : 0 < p.toReal := ENNReal.toReal_pos hp hp' - have : ∀ i, 0 ≤ ‖f i‖ ^ p.toReal := fun i => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + have : ∀ i, 0 ≤ ‖f i‖ ^ p.toReal := fun i => Real.rpow_nonneg (norm_nonneg _) _ rw [← Real.rpow_le_rpow_iff (norm_nonneg _) (norm_nonneg' _) hp''] convert le_hasSum (hasSum_norm hp'' f) i fun i _ => this i #align lp.norm_apply_le_norm lp.norm_apply_le_norm @@ -568,7 +567,7 @@ theorem norm_apply_le_norm (hp : p ≠ 0) (f : lp E p) (i : α) : ‖f i‖ ≤ theorem sum_rpow_le_norm_rpow (hp : 0 < p.toReal) (f : lp E p) (s : Finset α) : ∑ i in s, ‖f i‖ ^ p.toReal ≤ ‖f‖ ^ p.toReal := by rw [lp.norm_rpow_eq_tsum hp f] - have : ∀ i, 0 ≤ ‖f i‖ ^ p.toReal := fun i => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + have : ∀ i, 0 ≤ ‖f i‖ ^ p.toReal := fun i => Real.rpow_nonneg (norm_nonneg _) _ refine' sum_le_tsum _ (fun i _ => this i) _ exact (lp.memℓp f).summable hp #align lp.sum_rpow_le_norm_rpow lp.sum_rpow_le_norm_rpow @@ -1222,6 +1221,7 @@ end lp section Lipschitz open ENNReal lp +variable {ι : Type*} lemma LipschitzWith.uniformly_bounded [PseudoMetricSpace α] (g : α → ι → ℝ) {K : ℝ≥0} (hg : ∀ i, LipschitzWith K (g · i)) (a₀ : α) (hga₀b : Memℓp (g a₀) ∞) (a : α) : diff --git a/Mathlib/Analysis/ODE/Gronwall.lean b/Mathlib/Analysis/ODE/Gronwall.lean index 0a6b7049f0038..72ac9a2db8179 100644 --- a/Mathlib/Analysis/ODE/Gronwall.lean +++ b/Mathlib/Analysis/ODE/Gronwall.lean @@ -144,19 +144,24 @@ theorem norm_le_gronwallBound_of_norm_deriv_right_le {f f' : ℝ → E} {δ K ε (fun x hx _r hr => (hf' x hx).liminf_right_slope_norm_le hr) ha bound #align norm_le_gronwall_bound_of_norm_deriv_right_le norm_le_gronwallBound_of_norm_deriv_right_le +variable {v : ℝ → E → E} {s : ℝ → Set E} {K : ℝ≥0} {f g f' g' : ℝ → E} {a b t₀ : ℝ} {εf εg δ : ℝ} + (hv : ∀ t, LipschitzOnWith K (v t) (s t)) + /-- If `f` and `g` are two approximate solutions of the same ODE, then the distance between them can't grow faster than exponentially. This is a simple corollary of Grönwall's inequality, and some people call this Grönwall's inequality too. This version assumes all inequalities to be true in some time-dependent set `s t`, and assumes that the solutions never leave this set. -/ -theorem dist_le_of_approx_trajectories_ODE_of_mem_set {v : ℝ → E → E} {s : ℝ → Set E} {K : ℝ≥0} - (hv : ∀ t, LipschitzOnWith K (v t) (s t)) - {f g f' g' : ℝ → E} {a b : ℝ} {εf εg δ : ℝ} (hf : ContinuousOn f (Icc a b)) +theorem dist_le_of_approx_trajectories_ODE_of_mem + (hf : ContinuousOn f (Icc a b)) (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (f' t) (Ici t) t) - (f_bound : ∀ t ∈ Ico a b, dist (f' t) (v t (f t)) ≤ εf) (hfs : ∀ t ∈ Ico a b, f t ∈ s t) - (hg : ContinuousOn g (Icc a b)) (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (g' t) (Ici t) t) - (g_bound : ∀ t ∈ Ico a b, dist (g' t) (v t (g t)) ≤ εg) (hgs : ∀ t ∈ Ico a b, g t ∈ s t) + (f_bound : ∀ t ∈ Ico a b, dist (f' t) (v t (f t)) ≤ εf) + (hfs : ∀ t ∈ Ico a b, f t ∈ s t) + (hg : ContinuousOn g (Icc a b)) + (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (g' t) (Ici t) t) + (g_bound : ∀ t ∈ Ico a b, dist (g' t) (v t (g t)) ≤ εg) + (hgs : ∀ t ∈ Ico a b, g t ∈ s t) (ha : dist (f a) (g a) ≤ δ) : ∀ t ∈ Icc a b, dist (f t) (g t) ≤ gronwallBound δ K (εf + εg) (t - a) := by simp only [dist_eq_norm] at ha ⊢ @@ -170,22 +175,25 @@ theorem dist_le_of_approx_trajectories_ODE_of_mem_set {v : ℝ → E → E} {s : refine this.trans ((add_le_add (add_le_add (f_bound t ht) (g_bound t ht)) hv).trans ?_) rw [add_comm] set_option linter.uppercaseLean3 false in -#align dist_le_of_approx_trajectories_ODE_of_mem_set dist_le_of_approx_trajectories_ODE_of_mem_set +#align dist_le_of_approx_trajectories_ODE_of_mem_set dist_le_of_approx_trajectories_ODE_of_mem /-- If `f` and `g` are two approximate solutions of the same ODE, then the distance between them can't grow faster than exponentially. This is a simple corollary of Grönwall's inequality, and some people call this Grönwall's inequality too. This version assumes all inequalities to be true in the whole space. -/ -theorem dist_le_of_approx_trajectories_ODE {v : ℝ → E → E} {K : ℝ≥0} - (hv : ∀ t, LipschitzWith K (v t)) {f g f' g' : ℝ → E} {a b : ℝ} {εf εg δ : ℝ} - (hf : ContinuousOn f (Icc a b)) (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (f' t) (Ici t) t) - (f_bound : ∀ t ∈ Ico a b, dist (f' t) (v t (f t)) ≤ εf) (hg : ContinuousOn g (Icc a b)) +theorem dist_le_of_approx_trajectories_ODE + (hv : ∀ t, LipschitzWith K (v t)) + (hf : ContinuousOn f (Icc a b)) + (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (f' t) (Ici t) t) + (f_bound : ∀ t ∈ Ico a b, dist (f' t) (v t (f t)) ≤ εf) + (hg : ContinuousOn g (Icc a b)) (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (g' t) (Ici t) t) - (g_bound : ∀ t ∈ Ico a b, dist (g' t) (v t (g t)) ≤ εg) (ha : dist (f a) (g a) ≤ δ) : + (g_bound : ∀ t ∈ Ico a b, dist (g' t) (v t (g t)) ≤ εg) + (ha : dist (f a) (g a) ≤ δ) : ∀ t ∈ Icc a b, dist (f t) (g t) ≤ gronwallBound δ K (εf + εg) (t - a) := have hfs : ∀ t ∈ Ico a b, f t ∈ @univ E := fun _ _ => trivial - dist_le_of_approx_trajectories_ODE_of_mem_set (fun t => (hv t).lipschitzOnWith _) hf hf' + dist_le_of_approx_trajectories_ODE_of_mem (fun t => (hv t).lipschitzOnWith _) hf hf' f_bound hfs hg hg' g_bound (fun _ _ => trivial) ha set_option linter.uppercaseLean3 false in #align dist_le_of_approx_trajectories_ODE dist_le_of_approx_trajectories_ODE @@ -196,10 +204,10 @@ people call this Grönwall's inequality too. This version assumes all inequalities to be true in some time-dependent set `s t`, and assumes that the solutions never leave this set. -/ -theorem dist_le_of_trajectories_ODE_of_mem_set {v : ℝ → E → E} {s : ℝ → Set E} {K : ℝ≥0} - (hv : ∀ t, LipschitzOnWith K (v t) (s t)) - {f g : ℝ → E} {a b : ℝ} {δ : ℝ} (hf : ContinuousOn f (Icc a b)) - (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (v t (f t)) (Ici t) t) (hfs : ∀ t ∈ Ico a b, f t ∈ s t) +theorem dist_le_of_trajectories_ODE_of_mem + (hf : ContinuousOn f (Icc a b)) + (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (v t (f t)) (Ici t) t) + (hfs : ∀ t ∈ Ico a b, f t ∈ s t) (hg : ContinuousOn g (Icc a b)) (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (v t (g t)) (Ici t) t) (hgs : ∀ t ∈ Ico a b, g t ∈ s t) (ha : dist (f a) (g a) ≤ δ) : ∀ t ∈ Icc a b, dist (f t) (g t) ≤ δ * exp (K * (t - a)) := by @@ -207,23 +215,26 @@ theorem dist_le_of_trajectories_ODE_of_mem_set {v : ℝ → E → E} {s : ℝ have g_bound : ∀ t ∈ Ico a b, dist (v t (g t)) (v t (g t)) ≤ 0 := by intros; rw [dist_self] intro t ht have := - dist_le_of_approx_trajectories_ODE_of_mem_set hv hf hf' f_bound hfs hg hg' g_bound hgs ha t ht + dist_le_of_approx_trajectories_ODE_of_mem hv hf hf' f_bound hfs hg hg' g_bound hgs ha t ht rwa [zero_add, gronwallBound_ε0] at this set_option linter.uppercaseLean3 false in -#align dist_le_of_trajectories_ODE_of_mem_set dist_le_of_trajectories_ODE_of_mem_set +#align dist_le_of_trajectories_ODE_of_mem_set dist_le_of_trajectories_ODE_of_mem /-- If `f` and `g` are two exact solutions of the same ODE, then the distance between them can't grow faster than exponentially. This is a simple corollary of Grönwall's inequality, and some people call this Grönwall's inequality too. This version assumes all inequalities to be true in the whole space. -/ -theorem dist_le_of_trajectories_ODE {v : ℝ → E → E} {K : ℝ≥0} (hv : ∀ t, LipschitzWith K (v t)) - {f g : ℝ → E} {a b : ℝ} {δ : ℝ} (hf : ContinuousOn f (Icc a b)) - (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (v t (f t)) (Ici t) t) (hg : ContinuousOn g (Icc a b)) - (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (v t (g t)) (Ici t) t) (ha : dist (f a) (g a) ≤ δ) : +theorem dist_le_of_trajectories_ODE + (hv : ∀ t, LipschitzWith K (v t)) + (hf : ContinuousOn f (Icc a b)) + (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (v t (f t)) (Ici t) t) + (hg : ContinuousOn g (Icc a b)) + (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (v t (g t)) (Ici t) t) + (ha : dist (f a) (g a) ≤ δ) : ∀ t ∈ Icc a b, dist (f t) (g t) ≤ δ * exp (K * (t - a)) := have hfs : ∀ t ∈ Ico a b, f t ∈ @univ E := fun _ _ => trivial - dist_le_of_trajectories_ODE_of_mem_set (fun t => (hv t).lipschitzOnWith _) hf hf' hfs hg + dist_le_of_trajectories_ODE_of_mem (fun t => (hv t).lipschitzOnWith _) hf hf' hfs hg hg' (fun _ _ => trivial) ha set_option linter.uppercaseLean3 false in #align dist_le_of_trajectories_ODE dist_le_of_trajectories_ODE @@ -233,26 +244,137 @@ a given initial value provided that the RHS is Lipschitz continuous in `x` withi and we consider only solutions included in `s`. This version shows uniqueness in a closed interval `Icc a b`, where `a` is the initial time. -/ -theorem ODE_solution_unique_of_mem_set {v : ℝ → E → E} {s : ℝ → Set E} {K : ℝ≥0} - (hv : ∀ t, LipschitzOnWith K (v t) (s t)) - {f g : ℝ → E} {a b : ℝ} (hf : ContinuousOn f (Icc a b)) - (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (v t (f t)) (Ici t) t) (hfs : ∀ t ∈ Ico a b, f t ∈ s t) - (hg : ContinuousOn g (Icc a b)) (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (v t (g t)) (Ici t) t) - (hgs : ∀ t ∈ Ico a b, g t ∈ s t) (ha : f a = g a) : EqOn f g (Icc a b) := fun t ht ↦ by - have := dist_le_of_trajectories_ODE_of_mem_set hv hf hf' hfs hg hg' hgs (dist_le_zero.2 ha) t ht +theorem ODE_solution_unique_of_mem_Icc_right + (hf : ContinuousOn f (Icc a b)) + (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (v t (f t)) (Ici t) t) + (hfs : ∀ t ∈ Ico a b, f t ∈ s t) + (hg : ContinuousOn g (Icc a b)) + (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (v t (g t)) (Ici t) t) + (hgs : ∀ t ∈ Ico a b, g t ∈ s t) + (ha : f a = g a) : + EqOn f g (Icc a b) := fun t ht ↦ by + have := dist_le_of_trajectories_ODE_of_mem hv hf hf' hfs hg hg' hgs (dist_le_zero.2 ha) t ht rwa [zero_mul, dist_le_zero] at this set_option linter.uppercaseLean3 false in -#align ODE_solution_unique_of_mem_set ODE_solution_unique_of_mem_set +#align ODE_solution_unique_of_mem_set ODE_solution_unique_of_mem_Icc_right + +/-- A time-reversed version of `ODE_solution_unique_of_mem_Icc_right`. Uniqueness is shown in a +closed interval `Icc a b`, where `b` is the "initial" time. -/ +theorem ODE_solution_unique_of_mem_Icc_left + (hf : ContinuousOn f (Icc a b)) + (hf' : ∀ t ∈ Ioc a b, HasDerivWithinAt f (v t (f t)) (Iic t) t) + (hfs : ∀ t ∈ Ioc a b, f t ∈ s t) + (hg : ContinuousOn g (Icc a b)) + (hg' : ∀ t ∈ Ioc a b, HasDerivWithinAt g (v t (g t)) (Iic t) t) + (hgs : ∀ t ∈ Ioc a b, g t ∈ s t) + (hb : f b = g b) : + EqOn f g (Icc a b) := by + have hv' t : LipschitzOnWith K (Neg.neg ∘ (v (-t))) (s (-t)) := by + rw [← one_mul K] + exact LipschitzWith.id.neg.comp_lipschitzOnWith (hv _) + have hmt1 : MapsTo Neg.neg (Icc (-b) (-a)) (Icc a b) := + fun _ ht ↦ ⟨le_neg.mp ht.2, neg_le.mp ht.1⟩ + have hmt2 : MapsTo Neg.neg (Ico (-b) (-a)) (Ioc a b) := + fun _ ht ↦ ⟨lt_neg.mp ht.2, neg_le.mp ht.1⟩ + have hmt3 (t : ℝ) : MapsTo Neg.neg (Ici t) (Iic (-t)) := + fun _ ht' ↦ mem_Iic.mpr <| neg_le_neg ht' + suffices EqOn (f ∘ Neg.neg) (g ∘ Neg.neg) (Icc (-b) (-a)) by + rw [eqOn_comp_right_iff] at this + convert this + simp + apply ODE_solution_unique_of_mem_Icc_right hv' + (hf.comp continuousOn_neg hmt1) _ (fun _ ht ↦ hfs _ (hmt2 ht)) + (hg.comp continuousOn_neg hmt1) _ (fun _ ht ↦ hgs _ (hmt2 ht)) (by simp [hb]) + · intros t ht + convert HasFDerivWithinAt.comp_hasDerivWithinAt t (hf' (-t) (hmt2 ht)) + (hasDerivAt_neg t).hasDerivWithinAt (hmt3 t) + simp + · intros t ht + convert HasFDerivWithinAt.comp_hasDerivWithinAt t (hg' (-t) (hmt2 ht)) + (hasDerivAt_neg t).hasDerivWithinAt (hmt3 t) + simp + +/-- A version of `ODE_solution_unique_of_mem_Icc_right` for uniqueness in a closed interval whose +interior contains the initial time. -/ +theorem ODE_solution_unique_of_mem_Icc + (ht : t₀ ∈ Ioo a b) + (hf : ContinuousOn f (Icc a b)) + (hf' : ∀ t ∈ Ioo a b, HasDerivAt f (v t (f t)) t) + (hfs : ∀ t ∈ Ioo a b, f t ∈ s t) + (hg : ContinuousOn g (Icc a b)) + (hg' : ∀ t ∈ Ioo a b, HasDerivAt g (v t (g t)) t) + (hgs : ∀ t ∈ Ioo a b, g t ∈ s t) + (heq : f t₀ = g t₀) : + EqOn f g (Icc a b) := by + rw [← Icc_union_Icc_eq_Icc (le_of_lt ht.1) (le_of_lt ht.2)] + apply EqOn.union + · have hss : Ioc a t₀ ⊆ Ioo a b := Ioc_subset_Ioo_right ht.2 + exact ODE_solution_unique_of_mem_Icc_left hv + (hf.mono <| Icc_subset_Icc_right <| le_of_lt ht.2) + (fun _ ht' ↦ (hf' _ (hss ht')).hasDerivWithinAt) (fun _ ht' ↦ (hfs _ (hss ht'))) + (hg.mono <| Icc_subset_Icc_right <| le_of_lt ht.2) + (fun _ ht' ↦ (hg' _ (hss ht')).hasDerivWithinAt) (fun _ ht' ↦ (hgs _ (hss ht'))) heq + · have hss : Ico t₀ b ⊆ Ioo a b := Ico_subset_Ioo_left ht.1 + exact ODE_solution_unique_of_mem_Icc_right hv + (hf.mono <| Icc_subset_Icc_left <| le_of_lt ht.1) + (fun _ ht' ↦ (hf' _ (hss ht')).hasDerivWithinAt) (fun _ ht' ↦ (hfs _ (hss ht'))) + (hg.mono <| Icc_subset_Icc_left <| le_of_lt ht.1) + (fun _ ht' ↦ (hg' _ (hss ht')).hasDerivWithinAt) (fun _ ht' ↦ (hgs _ (hss ht'))) heq + +/-- A version of `ODE_solution_unique_of_mem_Icc` for uniqueness in an open interval. -/ +theorem ODE_solution_unique_of_mem_Ioo + (ht : t₀ ∈ Ioo a b) + (hf : ∀ t ∈ Ioo a b, HasDerivAt f (v t (f t)) t ∧ f t ∈ s t) + (hg : ∀ t ∈ Ioo a b, HasDerivAt g (v t (g t)) t ∧ g t ∈ s t) + (heq : f t₀ = g t₀) : + EqOn f g (Ioo a b) := by + intros t' ht' + rcases lt_or_le t' t₀ with (h | h) + · have hss : Icc t' t₀ ⊆ Ioo a b := + fun _ ht'' ↦ ⟨lt_of_lt_of_le ht'.1 ht''.1, lt_of_le_of_lt ht''.2 ht.2⟩ + exact ODE_solution_unique_of_mem_Icc_left hv + (ContinuousAt.continuousOn fun _ ht'' ↦ (hf _ <| hss ht'').1.continuousAt) + (fun _ ht'' ↦ (hf _ <| hss <| Ioc_subset_Icc_self ht'').1.hasDerivWithinAt) + (fun _ ht'' ↦ (hf _ <| hss <| Ioc_subset_Icc_self ht'').2) + (ContinuousAt.continuousOn fun _ ht'' ↦ (hg _ <| hss ht'').1.continuousAt) + (fun _ ht'' ↦ (hg _ <| hss <| Ioc_subset_Icc_self ht'').1.hasDerivWithinAt) + (fun _ ht'' ↦ (hg _ <| hss <| Ioc_subset_Icc_self ht'').2) heq + ⟨le_rfl, le_of_lt h⟩ + · have hss : Icc t₀ t' ⊆ Ioo a b := + fun _ ht'' ↦ ⟨lt_of_lt_of_le ht.1 ht''.1, lt_of_le_of_lt ht''.2 ht'.2⟩ + exact ODE_solution_unique_of_mem_Icc_right hv + (ContinuousAt.continuousOn fun _ ht'' ↦ (hf _ <| hss ht'').1.continuousAt) + (fun _ ht'' ↦ (hf _ <| hss <| Ico_subset_Icc_self ht'').1.hasDerivWithinAt) + (fun _ ht'' ↦ (hf _ <| hss <| Ico_subset_Icc_self ht'').2) + (ContinuousAt.continuousOn fun _ ht'' ↦ (hg _ <| hss ht'').1.continuousAt) + (fun _ ht'' ↦ (hg _ <| hss <| Ico_subset_Icc_self ht'').1.hasDerivWithinAt) + (fun _ ht'' ↦ (hg _ <| hss <| Ico_subset_Icc_self ht'').2) heq + ⟨h, le_rfl⟩ + +/-- Local unqueness of ODE solutions. -/ +theorem ODE_solution_unique_of_eventually + (hf : ∀ᶠ t in 𝓝 t₀, HasDerivAt f (v t (f t)) t ∧ f t ∈ s t) + (hg : ∀ᶠ t in 𝓝 t₀, HasDerivAt g (v t (g t)) t ∧ g t ∈ s t) + (heq : f t₀ = g t₀) : f =ᶠ[𝓝 t₀] g := by + obtain ⟨ε, hε, h⟩ := eventually_nhds_iff_ball.mp (hf.and hg) + rw [Filter.eventuallyEq_iff_exists_mem] + refine ⟨ball t₀ ε, ball_mem_nhds _ hε, ?_⟩ + simp_rw [Real.ball_eq_Ioo] at * + apply ODE_solution_unique_of_mem_Ioo hv (Real.ball_eq_Ioo t₀ ε ▸ mem_ball_self hε) + (fun _ ht ↦ (h _ ht).1) (fun _ ht ↦ (h _ ht).2) heq /-- There exists only one solution of an ODE \(\dot x=v(t, x)\) with -a given initial value provided that RHS is Lipschitz continuous in `x`. -/ -theorem ODE_solution_unique {v : ℝ → E → E} {K : ℝ≥0} (hv : ∀ t, LipschitzWith K (v t)) - {f g : ℝ → E} {a b : ℝ} (hf : ContinuousOn f (Icc a b)) - (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (v t (f t)) (Ici t) t) (hg : ContinuousOn g (Icc a b)) - (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (v t (g t)) (Ici t) t) (ha : f a = g a) : +a given initial value provided that the RHS is Lipschitz continuous in `x`. -/ +theorem ODE_solution_unique + (hv : ∀ t, LipschitzWith K (v t)) + (hf : ContinuousOn f (Icc a b)) + (hf' : ∀ t ∈ Ico a b, HasDerivWithinAt f (v t (f t)) (Ici t) t) + (hg : ContinuousOn g (Icc a b)) + (hg' : ∀ t ∈ Ico a b, HasDerivWithinAt g (v t (g t)) (Ici t) t) + (ha : f a = g a) : EqOn f g (Icc a b) := have hfs : ∀ t ∈ Ico a b, f t ∈ @univ E := fun _ _ => trivial - ODE_solution_unique_of_mem_set (fun t => (hv t).lipschitzOnWith _) hf hf' hfs hg hg' + ODE_solution_unique_of_mem_Icc_right (fun t => (hv t).lipschitzOnWith _) hf hf' hfs hg hg' (fun _ _ => trivial) ha set_option linter.uppercaseLean3 false in #align ODE_solution_unique ODE_solution_unique diff --git a/Mathlib/Analysis/ODE/PicardLindelof.lean b/Mathlib/Analysis/ODE/PicardLindelof.lean index e89de73ef5015..dc9140690925b 100644 --- a/Mathlib/Analysis/ODE/PicardLindelof.lean +++ b/Mathlib/Analysis/ODE/PicardLindelof.lean @@ -423,18 +423,19 @@ variable [CompleteSpace E] /-- A time-independent, continuously differentiable ODE admits a solution in some open interval. -/ theorem exists_forall_hasDerivAt_Ioo_eq_of_contDiffAt (hv : ContDiffAt ℝ 1 v x₀) : - ∃ ε > (0 : ℝ), - ∃ f : ℝ → E, f t₀ = x₀ ∧ ∀ t ∈ Ioo (t₀ - ε) (t₀ + ε), HasDerivAt f (v (f t)) t := by + ∃ f : ℝ → E, f t₀ = x₀ ∧ + ∃ ε > (0 : ℝ), ∀ t ∈ Ioo (t₀ - ε) (t₀ + ε), HasDerivAt f (v (f t)) t := by obtain ⟨ε, hε, _, _, _, hpl⟩ := exists_isPicardLindelof_const_of_contDiffAt t₀ hv obtain ⟨f, hf1, hf2⟩ := hpl.exists_forall_hasDerivWithinAt_Icc_eq x₀ - exact ⟨ε, hε, f, hf1, fun t ht => + exact ⟨f, hf1, ε, hε, fun t ht => (hf2 t (Ioo_subset_Icc_self ht)).hasDerivAt (Icc_mem_nhds ht.1 ht.2)⟩ #align exists_forall_deriv_at_Ioo_eq_of_cont_diff_on_nhds exists_forall_hasDerivAt_Ioo_eq_of_contDiffAt /-- A time-independent, continuously differentiable ODE admits a solution in some open interval. -/ theorem exists_forall_hasDerivAt_Ioo_eq_of_contDiff (hv : ContDiff ℝ 1 v) : - ∃ ε > (0 : ℝ), ∃ f : ℝ → E, f t₀ = x₀ ∧ ∀ t ∈ Ioo (t₀ - ε) (t₀ + ε), HasDerivAt f (v (f t)) t := - let ⟨ε, hε, f, hf1, hf2⟩ := + ∃ f : ℝ → E, f t₀ = x₀ ∧ + ∃ ε > (0 : ℝ), ∀ t ∈ Ioo (t₀ - ε) (t₀ + ε), HasDerivAt f (v (f t)) t := + let ⟨f, hf1, ε, hε, hf2⟩ := exists_forall_hasDerivAt_Ioo_eq_of_contDiffAt t₀ hv.contDiffAt - ⟨ε, hε, f, hf1, fun _ h => hf2 _ h⟩ + ⟨f, hf1, ε, hε, fun _ h => hf2 _ h⟩ #align exists_forall_deriv_at_Ioo_eq_of_cont_diff exists_forall_hasDerivAt_Ioo_eq_of_contDiff diff --git a/Mathlib/Analysis/Seminorm.lean b/Mathlib/Analysis/Seminorm.lean index 7edf4981f3efe..70dd8a3507973 100644 --- a/Mathlib/Analysis/Seminorm.lean +++ b/Mathlib/Analysis/Seminorm.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Real.Pointwise import Mathlib.Analysis.Convex.Function import Mathlib.Analysis.LocallyConvex.Basic import Mathlib.Analysis.Normed.Group.AddTorsor +import Mathlib.Data.Real.Sqrt #align_import analysis.seminorm from "leanprover-community/mathlib"@"09079525fd01b3dda35e96adaa08d2f943e1648c" @@ -35,9 +36,6 @@ For a module over a normed ring: seminorm, locally convex, LCTVS -/ -set_option autoImplicit true - - open NormedField Set Filter open scoped BigOperators NNReal Pointwise Topology Uniformity @@ -129,13 +127,13 @@ instance instSeminormClass : SeminormClass (Seminorm 𝕜 E) 𝕜 E where map_smul_eq_mul f := f.smul' #align seminorm.seminorm_class Seminorm.instSeminormClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`. -/ +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`. -/ instance instCoeFun : CoeFun (Seminorm 𝕜 E) fun _ => E → ℝ := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[ext] theorem ext {p q : Seminorm 𝕜 E} (h : ∀ x, (p : E → ℝ) x = q x) : p = q := - FunLike.ext p q h + DFunLike.ext p q h #align seminorm.ext Seminorm.ext instance instZero : Zero (Seminorm 𝕜 E) := @@ -198,14 +196,14 @@ theorem add_apply (p q : Seminorm 𝕜 E) (x : E) : (p + q) x = p x + q x := #align seminorm.add_apply Seminorm.add_apply instance instAddMonoid : AddMonoid (Seminorm 𝕜 E) := - FunLike.coe_injective.addMonoid _ rfl coe_add fun _ _ => by rfl + DFunLike.coe_injective.addMonoid _ rfl coe_add fun _ _ => by rfl instance instOrderedCancelAddCommMonoid : OrderedCancelAddCommMonoid (Seminorm 𝕜 E) := - FunLike.coe_injective.orderedCancelAddCommMonoid _ rfl coe_add fun _ _ => rfl + DFunLike.coe_injective.orderedCancelAddCommMonoid _ rfl coe_add fun _ _ => rfl instance instMulAction [Monoid R] [MulAction R ℝ] [SMul R ℝ≥0] [IsScalarTower R ℝ≥0 ℝ] : MulAction R (Seminorm 𝕜 E) := - FunLike.coe_injective.mulAction _ (by intros; rfl) + DFunLike.coe_injective.mulAction _ (by intros; rfl) variable (𝕜 E) @@ -218,7 +216,7 @@ def coeFnAddMonoidHom : AddMonoidHom (Seminorm 𝕜 E) (E → ℝ) where #align seminorm.coe_fn_add_monoid_hom Seminorm.coeFnAddMonoidHom theorem coeFnAddMonoidHom_injective : Function.Injective (coeFnAddMonoidHom 𝕜 E) := - show @Function.Injective (Seminorm 𝕜 E) (E → ℝ) (↑) from FunLike.coe_injective + show @Function.Injective (Seminorm 𝕜 E) (E → ℝ) (↑) from DFunLike.coe_injective #align seminorm.coe_fn_add_monoid_hom_injective Seminorm.coeFnAddMonoidHom_injective variable {𝕜 E} @@ -257,7 +255,7 @@ theorem smul_sup [SMul R ℝ] [SMul R ℝ≥0] [IsScalarTower R ℝ≥0 ℝ] (r #align seminorm.smul_sup Seminorm.smul_sup instance instPartialOrder : PartialOrder (Seminorm 𝕜 E) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective @[simp, norm_cast] theorem coe_le_coe {p q : Seminorm 𝕜 E} : (p : E → ℝ) ≤ q ↔ p ≤ q := @@ -278,7 +276,7 @@ theorem lt_def {p q : Seminorm 𝕜 E} : p < q ↔ p ≤ q ∧ ∃ x, p x < q x #align seminorm.lt_def Seminorm.lt_def instance instSemilatticeSup : SemilatticeSup (Seminorm 𝕜 E) := - Function.Injective.semilatticeSup _ FunLike.coe_injective coe_sup + Function.Injective.semilatticeSup _ DFunLike.coe_injective coe_sup end SMul @@ -966,7 +964,7 @@ theorem closedBall_smul_closedBall (p : Seminorm 𝕜 E) (r₁ r₂ : ℝ) : #align seminorm.closed_ball_smul_closed_ball Seminorm.closedBall_smul_closedBall -- Porting note: TODO: make that an `iff` -theorem neg_mem_ball_zero (r : ℝ) (hx : x ∈ ball p 0 r) : -x ∈ ball p 0 r := by +theorem neg_mem_ball_zero (r : ℝ) {x : E} (hx : x ∈ ball p 0 r) : -x ∈ ball p 0 r := by simpa only [mem_ball_zero, map_neg_eq_map] using hx #align seminorm.symmetric_ball_zero Seminorm.neg_mem_ball_zero @@ -1039,7 +1037,7 @@ theorem smul_closedBall_zero {p : Seminorm 𝕜 E} {k : 𝕜} {r : ℝ} (hk : 0 theorem ball_zero_absorbs_ball_zero (p : Seminorm 𝕜 E) {r₁ r₂ : ℝ} (hr₁ : 0 < r₁) : Absorbs 𝕜 (p.ball 0 r₁) (p.ball 0 r₂) := by rcases exists_pos_lt_mul hr₁ r₂ with ⟨r, hr₀, hr⟩ - refine' ⟨r, hr₀, fun a ha x hx => _⟩ + refine .of_norm ⟨r, fun a ha x hx => ?_⟩ rw [smul_ball_zero (norm_pos_iff.1 <| hr₀.trans_le ha), p.mem_ball_zero] rw [p.mem_ball_zero] at hx exact hx.trans (hr.trans_le <| by gcongr) @@ -1374,7 +1372,7 @@ lemma bound_of_shell_sup (p : ι → Seminorm 𝕜 E) (s : Finset ι) q x ≤ (C • s.sup p) x := by rcases hx with ⟨j, hj, hjx⟩ have : (s.sup p) x ≠ 0 := - ne_of_gt ((hjx.symm.lt_of_le $ map_nonneg _ _).trans_le (le_finset_sup_apply hj)) + ne_of_gt ((hjx.symm.lt_of_le <| map_nonneg _ _).trans_le (le_finset_sup_apply hj)) refine (s.sup p).bound_of_shell_smul q ε_pos hc (fun y hle hlt ↦ ?_) this rcases exists_apply_eq_finset_sup p ⟨j, hj⟩ y with ⟨i, hi, hiy⟩ rw [smul_apply, hiy] @@ -1391,12 +1389,12 @@ lemma bddAbove_of_absorbent {p : ι → Seminorm 𝕜 E} {s : Set E} (hs : Absor BddAbove (range p) := by rw [Seminorm.bddAbove_range_iff] intro x - rcases hs x with ⟨r, hr, hrx⟩ + rcases (hs x).exists_pos with ⟨r, hr, hrx⟩ rcases exists_lt_norm 𝕜 r with ⟨k, hk⟩ have hk0 : k ≠ 0 := norm_pos_iff.mp (hr.trans hk) have : k⁻¹ • x ∈ s := by rw [← mem_smul_set_iff_inv_smul_mem₀ hk0] - exact hrx k hk.le + exact hrx k hk.le rfl rcases h (k⁻¹ • x) this with ⟨M, hM⟩ refine ⟨‖k‖ * M, forall_range_iff.mpr fun i ↦ ?_⟩ have := (forall_range_iff.mp hM) i diff --git a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean index 06e90e53601ed..d114cbc4d3223 100644 --- a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean +++ b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean @@ -75,7 +75,7 @@ namespace Mathlib.Meta.Positivity open Lean Meta Qq Function -@[positivity FunLike.coe _ _] +@[positivity DFunLike.coe _ _] def evalBernstein : PositivityExt where eval {_ _} _zα _pα e := do let .app (.app _coe (.app (.app _ n) ν)) x ← whnfR e | throwError "not bernstein polynomial" let p ← mkAppOptM ``bernstein_nonneg #[n, ν, x] diff --git a/Mathlib/Analysis/SpecialFunctions/CompareExp.lean b/Mathlib/Analysis/SpecialFunctions/CompareExp.lean index f87f45038313c..a37b621052846 100644 --- a/Mathlib/Analysis/SpecialFunctions/CompareExp.lean +++ b/Mathlib/Analysis/SpecialFunctions/CompareExp.lean @@ -173,7 +173,7 @@ theorem isLittleO_cpow_exp (hl : IsExpCmpFilter l) (a : ℂ) {b : ℝ} (hb : 0 < hl.isTheta_cpow_exp_re_mul_log a _ =o[l] fun z => exp (b * z) := IsLittleO.of_norm_right <| by - simp only [norm_eq_abs, abs_exp, ofReal_mul_re, Real.isLittleO_exp_comp_exp_comp] + simp only [norm_eq_abs, abs_exp, re_ofReal_mul, Real.isLittleO_exp_comp_exp_comp] refine (IsEquivalent.refl.sub_isLittleO ?_).symm.tendsto_atTop (hl.tendsto_re.const_mul_atTop hb) exact (hl.isLittleO_log_abs_re.const_mul_left _).const_mul_right hb.ne' diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean index 6789f86147e78..9906a2abf8960 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean @@ -96,7 +96,7 @@ set_option linter.uppercaseLean3 false in theorem arg_mul_cos_add_sin_mul_I {r : ℝ} (hr : 0 < r) {θ : ℝ} (hθ : θ ∈ Set.Ioc (-π) π) : arg (r * (cos θ + sin θ * I)) = θ := by simp only [arg, map_mul, abs_cos_add_sin_mul_I, abs_of_nonneg hr.le, mul_one] - simp only [ofReal_mul_re, ofReal_mul_im, neg_im, ← ofReal_cos, ← ofReal_sin, ← + simp only [re_ofReal_mul, im_ofReal_mul, neg_im, ← ofReal_cos, ← ofReal_sin, ← mk_eq_add_mul_I, neg_div, mul_div_cancel_left _ hr.ne', mul_nonneg_iff_right_nonneg_of_pos hr] by_cases h₁ : θ ∈ Set.Icc (-(π / 2)) (π / 2) · rw [if_pos] @@ -640,7 +640,7 @@ theorem tendsto_arg_nhdsWithin_im_nonneg_of_re_neg_of_im_zero {z : ℂ} (hre : z theorem continuousAt_arg_coe_angle (h : x ≠ 0) : ContinuousAt ((↑) ∘ arg : ℂ → Real.Angle) x := by by_cases hs : x ∈ slitPlane · exact Real.Angle.continuous_coe.continuousAt.comp (continuousAt_arg hs) - · rw [← Function.comp.right_id (((↑) : ℝ → Real.Angle) ∘ arg), + · rw [← Function.comp_id (((↑) : ℝ → Real.Angle) ∘ arg), (Function.funext_iff.2 fun _ => (neg_neg _).symm : (id : ℂ → ℂ) = Neg.neg ∘ Neg.neg), ← Function.comp.assoc] refine' ContinuousAt.comp _ continuous_neg.continuousAt diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean b/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean new file mode 100644 index 0000000000000..c68a1fc624b0b --- /dev/null +++ b/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean @@ -0,0 +1,247 @@ +/- +Copyright (c) 2023 Michael Stoll. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Michael Stoll +-/ +import Mathlib.Analysis.Complex.Convex +import Mathlib.Analysis.SpecialFunctions.Integrals +import Mathlib.Analysis.Calculus.Deriv.Shift + +/-! +# Estimates for the complex logarithm + +We show that `log (1+z)` differs from its Taylor polynomial up to degree `n` by at most +`‖z‖^(n+1)/((n+1)*(1-‖z‖))` when `‖z‖ < 1`; see `Complex.norm_log_sub_logTaylor_le`. + +To this end, we derive the representation of `log (1+z)` as the integral of `1/(1+tz)` +over the unit interval (`Complex.log_eq_integral`) and introduce notation +`Complex.logTaylor n` for the Taylor polynomial up to degree `n-1`. + +### TODO + +Refactor using general Taylor series theory, once this exists in Mathlib. +-/ + +namespace Complex + +/-! +### Integral representation of the complex log +-/ + +lemma continuousOn_one_add_mul_inv {z : ℂ} (hz : 1 + z ∈ slitPlane) : + ContinuousOn (fun t : ℝ ↦ (1 + t • z)⁻¹) (Set.Icc 0 1) := + ContinuousOn.inv₀ (Continuous.continuousOn (by continuity)) + (fun t ht ↦ slitPlane_ne_zero <| StarConvex.add_smul_mem starConvex_one_slitPlane hz ht.1 ht.2) + +open intervalIntegral in +/-- Represent `log (1 + z)` as an integral over the unit interval -/ +lemma log_eq_integral {z : ℂ} (hz : 1 + z ∈ slitPlane) : + log (1 + z) = z * ∫ (t : ℝ) in (0 : ℝ)..1, (1 + t • z)⁻¹ := by + convert (integral_unitInterval_deriv_eq_sub (continuousOn_one_add_mul_inv hz) + (fun _ ht ↦ hasDerivAt_log <| + StarConvex.add_smul_mem starConvex_one_slitPlane hz ht.1 ht.2)).symm using 1 + simp only [log_one, sub_zero] + +/-- Represent `log (1 - z)⁻¹` as an integral over the unit interval -/ +lemma log_inv_eq_integral {z : ℂ} (hz : 1 - z ∈ slitPlane) : + log (1 - z)⁻¹ = z * ∫ (t : ℝ) in (0 : ℝ)..1, (1 - t • z)⁻¹ := by + rw [sub_eq_add_neg 1 z] at hz ⊢ + rw [log_inv _ <| slitPlane_arg_ne_pi hz, neg_eq_iff_eq_neg, ← neg_mul] + convert log_eq_integral hz using 5 + rw [sub_eq_add_neg, smul_neg] + +/-! +### The Taylor polynomials of the logarithm +-/ + +open BigOperators + +/-- The `n`th Taylor polynomial of `log` at `1`, as a function `ℂ → ℂ` -/ +noncomputable +def logTaylor (n : ℕ) : ℂ → ℂ := fun z ↦ ∑ j in Finset.range n, (-1) ^ (j + 1) * z ^ j / j + +lemma logTaylor_zero : logTaylor 0 = fun _ ↦ 0 := by + funext + simp only [logTaylor, Finset.range_zero, Nat.odd_iff_not_even, Int.cast_pow, Int.cast_neg, + Int.cast_one, Finset.sum_empty] + +lemma logTaylor_succ (n : ℕ) : + logTaylor (n + 1) = logTaylor n + (fun z : ℂ ↦ (-1) ^ (n + 1) * z ^ n / n) := by + funext + simpa only [logTaylor] using Finset.sum_range_succ .. + +lemma logTaylor_at_zero (n : ℕ) : logTaylor n 0 = 0 := by + induction n with + | zero => simp [logTaylor_zero] + | succ n ih => simpa [logTaylor_succ, ih] using ne_or_eq n 0 + +lemma hasDerivAt_logTaylor (n : ℕ) (z : ℂ) : + HasDerivAt (logTaylor (n + 1)) (∑ j in Finset.range n, (-1) ^ j * z ^ j) z := by + induction n with + | zero => simp [logTaylor_succ, logTaylor_zero, Pi.add_def, hasDerivAt_const] + | succ n ih => + rw [logTaylor_succ] + simp only [cpow_nat_cast, Nat.cast_add, Nat.cast_one, Nat.odd_iff_not_even, + Finset.sum_range_succ, (show (-1) ^ (n + 1 + 1) = (-1) ^ n by ring)] + refine HasDerivAt.add ih ?_ + simp only [Nat.odd_iff_not_even, Int.cast_pow, Int.cast_neg, Int.cast_one, mul_div_assoc] + have : HasDerivAt (fun x : ℂ ↦ (x ^ (n + 1) / (n + 1))) (z ^ n) z + · simp_rw [div_eq_mul_inv] + convert HasDerivAt.mul_const (hasDerivAt_pow (n + 1) z) (((n : ℂ) + 1)⁻¹) using 1 + field_simp [Nat.cast_add_one_ne_zero n] + ring + convert HasDerivAt.const_mul _ this using 2 + ring + +/-! +### Bounds for the difference between log and its Taylor polynomials +-/ + +lemma hasDerivAt_log_sub_logTaylor (n : ℕ) {z : ℂ} (hz : 1 + z ∈ slitPlane) : + HasDerivAt (fun z : ℂ ↦ log (1 + z) - logTaylor (n + 1) z) ((-z) ^ n * (1 + z)⁻¹) z := by + convert ((hasDerivAt_log hz).comp_const_add 1 z).sub (hasDerivAt_logTaylor n z) using 1 + push_cast + have hz' : -z ≠ 1 + · intro H + rw [neg_eq_iff_eq_neg] at H + simp only [H, add_right_neg] at hz + exact slitPlane_ne_zero hz rfl + simp_rw [← mul_pow, neg_one_mul, geom_sum_eq hz', ← neg_add', div_neg, add_comm z] + field_simp [add_comm z 1 ▸ slitPlane_ne_zero hz] + +/-- Give a bound on `‖(1 + t * z)⁻¹‖` for `0 ≤ t ≤ 1` and `‖z‖ < 1`. -/ +lemma norm_one_add_mul_inv_le {t : ℝ} (ht : t ∈ Set.Icc 0 1) {z : ℂ} (hz : ‖z‖ < 1) : + ‖(1 + t * z)⁻¹‖ ≤ (1 - ‖z‖)⁻¹ := by + rw [Set.mem_Icc] at ht + rw [norm_inv, norm_eq_abs] + refine inv_le_inv_of_le (by linarith) ?_ + calc 1 - ‖z‖ + _ ≤ 1 - t * ‖z‖ := by + nlinarith [norm_nonneg z] + _ = 1 - ‖t * z‖ := by + rw [norm_mul, norm_eq_abs (t :ℂ), abs_of_nonneg ht.1] + _ ≤ ‖1 + t * z‖ := by + rw [← norm_neg (t * z), ← sub_neg_eq_add] + convert norm_sub_norm_le 1 (-(t * z)) + exact norm_one.symm + +lemma integrable_pow_mul_norm_one_add_mul_inv (n : ℕ) {z : ℂ} (hz : ‖z‖ < 1) : + IntervalIntegrable (fun t : ℝ ↦ t ^ n * ‖(1 + t * z)⁻¹‖) MeasureTheory.volume 0 1 := by + have := continuousOn_one_add_mul_inv <| mem_slitPlane_of_norm_lt_one hz + rw [← Set.uIcc_of_le zero_le_one] at this + exact ContinuousOn.intervalIntegrable <| + Continuous.continuousOn (by continuity) |>.mul <| ContinuousOn.norm this + +open intervalIntegral in +/-- The difference of `log (1+z)` and its `(n+1)`st Taylor polynomial can be bounded in +terms of `‖z‖`. -/ +lemma norm_log_sub_logTaylor_le (n : ℕ) {z : ℂ} (hz : ‖z‖ < 1) : + ‖log (1 + z) - logTaylor (n + 1) z‖ ≤ ‖z‖ ^ (n + 1) * (1 - ‖z‖)⁻¹ / (n + 1) := by + have help : IntervalIntegrable (fun t : ℝ ↦ t ^ n * (1 - ‖z‖)⁻¹) MeasureTheory.volume 0 1 := + IntervalIntegrable.mul_const (Continuous.intervalIntegrable (by continuity) 0 1) (1 - ‖z‖)⁻¹ + let f (z : ℂ) : ℂ := log (1 + z) - logTaylor (n + 1) z + let f' (z : ℂ) : ℂ := (-z) ^ n * (1 + z)⁻¹ + have hderiv : ∀ t ∈ Set.Icc (0 : ℝ) 1, HasDerivAt f (f' (0 + t * z)) (0 + t * z) + · intro t ht + rw [zero_add] + exact hasDerivAt_log_sub_logTaylor n <| + StarConvex.add_smul_mem starConvex_one_slitPlane (mem_slitPlane_of_norm_lt_one hz) ht.1 ht.2 + have hcont : ContinuousOn (fun t : ℝ ↦ f' (0 + t * z)) (Set.Icc 0 1) + · simp only [zero_add, zero_le_one, not_true_eq_false] + exact (Continuous.continuousOn (by continuity)).mul <| + continuousOn_one_add_mul_inv <| mem_slitPlane_of_norm_lt_one hz + have H : f z = z * ∫ t in (0 : ℝ)..1, (-(t * z)) ^ n * (1 + t * z)⁻¹ + · convert (integral_unitInterval_deriv_eq_sub hcont hderiv).symm using 1 + · simp only [zero_add, add_zero, log_one, logTaylor_at_zero, sub_self, sub_zero] + · simp only [add_zero, log_one, logTaylor_at_zero, sub_self, real_smul, zero_add, smul_eq_mul] + simp only [H, norm_mul] + simp_rw [neg_pow (_ * z) n, mul_assoc, intervalIntegral.integral_const_mul, mul_pow, + mul_comm _ (z ^ n), mul_assoc, intervalIntegral.integral_const_mul, norm_mul, norm_pow, + norm_neg, norm_one, one_pow, one_mul, ← mul_assoc, ← pow_succ, mul_div_assoc] + refine mul_le_mul_of_nonneg_left ?_ (pow_nonneg (norm_nonneg z) (n + 1)) + calc ‖∫ t in (0 : ℝ)..1, (t : ℂ) ^ n * (1 + t * z)⁻¹‖ + _ ≤ ∫ t in (0 : ℝ)..1, ‖(t : ℂ) ^ n * (1 + t * z)⁻¹‖ := + intervalIntegral.norm_integral_le_integral_norm zero_le_one + _ = ∫ t in (0 : ℝ)..1, t ^ n * ‖(1 + t * z)⁻¹‖ := by + refine intervalIntegral.integral_congr <| fun t ht ↦ ?_ + rw [Set.uIcc_of_le zero_le_one, Set.mem_Icc] at ht + simp_rw [norm_mul, norm_pow, norm_eq_abs, abs_of_nonneg ht.1] + _ ≤ ∫ t in (0 : ℝ)..1, t ^ n * (1 - ‖z‖)⁻¹ := + intervalIntegral.integral_mono_on zero_le_one + (integrable_pow_mul_norm_one_add_mul_inv n hz) help <| + fun t ht ↦ mul_le_mul_of_nonneg_left (norm_one_add_mul_inv_le ht hz) + (pow_nonneg ((Set.mem_Icc.mp ht).1) _) + _ = (1 - ‖z‖)⁻¹ / (n + 1) := by + rw [intervalIntegral.integral_mul_const, mul_comm, integral_pow] + field_simp + +/-- The difference `log (1+z) - z` is bounded by `‖z‖^2/(2*(1-‖z‖))` when `‖z‖ < 1`. -/ +lemma norm_log_one_add_sub_self_le {z : ℂ} (hz : ‖z‖ < 1) : + ‖log (1 + z) - z‖ ≤ ‖z‖ ^ 2 * (1 - ‖z‖)⁻¹ / 2 := by + convert norm_log_sub_logTaylor_le 1 hz using 2 + · simp [logTaylor_succ, logTaylor_zero, sub_eq_add_neg] + · norm_num + +/-- The difference of `log (1-z)⁻¹` and its `(n+1)`st Taylor polynomial can be bounded in +terms of `‖z‖`. -/ +lemma norm_log_one_sub_inv_add_logTaylor_neg_le (n : ℕ) {z : ℂ} (hz : ‖z‖ < 1) : + ‖log (1 - z)⁻¹ + logTaylor (n + 1) (-z)‖ ≤ ‖z‖ ^ (n + 1) * (1 - ‖z‖)⁻¹ / (n + 1) := by + rw [sub_eq_add_neg, + log_inv _ <| slitPlane_arg_ne_pi <| mem_slitPlane_of_norm_lt_one <| (norm_neg z).symm ▸ hz, + ← sub_neg_eq_add, ← neg_sub', norm_neg] + convert norm_log_sub_logTaylor_le n <| (norm_neg z).symm ▸ hz using 4 <;> rw [norm_neg] + +/-- The difference `log (1-z)⁻¹ - z` is bounded by `‖z‖^2/(2*(1-‖z‖))` when `‖z‖ < 1`. -/ +lemma norm_log_one_sub_inv_sub_self_le {z : ℂ} (hz : ‖z‖ < 1) : + ‖log (1 - z)⁻¹ - z‖ ≤ ‖z‖ ^ 2 * (1 - ‖z‖)⁻¹ / 2 := by + convert norm_log_one_sub_inv_add_logTaylor_neg_le 1 hz using 2 + · simp [logTaylor_succ, logTaylor_zero, sub_eq_add_neg] + · norm_num + +open Filter Asymptotics in +/-- The Taylor series of the complex logarithm at `1` converges to the logarithm in the +open unit disk. -/ +lemma hasSum_taylorSeries_log {z : ℂ} (hz : ‖z‖ < 1) : + HasSum (fun n : ℕ ↦ (-1) ^ (n + 1) * z ^ n / n) (log (1 + z)) := by + refine (hasSum_iff_tendsto_nat_of_summable_norm ?_).mpr ?_ + · refine (summable_geometric_of_norm_lt_1 hz).norm.of_nonneg_of_le (fun _ ↦ norm_nonneg _) ?_ + intro n + simp only [norm_div, norm_mul, norm_pow, norm_neg, norm_one, one_pow, one_mul, norm_nat] + rcases n.eq_zero_or_pos with rfl | hn + · simp + conv => enter [2]; rw [← div_one (‖z‖ ^ n)] + gcongr + norm_cast + · rw [← tendsto_sub_nhds_zero_iff] + conv => enter [1, x]; rw [← div_one (_ - _), ← logTaylor] + rw [← isLittleO_iff_tendsto fun _ h ↦ (one_ne_zero h).elim] + refine IsLittleO.trans_isBigO ?_ <| isBigO_const_one ℂ (1 : ℝ) atTop + have H : (fun n ↦ logTaylor n z - log (1 + z)) =O[atTop] (fun n : ℕ ↦ ‖z‖ ^ n) + · have (n : ℕ) : ‖logTaylor n z - log (1 + z)‖ ≤ (max ‖log (1 + z)‖ (1 - ‖z‖)⁻¹) * ‖(‖z‖ ^ n)‖ + · rw [norm_sub_rev, norm_pow, norm_norm] + cases n with + | zero => simp [logTaylor_zero] + | succ n => + refine (norm_log_sub_logTaylor_le n hz).trans ?_ + rw [mul_comm, ← div_one ((max _ _) * _)] + gcongr + · exact le_max_right .. + · linarith + exact (isBigOWith_of_le' atTop this).isBigO + refine IsBigO.trans_isLittleO H ?_ + convert isLittleO_pow_pow_of_lt_left (norm_nonneg z) hz + exact (one_pow _).symm + +/-- The series `∑ z^n/n` converges to `-log (1-z)` on the open unit disk. -/ +lemma hasSum_taylorSeries_neg_log {z : ℂ} (hz : ‖z‖ < 1) : + HasSum (fun n : ℕ ↦ z ^ n / n) (-log (1 - z)) := by + conv => enter [1, n]; rw [← neg_neg (z ^ n / n)] + refine HasSum.neg ?_ + convert hasSum_taylorSeries_log (z := -z) (norm_neg z ▸ hz) using 2 with n + rcases n.eq_zero_or_pos with rfl | hn + · simp + field_simp + rw [div_eq_div_iff, pow_succ, mul_assoc (-1), ← mul_pow, neg_mul_neg, neg_one_mul, one_mul] + all_goals {norm_cast; exact hn.ne'} + +end Complex diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/LogDeriv.lean b/Mathlib/Analysis/SpecialFunctions/Complex/LogDeriv.lean index 7fddce82151b9..2b3a53e9ffd9a 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/LogDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/LogDeriv.lean @@ -56,6 +56,12 @@ theorem hasStrictDerivAt_log {x : ℂ} (h : x ∈ slitPlane) : HasStrictDerivAt simpa [exp_log h0] using hasStrictDerivAt_exp (log x) #align complex.has_strict_deriv_at_log Complex.hasStrictDerivAt_log +lemma hasDerivAt_log {z : ℂ} (hz : z ∈ slitPlane) : HasDerivAt log z⁻¹ z := + HasStrictDerivAt.hasDerivAt <| hasStrictDerivAt_log hz + +lemma differentiableAt_log {z : ℂ} (hz : z ∈ slitPlane) : DifferentiableAt ℂ log z := + (hasDerivAt_log hz).differentiableAt + theorem hasStrictFDerivAt_log_real {x : ℂ} (h : x ∈ slitPlane) : HasStrictFDerivAt log (x⁻¹ • (1 : ℂ →L[ℝ] ℂ)) x := (hasStrictDerivAt_log h).complexToReal_fderiv diff --git a/Mathlib/Analysis/SpecialFunctions/Exp.lean b/Mathlib/Analysis/SpecialFunctions/Exp.lean index 4dcce95fbf30f..5ecb89f1db009 100644 --- a/Mathlib/Analysis/SpecialFunctions/Exp.lean +++ b/Mathlib/Analysis/SpecialFunctions/Exp.lean @@ -416,6 +416,14 @@ theorem isTheta_exp_comp_one {f : α → ℝ} : set_option linter.uppercaseLean3 false in #align real.is_Theta_exp_comp_one Real.isTheta_exp_comp_one +lemma summable_exp_nat_mul_iff {a : ℝ} : + Summable (fun n : ℕ ↦ exp (n * a)) ↔ a < 0 := by + simp only [exp_nat_mul, summable_geometric_iff_norm_lt_1, norm_of_nonneg (exp_nonneg _), + exp_lt_one_iff] + +lemma summable_exp_neg_nat : Summable fun n : ℕ ↦ exp (-n) := by + simpa only [mul_neg_one] using summable_exp_nat_mul_iff.mpr neg_one_lt_zero + end Real namespace Complex diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean index 7a72ab6af7875..030cd02b70ad1 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean @@ -398,7 +398,8 @@ lemma integral_cpow_mul_exp_neg_mul_Ioi {a : ℂ} {r : ℝ} (ha : 0 < a.re) (hr rw [← cpow_add _ _ (one_div_ne_zero <| ofReal_ne_zero.mpr hr.ne'), add_sub_cancel'_right] calc _ = ∫ (t : ℝ) in Ioi 0, (1 / r) ^ (a - 1) * (r * t) ^ (a - 1) * exp (-(r * t)) := by - refine MeasureTheory.set_integral_congr measurableSet_Ioi (fun x (hx : 0 < x) ↦ ?_) + refine MeasureTheory.set_integral_congr measurableSet_Ioi (fun x hx ↦ ?_) + rw [mem_Ioi] at hx rw [mul_cpow_ofReal_nonneg hr.le hx.le, ← mul_assoc, one_div, ← ofReal_inv, ← mul_cpow_ofReal_nonneg (inv_pos.mpr hr).le hr.le, ← ofReal_mul r⁻¹, inv_mul_cancel hr.ne', ofReal_one, one_cpow, one_mul] @@ -524,7 +525,7 @@ theorem Gamma_eq_integral {s : ℝ} (hs : 0 < s) : theorem Gamma_add_one {s : ℝ} (hs : s ≠ 0) : Gamma (s + 1) = s * Gamma s := by simp_rw [Gamma] - rw [Complex.ofReal_add, Complex.ofReal_one, Complex.Gamma_add_one, Complex.ofReal_mul_re] + rw [Complex.ofReal_add, Complex.ofReal_one, Complex.Gamma_add_one, Complex.re_ofReal_mul] rwa [Complex.ofReal_ne_zero] #align real.Gamma_add_one Real.Gamma_add_one diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean index f8b6c25e9c37e..3f20ca11aa08c 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean @@ -339,7 +339,7 @@ theorem approx_Gamma_integral_tendsto_Gamma_integral {s : ℂ} (hs : 0 < re s) : rcases lt_or_le (n : ℝ) x with (hxn | hxn) · rw [indicator_of_not_mem (not_mem_Ioc_of_gt hxn), norm_zero, mul_nonneg_iff_right_nonneg_of_pos (exp_pos _)] - exact rpow_nonneg_of_nonneg (le_of_lt hx) _ + exact rpow_nonneg (le_of_lt hx) _ · rw [indicator_of_mem (mem_Ioc.mpr ⟨mem_Ioi.mp hx, hxn⟩), norm_mul, Complex.norm_eq_abs, Complex.abs_of_nonneg (pow_nonneg (sub_nonneg.mpr <| div_le_one_of_le hxn <| by positivity) _), @@ -459,7 +459,7 @@ theorem Gamma_ne_zero {s : ℂ} (hs : ∀ m : ℕ, s ≠ -m) : Gamma s ≠ 0 := rw [Complex.sin_ne_zero_iff] intro k apply_fun im - rw [ofReal_mul_im, ← ofReal_int_cast, ← ofReal_mul, ofReal_im] + rw [im_ofReal_mul, ← ofReal_int_cast, ← ofReal_mul, ofReal_im] exact mul_ne_zero Real.pi_pos.ne' h_im have A := div_ne_zero (ofReal_ne_zero.mpr Real.pi_pos.ne') this rw [← Complex.Gamma_mul_Gamma_one_sub s, mul_ne_zero_iff] at A diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean index 35d1b69b10ee4..bafd56e0d710b 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean @@ -122,7 +122,7 @@ theorem Gamma_mul_add_mul_le_rpow_Gamma_mul_rpow_Gamma {s t a b : ℝ} (hs : 0 < ∀ {c x : ℝ} (_ : 0 < c) (u : ℝ) (_ : 0 < x), exp (-x) * x ^ (u - 1) = f c u x ^ (1 / c) := by intro c x hc u hx dsimp only - rw [mul_rpow (exp_pos _).le ((rpow_nonneg_of_nonneg hx.le) _), ← exp_mul, ← rpow_mul hx.le] + rw [mul_rpow (exp_pos _).le ((rpow_nonneg hx.le) _), ← exp_mul, ← rpow_mul hx.le] congr 2 <;> · field_simp [hc.ne']; ring -- show `f c u` is in `ℒp` for `p = 1/c`: have f_mem_Lp : diff --git a/Mathlib/Analysis/SpecialFunctions/Gaussian.lean b/Mathlib/Analysis/SpecialFunctions/Gaussian.lean index 02eb3077c9828..8ea6a7f03644a 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gaussian.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gaussian.lean @@ -23,14 +23,13 @@ We prove various versions of the formula for the Gaussian integral: We also prove, more generally, that the Fourier transform of the Gaussian is another Gaussian: -* `integral_cexp_neg_mul_sq_add_const`: for all complex `b` and `c` with `0 < re b` we have - `∫ (x : ℝ), exp (-b * (x + c) ^ 2) = (π / b) ^ (1 / 2)`. +* `integral_cexp_quadratic`: general formula for `∫ (x : ℝ), exp (b * x ^ 2 + c * x + d)` * `fourier_transform_gaussian`: for all complex `b` and `t` with `0 < re b`, we have `∫ x:ℝ, exp (I * t * x) * exp (-b * x^2) = (π / b) ^ (1 / 2) * exp (-t ^ 2 / (4 * b))`. * `fourier_transform_gaussian_pi`: a variant with `b` and `t` scaled to give a more symmetric statement, and formulated in terms of the Fourier transform operator `𝓕`. -As an application, in `Real.tsum_exp_neg_mul_int_sq` and `cCmplex.tsum_exp_neg_mul_int_sq`, we use +As an application, in `Real.tsum_exp_neg_mul_int_sq` and `Complex.tsum_exp_neg_mul_int_sq`, we use Poisson summation to prove the identity `∑' (n : ℤ), exp (-π * a * n ^ 2) = 1 / a ^ (1 / 2) * ∑' (n : ℤ), exp (-π / a * n ^ 2)` for positive real `a`, or complex `a` with positive real part. (See also @@ -172,7 +171,7 @@ theorem integrable_mul_exp_neg_mul_sq {b : ℝ} (hb : 0 < b) : theorem norm_cexp_neg_mul_sq (b : ℂ) (x : ℝ) : ‖Complex.exp (-b * (x : ℂ) ^ 2)‖ = exp (-b.re * x ^ 2) := by - rw [Complex.norm_eq_abs, Complex.abs_exp, ← ofReal_pow, mul_comm (-b) _, ofReal_mul_re, neg_re, + rw [Complex.norm_eq_abs, Complex.abs_exp, ← ofReal_pow, mul_comm (-b) _, re_ofReal_mul, neg_re, mul_comm] #align norm_cexp_neg_mul_sq norm_cexp_neg_mul_sq @@ -553,45 +552,54 @@ theorem integral_cexp_neg_mul_sq_add_real_mul_I (hb : 0 < b.re) (c : ℝ) : set_option linter.uppercaseLean3 false in #align gaussian_fourier.integral_cexp_neg_mul_sq_add_real_mul_I GaussianFourier.integral_cexp_neg_mul_sq_add_real_mul_I -theorem _root_.integral_cexp_neg_mul_sq_add_const (hb : 0 < b.re) (c : ℂ) : - ∫ x : ℝ, cexp (-b * (x + c) ^ 2) = (π / b) ^ (1 / 2 : ℂ) := by - rw [← re_add_im c] +theorem _root_.integral_cexp_quadratic (hb : b.re < 0) (c d : ℂ) : + ∫ x : ℝ, cexp (b * x ^ 2 + c * x + d) = (π / -b) ^ (1 / 2 : ℂ) * cexp (d - c^2 / (4 * b)) := by + have hb' : b ≠ 0 := by contrapose! hb; rw [hb, zero_re] + have h (x : ℝ) : cexp (b * x ^ 2 + c * x + d) = + cexp (- -b * (x + c / (2 * b)) ^ 2) * cexp (d - c ^ 2 / (4 * b)) + · simp_rw [← Complex.exp_add] + congr 1 + field_simp + ring_nf + simp_rw [h, integral_mul_right] + rw [← re_add_im (c / (2 * b))] simp_rw [← add_assoc, ← ofReal_add] - rw [integral_add_right_eq_self fun x : ℝ => cexp (-b * (↑x + ↑c.im * I) ^ 2)] - · apply integral_cexp_neg_mul_sq_add_real_mul_I hb -#align integral_cexp_neg_mul_sq_add_const integral_cexp_neg_mul_sq_add_const + rw [integral_add_right_eq_self fun a : ℝ ↦ cexp (- -b * (↑a + ↑(c / (2 * b)).im * I) ^ 2), + integral_cexp_neg_mul_sq_add_real_mul_I ((neg_re b).symm ▸ (neg_pos.mpr hb))] theorem _root_.fourier_transform_gaussian (hb : 0 < b.re) (t : ℂ) : - ∫ x : ℝ, cexp (I * t * x) * cexp (-b * (x : ℂ) ^ 2) = - cexp (-t ^ 2 / (4 * b)) * (π / b) ^ (1 / 2 : ℂ) := by - have : b ≠ 0 := by contrapose! hb; rw [hb, zero_re] - simp_rw [← Complex.exp_add] - have : ∀ x : ℂ, - I * t * x + -b * x ^ 2 = -t ^ 2 / ((4 : ℂ) * b) + -b * (x + -I * t / 2 / b) ^ 2 := by - intro x - ring_nf - rw [I_sq] - field_simp; ring - simp_rw [this, Complex.exp_add, integral_mul_left, integral_cexp_neg_mul_sq_add_const hb] + ∫ x : ℝ, cexp (I * t * x) * cexp (-b * x ^ 2) = + (π / b) ^ (1 / 2 : ℂ) * cexp (-t ^ 2 / (4 * b)) := by + conv => enter [1, 2, x]; rw [← Complex.exp_add, add_comm, ← add_zero (-b * x ^ 2 + I * t * x)] + rw [integral_cexp_quadratic (show (-b).re < 0 by rwa [neg_re, neg_lt_zero]), neg_neg, zero_sub, + mul_neg, div_neg, neg_neg, mul_pow, I_sq, neg_one_mul, mul_comm] #align fourier_transform_gaussian fourier_transform_gaussian -theorem _root_.fourier_transform_gaussian_pi (hb : 0 < b.re) : - (𝓕 fun x : ℝ => cexp (-π * b * (x : ℂ) ^ 2)) = fun t : ℝ => - (1 : ℂ) / b ^ (1 / 2 : ℂ) * cexp (-π / b * (t : ℂ) ^ 2) := by +theorem _root_.fourier_transform_gaussian_pi' (hb : 0 < b.re) (c : ℂ) : + (𝓕 fun x : ℝ => cexp (-π * b * x ^ 2 + 2 * π * c * x)) = fun t : ℝ => + 1 / b ^ (1 / 2 : ℂ) * cexp (-π / b * (t + I * c) ^ 2) := by + haveI : b ≠ 0 := by contrapose! hb; rw [hb, zero_re] + have h : (-↑π * b).re < 0 + · simpa only [neg_mul, neg_re, re_ofReal_mul, neg_lt_zero] using mul_pos pi_pos hb ext1 t - simp_rw [fourierIntegral_eq_integral_exp_smul, smul_eq_mul] - have h1 : 0 < re (π * b) := by rw [ofReal_mul_re]; exact mul_pos pi_pos hb - have h2 : b ≠ 0 := by contrapose! hb; rw [hb, zero_re] - convert _root_.fourier_transform_gaussian h1 (-2 * π * t) using 1 - · congr 1 with x : 1 - congr 2 - any_goals push_cast; ring - · conv_lhs => rw [mul_comm] - congr 2 - · field_simp [ofReal_ne_zero.mpr pi_ne_zero]; ring - · rw [← div_div, div_self (ofReal_ne_zero.mpr pi_ne_zero), one_div, one_div b, inv_cpow] - rw [Ne.def, arg_eq_pi_iff, not_and_or, not_lt] - exact Or.inl hb.le + simp_rw [fourierIntegral_eq_integral_exp_smul, smul_eq_mul, ← Complex.exp_add, ← add_assoc] + have (x : ℝ) : ↑(-2 * π * x * t) * I + -π * b * x ^ 2 + 2 * π * c * x = + -π * b * x ^ 2 + (-2 * π * I * t + 2 * π * c) * x + 0 + · push_cast; ring + simp_rw [this, integral_cexp_quadratic h, neg_mul, neg_neg] + congr 2 + · rw [← div_div, div_self <| ofReal_ne_zero.mpr pi_ne_zero, one_div, inv_cpow, ← one_div] + rw [Ne.def, arg_eq_pi_iff, not_and_or, not_lt] + exact Or.inl hb.le + · field_simp [ofReal_ne_zero.mpr pi_ne_zero] + ring_nf + simp only [I_sq] + ring + +theorem _root_.fourier_transform_gaussian_pi (hb : 0 < b.re) : + (𝓕 fun x ↦ cexp (-π * b * x ^ 2)) = + fun t : ℝ ↦ 1 / b ^ (1 / 2 : ℂ) * cexp (-π / b * t ^ 2) := by + simpa only [mul_zero, zero_mul, add_zero] using fourier_transform_gaussian_pi' hb 0 #align fourier_transform_gaussian_pi fourier_transform_gaussian_pi end GaussianFourier @@ -600,9 +608,42 @@ section GaussianPoisson /-! ## Poisson summation applied to the Gaussian -/ - variable {E : Type*} [NormedAddCommGroup E] +/-! First we show that Gaussian-type functions have rapid decay along `cocompact ℝ`. -/ + +lemma rexp_neg_quadratic_isLittleO_rpow_atTop {a : ℝ} (ha : a < 0) (b s : ℝ) : + (fun x ↦ rexp (a * x ^ 2 + b * x)) =o[atTop] (· ^ s) := by + suffices : (fun x ↦ rexp (a * x ^ 2 + b * x)) =o[atTop] (fun x ↦ rexp (-x)) + · refine this.trans ?_ + simpa only [neg_one_mul] using isLittleO_exp_neg_mul_rpow_atTop zero_lt_one s + rw [isLittleO_exp_comp_exp_comp] + have : (fun x ↦ -x - (a * x ^ 2 + b * x)) = fun x ↦ x * (-a * x - (b + 1)) + · ext1 x; ring_nf + rw [this] + exact tendsto_id.atTop_mul_atTop <| + Filter.tendsto_atTop_add_const_right _ _ <| tendsto_id.const_mul_atTop (neg_pos.mpr ha) + +lemma cexp_neg_quadratic_isLittleO_rpow_atTop {a : ℂ} (ha : a.re < 0) (b : ℂ) (s : ℝ) : + (fun x : ℝ ↦ cexp (a * x ^ 2 + b * x)) =o[atTop] (· ^ s) := by + apply Asymptotics.IsLittleO.of_norm_left + convert rexp_neg_quadratic_isLittleO_rpow_atTop ha b.re s with x + simp_rw [Complex.norm_eq_abs, Complex.abs_exp, add_re, ← ofReal_pow, mul_comm (_ : ℂ) ↑(_ : ℝ), + re_ofReal_mul, mul_comm _ (re _)] + +lemma cexp_neg_quadratic_isLittleO_abs_rpow_cocompact {a : ℂ} (ha : a.re < 0) (b : ℂ) (s : ℝ) : + (fun x : ℝ ↦ cexp (a * x ^ 2 + b * x)) =o[cocompact ℝ] (|·| ^ s) := by + rw [Real.cocompact_eq, isLittleO_sup] + constructor + · refine ((cexp_neg_quadratic_isLittleO_rpow_atTop ha (-b) s).comp_tendsto + Filter.tendsto_neg_atBot_atTop).congr' (eventually_of_forall fun x ↦ ?_) ?_ + · simp only [neg_mul, Function.comp_apply, ofReal_neg, neg_sq, mul_neg, neg_neg] + · refine (eventually_lt_atBot 0).mp (eventually_of_forall fun x hx ↦ ?_) + simp only [Function.comp_apply, abs_of_neg hx] + · refine (cexp_neg_quadratic_isLittleO_rpow_atTop ha b s).congr' EventuallyEq.rfl ?_ + refine (eventually_gt_atTop 0).mp (eventually_of_forall fun x hx ↦ ?_) + simp_rw [abs_of_pos hx] + theorem tendsto_rpow_abs_mul_exp_neg_mul_sq_cocompact {a : ℝ} (ha : 0 < a) (s : ℝ) : Tendsto (fun x : ℝ => |x| ^ s * rexp (-a * x ^ 2)) (cocompact ℝ) (𝓝 0) := by conv in rexp _ => rw [← sq_abs] @@ -615,58 +656,62 @@ theorem tendsto_rpow_abs_mul_exp_neg_mul_sq_cocompact {a : ℝ} (ha : 0 < a) (s #align tendsto_rpow_abs_mul_exp_neg_mul_sq_cocompact tendsto_rpow_abs_mul_exp_neg_mul_sq_cocompact theorem isLittleO_exp_neg_mul_sq_cocompact {a : ℂ} (ha : 0 < a.re) (s : ℝ) : - (fun x : ℝ => Complex.exp (-a * (x : ℂ) ^ 2)) =o[cocompact ℝ] fun x : ℝ => |x| ^ s := by - rw [← isLittleO_norm_left] - simp_rw [norm_cexp_neg_mul_sq] - apply isLittleO_of_tendsto' - · refine' Eventually.filter_mono cocompact_le_cofinite _ - refine' (eventually_cofinite_ne 0).mp (eventually_of_forall fun x hx h => _) - exact ((rpow_pos_of_pos (abs_pos.mpr hx) _).ne' h).elim - · refine' - Tendsto.congr' (Eventually.filter_mono cocompact_le_cofinite _) - (tendsto_zero_iff_norm_tendsto_zero.mp <| - tendsto_rpow_abs_mul_exp_neg_mul_sq_cocompact ha (-s)) - refine' (eventually_cofinite_ne 0).mp (eventually_of_forall fun x _ => _) - dsimp only - rw [norm_mul, norm_of_nonneg (rpow_nonneg_of_nonneg (abs_nonneg _) _), mul_comm, - rpow_neg (abs_nonneg x), div_eq_mul_inv, norm_of_nonneg (exp_pos _).le] + (fun x : ℝ => Complex.exp (-a * x ^ 2)) =o[cocompact ℝ] fun x : ℝ => |x| ^ s := by + convert cexp_neg_quadratic_isLittleO_abs_rpow_cocompact (?_ : (-a).re < 0) 0 s using 1 + · simp_rw [zero_mul, add_zero] + · rwa [neg_re, neg_lt_zero] #align is_o_exp_neg_mul_sq_cocompact isLittleO_exp_neg_mul_sq_cocompact -theorem Complex.tsum_exp_neg_mul_int_sq {a : ℂ} (ha : 0 < a.re) : - (∑' n : ℤ, cexp (-π * a * (n : ℂ) ^ 2)) = - (1 : ℂ) / a ^ (1 / 2 : ℂ) * ∑' n : ℤ, cexp (-π / a * (n : ℂ) ^ 2) := by - let f := fun x : ℝ => cexp (-π * a * (x : ℂ) ^ 2) +/-- Jacobi's theta-function transformation formula for the sum of `exp -Q(x)`, where `Q` is a +negative definite quadratic form. -/ +theorem Complex.tsum_exp_neg_quadratic {a : ℂ} (ha : 0 < a.re) (b : ℂ) : + (∑' n : ℤ, cexp (-π * a * n ^ 2 + 2 * π * b * n)) = + 1 / a ^ (1 / 2 : ℂ) * ∑' n : ℤ, cexp (-π / a * (n + I * b) ^ 2) := by + let f : ℝ → ℂ := fun x ↦ cexp (-π * a * x ^ 2 + 2 * π * b * x) + have hCf : Continuous f + · refine Complex.continuous_exp.comp (Continuous.add ?_ ?_) + · exact continuous_const.mul (Complex.continuous_ofReal.pow 2) + · exact continuous_const.mul Complex.continuous_ofReal + have hFf : 𝓕 f = fun x : ℝ ↦ 1 / a ^ (1 / 2 : ℂ) * cexp (-π / a * (x + I * b) ^ 2) + · exact fourier_transform_gaussian_pi' ha b have h1 : 0 < (↑π * a).re := by - rw [ofReal_mul_re] + rw [re_ofReal_mul] exact mul_pos pi_pos ha have h2 : 0 < (↑π / a).re := by - rw [div_eq_mul_inv, ofReal_mul_re, inv_re] + rw [div_eq_mul_inv, re_ofReal_mul, inv_re] refine' mul_pos pi_pos (div_pos ha <| normSq_pos.mpr _) contrapose! ha rw [ha, zero_re] - have f_bd : f =O[cocompact ℝ] fun x => |x| ^ (-2 : ℝ) := by - convert (isLittleO_exp_neg_mul_sq_cocompact h1 (-2)).isBigO using 2 - dsimp only - congr 1 - ring - have Ff_bd : 𝓕 f =O[cocompact ℝ] fun x => |x| ^ (-2 : ℝ) := by - rw [fourier_transform_gaussian_pi ha] - convert (isLittleO_exp_neg_mul_sq_cocompact h2 (-2)).isBigO.const_mul_left - ((1 : ℂ) / a ^ (1 / 2 : ℂ)) using 2 - congr 1 - ring_nf - simpa only [fourier_transform_gaussian_pi ha, tsum_mul_left, Function.comp] using - Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay - (Complex.continuous_exp.comp (continuous_const.mul (continuous_ofReal.pow 2)) : Continuous f) - one_lt_two f_bd Ff_bd + have f_bd : f =O[cocompact ℝ] (fun x => |x| ^ (-2 : ℝ)) := by + convert (cexp_neg_quadratic_isLittleO_abs_rpow_cocompact ?_ _ (-2)).isBigO + rwa [neg_mul, neg_re, neg_lt_zero] + have Ff_bd : (𝓕 f) =O[cocompact ℝ] (fun x => |x| ^ (-2 : ℝ)) + · rw [hFf] + have : ∀ (x : ℝ), -↑π / a * (↑x + I * b) ^ 2 = + -↑π / a * x ^ 2 + (-2 * π * I * b) / a * x + π * b ^ 2 / a + · intro x; ring_nf; rw [I_sq]; ring + simp_rw [this] + conv => enter [2, x]; rw [Complex.exp_add, ← mul_assoc _ _ (Complex.exp _), mul_comm] + refine ((cexp_neg_quadratic_isLittleO_abs_rpow_cocompact + (?_) (-2 * ↑π * I * b / a) (-2)).isBigO.const_mul_left _).const_mul_left _ + rwa [neg_div, neg_re, neg_lt_zero] + convert Real.tsum_eq_tsum_fourierIntegral_of_rpow_decay hCf one_lt_two f_bd Ff_bd 0 using 1 + · simp only [zero_add, ofReal_int_cast] + · rw [← tsum_mul_left] + simp only [QuotientAddGroup.mk_zero, fourier_eval_zero, mul_one, hFf, ofReal_int_cast] + +theorem Complex.tsum_exp_neg_mul_int_sq {a : ℂ} (ha : 0 < a.re) : + (∑' n : ℤ, cexp (-π * a * (n : ℂ) ^ 2)) = + 1 / a ^ (1 / 2 : ℂ) * ∑' n : ℤ, cexp (-π / a * (n : ℂ) ^ 2) := by + simpa only [mul_zero, zero_mul, add_zero] using Complex.tsum_exp_neg_quadratic ha 0 #align complex.tsum_exp_neg_mul_int_sq Complex.tsum_exp_neg_mul_int_sq theorem Real.tsum_exp_neg_mul_int_sq {a : ℝ} (ha : 0 < a) : (∑' n : ℤ, exp (-π * a * (n : ℝ) ^ 2)) = (1 : ℝ) / a ^ (1 / 2 : ℝ) * (∑' n : ℤ, exp (-π / a * (n : ℝ) ^ 2)) := by - simpa only [← ofReal_inj, ofReal_mul, ofReal_tsum, ofReal_exp, ofReal_div, ofReal_pow, - ofReal_int_cast, ofReal_neg, ofReal_cpow ha.le, ofReal_ofNat, ofReal_one] using - Complex.tsum_exp_neg_mul_int_sq (by rwa [ofReal_re] : 0 < (a : ℂ).re) + simpa only [← ofReal_inj, ofReal_tsum, ofReal_exp, ofReal_mul, ofReal_neg, ofReal_pow, + ofReal_int_cast, ofReal_div, ofReal_one, ofReal_cpow ha.le, ofReal_ofNat, mul_zero, zero_mul, + add_zero] using Complex.tsum_exp_neg_quadratic (by rwa [ofReal_re] : 0 < (a : ℂ).re) 0 #align real.tsum_exp_neg_mul_int_sq Real.tsum_exp_neg_mul_int_sq end GaussianPoisson diff --git a/Mathlib/Analysis/SpecialFunctions/ImproperIntegrals.lean b/Mathlib/Analysis/SpecialFunctions/ImproperIntegrals.lean index c145ba886127f..ebc844c93ef2d 100644 --- a/Mathlib/Analysis/SpecialFunctions/ImproperIntegrals.lean +++ b/Mathlib/Analysis/SpecialFunctions/ImproperIntegrals.lean @@ -5,7 +5,6 @@ Authors: David Loeffler -/ import Mathlib.Analysis.SpecialFunctions.Integrals import Mathlib.MeasureTheory.Group.Integral -import Mathlib.MeasureTheory.Integral.ExpDecay import Mathlib.MeasureTheory.Integral.IntegralEqImproper import Mathlib.MeasureTheory.Measure.Lebesgue.Integral @@ -70,7 +69,7 @@ theorem integrableOn_Ioi_rpow_of_lt {a : ℝ} (ha : a < -1) {c : ℝ} (hc : 0 < apply Tendsto.div_const simpa only [neg_neg] using tendsto_rpow_neg_atTop (by linarith : 0 < -(a + 1)) exact - integrableOn_Ioi_deriv_of_nonneg' hd (fun t ht => rpow_nonneg_of_nonneg (hc.trans ht).le a) ht + integrableOn_Ioi_deriv_of_nonneg' hd (fun t ht => rpow_nonneg (hc.trans ht).le a) ht #align integrable_on_Ioi_rpow_of_lt integrableOn_Ioi_rpow_of_lt theorem integrableOn_Ioi_rpow_iff {s t : ℝ} (ht : 0 < t) : diff --git a/Mathlib/Analysis/SpecialFunctions/Integrals.lean b/Mathlib/Analysis/SpecialFunctions/Integrals.lean index ff8cef8b00bee..d4a4264f9f1bb 100644 --- a/Mathlib/Analysis/SpecialFunctions/Integrals.lean +++ b/Mathlib/Analysis/SpecialFunctions/Integrals.lean @@ -6,6 +6,7 @@ Authors: Benjamin Davidson import Mathlib.MeasureTheory.Integral.FundThmCalculus import Mathlib.Analysis.SpecialFunctions.Trigonometric.ArctanDeriv import Mathlib.Analysis.SpecialFunctions.NonIntegrable +import Mathlib.Analysis.SpecialFunctions.Pow.Deriv #align_import analysis.special_functions.integrals from "leanprover-community/mathlib"@"011cafb4a5bc695875d186e245d6b3df03bf6c40" @@ -81,7 +82,7 @@ theorem intervalIntegrable_rpow' {r : ℝ} (h : -1 < r) : convert (Real.hasDerivAt_rpow_const (p := r + 1) (Or.inl hx.1.ne')).div_const (r + 1) using 1 field_simp [(by linarith : r + 1 ≠ 0)]; ring apply integrableOn_deriv_of_nonneg _ hderiv - · intro x hx; apply rpow_nonneg_of_nonneg hx.1.le + · intro x hx; apply rpow_nonneg hx.1.le · refine' (continuousOn_id.rpow_const _).div_const _; intro x _; right; linarith intro c; rcases le_total 0 c with (hc | hc) · exact this c hc @@ -385,7 +386,7 @@ theorem integral_rpow {r : ℝ} (h : -1 < r ∨ r ≠ -1 ∧ (0 : ℝ) ∉ [[a, (∫ x in a..b, (x : ℂ) ^ (r : ℂ)) = ((b : ℂ) ^ (r + 1 : ℂ) - (a : ℂ) ^ (r + 1 : ℂ)) / (r + 1) := integral_cpow h' apply_fun Complex.re at this; convert this - · simp_rw [intervalIntegral_eq_integral_uIoc, Complex.real_smul, Complex.ofReal_mul_re] + · simp_rw [intervalIntegral_eq_integral_uIoc, Complex.real_smul, Complex.re_ofReal_mul] · -- Porting note: was `change ... with ...` have : Complex.re = IsROrC.re := rfl rw [this, ← integral_re]; rfl @@ -394,7 +395,7 @@ theorem integral_rpow {r : ℝ} (h : -1 < r ∨ r ≠ -1 ∧ (0 : ℝ) ∉ [[a, · exact intervalIntegrable_cpow' h' · exact intervalIntegrable_cpow (Or.inr h'.2) · rw [(by push_cast; rfl : (r : ℂ) + 1 = ((r + 1 : ℝ) : ℂ))] - simp_rw [div_eq_inv_mul, ← Complex.ofReal_inv, Complex.ofReal_mul_re, Complex.sub_re] + simp_rw [div_eq_inv_mul, ← Complex.ofReal_inv, Complex.re_ofReal_mul, Complex.sub_re] rfl #align integral_rpow integral_rpow diff --git a/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean b/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean index 282ce63bab599..c3a00d8725ab3 100644 --- a/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean +++ b/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean @@ -145,7 +145,7 @@ theorem integrable_one_add_norm [MeasureSpace E] [BorelSpace E] [(@volume E _).I exact ((measurable_norm.const_add _).pow_const _).aestronglyMeasurable -- Lower Lebesgue integral have : (∫⁻ a : E, ‖(1 + ‖a‖) ^ (-r)‖₊) = ∫⁻ a : E, ENNReal.ofReal ((1 + ‖a‖) ^ (-r)) := - lintegral_nnnorm_eq_of_nonneg fun _ => rpow_nonneg_of_nonneg (by positivity) _ + lintegral_nnnorm_eq_of_nonneg fun _ => rpow_nonneg (by positivity) _ rw [HasFiniteIntegral, this] exact finite_integral_one_add_norm hnr #align integrable_one_add_norm integrable_one_add_norm diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean index a33fb9175e3e9..8726a07363b83 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean @@ -22,9 +22,6 @@ We prove some basic properties of this function and show that it is continuous. logarithm, continuity -/ -set_option autoImplicit true - - open Set Filter Function open Topology @@ -484,26 +481,31 @@ end TendstoCompAddSub namespace Mathlib.Meta.Positivity open Lean.Meta Qq -lemma log_nonneg_of_isNat (h : NormNum.IsNat e n) : 0 ≤ Real.log (e : ℝ) := by +variable {e : ℝ} {d : ℕ} + +lemma log_nonneg_of_isNat {n : ℕ} (h : NormNum.IsNat e n) : 0 ≤ Real.log (e : ℝ) := by rw [NormNum.IsNat.to_eq h rfl] exact Real.log_nat_cast_nonneg _ -lemma log_pos_of_isNat (h : NormNum.IsNat e n) (w : Nat.blt 1 n = true) : 0 < Real.log (e : ℝ) := by +lemma log_pos_of_isNat {n : ℕ} (h : NormNum.IsNat e n) (w : Nat.blt 1 n = true) : + 0 < Real.log (e : ℝ) := by rw [NormNum.IsNat.to_eq h rfl] apply Real.log_pos simpa using w -lemma log_nonneg_of_isNegNat (h : NormNum.IsInt e (.negOfNat n)) : 0 ≤ Real.log (e : ℝ) := by +lemma log_nonneg_of_isNegNat {n : ℕ} (h : NormNum.IsInt e (.negOfNat n)) : + 0 ≤ Real.log (e : ℝ) := by rw [NormNum.IsInt.neg_to_eq h rfl] exact Real.log_neg_nat_cast_nonneg _ -lemma log_pos_of_isNegNat (h : NormNum.IsInt e (.negOfNat n)) (w : Nat.blt 1 n = true) : +lemma log_pos_of_isNegNat {n : ℕ} (h : NormNum.IsInt e (.negOfNat n)) (w : Nat.blt 1 n = true) : 0 < Real.log (e : ℝ) := by rw [NormNum.IsInt.neg_to_eq h rfl] rw [Real.log_neg_eq_log] apply Real.log_pos simpa using w +set_option autoImplicit true in lemma log_pos_of_isRat : (NormNum.IsRat e n d) → (decide ((1 : ℚ) < n / d)) → (0 < Real.log (e : ℝ)) | ⟨inv, eq⟩, h => by @@ -511,6 +513,7 @@ lemma log_pos_of_isRat : have : 1 < (n : ℝ) / d := by exact_mod_cast of_decide_eq_true h exact Real.log_pos this +set_option autoImplicit true in lemma log_pos_of_isRat_neg : (NormNum.IsRat e n d) → (decide (n / d < (-1 : ℚ))) → (0 < Real.log (e : ℝ)) | ⟨inv, eq⟩, h => by @@ -518,6 +521,7 @@ lemma log_pos_of_isRat_neg : have : (n : ℝ) / d < -1 := by exact_mod_cast of_decide_eq_true h exact Real.log_pos_of_lt_neg_one this +set_option autoImplicit true in lemma log_nz_of_isRat : (NormNum.IsRat e n d) → (decide ((0 : ℚ) < n / d)) → (decide (n / d < (1 : ℚ))) → (Real.log (e : ℝ) ≠ 0) | ⟨inv, eq⟩, h₁, h₂ => by @@ -526,6 +530,7 @@ lemma log_nz_of_isRat : (NormNum.IsRat e n d) → (decide ((0 : ℚ) < n / d)) have h₂' : (n : ℝ) / d < 1 := by exact_mod_cast of_decide_eq_true h₂ exact ne_of_lt <| Real.log_neg h₁' h₂' +set_option autoImplicit true in lemma log_nz_of_isRat_neg : (NormNum.IsRat e n d) → (decide (n / d < (0 : ℚ))) → (decide ((-1 : ℚ) < n / d)) → (Real.log (e : ℝ) ≠ 0) | ⟨inv, eq⟩, h₁, h₂ => by diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean b/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean index be85cf44b13d3..32db905b4de26 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Abhimanyu Pallavi Sudhir, Jean Lo, Calle Sönne -/ import Mathlib.Analysis.Calculus.Deriv.Pow -import Mathlib.Analysis.Calculus.Deriv.Inv import Mathlib.Analysis.SpecialFunctions.Log.Basic import Mathlib.Analysis.SpecialFunctions.ExpDeriv @@ -260,7 +259,7 @@ theorem abs_log_sub_add_sum_range_le {x : ℝ} (h : |x| < 1) (n : ℕ) : (fun y hy ↦ (A _ ?_).hasDerivWithinAt) B (convex_Icc _ _) ?_ ?_ · exact Icc_subset_Ioo (neg_lt_neg h) h hy · simp - · simp [le_abs_self x, neg_le.mp (neg_le_abs_self x)] + · simp [le_abs_self x, neg_le.mp (neg_le_abs x)] -- fourth step: conclude by massaging the inequality of the third step simpa [div_mul_eq_mul_div, pow_succ'] using C #align real.abs_log_sub_add_sum_range_le Real.abs_log_sub_add_sum_range_le diff --git a/Mathlib/Analysis/SpecialFunctions/Log/NegMulLog.lean b/Mathlib/Analysis/SpecialFunctions/Log/NegMulLog.lean index 066f81e187631..3b4e6cd396796 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/NegMulLog.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/NegMulLog.lean @@ -52,8 +52,7 @@ lemma hasDerivAt_mul_log {x : ℝ} (hx : x ≠ 0) : HasDerivAt (fun x ↦ x * lo simp [hx] lemma deriv2_mul_log {x : ℝ} (hx : x ≠ 0) : deriv^[2] (fun x ↦ x * log x) x = x⁻¹ := by - simp only [Function.iterate_succ, Function.iterate_zero, Function.comp.left_id, - Function.comp_apply] + simp only [Function.iterate_succ, Function.iterate_zero, Function.id_comp, Function.comp_apply] suffices ∀ᶠ y in (𝓝 x), deriv (fun x ↦ x * log x) y = log y + 1 by refine (Filter.EventuallyEq.deriv_eq this).trans ?_ rw [deriv_add_const, deriv_log x] @@ -118,7 +117,7 @@ lemma hasDerivAt_negMulLog {x : ℝ} (hx : x ≠ 0) : HasDerivAt negMulLog (- lo lemma deriv2_negMulLog {x : ℝ} (hx : x ≠ 0) : deriv^[2] negMulLog x = - x⁻¹ := by rw [negMulLog_eq_neg] have h := deriv2_mul_log hx - simp only [Function.iterate_succ, Function.iterate_zero, Function.comp.left_id, + simp only [Function.iterate_succ, Function.iterate_zero, Function.id_comp, Function.comp_apply, deriv.neg', differentiableAt_id', differentiableAt_log_iff, ne_eq] at h ⊢ rw [h] diff --git a/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean b/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean index 803728dbdc93b..5c065b786d69e 100644 --- a/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean +++ b/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.MeasureTheory.Function.Jacobian import Mathlib.MeasureTheory.Measure.Lebesgue.Complex +import Mathlib.Analysis.SpecialFunctions.Trigonometric.Deriv #align_import analysis.special_functions.polar_coord from "leanprover-community/mathlib"@"8f9fea08977f7e450770933ee6abb20733b47c92" diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean index 515844e618e49..32f4903d0b9c2 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean @@ -40,7 +40,7 @@ theorem tendsto_rpow_atTop {y : ℝ} (hy : 0 < y) : Tendsto (fun x : ℝ => x ^ exact le_of_max_le_left (by - convert rpow_le_rpow (rpow_nonneg_of_nonneg (le_max_right b 0) (1 / y)) hx (le_of_lt hy) + convert rpow_le_rpow (rpow_nonneg (le_max_right b 0) (1 / y)) hx (le_of_lt hy) using 1 rw [← rpow_mul (le_max_right b 0), (eq_div_iff (ne_of_gt hy)).mp rfl, Real.rpow_one]) #align tendsto_rpow_at_top tendsto_rpow_atTop @@ -148,7 +148,7 @@ theorem tendsto_exp_mul_div_rpow_atTop (s : ℝ) (b : ℝ) (hb : 0 < b) : Tendsto (fun x : ℝ => exp (b * x) / x ^ s) atTop atTop := by refine' ((tendsto_rpow_atTop hb).comp (tendsto_exp_div_rpow_atTop (s / b))).congr' _ filter_upwards [eventually_ge_atTop (0 : ℝ)] with x hx₀ - simp [Real.div_rpow, (exp_pos x).le, rpow_nonneg_of_nonneg, ← Real.rpow_mul, ← exp_mul, + simp [Real.div_rpow, (exp_pos x).le, rpow_nonneg, ← Real.rpow_mul, ← exp_mul, mul_comm x, hb.ne', *] #align tendsto_exp_mul_div_rpow_at_top tendsto_exp_mul_div_rpow_atTop @@ -280,7 +280,7 @@ theorem IsBigO.rpow (hr : 0 ≤ r) (hg : 0 ≤ᶠ[l] g) (h : f =O[l] g) : theorem IsLittleO.rpow (hr : 0 < r) (hg : 0 ≤ᶠ[l] g) (h : f =o[l] g) : (fun x => f x ^ r) =o[l] fun x => g x ^ r := IsLittleO.of_isBigOWith fun c hc => - ((h.forall_isBigOWith (rpow_pos_of_pos hc r⁻¹)).rpow (rpow_nonneg_of_nonneg hc.le _) hr.le + ((h.forall_isBigOWith (rpow_pos_of_pos hc r⁻¹)).rpow (rpow_nonneg hc.le _) hr.le hg).congr_const (by rw [← rpow_mul hc.le, inv_mul_cancel hr.ne', Real.rpow_one]) #align asymptotics.is_o.rpow Asymptotics.IsLittleO.rpow diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean index 79902cf702f13..c9a2a657eda95 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean @@ -348,7 +348,7 @@ theorem continuousAt_cpow_zero_of_re_pos {z : ℂ} (hz : 0 < z.re) : refine' ⟨Real.exp (π * C), eventually_map.2 _⟩ refine' (((continuous_im.comp continuous_snd).abs.tendsto (_, z)).eventually (gt_mem_nhds hC)).mono - fun z hz => Real.exp_le_exp.2 <| (neg_le_abs_self _).trans _ + fun z hz => Real.exp_le_exp.2 <| (neg_le_abs _).trans _ rw [_root_.abs_mul] exact mul_le_mul (abs_le.2 ⟨(neg_pi_lt_arg _).le, arg_le_pi _⟩) hz.le (_root_.abs_nonneg _) @@ -390,7 +390,7 @@ theorem continuousAt_ofReal_cpow (x : ℝ) (y : ℂ) (h : 0 < y.re ∨ x ≠ 0) tauto have B : ContinuousAt (fun p => ⟨↑p.1, p.2⟩ : ℝ × ℂ → ℂ × ℂ) ⟨0, y⟩ := continuous_ofReal.continuousAt.prod_map continuousAt_id - exact ContinuousAt.comp (α := ℝ × ℂ) (f := fun p => ⟨↑p.1, p.2⟩) (x := ⟨0, y⟩) A B + exact A.comp_of_eq B rfl · -- x < 0 : difficult case suffices ContinuousAt (fun p => (-(p.1 : ℂ)) ^ p.2 * exp (π * I * p.2) : ℝ × ℂ → ℂ) (x, y) by refine' this.congr (eventually_of_mem (prod_mem_nhds (Iio_mem_nhds hx) univ_mem) _) @@ -429,7 +429,7 @@ theorem continuousAt_rpow {x : ℝ≥0} {y : ℝ} (h : x ≠ 0 ∨ 0 < y) : (fun p : ℝ≥0 × ℝ => p.1 ^ p.2) = Real.toNNReal ∘ (fun p : ℝ × ℝ => p.1 ^ p.2) ∘ fun p : ℝ≥0 × ℝ => (p.1.1, p.2) := by ext p - erw [coe_rpow, Real.coe_toNNReal _ (Real.rpow_nonneg_of_nonneg p.1.2 _)] + erw [coe_rpow, Real.coe_toNNReal _ (Real.rpow_nonneg p.1.2 _)] rfl rw [this] refine' continuous_real_toNNReal.continuousAt.comp (ContinuousAt.comp _ _) diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean b/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean index 598828dcdd8ff..51528e4ea1e7d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean @@ -30,7 +30,7 @@ namespace NNReal restriction of the real power function. For `x > 0`, it is equal to `exp (y log x)`. For `x = 0`, one sets `0 ^ 0 = 1` and `0 ^ y = 0` for `y ≠ 0`. -/ noncomputable def rpow (x : ℝ≥0) (y : ℝ) : ℝ≥0 := - ⟨(x : ℝ) ^ y, Real.rpow_nonneg_of_nonneg x.2 y⟩ + ⟨(x : ℝ) ^ y, Real.rpow_nonneg x.2 y⟩ #align nnreal.rpow NNReal.rpow noncomputable instance : Pow ℝ≥0 ℝ := diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean index a5323ca6ac8ca..4459d090b2e71 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean @@ -155,13 +155,13 @@ theorem zero_rpow_nonneg (x : ℝ) : 0 ≤ (0 : ℝ) ^ x := by by_cases h : x = 0 <;> simp [h, zero_le_one] #align real.zero_rpow_nonneg Real.zero_rpow_nonneg -theorem rpow_nonneg_of_nonneg {x : ℝ} (hx : 0 ≤ x) (y : ℝ) : 0 ≤ x ^ y := by +theorem rpow_nonneg {x : ℝ} (hx : 0 ≤ x) (y : ℝ) : 0 ≤ x ^ y := by rw [rpow_def_of_nonneg hx]; split_ifs <;> simp only [zero_le_one, le_refl, le_of_lt (exp_pos _)] -#align real.rpow_nonneg_of_nonneg Real.rpow_nonneg_of_nonneg +#align real.rpow_nonneg_of_nonneg Real.rpow_nonneg theorem abs_rpow_of_nonneg {x y : ℝ} (hx_nonneg : 0 ≤ x) : |x ^ y| = |x| ^ y := by - have h_rpow_nonneg : 0 ≤ x ^ y := Real.rpow_nonneg_of_nonneg hx_nonneg _ + have h_rpow_nonneg : 0 ≤ x ^ y := Real.rpow_nonneg hx_nonneg _ rw [abs_eq_self.mpr hx_nonneg, abs_eq_self.mpr h_rpow_nonneg] #align real.abs_rpow_of_nonneg Real.abs_rpow_of_nonneg @@ -278,7 +278,7 @@ lemma cpow_ofReal (x : ℂ) (y : ℝ) : · simp [ofReal_cpow le_rfl] · rw [cpow_def_of_ne_zero hx, exp_eq_exp_re_mul_sin_add_cos, mul_comm (log x)] norm_cast - rw [ofReal_mul_re, ofReal_mul_im, log_re, log_im, mul_comm y, mul_comm y, Real.exp_mul, + rw [re_ofReal_mul, im_ofReal_mul, log_re, log_im, mul_comm y, mul_comm y, Real.exp_mul, Real.exp_log] rwa [abs.pos_iff] @@ -360,7 +360,7 @@ def evalRpow : Mathlib.Meta.Positivity.PositivityExt where eval {_ _} zα pα e pure (.positive (q(Real.rpow_pos_of_pos $pa' $b) : Expr)) | .nonnegative pa => have pa' : Q(0 ≤ $a) := pa - pure (.nonnegative (q(Real.rpow_nonneg_of_nonneg $pa' $b) : Expr)) + pure (.nonnegative (q(Real.rpow_nonneg $pa' $b) : Expr)) | _ => pure .none end Mathlib.Meta.Positivity @@ -375,7 +375,7 @@ namespace Real variable {x y z : ℝ} {n : ℕ} theorem rpow_mul {x : ℝ} (hx : 0 ≤ x) (y z : ℝ) : x ^ (y * z) = (x ^ y) ^ z := by - rw [← Complex.ofReal_inj, Complex.ofReal_cpow (rpow_nonneg_of_nonneg hx _), + rw [← Complex.ofReal_inj, Complex.ofReal_cpow (rpow_nonneg hx _), Complex.ofReal_cpow hx, Complex.ofReal_mul, Complex.cpow_mul, Complex.ofReal_cpow hx] <;> simp only [(Complex.ofReal_mul _ _).symm, (Complex.ofReal_log hx).symm, Complex.ofReal_im, neg_lt_zero, pi_pos, le_of_lt pi_pos] @@ -384,7 +384,7 @@ theorem rpow_mul {x : ℝ} (hx : 0 ≤ x) (y z : ℝ) : x ^ (y * z) = (x ^ y) ^ theorem rpow_add_int {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℤ) : x ^ (y + n) = x ^ y * x ^ n := by rw [rpow_def, rpow_def, Complex.ofReal_add, Complex.cpow_add _ _ (Complex.ofReal_ne_zero.mpr hx), Complex.ofReal_int_cast, - Complex.cpow_int_cast, ← Complex.ofReal_zpow, mul_comm, Complex.ofReal_mul_re, mul_comm] + Complex.cpow_int_cast, ← Complex.ofReal_zpow, mul_comm, Complex.re_ofReal_mul, mul_comm] #align real.rpow_add_int Real.rpow_add_int theorem rpow_add_nat {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℕ) : x ^ (y + n) = x ^ y * x ^ n := @@ -551,7 +551,7 @@ lemma rpow_lt_rpow_iff_of_neg (hx : 0 < x) (hy : 0 < y) (hz : z < 0) : x ^ z < y fun h ↦ rpow_lt_rpow_of_neg hy h hz⟩ lemma rpow_le_rpow_iff_of_neg (hx : 0 < x) (hy : 0 < y) (hz : z < 0) : x ^ z ≤ y ^ z ↔ y ≤ x := - le_iff_le_iff_lt_iff_lt.2 $ rpow_lt_rpow_iff_of_neg hy hx hz + le_iff_le_iff_lt_iff_lt.2 <| rpow_lt_rpow_iff_of_neg hy hx hz lemma le_rpow_inv_iff_of_pos (hx : 0 ≤ x) (hy : 0 ≤ y) (hz : 0 < z) : x ≤ y ^ z⁻¹ ↔ x ^ z ≤ y := by rw [← rpow_le_rpow_iff hx _ hz, rpow_inv_rpow] <;> positivity @@ -560,10 +560,10 @@ lemma rpow_inv_le_iff_of_pos (hx : 0 ≤ x) (hy : 0 ≤ y) (hz : 0 < z) : x ^ z rw [← rpow_le_rpow_iff _ hy hz, rpow_inv_rpow] <;> positivity lemma lt_rpow_inv_iff_of_pos (hx : 0 ≤ x) (hy : 0 ≤ y) (hz : 0 < z) : x < y ^ z⁻¹ ↔ x ^ z < y := - lt_iff_lt_of_le_iff_le $ rpow_inv_le_iff_of_pos hy hx hz + lt_iff_lt_of_le_iff_le <| rpow_inv_le_iff_of_pos hy hx hz lemma rpow_inv_lt_iff_of_pos (hx : 0 ≤ x) (hy : 0 ≤ y) (hz : 0 < z) : x ^ z⁻¹ < y ↔ x < y ^ z := - lt_iff_lt_of_le_iff_le $ le_rpow_inv_iff_of_pos hy hx hz + lt_iff_lt_of_le_iff_le <| le_rpow_inv_iff_of_pos hy hx hz theorem le_rpow_inv_iff_of_neg (hx : 0 < x) (hy : 0 < y) (hz : z < 0) : x ≤ y ^ z⁻¹ ↔ y ≤ x ^ z := by @@ -820,7 +820,7 @@ section Sqrt theorem sqrt_eq_rpow (x : ℝ) : sqrt x = x ^ (1 / (2 : ℝ)) := by obtain h | h := le_or_lt 0 x - · rw [← mul_self_inj_of_nonneg (sqrt_nonneg _) (rpow_nonneg_of_nonneg h _), mul_self_sqrt h, ← sq, + · rw [← mul_self_inj_of_nonneg (sqrt_nonneg _) (rpow_nonneg h _), mul_self_sqrt h, ← sq, ← rpow_nat_cast, ← rpow_mul h] norm_num · have : 1 / (2 : ℝ) * π = π / (2 : ℝ) := by ring @@ -842,7 +842,7 @@ theorem exists_rat_pow_btwn_rat_aux (hn : n ≠ 0) (x y : ℝ) (h : x < y) (hy : have hn' : 0 < (n : ℝ) := mod_cast hn.bot_lt obtain ⟨q, hxq, hqy⟩ := exists_rat_btwn (rpow_lt_rpow (le_max_left 0 x) (max_lt hy h) <| inv_pos.mpr hn') - have := rpow_nonneg_of_nonneg (le_max_left 0 x) n⁻¹ + have := rpow_nonneg (le_max_left 0 x) n⁻¹ have hq := this.trans_lt hxq replace hxq := rpow_lt_rpow this hxq hn' replace hqy := rpow_lt_rpow hq.le hqy hn' @@ -905,55 +905,89 @@ section Tactics /-! ## Tactic extensions for real powers -/ +namespace Mathlib.Meta.NormNum + +open Lean.Meta Qq + +theorem isNat_rpow_pos {a b : ℝ} {nb ne : ℕ} + (pb : IsNat b nb) (pe' : IsNat (a ^ nb) ne) : + IsNat (a ^ b) ne := by + rwa [pb.out, rpow_nat_cast] + +theorem isNat_rpow_neg {a b : ℝ} {nb ne : ℕ} + (pb : IsInt b (Int.negOfNat nb)) (pe' : IsNat (a ^ (Int.negOfNat nb)) ne) : + IsNat (a ^ b) ne := by + rwa [pb.out, Real.rpow_int_cast] + +theorem isInt_rpow_pos {a b : ℝ} {nb ne : ℕ} + (pb : IsNat b nb) (pe' : IsInt (a ^ nb) (Int.negOfNat ne)) : + IsInt (a ^ b) (Int.negOfNat ne) := by + rwa [pb.out, rpow_nat_cast] + +theorem isInt_rpow_neg {a b : ℝ} {nb ne : ℕ} + (pb : IsInt b (Int.negOfNat nb)) (pe' : IsInt (a ^ (Int.negOfNat nb)) (Int.negOfNat ne)) : + IsInt (a ^ b) (Int.negOfNat ne) := by + rwa [pb.out, Real.rpow_int_cast] + +theorem isRat_rpow_pos {a b : ℝ} {nb : ℕ} + {num : ℤ} {den : ℕ} + (pb : IsNat b nb) (pe' : IsRat (a^nb) num den) : + IsRat (a^b) num den := by + rwa [pb.out, rpow_nat_cast] + +theorem isRat_rpow_neg {a b : ℝ} {nb : ℕ} + {num : ℤ} {den : ℕ} + (pb : IsInt b (Int.negOfNat nb)) (pe' : IsRat (a^(Int.negOfNat nb)) num den) : + IsRat (a^b) num den := by + rwa [pb.out, Real.rpow_int_cast] + +/-- Evaluates expressions of the form `a ^ b` when `a` and `b` are both reals.-/ +@[norm_num (_ : ℝ) ^ (_ : ℝ)] +def evalRPow : NormNumExt where eval {u α} e := do + let .app (.app f (a : Q(ℝ))) (b : Q(ℝ)) ← Lean.Meta.whnfR e | failure + guard <|← withNewMCtxDepth <| isDefEq f q(HPow.hPow (α := ℝ) (β := ℝ)) + haveI' : u =QL 0 := ⟨⟩ + haveI' : $α =Q ℝ := ⟨⟩ + haveI' h : $e =Q $a ^ $b := ⟨⟩ + h.check + let (rb : Result b) ← derive (α := q(ℝ)) b + match rb with + | .isBool .. | .isRat _ .. => failure + | .isNat sβ nb pb => + match ← derive q($a ^ $nb) with + | .isBool .. => failure + | .isNat sα' ne' pe' => + assumeInstancesCommute + haveI' : $sα' =Q AddGroupWithOne.toAddMonoidWithOne := ⟨⟩ + return .isNat sα' ne' q(isNat_rpow_pos $pb $pe') + | .isNegNat sα' ne' pe' => + assumeInstancesCommute + return .isNegNat sα' ne' q(isInt_rpow_pos $pb $pe') + | .isRat sα' qe' nume' dene' pe' => + assumeInstancesCommute + return .isRat sα' qe' nume' dene' q(isRat_rpow_pos $pb $pe') + | .isNegNat sβ nb pb => + match ← derive q($a ^ (-($nb : ℤ))) with + | .isBool .. => failure + | .isNat sα' ne' pe' => + assumeInstancesCommute + return .isNat sα' ne' q(isNat_rpow_neg $pb $pe') + | .isNegNat sα' ne' pe' => + let _ := q(instRingReal) + assumeInstancesCommute + return .isNegNat sα' ne' q(isInt_rpow_neg $pb $pe') + | .isRat sα' qe' nume' dene' pe' => + assumeInstancesCommute + return .isRat sα' qe' nume' dene' q(isRat_rpow_neg $pb $pe') + +end Mathlib.Meta.NormNum +end Tactics --- namespace NormNum - --- open Tactic - --- theorem rpow_pos (a b : ℝ) (b' : ℕ) (c : ℝ) (hb : (b' : ℝ) = b) (h : a ^ b' = c) : --- a ^ b = c := by --- rw [← h, ← hb, Real.rpow_nat_cast] --- #align norm_num.rpow_pos NormNum.rpow_pos - --- theorem rpow_neg (a b : ℝ) (b' : ℕ) (c c' : ℝ) (a0 : 0 ≤ a) (hb : (b' : ℝ) = b) (h : a ^ b' = c) --- (hc : c⁻¹ = c') : a ^ (-b) = c' := by --- rw [← hc, ← h, ← hb, Real.rpow_neg a0, Real.rpow_nat_cast] --- #align norm_num.rpow_neg NormNum.rpow_neg - --- /-- Evaluate `Real.rpow a b` where `a` is a rational numeral and `b` is an integer. --- (This cannot go via the generalized version `prove_rpow'` because `rpow_pos` has a --- side condition; we do not attempt to evaluate `a ^ b` where `a` and `b` are both negative because --- it comes out to some garbage.) -/ --- unsafe def prove_rpow (a b : expr) : tactic (expr × expr) := do --- let na ← a.to_rat --- let ic ← mk_instance_cache q(ℝ) --- match match_sign b with --- | Sum.inl b => do --- let (ic, a0) ← guard (na ≥ 0) >> prove_nonneg ic a --- let nc ← mk_instance_cache q(ℕ) --- let (ic, nc, b', hb) ← prove_nat_uncast ic nc b --- let (ic, c, h) ← prove_pow a na ic b' --- let cr ← c --- let (ic, c', hc) ← prove_inv ic c cr --- pure (c', (expr.const `` rpow_neg []).mk_app [a, b, b', c, c', a0, hb, h, hc]) --- | Sum.inr ff => pure (q((1 : ℝ)), expr.const `` Real.rpow_zero [] a) --- | Sum.inr tt => do --- let nc ← mk_instance_cache q(ℕ) --- let (ic, nc, b', hb) ← prove_nat_uncast ic nc b --- let (ic, c, h) ← prove_pow a na ic b' --- pure (c, (expr.const `` rpow_pos []).mk_app [a, b, b', c, hb, h]) --- #align norm_num.prove_rpow norm_num.prove_rpow - --- /-- Evaluates expressions of the form `rpow a b` and `a ^ b` in the special case where --- `b` is an integer and `a` is a positive rational (so it's really just a rational power). -/ --- @[norm_num] --- unsafe def eval_rpow : expr → tactic (expr × expr) --- | q(@Pow.pow _ _ Real.hasPow $(a) $(b)) => b.to_int >> prove_rpow a b --- | q(Real.rpow $(a) $(b)) => b.to_int >> prove_rpow a b --- | _ => tactic.failed --- #align norm_num.eval_rpow norm_num.eval_rpow - --- end NormNum +/-! +### Deprecated lemmas -end Tactics +These lemmas have been deprecated on 2024-01-07. +-/ + +@[deprecated] alias rpow_nonneg_of_nonneg := rpow_nonneg diff --git a/Mathlib/Analysis/SpecialFunctions/SmoothTransition.lean b/Mathlib/Analysis/SpecialFunctions/SmoothTransition.lean index ac3ec7e95c8cf..f8d2408b4341e 100644 --- a/Mathlib/Analysis/SpecialFunctions/SmoothTransition.lean +++ b/Mathlib/Analysis/SpecialFunctions/SmoothTransition.lean @@ -5,8 +5,6 @@ Authors: Sébastien Gouëzel, Yury Kudryashov -/ import Mathlib.Analysis.Calculus.Deriv.Inv import Mathlib.Analysis.Calculus.Deriv.Polynomial -import Mathlib.Analysis.Calculus.FDeriv.Extend -import Mathlib.Analysis.Calculus.IteratedDeriv import Mathlib.Analysis.SpecialFunctions.ExpDeriv import Mathlib.Analysis.SpecialFunctions.PolynomialExp @@ -25,8 +23,6 @@ cannot have: by `expNegInvGlue x / (expNegInvGlue x + expNegInvGlue (1 - x))`; -/ -set_option autoImplicit true - noncomputable section open scoped Classical Topology @@ -66,7 +62,7 @@ theorem nonneg (x : ℝ) : 0 ≤ expNegInvGlue x := by #align exp_neg_inv_glue.nonneg expNegInvGlue.nonneg -- porting note: new lemma -@[simp] theorem zero_iff_nonpos : expNegInvGlue x = 0 ↔ x ≤ 0 := +@[simp] theorem zero_iff_nonpos {x : ℝ} : expNegInvGlue x = 0 ↔ x ≤ 0 := ⟨fun h ↦ not_lt.mp fun h' ↦ (pos_of_pos h').ne' h, zero_of_nonpos⟩ /-! diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean index c5a7067b57b25..f0a90a0858a65 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean @@ -575,36 +575,29 @@ theorem cos_eq_one_iff_of_lt_of_lt {x : ℝ} (hx₁ : -(2 * π) < x) (hx₂ : x simp, fun h => by simp [h]⟩ #align real.cos_eq_one_iff_of_lt_of_lt Real.cos_eq_one_iff_of_lt_of_lt -theorem cos_lt_cos_of_nonneg_of_le_pi_div_two {x y : ℝ} (hx₁ : 0 ≤ x) (hy₂ : y ≤ π / 2) - (hxy : x < y) : cos y < cos x := by - rw [← sub_lt_zero, cos_sub_cos] - have : 0 < sin ((y + x) / 2) := by refine' sin_pos_of_pos_of_lt_pi _ _ <;> linarith - have : 0 < sin ((y - x) / 2) := by refine' sin_pos_of_pos_of_lt_pi _ _ <;> linarith - nlinarith -#align real.cos_lt_cos_of_nonneg_of_le_pi_div_two Real.cos_lt_cos_of_nonneg_of_le_pi_div_two +theorem sin_lt_sin_of_lt_of_le_pi_div_two {x y : ℝ} (hx₁ : -(π / 2) ≤ x) (hy₂ : y ≤ π / 2) + (hxy : x < y) : sin x < sin y := by + rw [← sub_pos, sin_sub_sin] + have : 0 < sin ((y - x) / 2) := by apply sin_pos_of_pos_of_lt_pi <;> linarith + have : 0 < cos ((y + x) / 2) := by refine cos_pos_of_mem_Ioo ⟨?_, ?_⟩ <;> linarith + positivity +#align real.sin_lt_sin_of_lt_of_le_pi_div_two Real.sin_lt_sin_of_lt_of_le_pi_div_two + +theorem strictMonoOn_sin : StrictMonoOn sin (Icc (-(π / 2)) (π / 2)) := fun _ hx _ hy hxy => + sin_lt_sin_of_lt_of_le_pi_div_two hx.1 hy.2 hxy +#align real.strict_mono_on_sin Real.strictMonoOn_sin theorem cos_lt_cos_of_nonneg_of_le_pi {x y : ℝ} (hx₁ : 0 ≤ x) (hy₂ : y ≤ π) (hxy : x < y) : - cos y < cos x := - match (le_total x (π / 2) : x ≤ π / 2 ∨ π / 2 ≤ x), le_total y (π / 2) with - | Or.inl _, Or.inl hy => cos_lt_cos_of_nonneg_of_le_pi_div_two hx₁ hy hxy - | Or.inl hx, Or.inr hy => - (lt_or_eq_of_le hx).elim - (fun hx => - calc - cos y ≤ 0 := cos_nonpos_of_pi_div_two_le_of_le hy (by linarith [pi_pos]) - _ < cos x := cos_pos_of_mem_Ioo ⟨by linarith, hx⟩) - fun hx => - calc - cos y < 0 := cos_neg_of_pi_div_two_lt_of_lt (by linarith) (by linarith [pi_pos]) - _ = cos x := by rw [hx, cos_pi_div_two] - | Or.inr hx, Or.inl hy => by linarith - | Or.inr hx, Or.inr hy => - neg_lt_neg_iff.1 - (by - rw [← cos_pi_sub, ← cos_pi_sub]; apply cos_lt_cos_of_nonneg_of_le_pi_div_two <;> - linarith) + cos y < cos x := by + rw [← sin_pi_div_two_sub, ← sin_pi_div_two_sub] + apply sin_lt_sin_of_lt_of_le_pi_div_two <;> linarith #align real.cos_lt_cos_of_nonneg_of_le_pi Real.cos_lt_cos_of_nonneg_of_le_pi +theorem cos_lt_cos_of_nonneg_of_le_pi_div_two {x y : ℝ} (hx₁ : 0 ≤ x) (hy₂ : y ≤ π / 2) + (hxy : x < y) : cos y < cos x := + cos_lt_cos_of_nonneg_of_le_pi hx₁ (hy₂.trans (by linarith)) hxy +#align real.cos_lt_cos_of_nonneg_of_le_pi_div_two Real.cos_lt_cos_of_nonneg_of_le_pi_div_two + theorem strictAntiOn_cos : StrictAntiOn cos (Icc 0 π) := fun _ hx _ hy hxy => cos_lt_cos_of_nonneg_of_le_pi hx.1 hy.2 hxy #align real.strict_anti_on_cos Real.strictAntiOn_cos @@ -614,16 +607,6 @@ theorem cos_le_cos_of_nonneg_of_le_pi {x y : ℝ} (hx₁ : 0 ≤ x) (hy₂ : y (strictAntiOn_cos.le_iff_le ⟨hx₁.trans hxy, hy₂⟩ ⟨hx₁, hxy.trans hy₂⟩).2 hxy #align real.cos_le_cos_of_nonneg_of_le_pi Real.cos_le_cos_of_nonneg_of_le_pi -theorem sin_lt_sin_of_lt_of_le_pi_div_two {x y : ℝ} (hx₁ : -(π / 2) ≤ x) (hy₂ : y ≤ π / 2) - (hxy : x < y) : sin x < sin y := by - rw [← cos_sub_pi_div_two, ← cos_sub_pi_div_two, ← cos_neg (x - _), ← cos_neg (y - _)] - apply cos_lt_cos_of_nonneg_of_le_pi <;> linarith -#align real.sin_lt_sin_of_lt_of_le_pi_div_two Real.sin_lt_sin_of_lt_of_le_pi_div_two - -theorem strictMonoOn_sin : StrictMonoOn sin (Icc (-(π / 2)) (π / 2)) := fun _ hx _ hy hxy => - sin_lt_sin_of_lt_of_le_pi_div_two hx.1 hy.2 hxy -#align real.strict_mono_on_sin Real.strictMonoOn_sin - theorem sin_le_sin_of_le_of_le_pi_div_two {x y : ℝ} (hx₁ : -(π / 2) ≤ x) (hy₂ : y ≤ π / 2) (hxy : x ≤ y) : sin x ≤ sin y := (strictMonoOn_sin.le_iff_le ⟨hx₁, hxy.trans hy₂⟩ ⟨hx₁.trans hxy, hy₂⟩).2 hxy @@ -948,38 +931,22 @@ theorem tan_nonpos_of_nonpos_of_neg_pi_div_two_le {x : ℝ} (hx0 : x ≤ 0) (hpx neg_nonneg.1 (tan_neg x ▸ tan_nonneg_of_nonneg_of_le_pi_div_two (by linarith) (by linarith)) #align real.tan_nonpos_of_nonpos_of_neg_pi_div_two_le Real.tan_nonpos_of_nonpos_of_neg_pi_div_two_le -theorem tan_lt_tan_of_nonneg_of_lt_pi_div_two {x y : ℝ} (hx₁ : 0 ≤ x) (hy₂ : y < π / 2) - (hxy : x < y) : tan x < tan y := by - rw [tan_eq_sin_div_cos, tan_eq_sin_div_cos] - exact - div_lt_div (sin_lt_sin_of_lt_of_le_pi_div_two (by linarith) (le_of_lt hy₂) hxy) - (cos_le_cos_of_nonneg_of_le_pi hx₁ (by linarith) (le_of_lt hxy)) - (sin_nonneg_of_nonneg_of_le_pi (by linarith) (by linarith)) - (cos_pos_of_mem_Ioo ⟨by linarith, hy₂⟩) -#align real.tan_lt_tan_of_nonneg_of_lt_pi_div_two Real.tan_lt_tan_of_nonneg_of_lt_pi_div_two +theorem strictMonoOn_tan : StrictMonoOn tan (Ioo (-(π / 2)) (π / 2)) := by + rintro x hx y hy hlt + rw [tan_eq_sin_div_cos, tan_eq_sin_div_cos, + div_lt_div_iff (cos_pos_of_mem_Ioo hx) (cos_pos_of_mem_Ioo hy), mul_comm, ← sub_pos, ← sin_sub] + exact sin_pos_of_pos_of_lt_pi (sub_pos.2 hlt) <| by linarith [hx.1, hy.2] +#align real.strict_mono_on_tan Real.strictMonoOn_tan theorem tan_lt_tan_of_lt_of_lt_pi_div_two {x y : ℝ} (hx₁ : -(π / 2) < x) (hy₂ : y < π / 2) (hxy : x < y) : tan x < tan y := - match le_total x 0, le_total y 0 with - | Or.inl hx0, Or.inl hy0 => - neg_lt_neg_iff.1 <| by - rw [← tan_neg, ← tan_neg] - exact tan_lt_tan_of_nonneg_of_lt_pi_div_two (neg_nonneg.2 hy0) (neg_lt.2 hx₁) (neg_lt_neg hxy) - | Or.inl hx0, Or.inr hy0 => - (lt_or_eq_of_le hy0).elim - (fun hy0 => - calc - tan x ≤ 0 := tan_nonpos_of_nonpos_of_neg_pi_div_two_le hx0 (le_of_lt hx₁) - _ < tan y := tan_pos_of_pos_of_lt_pi_div_two hy0 hy₂) - fun hy0 => by - rw [← hy0, tan_zero]; exact tan_neg_of_neg_of_pi_div_two_lt (hy0.symm ▸ hxy) hx₁ - | Or.inr hx0, Or.inl hy0 => by linarith - | Or.inr hx0, Or.inr _ => tan_lt_tan_of_nonneg_of_lt_pi_div_two hx0 hy₂ hxy + strictMonoOn_tan ⟨hx₁, hxy.trans hy₂⟩ ⟨hx₁.trans hxy, hy₂⟩ hxy #align real.tan_lt_tan_of_lt_of_lt_pi_div_two Real.tan_lt_tan_of_lt_of_lt_pi_div_two -theorem strictMonoOn_tan : StrictMonoOn tan (Ioo (-(π / 2)) (π / 2)) := fun _ hx _ hy => - tan_lt_tan_of_lt_of_lt_pi_div_two hx.1 hy.2 -#align real.strict_mono_on_tan Real.strictMonoOn_tan +theorem tan_lt_tan_of_nonneg_of_lt_pi_div_two {x y : ℝ} (hx₁ : 0 ≤ x) (hy₂ : y < π / 2) + (hxy : x < y) : tan x < tan y := + tan_lt_tan_of_lt_of_lt_pi_div_two (by linarith) hy₂ hxy +#align real.tan_lt_tan_of_nonneg_of_lt_pi_div_two Real.tan_lt_tan_of_nonneg_of_lt_pi_div_two theorem injOn_tan : InjOn tan (Ioo (-(π / 2)) (π / 2)) := strictMonoOn_tan.injOn @@ -1398,7 +1365,7 @@ $$\left|exp^{a\left(e^{z}+e^{-z}\right)}\right| \le e^{a\cos b \exp^{|re z|}}.$$ theorem abs_exp_mul_exp_add_exp_neg_le_of_abs_im_le {a b : ℝ} (ha : a ≤ 0) {z : ℂ} (hz : |z.im| ≤ b) (hb : b ≤ π / 2) : abs (exp (a * (exp z + exp (-z)))) ≤ Real.exp (a * Real.cos b * Real.exp |z.re|) := by - simp only [abs_exp, Real.exp_le_exp, ofReal_mul_re, add_re, exp_re, neg_im, Real.cos_neg, ← + simp only [abs_exp, Real.exp_le_exp, re_ofReal_mul, add_re, exp_re, neg_im, Real.cos_neg, ← add_mul, mul_assoc, mul_comm (Real.cos b), neg_re, ← Real.cos_abs z.im] have : Real.exp |z.re| ≤ Real.exp z.re + Real.exp (-z.re) := apply_abs_le_add_of_nonneg (fun x => (Real.exp_pos x).le) z.re diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean index 11ce2a52ad88a..2ba8d14e5d27d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean @@ -5,6 +5,7 @@ Authors: Chris Hughes, Abhimanyu Pallavi Sudhir, Jean Lo, Calle Sönne, Benjamin -/ import Mathlib.Algebra.QuadraticDiscriminant import Mathlib.Analysis.Convex.SpecificFunctions.Deriv +import Mathlib.Analysis.SpecialFunctions.Pow.Complex #align_import analysis.special_functions.trigonometric.complex from "leanprover-community/mathlib"@"8f9fea08977f7e450770933ee6abb20733b47c92" diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/EulerSineProd.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/EulerSineProd.lean index 409c92704e6b2..5b65076da7b06 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/EulerSineProd.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/EulerSineProd.lean @@ -331,7 +331,7 @@ theorem _root_.Real.tendsto_euler_sin_prod (x : ℝ) : atTop (𝓝 <| sin (π * x)) := by convert (Complex.continuous_re.tendsto _).comp (Complex.tendsto_euler_sin_prod x) using 1 · ext1 n - rw [Function.comp_apply, ← Complex.ofReal_mul, Complex.ofReal_mul_re] + rw [Function.comp_apply, ← Complex.ofReal_mul, Complex.re_ofReal_mul] suffices (∏ j : ℕ in Finset.range n, (1 - x ^ 2 / (j + 1) ^ 2) : ℂ) = (∏ j : ℕ in Finset.range n, (1 - x ^ 2 / (j + 1) ^ 2) : ℝ) by diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Series.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Series.lean index 16fd6f486ed8e..81952fdafd510 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Series.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Series.lean @@ -160,7 +160,7 @@ lemma sinh_eq_tsum (r : ℝ) : sinh r = ∑' n, r ^ (2 * n + 1) / ↑(2 * n + 1) lemma cosh_le_exp_half_sq (x : ℝ) : cosh x ≤ exp (x ^ 2 / 2) := by rw [cosh_eq_tsum, exp_eq_exp_ℝ, exp_eq_tsum] - refine tsum_le_tsum (fun i ↦ ?_) x.hasSum_cosh.summable $ expSeries_summable' (x ^ 2 / 2) + refine tsum_le_tsum (fun i ↦ ?_) x.hasSum_cosh.summable <| expSeries_summable' (x ^ 2 / 2) simp only [div_pow, pow_mul, smul_eq_mul, inv_mul_eq_div, div_div] gcongr norm_cast diff --git a/Mathlib/Analysis/SpecificLimits/Basic.lean b/Mathlib/Analysis/SpecificLimits/Basic.lean index 20e45259933f5..fd8f02ceb43ae 100644 --- a/Mathlib/Analysis/SpecificLimits/Basic.lean +++ b/Mathlib/Analysis/SpecificLimits/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Johannes Hölzl, Yury G. Kudryashov, Patrick Massot -/ import Mathlib.Algebra.GeomSum +import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Order.Filter.Archimedean import Mathlib.Order.Iterate import Mathlib.Topology.Instances.ENNReal @@ -96,7 +97,7 @@ theorem tendsto_coe_nat_div_add_atTop {𝕜 : Type*} [DivisionRing 𝕜] [Topolo theorem tendsto_add_one_pow_atTop_atTop_of_pos [LinearOrderedSemiring α] [Archimedean α] {r : α} (h : 0 < r) : Tendsto (fun n : ℕ ↦ (r + 1) ^ n) atTop atTop := - tendsto_atTop_atTop_of_monotone' (fun _ _ ↦ pow_le_pow_right $ le_add_of_nonneg_left h.le) <| + tendsto_atTop_atTop_of_monotone' (fun _ _ ↦ pow_le_pow_right <| le_add_of_nonneg_left h.le) <| not_bddAbove_iff.2 fun _ ↦ Set.exists_range_iff.2 <| add_one_pow_unbounded_of_pos _ h #align tendsto_add_one_pow_at_top_at_top_of_pos tendsto_add_one_pow_atTop_atTop_of_pos @@ -131,7 +132,7 @@ theorem tendsto_pow_atTop_nhds_0_of_lt_1 {𝕜 : Type*} [LinearOrderedField 𝕜 simp only [hr.symm, one_pow] at h exact zero_ne_one <| tendsto_nhds_unique h tendsto_const_nhds · apply @not_tendsto_nhds_of_tendsto_atTop 𝕜 ℕ _ _ _ _ atTop _ (fun n ↦ |r| ^ n) _ 0 _ - refine (pow_right_strictMono $ lt_of_le_of_ne (le_of_not_lt hr_le) + refine (pow_right_strictMono <| lt_of_le_of_ne (le_of_not_lt hr_le) hr).monotone.tendsto_atTop_atTop (fun b ↦ ?_) obtain ⟨n, hn⟩ := (pow_unbounded_of_one_lt b (lt_of_le_of_ne (le_of_not_lt hr_le) hr)) exacts [⟨n, le_of_lt hn⟩, by simpa only [← abs_pow]] @@ -580,7 +581,7 @@ theorem tendsto_factorial_div_pow_self_atTop : mul_le_of_le_one_left (inv_nonneg.mpr <| mod_cast hn.le) (prod_le_one _ _) <;> intro x hx <;> rw [Finset.mem_range] at hx - · refine' mul_nonneg _ (inv_nonneg.mpr _) <;> norm_cast <;> linarith + · positivity · refine' (div_le_one <| mod_cast hn).mpr _ norm_cast linarith) diff --git a/Mathlib/Analysis/SpecificLimits/FloorPow.lean b/Mathlib/Analysis/SpecificLimits/FloorPow.lean index a9a3408c43b1e..88fcb15dc8966 100644 --- a/Mathlib/Analysis/SpecificLimits/FloorPow.lean +++ b/Mathlib/Analysis/SpecificLimits/FloorPow.lean @@ -41,9 +41,9 @@ theorem tendsto_div_of_monotone_of_exists_subseq_tendsto_div (u : ℕ → ℝ) ( rcases hlim 2 one_lt_two with ⟨c, _, ctop, clim⟩ have : Tendsto (fun n => u 0 / c n) atTop (𝓝 0) := tendsto_const_nhds.div_atTop (tendsto_nat_cast_atTop_iff.2 ctop) - apply le_of_tendsto_of_tendsto' this clim fun n => _ - simp_rw [div_eq_inv_mul] - exact fun n => mul_le_mul_of_nonneg_left (hmono (zero_le _)) (inv_nonneg.2 (Nat.cast_nonneg _)) + apply le_of_tendsto_of_tendsto' this clim fun n => ?_ + gcongr + exact hmono (zero_le _) have A : ∀ ε : ℝ, 0 < ε → ∀ᶠ n in atTop, u n - n * l ≤ ε * (1 + ε + l) * n := by intro ε εpos rcases hlim (1 + ε) ((lt_add_iff_pos_right _).2 εpos) with ⟨c, cgrowth, ctop, clim⟩ @@ -56,9 +56,9 @@ theorem tendsto_div_of_monotone_of_exists_subseq_tendsto_div (u : ℕ → ℝ) ( u (c n) - c n * l = (u (c n) / c n - l) * c n := by simp only [cnpos.ne', Ne.def, Nat.cast_eq_zero, not_false_iff, field_simps] _ ≤ ε * c n := by - refine' mul_le_mul_of_nonneg_right _ (Nat.cast_nonneg _) - simp only [mul_one, Real.norm_eq_abs, abs_one] at hn - exact le_trans (le_abs_self _) hn + gcongr + refine (le_abs_self _).trans ?_ + simpa using hn obtain ⟨a, ha⟩ : ∃ a : ℕ, ∀ b : ℕ, a ≤ b → (c (b + 1) : ℝ) ≤ (1 + ε) * c b ∧ u (c b) - c b * l ≤ ε * c b := eventually_atTop.1 (cgrowth.and L) @@ -89,23 +89,15 @@ theorem tendsto_div_of_monotone_of_exists_subseq_tendsto_div (u : ℕ → ℝ) ( have := (ha _ A).1 rwa [B] at this calc - u n - n * l ≤ u (c N) - c (N - 1) * l := by - apply sub_le_sub (hmono ncN.le) - apply mul_le_mul_of_nonneg_right (Nat.cast_le.2 cNn) lnonneg + u n - n * l ≤ u (c N) - c (N - 1) * l := by gcongr; exact hmono ncN.le _ = u (c N) - c N * l + (c N - c (N - 1)) * l := by ring _ ≤ ε * c N + ε * c (N - 1) * l := by - apply add_le_add - · apply (ha _ _).2 - exact le_trans (by simp only [le_add_iff_nonneg_right, zero_le']) aN - · apply mul_le_mul_of_nonneg_right _ lnonneg - linarith only [IcN] - _ ≤ ε * ((1 + ε) * c (N - 1)) + ε * c (N - 1) * l := - (add_le_add (mul_le_mul_of_nonneg_left IcN εpos.le) le_rfl) + gcongr + · exact (ha N (a.le_succ.trans aN)).2 + · linarith only [IcN] + _ ≤ ε * ((1 + ε) * c (N - 1)) + ε * c (N - 1) * l := by gcongr _ = ε * (1 + ε + l) * c (N - 1) := by ring - _ ≤ ε * (1 + ε + l) * n := by - refine' mul_le_mul_of_nonneg_left (Nat.cast_le.2 cNn) _ - apply mul_nonneg εpos.le - linarith only [εpos, lnonneg] + _ ≤ ε * (1 + ε + l) * n := by gcongr have B : ∀ ε : ℝ, 0 < ε → ∀ᶠ n : ℕ in atTop, (n : ℝ) * l - u n ≤ ε * (1 + l) * n := by intro ε εpos rcases hlim (1 + ε) ((lt_add_iff_pos_right _).2 εpos) with ⟨c, cgrowth, ctop, clim⟩ @@ -118,9 +110,9 @@ theorem tendsto_div_of_monotone_of_exists_subseq_tendsto_div (u : ℕ → ℝ) ( (c n : ℝ) * l - u (c n) = -(u (c n) / c n - l) * c n := by simp only [cnpos.ne', Ne.def, Nat.cast_eq_zero, not_false_iff, neg_sub, field_simps] _ ≤ ε * c n := by - refine' mul_le_mul_of_nonneg_right _ (Nat.cast_nonneg _) - simp only [mul_one, Real.norm_eq_abs, abs_one] at hn - exact le_trans (neg_le_abs_self _) hn + gcongr + refine le_trans (neg_le_abs _) ?_ + simpa using hn obtain ⟨a, ha⟩ : ∃ a : ℕ, ∀ b : ℕ, a ≤ b → (c (b + 1) : ℝ) ≤ (1 + ε) * c b ∧ (c b : ℝ) * l - u (c b) ≤ ε * c b := @@ -149,19 +141,16 @@ theorem tendsto_div_of_monotone_of_exists_subseq_tendsto_div (u : ℕ → ℝ) ( simpa only [not_lt] using Nat.find_min exN this calc (n : ℝ) * l - u n ≤ c N * l - u (c (N - 1)) := by - refine' add_le_add (mul_le_mul_of_nonneg_right (Nat.cast_le.2 ncN.le) lnonneg) _ - exact neg_le_neg (hmono cNn) + gcongr + exact hmono cNn _ ≤ (1 + ε) * c (N - 1) * l - u (c (N - 1)) := by - refine' add_le_add (mul_le_mul_of_nonneg_right _ lnonneg) le_rfl + gcongr have B : N - 1 + 1 = N := Nat.succ_pred_eq_of_pos Npos - have := (ha _ aN').1 - rwa [B] at this + simpa [B] using (ha _ aN').1 _ = c (N - 1) * l - u (c (N - 1)) + ε * c (N - 1) * l := by ring _ ≤ ε * c (N - 1) + ε * c (N - 1) * l := (add_le_add (ha _ aN').2 le_rfl) _ = ε * (1 + l) * c (N - 1) := by ring - _ ≤ ε * (1 + l) * n := by - refine' mul_le_mul_of_nonneg_left (Nat.cast_le.2 cNn) _ - exact mul_nonneg εpos.le (add_nonneg zero_le_one lnonneg) + _ ≤ ε * (1 + l) * n := by gcongr refine' tendsto_order.2 ⟨fun d hd => _, fun d hd => _⟩ · obtain ⟨ε, hε, εpos⟩ : ∃ ε : ℝ, d + ε * (1 + l) < l ∧ 0 < ε := by have L : Tendsto (fun ε => d + ε * (1 + l)) (𝓝[>] 0) (𝓝 (d + 0 * (1 + l))) := by @@ -177,9 +166,7 @@ theorem tendsto_div_of_monotone_of_exists_subseq_tendsto_div (u : ℕ → ℝ) ( · linarith only [hε] · exact Nat.cast_ne_zero.2 (ne_of_gt npos) _ = (n : ℝ)⁻¹ * (n * l - ε * (1 + l) * n) := by ring - _ ≤ (n : ℝ)⁻¹ * u n := by - refine' mul_le_mul_of_nonneg_left _ (inv_nonneg.2 (Nat.cast_nonneg _)) - linarith only [hn] + _ ≤ (n : ℝ)⁻¹ * u n := by gcongr; linarith only [hn] · obtain ⟨ε, hε, εpos⟩ : ∃ ε : ℝ, l + ε * (1 + ε + l) < d ∧ 0 < ε := by have L : Tendsto (fun ε => l + ε * (1 + ε + l)) (𝓝[>] 0) (𝓝 (l + 0 * (1 + 0 + l))) := by apply Tendsto.mono_left _ nhdsWithin_le_nhds @@ -188,17 +175,11 @@ theorem tendsto_div_of_monotone_of_exists_subseq_tendsto_div (u : ℕ → ℝ) ( (tendsto_id.mul ((tendsto_const_nhds.add tendsto_id).add tendsto_const_nhds)) simp only [zero_mul, add_zero] at L exact (((tendsto_order.1 L).2 d hd).and self_mem_nhdsWithin).exists - filter_upwards [A ε εpos, Ioi_mem_atTop 0] with n hn npos - simp_rw [div_eq_inv_mul] + filter_upwards [A ε εpos, Ioi_mem_atTop 0] with n hn (npos : 0 < n) calc - (n : ℝ)⁻¹ * u n ≤ (n : ℝ)⁻¹ * (n * l + ε * (1 + ε + l) * n) := by - refine' mul_le_mul_of_nonneg_left _ (inv_nonneg.2 (Nat.cast_nonneg _)) - linarith only [hn] - _ = (n : ℝ)⁻¹ * n * (l + ε * (1 + ε + l)) := by ring - _ < d := by - rwa [inv_mul_cancel, one_mul] - exact Nat.cast_ne_zero.2 (ne_of_gt npos) - + u n / n ≤ (n * l + ε * (1 + ε + l) * n) / n := by gcongr; linarith only [hn] + _ = (l + ε * (1 + ε + l)) := by field_simp; ring + _ < d := hε #align tendsto_div_of_monotone_of_exists_subseq_tendsto_div tendsto_div_of_monotone_of_exists_subseq_tendsto_div /-- If a monotone sequence `u` is such that `u ⌊c^n⌋₊ / ⌊c^n⌋₊` converges to a limit `l` for all @@ -251,12 +232,11 @@ theorem sum_div_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : ℝ} (hc simp only [mul_sub, this, mul_one, inv_pow, sub_le_sub_iff_left] rw [mul_assoc, mul_comm c, ← mul_assoc, mul_inv_cancel (sq_pos_of_pos cpos).ne', one_mul] simpa using pow_le_pow_right hc.le one_le_two + have C : c⁻¹ ^ 2 < 1 := pow_lt_one (inv_nonneg.2 cpos.le) (inv_lt_one hc) two_ne_zero calc - (∑ i in (range N).filter fun i => j < c ^ i, (1 : ℝ) / (c ^ i) ^ 2) ≤ + (∑ i in (range N).filter (j < c ^ ·), (1 : ℝ) / (c ^ i) ^ 2) ≤ ∑ i in Ico ⌊Real.log j / Real.log c⌋₊ N, (1 : ℝ) / (c ^ i) ^ 2 := by - refine' - sum_le_sum_of_subset_of_nonneg _ fun i _hi _hident => div_nonneg zero_le_one (sq_nonneg _) - intro i hi + refine sum_le_sum_of_subset_of_nonneg (fun i hi ↦ ?_) (by intros; positivity) simp only [mem_filter, mem_range] at hi simp only [hi.1, mem_Ico, and_true_iff] apply Nat.floor_le_of_le @@ -266,50 +246,38 @@ theorem sum_div_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : ℝ} (hc _ = ∑ i in Ico ⌊Real.log j / Real.log c⌋₊ N, (c⁻¹ ^ 2) ^ i := by congr 1 with i simp [← pow_mul, mul_comm] - _ ≤ (c⁻¹ ^ 2) ^ ⌊Real.log j / Real.log c⌋₊ / ((1 : ℝ) - c⁻¹ ^ 2) := by - apply geom_sum_Ico_le_of_lt_one (sq_nonneg _) - rw [sq_lt_one_iff (inv_nonneg.2 (zero_le_one.trans hc.le))] - exact inv_lt_one hc + _ ≤ (c⁻¹ ^ 2) ^ ⌊Real.log j / Real.log c⌋₊ / ((1 : ℝ) - c⁻¹ ^ 2) := + geom_sum_Ico_le_of_lt_one (sq_nonneg _) C _ ≤ (c⁻¹ ^ 2) ^ (Real.log j / Real.log c - 1) / ((1 : ℝ) - c⁻¹ ^ 2) := by - apply div_le_div _ _ _ le_rfl - · apply Real.rpow_nonneg_of_nonneg (sq_nonneg _) + gcongr + · exact sub_nonneg.2 C.le · rw [← Real.rpow_nat_cast] - apply Real.rpow_le_rpow_of_exponent_ge A - · exact pow_le_one _ (inv_nonneg.2 (zero_le_one.trans hc.le)) (inv_le_one hc.le) - · exact (Nat.sub_one_lt_floor _).le - · simpa only [inv_pow, sub_pos] using inv_lt_one (one_lt_pow hc two_ne_zero) + exact Real.rpow_le_rpow_of_exponent_ge A C.le (Nat.sub_one_lt_floor _).le _ = c ^ 2 * ((1 : ℝ) - c⁻¹ ^ 2)⁻¹ / j ^ 2 := by have I : (c⁻¹ ^ 2) ^ (Real.log j / Real.log c) = (1 : ℝ) / j ^ 2 := by apply Real.log_injOn_pos (Real.rpow_pos_of_pos A _) - · rw [one_div] - exact inv_pos.2 (sq_pos_of_pos hj) + · rw [Set.mem_Ioi]; positivity rw [Real.log_rpow A] - simp only [one_div, Real.log_inv, Real.log_pow, Nat.cast_one, mul_neg, - neg_inj] + simp only [one_div, Real.log_inv, Real.log_pow, Nat.cast_one, mul_neg, neg_inj] field_simp [(Real.log_pos hc).ne'] ring rw [Real.rpow_sub A, I] have : c ^ 2 - 1 ≠ 0 := (sub_pos.2 (one_lt_pow hc two_ne_zero)).ne' field_simp [hj.ne', (zero_lt_one.trans hc).ne'] ring - _ ≤ c ^ 3 * (c - 1)⁻¹ / j ^ 2 := by - apply div_le_div _ B (sq_pos_of_pos hj) le_rfl - exact mul_nonneg (pow_nonneg cpos.le _) (inv_nonneg.2 (sub_pos.2 hc).le) - + _ ≤ c ^ 3 * (c - 1)⁻¹ / j ^ 2 := by gcongr #align sum_div_pow_sq_le_div_sq sum_div_pow_sq_le_div_sq theorem mul_pow_le_nat_floor_pow {c : ℝ} (hc : 1 < c) (i : ℕ) : (1 - c⁻¹) * c ^ i ≤ ⌊c ^ i⌋₊ := by have cpos : 0 < c := zero_lt_one.trans hc - rcases Nat.eq_zero_or_pos i with (rfl | hi) + rcases eq_or_ne i 0 with (rfl | hi) · simp only [pow_zero, Nat.floor_one, Nat.cast_one, mul_one, sub_le_self_iff, inv_nonneg, cpos.le] - have hident : 1 ≤ i := hi calc (1 - c⁻¹) * c ^ i = c ^ i - c ^ i * c⁻¹ := by ring _ ≤ c ^ i - 1 := by - simpa only [← div_eq_mul_inv, sub_le_sub_iff_left, one_le_div cpos, pow_one] using - pow_le_pow_right hc.le hident + gcongr + simpa only [← div_eq_mul_inv, one_le_div cpos, pow_one] using le_self_pow hc.le hi _ ≤ ⌊c ^ i⌋₊ := (Nat.sub_one_lt_floor _).le - #align mul_pow_le_nat_floor_pow mul_pow_le_nat_floor_pow /-- The sum of `1/⌊c^i⌋₊^2` above a threshold `j` is comparable to `1/j^2`, up to a multiplicative @@ -323,12 +291,8 @@ theorem sum_div_nat_floor_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : (∑ i in (range N).filter (j < ⌊c ^ ·⌋₊), (1 : ℝ) / (⌊c ^ i⌋₊ : ℝ) ^ 2) ≤ ∑ i in (range N).filter (j < c ^ ·), (1 : ℝ) / (⌊c ^ i⌋₊ : ℝ) ^ 2 := by apply sum_le_sum_of_subset_of_nonneg - · intro i hi - simp only [mem_filter, mem_range] at hi - simpa only [hi.1, mem_filter, mem_range, true_and_iff] using - hi.2.trans_le (Nat.floor_le (pow_nonneg cpos.le _)) - · intro i _hi _hident - exact div_nonneg zero_le_one (sq_nonneg _) + · exact monotone_filter_right _ fun k hk ↦ hk.trans_le <| Nat.floor_le (by positivity) + · intros; positivity _ ≤ ∑ i in (range N).filter (j < c ^ ·), (1 - c⁻¹)⁻¹ ^ 2 * ((1 : ℝ) / (c ^ i) ^ 2) := by refine' sum_le_sum fun i _hi => _ rw [mul_div_assoc', mul_one, div_le_div_iff]; rotate_left @@ -337,16 +301,15 @@ theorem sum_div_nat_floor_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : simp only [Nat.le_floor, one_le_pow_of_one_le, hc.le, Nat.one_le_cast, Nat.cast_one] · exact sq_pos_of_pos (pow_pos cpos _) rw [one_mul, ← mul_pow] - apply pow_le_pow_left (pow_nonneg cpos.le _) + gcongr rw [← div_eq_inv_mul, le_div_iff A, mul_comm] exact mul_pow_le_nat_floor_pow hc i _ ≤ (1 - c⁻¹)⁻¹ ^ 2 * (c ^ 3 * (c - 1)⁻¹) / j ^ 2 := by rw [← mul_sum, ← mul_div_assoc'] - refine' mul_le_mul_of_nonneg_left _ (sq_nonneg _) + gcongr exact sum_div_pow_sq_le_div_sq N hj hc _ = c ^ 5 * (c - 1)⁻¹ ^ 3 / j ^ 2 := by congr 1 - field_simp [cpos.ne', (sub_pos.2 hc).ne'] + field_simp [(sub_pos.2 hc).ne'] ring! - #align sum_div_nat_floor_pow_sq_le_div_sq sum_div_nat_floor_pow_sq_le_div_sq diff --git a/Mathlib/Analysis/SpecificLimits/IsROrC.lean b/Mathlib/Analysis/SpecificLimits/IsROrC.lean index 9c6ead85ba251..932658623f588 100644 --- a/Mathlib/Analysis/SpecificLimits/IsROrC.lean +++ b/Mathlib/Analysis/SpecificLimits/IsROrC.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Xavier Généreux, Patrick Massot -/ import Mathlib.Analysis.SpecificLimits.Basic -import Mathlib.Analysis.Complex.ReImTopology +import Mathlib.Data.IsROrC.Basic /-! # A collection of specific limit computations for `IsROrC` diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index 7097914871853..202ebe032f999 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Order.Field.Basic import Mathlib.Analysis.Asymptotics.Asymptotics import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.Data.List.TFAE +import Mathlib.Data.Real.Sqrt #align_import analysis.specific_limits.normed from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Analysis/SumIntegralComparisons.lean b/Mathlib/Analysis/SumIntegralComparisons.lean index b9d149e7c64b7..5e4cf6156c393 100644 --- a/Mathlib/Analysis/SumIntegralComparisons.lean +++ b/Mathlib/Analysis/SumIntegralComparisons.lean @@ -5,7 +5,6 @@ Authors: Kevin H. Wilson -/ import Mathlib.MeasureTheory.Integral.IntervalIntegral import Mathlib.Data.Set.Function -import Mathlib.Analysis.SpecialFunctions.Integrals #align_import analysis.sum_integral_comparisons from "leanprover-community/mathlib"@"9003f28797c0664a49e4179487267c494477d853" diff --git a/Mathlib/CategoryTheory/Abelian/DiagramLemmas/Four.lean b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/Four.lean index 00e434699c44d..c472617b130db 100644 --- a/Mathlib/CategoryTheory/Abelian/DiagramLemmas/Four.lean +++ b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/Four.lean @@ -106,7 +106,7 @@ theorem epi_of_epi_of_epi_of_mono' ← R₂.map'_comp 1 2 3, hR₂', comp_zero, comp_zero] obtain ⟨A₂, π₂, _, f₁, h₃⟩ := (hR₁.exact 0).exact_up_to_refinements _ h₂ dsimp at f₁ h₃ - have h₄ : (π₂ ≫ π₁ ≫ g₁ - f₁ ≫ app' φ 1) ≫ R₂.map' 1 2 = 0 := by + have h₄ : (π₂ ≫ π₁ ≫ g₁ - f₁ ≫ app' φ 1 _) ≫ R₂.map' 1 2 = 0 := by rw [sub_comp, assoc, assoc, assoc, ← NatTrans.naturality, ← reassoc_of% h₃, h₁, sub_self] obtain ⟨A₃, π₃, _, g₀, h₅⟩ := (hR₂.exact 0).exact_up_to_refinements _ h₄ dsimp at g₀ h₅ diff --git a/Mathlib/CategoryTheory/Abelian/Projective.lean b/Mathlib/CategoryTheory/Abelian/Projective.lean index 84d1f5049d829..a65dee9ce8dbb 100644 --- a/Mathlib/CategoryTheory/Abelian/Projective.lean +++ b/Mathlib/CategoryTheory/Abelian/Projective.lean @@ -5,6 +5,7 @@ Authors: Jakob von Raumer -/ import Mathlib.CategoryTheory.Preadditive.Yoneda.Projective import Mathlib.CategoryTheory.Preadditive.Yoneda.Limits +import Mathlib.Algebra.Category.ModuleCat.EpiMono /-! # Projective objects in abelian categories diff --git a/Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean b/Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean index 157ba1dceeb00..8b4a472ee6bf8 100644 --- a/Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean +++ b/Mathlib/CategoryTheory/Abelian/ProjectiveResolution.lean @@ -5,6 +5,7 @@ Authors: Markus Himmel, Scott Morrison, Jakob von Raumer, Joël Riou -/ import Mathlib.CategoryTheory.Preadditive.ProjectiveResolution import Mathlib.Algebra.Homology.HomotopyCategory +import Mathlib.Tactic.SuppressCompilation /-! # Abelian categories with enough projectives have projective resolutions @@ -26,6 +27,7 @@ When the underlying category is abelian: is projective, we can apply `Projective.d` repeatedly to obtain a projective resolution of `X`. -/ +suppress_compilation noncomputable section @@ -70,7 +72,7 @@ def liftFOne {Y Z : C} (f : Y ⟶ Z) (P : ProjectiveResolution Y) (Q : Projectiv @[simp] theorem liftFOne_zero_comm {Y Z : C} (f : Y ⟶ Z) (P : ProjectiveResolution Y) (Q : ProjectiveResolution Z) : - liftFOne f P Q ≫ Q.complex.d 1 0 = P.complex.d 1 0 ≫ liftFZero f P Q := by + liftFOne f P Q ≫ Q.complex.d 1 0 = P.complex.d 1 0 ≫ liftFZero f P Q := by apply Q.exact₀.liftFromProjective_comp #align category_theory.ProjectiveResolution.lift_f_one_zero_comm CategoryTheory.ProjectiveResolution.liftFOne_zero_comm @@ -296,8 +298,7 @@ variable (Z : C) /-- Auxiliary definition for `ProjectiveResolution.of`. -/ def ofComplex : ChainComplex C ℕ := ChainComplex.mk' (Projective.over Z) (Projective.syzygies (Projective.π Z)) - (Projective.d (Projective.π Z)) fun ⟨_, _, f⟩ => - ⟨Projective.syzygies f, Projective.d f, by simp⟩ + (Projective.d (Projective.π Z)) (fun f => ⟨_, Projective.d f, by simp⟩) #align category_theory.ProjectiveResolution.of_complex CategoryTheory.ProjectiveResolution.ofComplex lemma ofComplex_d_1_0 : @@ -307,12 +308,17 @@ lemma ofComplex_d_1_0 : lemma ofComplex_exactAt_succ (n : ℕ) : (ofComplex Z).ExactAt (n + 1) := by rw [HomologicalComplex.exactAt_iff' _ (n + 1 + 1) (n + 1) n (by simp) (by simp)] - cases n - all_goals - dsimp [ofComplex, HomologicalComplex.sc', HomologicalComplex.shortComplexFunctor', - ChainComplex.mk, ChainComplex.mk'] - simp - apply exact_d_f + dsimp [ofComplex, HomologicalComplex.sc', HomologicalComplex.shortComplexFunctor', + ChainComplex.mk', ChainComplex.mk] + simp only [ChainComplex.of_d] + -- TODO: this should just be apply exact_d_f so something is missing + match n with + | 0 => + apply exact_d_f ((ChainComplex.mkAux _ _ _ (d (Projective.π Z)) (d (d (Projective.π Z))) _ _ + 0).g) + | n+1 => + apply exact_d_f ((ChainComplex.mkAux _ _ _ (d (Projective.π Z)) (d (d (Projective.π Z))) _ _ + (n+1)).g) instance (n : ℕ) : Projective ((ofComplex Z).X n) := by obtain (_ | _ | _ | n) := n <;> apply Projective.projective_over diff --git a/Mathlib/CategoryTheory/Abelian/Transfer.lean b/Mathlib/CategoryTheory/Abelian/Transfer.lean index a135487f32a69..e6206ac7609c9 100644 --- a/Mathlib/CategoryTheory/Abelian/Transfer.lean +++ b/Mathlib/CategoryTheory/Abelian/Transfer.lean @@ -83,8 +83,6 @@ def cokernelIso {X Y : C} (f : X ⟶ Y) : G.obj (cokernel (F.map f)) ≅ cokerne -- We have to write an explicit `PreservesColimits` type here, -- as `leftAdjointPreservesColimits` has universe variables. have : PreservesColimits G := adj.leftAdjointPreservesColimits - -- porting note: the next `have` has been added, otherwise some instance were not found - have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance calc G.obj (cokernel (F.map f)) ≅ cokernel (G.map (F.map f)) := (asIso (cokernelComparison _ G)).symm @@ -99,8 +97,6 @@ variable [Limits.HasKernels C] [PreservesFiniteLimits G] def coimageIsoImageAux {X Y : C} (f : X ⟶ Y) : kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π f) := by have : PreservesColimits G := adj.leftAdjointPreservesColimits - -- porting note: the next `have` has been added, otherwise some instance were not found - have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance calc kernel (G.map (cokernel.π (F.map f))) ≅ kernel (cokernel.π (G.map (F.map f)) ≫ cokernelComparison (F.map f) G) := @@ -127,8 +123,6 @@ We still need to check that this agrees with the canonical morphism. -/ def coimageIsoImage {X Y : C} (f : X ⟶ Y) : Abelian.coimage f ≅ Abelian.image f := by have : PreservesLimits F := adj.rightAdjointPreservesLimits - -- porting note: the next `have` has been added, otherwise some instance were not found - haveI : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance calc Abelian.coimage f ≅ cokernel (kernel.ι f) := Iso.refl _ _ ≅ G.obj (cokernel (F.map (kernel.ι f))) := (cokernelIso _ _ i adj _).symm @@ -144,17 +138,10 @@ def coimageIsoImage {X Y : C} (f : X ⟶ Y) : Abelian.coimage f ≅ Abelian.imag #align category_theory.abelian_of_adjunction.coimage_iso_image CategoryTheory.AbelianOfAdjunction.coimageIsoImage -- The account of this proof in the Stacks project omits this calculation. -@[nolint unusedHavesSuffices] theorem coimageIsoImage_hom {X Y : C} (f : X ⟶ Y) : (coimageIsoImage F G i adj f).hom = Abelian.coimageImageComparison f := by - -- porting note: the next `have` have been added, otherwise some instance were not found - have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance - have : ∀ (X' Y' : C) (f' : X' ⟶ Y'), HasKernel f' := inferInstance - have : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasCokernel f' := inferInstance - have : ∀ (X' Y' : D) (f' : X' ⟶ Y'), HasKernel f' := inferInstance - dsimp only [coimageIsoImage, Iso.instTransIso_trans, Iso.refl, Iso.trans, Iso.symm, - Functor.mapIso, cokernelEpiComp, cokernelIso, cokernelCompIsIso_inv, - asIso, coimageIsoImageAux, kernelCompMono] + dsimp [coimageIsoImage, cokernelIso, cokernelEpiComp, cokernelCompIsIso_inv, + coimageIsoImageAux, kernelCompMono] simpa only [← cancel_mono (Abelian.image.ι f), ← cancel_epi (Abelian.coimage.π f), Category.assoc, Category.id_comp, cokernel.π_desc_assoc, π_comp_cokernelIsoOfEq_inv_assoc, PreservesKernel.iso_hom, diff --git a/Mathlib/CategoryTheory/Adhesive.lean b/Mathlib/CategoryTheory/Adhesive.lean index 4546551b9dc5f..a09fee0a5dd93 100644 --- a/Mathlib/CategoryTheory/Adhesive.lean +++ b/Mathlib/CategoryTheory/Adhesive.lean @@ -331,7 +331,7 @@ theorem adhesive_of_reflective [HasPullbacks D] [Adhesive C] [HasPullbacks C] [H (isoWhiskerLeft _ (asIso adj.counit) ≪≫ Functor.rightUnitor _).hom).mp ?_ refine ((this.precompose_isIso (spanCompIso _ _ _).hom).map_reflective adj).of_iso (IsColimit.uniqueUpToIso ?_ ?_) - · exact isColimitOfPreserves Gl ((IsColimit.precomposeHomEquiv _ _).symm $ pushoutIsPushout _ _) + · exact isColimitOfPreserves Gl ((IsColimit.precomposeHomEquiv _ _).symm <| pushoutIsPushout _ _) · exact (IsColimit.precomposeHomEquiv _ _).symm H.isColimit end functor diff --git a/Mathlib/CategoryTheory/Bicategory/Adjunction.lean b/Mathlib/CategoryTheory/Bicategory/Adjunction.lean index 653edd5bc8e91..cf087136d3014 100644 --- a/Mathlib/CategoryTheory/Bicategory/Adjunction.lean +++ b/Mathlib/CategoryTheory/Bicategory/Adjunction.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yuma Mizuno -/ import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.CategoryTheory.Bicategory.Coherence /-! # Adjunctions in bicategories diff --git a/Mathlib/CategoryTheory/Category/Basic.lean b/Mathlib/CategoryTheory/Category/Basic.lean index 631dff569279c..612ec3def031e 100644 --- a/Mathlib/CategoryTheory/Category/Basic.lean +++ b/Mathlib/CategoryTheory/Category/Basic.lean @@ -116,8 +116,8 @@ use in auto-params. -/ macro (name := aesop_cat) "aesop_cat" c:Aesop.tactic_clause* : tactic => `(tactic| - aesop $c* (options := { introsTransparency? := some .default, terminal := true }) - (simp_options := { decide := true }) + aesop $c* (config := { introsTransparency? := some .default, terminal := true }) + (simp_config := { decide := true }) (rule_sets [$(Lean.mkIdent `CategoryTheory):ident])) /-- @@ -125,7 +125,7 @@ We also use `aesop_cat?` to pass along a `Try this` suggestion when using `aesop -/ macro (name := aesop_cat?) "aesop_cat?" c:Aesop.tactic_clause* : tactic => `(tactic| - aesop? $c* (options := { introsTransparency? := some .default, terminal := true }) + aesop? $c* (config := { introsTransparency? := some .default, terminal := true }) (rule_sets [$(Lean.mkIdent `CategoryTheory):ident])) /-- A variant of `aesop_cat` which does not fail when it is unable to solve the @@ -134,7 +134,7 @@ nonterminal `simp`. -/ macro (name := aesop_cat_nonterminal) "aesop_cat_nonterminal" c:Aesop.tactic_clause* : tactic => `(tactic| - aesop $c* (options := { introsTransparency? := some .default, warnOnNonterminal := false }) + aesop $c* (config := { introsTransparency? := some .default, warnOnNonterminal := false }) (rule_sets [$(Lean.mkIdent `CategoryTheory):ident])) diff --git a/Mathlib/CategoryTheory/Closed/Cartesian.lean b/Mathlib/CategoryTheory/Closed/Cartesian.lean index 754756e8c33ec..ad1171b4cf2e7 100644 --- a/Mathlib/CategoryTheory/Closed/Cartesian.lean +++ b/Mathlib/CategoryTheory/Closed/Cartesian.lean @@ -119,13 +119,13 @@ open Lean PrettyPrinter.Delaborator SubExpr in @[delab app.Prefunctor.obj] def delabPrefunctorObjExp : Delab := do let e ← getExpr - guard $ e.isAppOfArity' ``Prefunctor.obj 6 + guard <| e.isAppOfArity' ``Prefunctor.obj 6 let A ← withNaryArg 4 do let e ← getExpr - guard $ e.isAppOfArity' ``Functor.toPrefunctor 5 + guard <| e.isAppOfArity' ``Functor.toPrefunctor 5 withNaryArg 4 do let e ← getExpr - guard $ e.isAppOfArity' ``exp 5 + guard <| e.isAppOfArity' ``exp 5 withNaryArg 2 delab let B ← withNaryArg 5 delab `($A ⟹ $B) diff --git a/Mathlib/CategoryTheory/ComposableArrows.lean b/Mathlib/CategoryTheory/ComposableArrows.lean index 19e67ac6f013c..9602eeec93ab6 100644 --- a/Mathlib/CategoryTheory/ComposableArrows.lean +++ b/Mathlib/CategoryTheory/ComposableArrows.lean @@ -7,7 +7,7 @@ import Mathlib.CategoryTheory.Category.Preorder import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Functor.Const import Mathlib.Tactic.FinCases -import Mathlib.Tactic.Linarith +import Std.Tactic.Omega /-! # Composable arrows @@ -52,23 +52,27 @@ namespace ComposableArrows variable {C} {n m : ℕ} variable (F G : ComposableArrows C n) +/-- A wrapper for `omega` which prefaces it with some quick and useful attempts -/ +macro "valid" : tactic => + `(tactic| first | assumption | apply zero_le | apply le_rfl | transitivity <;> assumption | omega) + /-- The `i`th object (with `i : ℕ` such that `i ≤ n`) of `F : ComposableArrows C n`. -/ @[simp] -abbrev obj' (i : ℕ) (hi : i ≤ n := by linarith) : C := F.obj ⟨i, by linarith⟩ +abbrev obj' (i : ℕ) (hi : i ≤ n := by valid) : C := F.obj ⟨i, by omega⟩ /-- The map `F.obj' i ⟶ F.obj' j` when `F : ComposableArrows C n`, and `i` and `j` are natural numbers such that `i ≤ j ≤ n`. -/ @[simp] -abbrev map' (i j : ℕ) (hij : i ≤ j := by linarith) (hjn : j ≤ n := by linarith) : - F.obj ⟨i, by linarith⟩ ⟶ F.obj ⟨j, by linarith⟩ := F.map (homOfLE (by +abbrev map' (i j : ℕ) (hij : i ≤ j := by valid) (hjn : j ≤ n := by valid) : + F.obj ⟨i, by omega⟩ ⟶ F.obj ⟨j, by omega⟩ := F.map (homOfLE (by simp only [Fin.mk_le_mk] - linarith)) + valid)) -lemma map'_self (i : ℕ) (hi : i ≤ n := by linarith) : +lemma map'_self (i : ℕ) (hi : i ≤ n := by valid) : F.map' i i = 𝟙 _ := F.map_id _ -lemma map'_comp (i j k : ℕ) (hij : i ≤ j := by linarith) - (hjk : j ≤ k := by linarith) (hk : k ≤ n := by linarith) : +lemma map'_comp (i j k : ℕ) (hij : i ≤ j := by valid) + (hjk : j ≤ k := by valid) (hk : k ≤ n := by valid) : F.map' i k = F.map' i j ≫ F.map' j k := F.map_comp _ _ @@ -86,12 +90,12 @@ variable {F G} /-- The map `F.obj' i ⟶ G.obj' i` induced on `i`th objects by a morphism `F ⟶ G` in `ComposableArrows C n` when `i` is a natural number such that `i ≤ n`. -/ @[simp] -abbrev app' (φ : F ⟶ G) (i : ℕ) (hi : i ≤ n := by linarith) : +abbrev app' (φ : F ⟶ G) (i : ℕ) (hi : i ≤ n := by valid) : F.obj' i ⟶ G.obj' i := φ.app _ @[reassoc] -lemma naturality' (φ : F ⟶ G) (i j : ℕ) (hij : i ≤ j := by linarith) - (hj : j ≤ n := by linarith) : +lemma naturality' (φ : F ⟶ G) (i j : ℕ) (hij : i ≤ j := by valid) + (hj : j ≤ n := by valid) : F.map' i j ≫ app' φ j = app' φ i ≫ G.map' i j := φ.naturality _ @@ -162,7 +166,7 @@ def homMk {F G : ComposableArrows C n} (app : ∀ i, F.obj i ⟶ G.obj i) have hij' := leOfHom hij simp only [Fin.mk_le_mk] at hij' obtain ⟨k, hk⟩ := Nat.le.dest hij' - exact this k i j hk (by linarith) + exact this k i j hk (by valid) intro k induction' k with k hk · intro i j hj hj' @@ -173,7 +177,7 @@ def homMk {F G : ComposableArrows C n} (app : ∀ i, F.obj i ⟶ G.obj i) rw [Nat.succ_eq_add_one, ← add_assoc] at hj subst hj rw [F.map'_comp i (i + k) (i + k + 1), G.map'_comp i (i + k) (i + k + 1), assoc, - w (i + k) (by linarith), reassoc_of% (hk i (i + k) rfl (by linarith))] + w (i + k) (by valid), reassoc_of% (hk i (i + k) rfl (by valid))] /-- Constructor for isomorphisms `F ≅ G` in `ComposableArrows C n` which takes as inputs a family of isomorphisms `F.obj i ≅ G.obj i` and the naturality condition only for the @@ -495,7 +499,7 @@ lemma hom_ext_succ {F G : ComposableArrows C (n + 1)} {f g : F ⟶ G} obtain _ | i := i · exact h₀ · rw [Nat.succ_eq_add_one] at hi - exact congr_app h₁ ⟨i, by linarith⟩ + exact congr_app h₁ ⟨i, by valid⟩ /-- Inductive construction of isomorphisms in `ComposableArrows C (n + 1)`: in order to construct an isomorphism `F ≅ G`, it suffices to provide `α : F.obj' 0 ≅ G.obj' 0` and @@ -527,7 +531,7 @@ lemma ext_succ {F G : ComposableArrows C (n + 1)} (h₀ : F.obj' 0 = G.obj' 0) cases' i with i · exact h₀ · rw [Nat.succ_eq_add_one] at hi - exact Functor.congr_obj h ⟨i, by linarith⟩ + exact Functor.congr_obj h ⟨i, by valid⟩ exact Functor.ext_of_iso (isoMkSucc (eqToIso h₀) (eqToIso h) (by rw [w] dsimp [app'] @@ -562,7 +566,7 @@ lemma homMk₂_app_zero : (homMk₂ app₀ app₁ app₂ w₀ w₁).app 0 = app lemma homMk₂_app_one : (homMk₂ app₀ app₁ app₂ w₀ w₁).app 1 = app₁ := rfl @[simp] -lemma homMk₂_app_two : (homMk₂ app₀ app₁ app₂ w₀ w₁).app ⟨2, by linarith⟩ = app₂ := rfl +lemma homMk₂_app_two : (homMk₂ app₀ app₁ app₂ w₀ w₁).app ⟨2, by valid⟩ = app₂ := rfl end @@ -615,10 +619,12 @@ lemma homMk₃_app_zero : (homMk₃ app₀ app₁ app₂ app₃ w₀ w₁ w₂). lemma homMk₃_app_one : (homMk₃ app₀ app₁ app₂ app₃ w₀ w₁ w₂).app 1 = app₁ := rfl @[simp] -lemma homMk₃_app_two : (homMk₃ app₀ app₁ app₂ app₃ w₀ w₁ w₂).app ⟨2, by linarith⟩ = app₂ := rfl +lemma homMk₃_app_two : (homMk₃ app₀ app₁ app₂ app₃ w₀ w₁ w₂).app ⟨2, by valid⟩ = app₂ := + rfl @[simp] -lemma homMk₃_app_three : (homMk₃ app₀ app₁ app₂ app₃ w₀ w₁ w₂).app ⟨3, by linarith⟩ = app₃ := rfl +lemma homMk₃_app_three : (homMk₃ app₀ app₁ app₂ app₃ w₀ w₁ w₂).app ⟨3, by valid⟩ = app₃ := + rfl end @@ -681,15 +687,15 @@ lemma homMk₄_app_one : (homMk₄ app₀ app₁ app₂ app₃ app₄ w₀ w₁ @[simp] lemma homMk₄_app_two : - (homMk₄ app₀ app₁ app₂ app₃ app₄ w₀ w₁ w₂ w₃).app ⟨2, by linarith⟩ = app₂ := rfl + (homMk₄ app₀ app₁ app₂ app₃ app₄ w₀ w₁ w₂ w₃).app ⟨2, by valid⟩ = app₂ := rfl @[simp] lemma homMk₄_app_three : - (homMk₄ app₀ app₁ app₂ app₃ app₄ w₀ w₁ w₂ w₃).app ⟨3, by linarith⟩ = app₃ := rfl + (homMk₄ app₀ app₁ app₂ app₃ app₄ w₀ w₁ w₂ w₃).app ⟨3, by valid⟩ = app₃ := rfl @[simp] lemma homMk₄_app_four : - (homMk₄ app₀ app₁ app₂ app₃ app₄ w₀ w₁ w₂ w₃).app ⟨4, by linarith⟩ = app₄ := rfl + (homMk₄ app₀ app₁ app₂ app₃ app₄ w₀ w₁ w₂ w₃).app ⟨4, by valid⟩ = app₄ := rfl end @@ -700,6 +706,12 @@ lemma hom_ext₄ {f g : ComposableArrows C 4} {φ φ' : f ⟶ g} φ = φ' := hom_ext_succ h₀ (hom_ext₃ h₁ h₂ h₃ h₄) +lemma map'_inv_eq_inv_map' {n m : ℕ} (h : n+1 ≤ m) {f g : ComposableArrows C m} + (app : f.obj' n ≅ g.obj' n) (app' : f.obj' (n+1) ≅ g.obj' (n+1)) + (w : f.map' n (n+1) ≫ app'.hom = app.hom ≫ g.map' n (n+1)) : + map' g n (n+1) ≫ app'.inv = app.inv ≫ map' f n (n+1) := by + rw [← cancel_epi app.hom, ← reassoc_of% w, app'.hom_inv_id, comp_id, app.hom_inv_id_assoc] + /-- Constructor for isomorphisms in `ComposableArrows C 4`. -/ @[simps] def isoMk₄ {f g : ComposableArrows C 4} @@ -712,14 +724,10 @@ def isoMk₄ {f g : ComposableArrows C 4} f ≅ g where hom := homMk₄ app₀.hom app₁.hom app₂.hom app₃.hom app₄.hom w₀ w₁ w₂ w₃ inv := homMk₄ app₀.inv app₁.inv app₂.inv app₃.inv app₄.inv - (by rw [← cancel_epi app₀.hom, ← reassoc_of% w₀, app₁.hom_inv_id, - comp_id, app₀.hom_inv_id_assoc]) - (by rw [← cancel_epi app₁.hom, ← reassoc_of% w₁, app₂.hom_inv_id, - comp_id, app₁.hom_inv_id_assoc]) - (by rw [← cancel_epi app₂.hom, ← reassoc_of% w₂, app₃.hom_inv_id, - comp_id, app₂.hom_inv_id_assoc]) - (by rw [← cancel_epi app₃.hom, ← reassoc_of% w₃, app₄.hom_inv_id, - comp_id, app₃.hom_inv_id_assoc]) + (by rw [map'_inv_eq_inv_map' (by valid) app₀ app₁ w₀]) + (by rw [map'_inv_eq_inv_map' (by valid) app₁ app₂ w₁]) + (by rw [map'_inv_eq_inv_map' (by valid) app₂ app₃ w₂]) + (by rw [map'_inv_eq_inv_map' (by valid) app₃ app₄ w₃]) lemma ext₄ {f g : ComposableArrows C 4} (h₀ : f.obj' 0 = g.obj' 0) (h₁ : f.obj' 1 = g.obj' 1) (h₂ : f.obj' 2 = g.obj' 2) @@ -760,19 +768,19 @@ lemma homMk₅_app_one : (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w @[simp] lemma homMk₅_app_two : - (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w₀ w₁ w₂ w₃ w₄).app ⟨2, by linarith⟩ = app₂ := rfl + (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w₀ w₁ w₂ w₃ w₄).app ⟨2, by valid⟩ = app₂ := rfl @[simp] lemma homMk₅_app_three : - (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w₀ w₁ w₂ w₃ w₄).app ⟨3, by linarith⟩ = app₃ := rfl + (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w₀ w₁ w₂ w₃ w₄).app ⟨3, by valid⟩ = app₃ := rfl @[simp] lemma homMk₅_app_four : - (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w₀ w₁ w₂ w₃ w₄).app ⟨4, by linarith⟩ = app₄ := rfl + (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w₀ w₁ w₂ w₃ w₄).app ⟨4, by valid⟩ = app₄ := rfl @[simp] lemma homMk₅_app_five : - (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w₀ w₁ w₂ w₃ w₄).app ⟨5, by linarith⟩ = app₅ := rfl + (homMk₅ app₀ app₁ app₂ app₃ app₄ app₅ w₀ w₁ w₂ w₃ w₄).app ⟨5, by valid⟩ = app₅ := rfl end @@ -783,7 +791,6 @@ lemma hom_ext₅ {f g : ComposableArrows C 5} {φ φ' : f ⟶ g} φ = φ' := hom_ext_succ h₀ (hom_ext₄ h₁ h₂ h₃ h₄ h₅) -set_option maxHeartbeats 400000 in /-- Constructor for isomorphisms in `ComposableArrows C 5`. -/ @[simps] def isoMk₅ {f g : ComposableArrows C 5} @@ -797,16 +804,11 @@ def isoMk₅ {f g : ComposableArrows C 5} f ≅ g where hom := homMk₅ app₀.hom app₁.hom app₂.hom app₃.hom app₄.hom app₅.hom w₀ w₁ w₂ w₃ w₄ inv := homMk₅ app₀.inv app₁.inv app₂.inv app₃.inv app₄.inv app₅.inv - (by rw [← cancel_epi app₀.hom, ← reassoc_of% w₀, app₁.hom_inv_id, - comp_id, app₀.hom_inv_id_assoc]) - (by rw [← cancel_epi app₁.hom, ← reassoc_of% w₁, app₂.hom_inv_id, - comp_id, app₁.hom_inv_id_assoc]) - (by rw [← cancel_epi app₂.hom, ← reassoc_of% w₂, app₃.hom_inv_id, - comp_id, app₂.hom_inv_id_assoc]) - (by rw [← cancel_epi app₃.hom, ← reassoc_of% w₃, app₄.hom_inv_id, - comp_id, app₃.hom_inv_id_assoc]) - (by rw [← cancel_epi app₄.hom, ← reassoc_of% w₄, app₅.hom_inv_id, - comp_id, app₄.hom_inv_id_assoc]) + (by rw [map'_inv_eq_inv_map' (by valid) app₀ app₁ w₀]) + (by rw [map'_inv_eq_inv_map' (by valid) app₁ app₂ w₁]) + (by rw [map'_inv_eq_inv_map' (by valid) app₂ app₃ w₂]) + (by rw [map'_inv_eq_inv_map' (by valid) app₃ app₄ w₃]) + (by rw [map'_inv_eq_inv_map' (by valid) app₄ app₅ w₄]) lemma ext₅ {f g : ComposableArrows C 5} (h₀ : f.obj' 0 = g.obj' 0) (h₁ : f.obj' 1 = g.obj' 1) (h₂ : f.obj' 2 = g.obj' 2) @@ -826,7 +828,7 @@ lemma mk₅_surjective (X : ComposableArrows C 5) : ext₅ rfl rfl rfl rfl rfl rfl (by simp) (by simp) (by simp) (by simp) (by simp)⟩ /-- The `i`th arrow of `F : ComposableArrows C n`. -/ -def arrow (i : ℕ) (hi : i < n := by linarith) : +def arrow (i : ℕ) (hi : i < n := by valid) : ComposableArrows C 1 := mk₁ (F.map' i (i + 1)) section mkOfObjOfMapSucc @@ -850,7 +852,7 @@ lemma mkOfObjOfMapSucc_exists : ∃ (F : ComposableArrows C n) (e : ∀ i, F.obj · dsimp rw [assoc, Iso.inv_hom_id, comp_id] erw [id_comp] - · exact h i (by linarith) + · exact h i (by valid) /-- Given `obj : Fin (n + 1) → C` and `mapSucc i : obj i.castSucc ⟶ obj i.succ` for all `i : Fin n`, this is `F : ComposableArrows C n` such that `F.obj i` is @@ -863,11 +865,11 @@ noncomputable def mkOfObjOfMapSucc : ComposableArrows C n := lemma mkOfObjOfMapSucc_obj (i : Fin (n + 1)) : (mkOfObjOfMapSucc obj mapSucc).obj i = obj i := rfl -lemma mkOfObjOfMapSucc_map_succ (i : ℕ) (hi : i < n := by linarith) : +lemma mkOfObjOfMapSucc_map_succ (i : ℕ) (hi : i < n := by valid) : (mkOfObjOfMapSucc obj mapSucc).map' i (i + 1) = mapSucc ⟨i, hi⟩ := ((mkOfObjOfMapSucc_exists obj mapSucc).choose_spec.choose_spec i hi).symm -lemma mkOfObjOfMapSucc_arrow (i : ℕ) (hi : i < n := by linarith) : +lemma mkOfObjOfMapSucc_arrow (i : ℕ) (hi : i < n := by valid) : (mkOfObjOfMapSucc obj mapSucc).arrow i = mk₁ (mapSucc ⟨i, hi⟩) := ext₁ rfl rfl (by simpa using mkOfObjOfMapSucc_map_succ obj mapSucc i hi) diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index 19883fe435036..19ba3f2c257cd 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -98,10 +98,10 @@ variable {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] #noalign category_theory.forget_obj_eq_coe @[reducible] -def ConcreteCategory.funLike {X Y : C} : FunLike (X ⟶ Y) X (fun _ => Y) where +def ConcreteCategory.instFunLike {X Y : C} : FunLike (X ⟶ Y) X Y where coe f := (forget C).map f coe_injective' _ _ h := (forget C).map_injective h -attribute [local instance] ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.instFunLike /-- In any concrete category, we can test equality of morphisms by pointwise evaluations.-/ @[ext low] -- Porting note: lowered priority @@ -212,7 +212,7 @@ def forget₂ (C : Type u) (D : Type u') [Category.{v} C] [ConcreteCategory.{w} HasForget₂.forget₂ #align category_theory.forget₂ CategoryTheory.forget₂ -attribute [local instance] ConcreteCategory.funLike ConcreteCategory.hasCoeToSort +attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort lemma forget₂_comp_apply {C : Type u} {D : Type u'} [Category.{v} C] [ConcreteCategory.{w} C] [Category.{v'} D] [ConcreteCategory.{w} D] [HasForget₂ C D] {X Y Z : C} diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean b/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean index 9319142866b45..ec706208b68ed 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Johannes Hölzl, Reid Barton, Sean Leather -/ -import Std.Tactic.Lint.Frontend import Std.Tactic.Lint.Misc import Std.Tactic.CoeExt import Mathlib.Mathport.Rename diff --git a/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean b/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean index a803a38428174..a006753291470 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean @@ -86,7 +86,7 @@ instance concreteCategory : ConcreteCategory.{u} (Bundled c) variable {hom} -attribute [local instance] ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.instFunLike /-- A version of `HasForget₂.mk'` for categories defined using `@BundledHom`. -/ def mkHasForget₂ {d : Type u → Type u} {hom_d : ∀ ⦃α β : Type u⦄ (_ : d α) (_ : d β), Type u} diff --git a/Mathlib/CategoryTheory/Countable.lean b/Mathlib/CategoryTheory/Countable.lean new file mode 100644 index 0000000000000..cc9b78e056777 --- /dev/null +++ b/Mathlib/CategoryTheory/Countable.lean @@ -0,0 +1,96 @@ +/- +Copyright (c) 2023 Dagur Asgeirsson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Dagur Asgeirsson +-/ +import Mathlib.Data.Countable.Small +import Mathlib.CategoryTheory.EssentiallySmall +import Mathlib.CategoryTheory.FinCategory +/-! +# Countable categories + +A category is countable in this sense if it has countably many objects and countably many morphisms. + +-/ + +universe w v u + +open Classical + +noncomputable section + +namespace CategoryTheory + +instance discreteCountable {α : Type*} [Countable α] : Countable (Discrete α) := + Countable.of_equiv α discreteEquiv.symm + +/-- A category with countably many objects and morphisms. -/ +class CountableCategory (J : Type*) [Category J] : Prop where + countableObj : Countable J := by infer_instance + countableHom : ∀ j j' : J, Countable (j ⟶ j') := by infer_instance + +attribute [instance] CountableCategory.countableObj CountableCategory.countableHom + +instance countablerCategoryDiscreteOfCountable (J : Type*) [Countable J] : + CountableCategory (Discrete J) where + +namespace CountableCategory + +variable (α : Type u) [Category.{v} α] [CountableCategory α] + +/-- A countable category `α` is equivalent to a category with objects in `Type`. -/ +abbrev ObjAsType : Type := + InducedCategory α (equivShrink.{0} α).symm + +instance : Countable (ObjAsType α) := Countable.of_equiv α (equivShrink.{0} α) + +instance {i j : ObjAsType α} : Countable (i ⟶ j) := + CountableCategory.countableHom ((equivShrink.{0} α).symm i) _ + +instance : CountableCategory (ObjAsType α) where + +/-- The constructed category is indeed equivalent to `α`. -/ +noncomputable def objAsTypeEquiv : ObjAsType α ≌ α := + (inducedFunctor (equivShrink.{0} α).symm).asEquivalence + +/-- A countable category `α` is equivalent to a *small* category with objects in `Type`. -/ +def HomAsType := ShrinkHoms (ObjAsType α) + +instance : LocallySmall.{0} (ObjAsType α) where + hom_small _ _ := inferInstance + +instance : SmallCategory (HomAsType α) := ShrinkHoms.instCategoryShrinkHoms.{0} _ + +instance : Countable (HomAsType α) := Countable.of_equiv α (equivShrink.{0} α) + +instance {i j : HomAsType α} : Countable (i ⟶ j) := + Countable.of_equiv ((ShrinkHoms.equivalence _).inverse.obj i ⟶ + (ShrinkHoms.equivalence _).inverse.obj j) (equivOfFullyFaithful _).symm + +instance : CountableCategory (HomAsType α) where + +/-- The constructed category is indeed equivalent to `α`. -/ +noncomputable def homAsTypeEquiv : HomAsType α ≌ α := + (ShrinkHoms.equivalence _).symm.trans (objAsTypeEquiv _) + +end CountableCategory + +instance (α : Type*) [Category α] [FinCategory α] : CountableCategory α where + +open Opposite + +/-- The opposite of a countable category is countable. -/ +instance countableCategoryOpposite {J : Type*} [Category J] [CountableCategory J] : + CountableCategory Jᵒᵖ where + countableObj := Countable.of_equiv _ equivToOpposite + countableHom j j' := Countable.of_equiv _ (opEquiv j j').symm + +/-- Applying `ULift` to morphisms and objects of a category preserves countability. -/ +instance countableCategoryUlift {J : Type v} [Category J] [CountableCategory J] : + CountableCategory.{max w v} (ULiftHom.{w, max w v} (ULift.{w, v} J)) where + countableObj := instCountableULift + countableHom := fun i j => + have : Countable ((ULiftHom.objDown i).down ⟶ (ULiftHom.objDown j).down) := inferInstance + instCountableULift + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/DifferentialObject.lean b/Mathlib/CategoryTheory/DifferentialObject.lean index 1e2da407c290b..2d94c912e7b31 100644 --- a/Mathlib/CategoryTheory/DifferentialObject.lean +++ b/Mathlib/CategoryTheory/DifferentialObject.lean @@ -3,7 +3,8 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.Data.Int.Basic +import Mathlib.Algebra.Group.Basic +import Mathlib.Data.Int.Cast.Defs import Mathlib.CategoryTheory.Shift.Basic import Mathlib.CategoryTheory.ConcreteCategory.Basic diff --git a/Mathlib/CategoryTheory/Endomorphism.lean b/Mathlib/CategoryTheory/Endomorphism.lean index fb1b90f8dbc23..5a1f8748cf251 100644 --- a/Mathlib/CategoryTheory/Endomorphism.lean +++ b/Mathlib/CategoryTheory/Endomorphism.lean @@ -200,6 +200,20 @@ def mapAut : Aut X →* Aut (f.obj X) where set_option linter.uppercaseLean3 false in #align category_theory.functor.map_Aut CategoryTheory.Functor.mapAut +/-- `equivOfFullyFaithful f` as an isomorphism between endomorphism monoids. -/ +@[simps!] +def mulEquivOfFullyFaithful [Full f] [Faithful f] : + End X ≃* End (f.obj X) where + toEquiv := equivOfFullyFaithful f + __ := mapEnd X f + +/-- `isoEquivOfFullyFaithful f` as an isomorphism between automorphism groups. -/ +@[simps!] +def autMulEquivOfFullyFaithful [Full f] [Faithful f] : + Aut X ≃* Aut (f.obj X) where + toEquiv := isoEquivOfFullyFaithful f + __ := mapAut X f + end Functor end CategoryTheory diff --git a/Mathlib/CategoryTheory/EqToHom.lean b/Mathlib/CategoryTheory/EqToHom.lean index 30258f19525ea..cdd6df33260d7 100644 --- a/Mathlib/CategoryTheory/EqToHom.lean +++ b/Mathlib/CategoryTheory/EqToHom.lean @@ -107,7 +107,7 @@ theorem congrArg_cast_hom_left {X Y Z : C} (p : X = Y) (q : Y ⟶ Z) : cases p simp - /-- If we (perhaps unintentionally) perform equational rewriting on +/-- If we (perhaps unintentionally) perform equational rewriting on the source object of a morphism, we can replace the resulting `_.mpr f` term by a composition with an `eqToHom`. diff --git a/Mathlib/CategoryTheory/Extensive.lean b/Mathlib/CategoryTheory/Extensive.lean index 33c247bf42898..28cbd17e8e31f 100644 --- a/Mathlib/CategoryTheory/Extensive.lean +++ b/Mathlib/CategoryTheory/Extensive.lean @@ -434,7 +434,7 @@ theorem finitaryExtensive_of_reflective · rintro ⟨⟨⟩⟩ ⟨j⟩ ⟨⟨rfl : _ = j⟩⟩ <;> simp rw [this] rintro Z ⟨_|_⟩ f <;> dsimp <;> infer_instance - refine ((FinitaryExtensive.vanKampen _ (colimit.isColimit $ pair X Y ⋙ _)).map_reflective + refine ((FinitaryExtensive.vanKampen _ (colimit.isColimit <| pair X Y ⋙ _)).map_reflective adj).of_iso (IsColimit.uniqueUpToIso ?_ ?_) · exact isColimitOfPreserves Gl (colimit.isColimit _) · exact (IsColimit.precomposeHomEquiv _ _).symm hc diff --git a/Mathlib/CategoryTheory/FintypeCat.lean b/Mathlib/CategoryTheory/FintypeCat.lean index cb106985af5a9..b74655ecc2259 100644 --- a/Mathlib/CategoryTheory/FintypeCat.lean +++ b/Mathlib/CategoryTheory/FintypeCat.lean @@ -6,7 +6,6 @@ Authors: Bhavik Mehta, Adam Topaz import Mathlib.CategoryTheory.ConcreteCategory.Basic import Mathlib.CategoryTheory.FullSubcategory import Mathlib.CategoryTheory.Skeletal -import Mathlib.CategoryTheory.Elementwise import Mathlib.Data.Fintype.Card #align_import category_theory.Fintype from "leanprover-community/mathlib"@"c3019c79074b0619edb4b27553a91b2e82242395" diff --git a/Mathlib/CategoryTheory/Functor/Currying.lean b/Mathlib/CategoryTheory/Functor/Currying.lean index 4ab1dafdfb27f..04cc7a8eadac7 100644 --- a/Mathlib/CategoryTheory/Functor/Currying.lean +++ b/Mathlib/CategoryTheory/Functor/Currying.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.CategoryTheory.Products.Bifunctor +import Mathlib.CategoryTheory.Products.Basic #align_import category_theory.functor.currying from "leanprover-community/mathlib"@"369525b73f229ccd76a6ec0e0e0bf2be57599768" diff --git a/Mathlib/CategoryTheory/Galois/Basic.lean b/Mathlib/CategoryTheory/Galois/Basic.lean new file mode 100644 index 0000000000000..d6e8e86725480 --- /dev/null +++ b/Mathlib/CategoryTheory/Galois/Basic.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2024 Christian Merten. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Merten +-/ +import Mathlib.CategoryTheory.FintypeCat +import Mathlib.CategoryTheory.Limits.Constructions.LimitsOfProductsAndEqualizers +import Mathlib.CategoryTheory.SingleObj + +/-! +# Definition and basic properties of Galois categories + +We define the notion of a Galois category and a fibre functor as in SGA1, following +the definitions in Lenstras notes (see below for a reference). + +## Main definitions + +* `PreGaloisCategory` : defining properties of Galois categories not involving a fibre functor +* `FibreFunctor` : a fibre functor from a PreGaloisCategory to `FintypeCat` +* `ConnectedObject` : an object of a category that is not initial and has no non-trivial + subobjects + +## Implementation details + +We mostly follow Def 3.1 in Lenstras notes. In axiom (G3) +we omit the factorisation of morphisms in epimorphisms and monomorphisms +as this is not needed for the proof of the fundamental theorem on Galois categories +(and then follows from it). + +## References + +* H. W. Lenstra. Galois theory for schemes + + +-/ + +universe u₁ u₂ v₁ v₂ w + +namespace CategoryTheory + +open Limits Functor + +/-! +A category `C` is a PreGalois category if it satisfies all properties +of a Galois category in the sense of SGA1 that do not involve a fibre functor. +A Galois category should furthermore admit a fibre functor. + +We do not provide a typeclass `GaloisCategory`; users should +assume `[PreGaloisCategory C] (F : C ⥤ FintypeCat) [FibreFunctor F]` instead. +-/ + +/-- Definition of a (Pre)Galois category. Lenstra, Def 3.1, (G1)-(G3) -/ +class PreGaloisCategory (C : Type u₁) [Category.{u₂, u₁} C] : Prop where + /-- `C` has a terminal object (G1). -/ + hasTerminal : HasTerminal C := by infer_instance + /-- `C` has pullbacks (G1). -/ + hasPullbacks : HasPullbacks C := by infer_instance + /-- `C` has finite coproducts (G2). -/ + hasFiniteCoproducts : HasFiniteCoproducts C := by infer_instance + /-- `C` has quotients by finite groups (G2). -/ + hasQuotientsByFiniteGroups (G : Type u₂) [Group G] [Finite G] : + HasColimitsOfShape (SingleObj G) C := by infer_instance + /-- Every monomorphism in `C` induces an isomorphism on a direct summand (G3). -/ + monoInducesIsoOnDirectSummand {X Y : C} (i : X ⟶ Y) [Mono i] : ∃ (Z : C) (u : Z ⟶ Y), + Nonempty (IsColimit (BinaryCofan.mk i u)) + +namespace PreGaloisCategory + +/-- Definition of a fibre functor from a Galois category. Lenstra, Def 3.1, (G4)-(G6) -/ +class FibreFunctor {C : Type u₁} [Category.{u₂, u₁} C] [PreGaloisCategory C] + (F : C ⥤ FintypeCat.{w}) where + /-- `F` preserves terminal objects (G4). -/ + preservesTerminalObjects : PreservesLimitsOfShape (CategoryTheory.Discrete PEmpty.{1}) F := + by infer_instance + /-- `F` preserves pullbacks (G4). -/ + preservesPullbacks : PreservesLimitsOfShape WalkingCospan F := by infer_instance + /-- `F` preserves finite coproducts (G5). -/ + preservesFiniteCoproducts : PreservesFiniteCoproducts F := by infer_instance + /-- `F` preserves epimorphisms (G5). -/ + preservesEpis : Functor.PreservesEpimorphisms F := by infer_instance + /-- `F` preserves quotients by finite groups (G5). -/ + preservesQuotientsByFiniteGroups (G : Type u₂) [Group G] [Finite G] : + PreservesColimitsOfShape (SingleObj G) F := by infer_instance + /-- `F` reflects isomorphisms (G6). -/ + reflectsIsos : ReflectsIsomorphisms F := by infer_instance + +/-- An object of a category `C` is connected if it is not initial +and has no non-trivial subobjects. Lenstra, 3.12. -/ +class ConnectedObject {C : Type u₁} [Category.{u₂, u₁} C] (X : C) : Prop where + /-- `X` is not an initial object. -/ + notInitial : IsInitial X → False + /-- `X` has no non-trivial subobjects. -/ + noTrivialComponent (Y : C) (i : Y ⟶ X) [Mono i] : (IsInitial Y → False) → IsIso i + +/-- A functor is said to preserve connected objects if it sends +connected objects to connected objects. -/ +class PreservesConnectedObjects {C : Type u₁} [Category.{u₂, u₁} C] {D : Type v₁} + [Category.{v₂, v₁} D] (F : C ⥤ D) : Prop where + /-- `F.obj X` is connected if `X` is connected. -/ + preserves : ∀ {X : C} [ConnectedObject X], ConnectedObject (F.obj X) + +variable {C : Type u₁} [Category.{u₂, u₁} C] [PreGaloisCategory C] + +attribute [instance] hasTerminal hasPullbacks hasFiniteCoproducts hasQuotientsByFiniteGroups + +instance : HasFiniteLimits C := hasFiniteLimits_of_hasTerminal_and_pullbacks + +instance : HasBinaryProducts C := hasBinaryProducts_of_hasTerminal_and_pullbacks C + +instance : HasEqualizers C := hasEqualizers_of_hasPullbacks_and_binary_products + +namespace FibreFunctor + +variable {C : Type u₁} [Category.{u₂, u₁} C] {F : C ⥤ FintypeCat.{w}} [PreGaloisCategory C] + [FibreFunctor F] + +attribute [instance] preservesTerminalObjects preservesPullbacks preservesEpis + preservesFiniteCoproducts reflectsIsos preservesQuotientsByFiniteGroups + +noncomputable instance : ReflectsColimitsOfShape (Discrete PEmpty.{1}) F := + reflectsColimitsOfShapeOfReflectsIsomorphisms + +noncomputable instance : PreservesFiniteLimits F := + preservesFiniteLimitsOfPreservesTerminalAndPullbacks F + +end FibreFunctor + +end PreGaloisCategory + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/GradedObject.lean b/Mathlib/CategoryTheory/GradedObject.lean index f44ec540ced44..6476711ce44ec 100644 --- a/Mathlib/CategoryTheory/GradedObject.lean +++ b/Mathlib/CategoryTheory/GradedObject.lean @@ -3,10 +3,10 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Joël Riou -/ -import Mathlib.Algebra.GroupPower.Lemmas -import Mathlib.CategoryTheory.Pi.Basic -import Mathlib.CategoryTheory.Shift.Basic +import Mathlib.Algebra.GroupPower.Basic import Mathlib.CategoryTheory.ConcreteCategory.Basic +import Mathlib.CategoryTheory.Shift.Basic +import Mathlib.Data.Int.Basic #align_import category_theory.graded_object from "leanprover-community/mathlib"@"6876fa15e3158ff3e4a4e2af1fb6e1945c6e8803" @@ -150,7 +150,7 @@ theorem comapEq_trans {β γ : Type w} {f g h : β → γ} (k : f = g) (l : g = #align category_theory.graded_object.comap_eq_trans CategoryTheory.GradedObject.comapEq_trans @[simp] -theorem eqToHom_apply {β : Type w} {X Y : ∀ _ : β, C} (h : X = Y) (b : β) : +theorem eqToHom_apply {β : Type w} {X Y : β → C} (h : X = Y) (b : β) : (eqToHom h : X ⟶ Y) b = eqToHom (by rw [h]) := by subst h rfl diff --git a/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean b/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean index 05dc4e7e11a50..3de433bbd233e 100644 --- a/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean +++ b/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean @@ -181,13 +181,13 @@ noncomputable def mapTrifunctorMapFunctorObj (X₁ : GradedObject I₁ C₁) { obj := fun X₃ => mapTrifunctorMapObj F p X₁ X₂ X₃ map := fun {X₃ Y₃} φ => mapTrifunctorMapMap F p (𝟙 X₁) (𝟙 X₂) φ map_id := fun X₃ => by - ext j i₁ i₂ i₃ h dsimp + ext j i₁ i₂ i₃ h simp only [ι_mapTrifunctorMapMap, categoryOfGradedObjects_id, Functor.map_id, NatTrans.id_app, id_comp, comp_id] map_comp := fun {X₃ Y₃ Z₃} φ ψ => by - ext j i₁ i₂ i₃ h dsimp + ext j i₁ i₂ i₃ h simp only [ι_mapTrifunctorMapMap, categoryOfGradedObjects_id, Functor.map_id, NatTrans.id_app, categoryOfGradedObjects_comp, Functor.map_comp, assoc, id_comp, ι_mapTrifunctorMapMap_assoc] } @@ -199,13 +199,13 @@ noncomputable def mapTrifunctorMapFunctorObj (X₁ : GradedObject I₁ C₁) simp only [ι_mapTrifunctorMapMap_assoc, categoryOfGradedObjects_id, Functor.map_id, NatTrans.id_app, ι_mapTrifunctorMapMap, id_comp, NatTrans.naturality_assoc] } map_id X₂ := by - ext X₃ j i₁ i₂ i₃ h dsimp + ext X₃ j i₁ i₂ i₃ h simp only [ι_mapTrifunctorMapMap, categoryOfGradedObjects_id, Functor.map_id, NatTrans.id_app, id_comp, comp_id] map_comp {X₂ Y₂ Z₂} φ ψ := by - ext X₃ j i₁ i₂ i₃ dsimp + ext X₃ j i₁ i₂ i₃ simp only [ι_mapTrifunctorMapMap, categoryOfGradedObjects_id, Functor.map_id, NatTrans.id_app, categoryOfGradedObjects_comp, Functor.map_comp, NatTrans.comp_app, id_comp, assoc, ι_mapTrifunctorMapMap_assoc] diff --git a/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean b/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean index 214a7d4fe997f..2a48a1318a324 100644 --- a/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean +++ b/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean @@ -52,13 +52,13 @@ universe u v u' v' u'' v'' variable {V : Type u} [Quiver.{v + 1} V] -/-- Shorthand for the "forward" arrow corresponding to `f` in `paths $ symmetrify V` -/ +/-- Shorthand for the "forward" arrow corresponding to `f` in `paths <| symmetrify V` -/ abbrev _root_.Quiver.Hom.toPosPath {X Y : V} (f : X ⟶ Y) : (CategoryTheory.Paths.categoryPaths <| Quiver.Symmetrify V).Hom X Y := f.toPos.toPath #align category_theory.groupoid.free.quiver.hom.to_pos_path Quiver.Hom.toPosPath -/-- Shorthand for the "forward" arrow corresponding to `f` in `paths $ symmetrify V` -/ +/-- Shorthand for the "forward" arrow corresponding to `f` in `paths <| symmetrify V` -/ abbrev _root_.Quiver.Hom.toNegPath {X Y : V} (f : X ⟶ Y) : (CategoryTheory.Paths.categoryPaths <| Quiver.Symmetrify V).Hom Y X := f.toNeg.toPath diff --git a/Mathlib/CategoryTheory/Groupoid/VertexGroup.lean b/Mathlib/CategoryTheory/Groupoid/VertexGroup.lean index ffeda75bc2923..14c29c99cfc66 100644 --- a/Mathlib/CategoryTheory/Groupoid/VertexGroup.lean +++ b/Mathlib/CategoryTheory/Groupoid/VertexGroup.lean @@ -9,7 +9,6 @@ import Mathlib.Algebra.Group.Defs import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.Combinatorics.Quiver.Path -import Mathlib.Combinatorics.Quiver.ConnectedComponent #align_import category_theory.groupoid.vertex_group from "leanprover-community/mathlib"@"47b51515e69f59bca5cf34ef456e6000fe205a69" diff --git a/Mathlib/CategoryTheory/Limits/ConcreteCategory.lean b/Mathlib/CategoryTheory/Limits/ConcreteCategory.lean index 8ca0ebd62812c..fbe9e10c42e36 100644 --- a/Mathlib/CategoryTheory/Limits/ConcreteCategory.lean +++ b/Mathlib/CategoryTheory/Limits/ConcreteCategory.lean @@ -21,7 +21,7 @@ open CategoryTheory namespace CategoryTheory.Limits -attribute [local instance] ConcreteCategory.funLike ConcreteCategory.hasCoeToSort +attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort section Limits diff --git a/Mathlib/CategoryTheory/Limits/Creates.lean b/Mathlib/CategoryTheory/Limits/Creates.lean index 4f52d8b6508f0..4dd745550d6a4 100644 --- a/Mathlib/CategoryTheory/Limits/Creates.lean +++ b/Mathlib/CategoryTheory/Limits/Creates.lean @@ -339,6 +339,11 @@ def createsLimitOfFullyFaithfulOfIso {K : J ⥤ C} {F : C ⥤ D} [Full F] [Faith createsLimitOfFullyFaithfulOfIso' (limit.isLimit _) X i #align category_theory.creates_limit_of_fully_faithful_of_iso CategoryTheory.createsLimitOfFullyFaithfulOfIso +/-- A fully faithful functor that preserves a limit that exists also creates the limit. -/ +def createsLimitOfFullyFaithfulOfPreserves {K : J ⥤ C} {F : C ⥤ D} [Full F] [Faithful F] + [HasLimit K] [PreservesLimit K F] : CreatesLimit K F := + createsLimitOfFullyFaithfulOfLift' (PreservesLimit.preserves <| limit.isLimit K) _ (Iso.refl _) + -- see Note [lower instance priority] /-- `F` preserves the limit of `K` if it creates the limit and `K ⋙ F` has the limit. -/ instance (priority := 100) preservesLimitOfCreatesLimitAndHasLimit (K : J ⥤ C) (F : C ⥤ D) @@ -416,6 +421,12 @@ def createsColimitOfFullyFaithfulOfLift {K : J ⥤ C} {F : C ⥤ D} [Full F] [Fa createsColimitOfFullyFaithfulOfLift' (colimit.isColimit _) c i #align category_theory.creates_colimit_of_fully_faithful_of_lift CategoryTheory.createsColimitOfFullyFaithfulOfLift +/-- A fully faithful functor that preserves a colimit that exists also creates the colimit. -/ +def createsColimitOfFullyFaithfulOfPreserves {K : J ⥤ C} {F : C ⥤ D} [Full F] [Faithful F] + [HasColimit K] [PreservesColimit K F] : CreatesColimit K F := + createsColimitOfFullyFaithfulOfLift' (PreservesColimit.preserves <| colimit.isColimit K) _ + (Iso.refl _) + -- Notice however that even if the isomorphism is `Iso.refl _`, -- this construction will insert additional identity morphisms in the cocone maps, -- so the constructed colimits may not be ideal, definitionally. diff --git a/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean b/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean index b2ce3b5fe1f5d..6a37db586bca9 100644 --- a/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean +++ b/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean @@ -9,6 +9,7 @@ import Mathlib.CategoryTheory.Limits.Preserves.Finite import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits import Mathlib.CategoryTheory.Limits.Preserves.Filtered import Mathlib.CategoryTheory.ConcreteCategory.Basic +import Mathlib.CategoryTheory.Products.Bifunctor #align_import category_theory.limits.filtered_colimit_commutes_finite_limit from "leanprover-community/mathlib"@"3f409bd9df181d26dd223170da7b6830ece18442" @@ -222,14 +223,9 @@ theorem colimitLimitToLimitColimit_surjective : have kfO : ∀ {j j'} (f : j ⟶ j'), kf f ∈ O := fun {j} {j'} f => Finset.mem_union.mpr (Or.inl - (by - rw [Finset.mem_biUnion] - refine' ⟨j, Finset.mem_univ j, _⟩ - rw [Finset.mem_biUnion] - refine' ⟨j', Finset.mem_univ j', _⟩ - rw [Finset.mem_image] - refine' ⟨f, Finset.mem_univ _, _⟩ - rfl)) + (Finset.mem_biUnion.mpr ⟨j, Finset.mem_univ j, + Finset.mem_biUnion.mpr ⟨j', Finset.mem_univ j', + Finset.mem_image.mpr ⟨f, Finset.mem_univ _, rfl⟩⟩⟩)) have k'O : k' ∈ O := Finset.mem_union.mpr (Or.inr (Finset.mem_singleton.mpr rfl)) let H : Finset (Σ' (X Y : K) (_ : X ∈ O) (_ : Y ∈ O), X ⟶ Y) := Finset.univ.biUnion fun j : J => @@ -244,23 +240,25 @@ theorem colimitLimitToLimitColimit_surjective : intros j₁ j₂ j₃ j₄ f f' rw [s', s'] -- porting note: the three goals here in Lean 3 were in a different order - exact k'O - swap - · rw [Finset.mem_biUnion] - refine' ⟨j₁, Finset.mem_univ _, _⟩ - rw [Finset.mem_biUnion] - refine' ⟨j₂, Finset.mem_univ _, _⟩ - rw [Finset.mem_biUnion] - refine' ⟨f, Finset.mem_univ _, _⟩ - simp only [true_or_iff, eq_self_iff_true, and_self_iff, Finset.mem_insert, heq_iff_eq] - · rw [Finset.mem_biUnion] - refine' ⟨j₃, Finset.mem_univ _, _⟩ - rw [Finset.mem_biUnion] - refine' ⟨j₄, Finset.mem_univ _, _⟩ - rw [Finset.mem_biUnion] - refine' ⟨f', Finset.mem_univ _, _⟩ - simp only [eq_self_iff_true, or_true_iff, and_self_iff, Finset.mem_insert, - Finset.mem_singleton, heq_iff_eq] + · exact k'O + · exact Finset.mem_biUnion.mpr ⟨j₃, Finset.mem_univ _, + Finset.mem_biUnion.mpr ⟨j₄, Finset.mem_univ _, + Finset.mem_biUnion.mpr ⟨f', Finset.mem_univ _, by + -- This works by `simp`, but has very high variation in heartbeats. + rw [Finset.mem_insert, PSigma.mk.injEq, heq_eq_eq, PSigma.mk.injEq, heq_eq_eq, + PSigma.mk.injEq, heq_eq_eq, PSigma.mk.injEq, heq_eq_eq, eq_self, true_and, eq_self, + true_and, eq_self, true_and, eq_self, true_and, Finset.mem_singleton, eq_self, + or_true] + trivial⟩⟩⟩ + · exact Finset.mem_biUnion.mpr ⟨j₁, Finset.mem_univ _, + Finset.mem_biUnion.mpr ⟨j₂, Finset.mem_univ _, + Finset.mem_biUnion.mpr ⟨f, Finset.mem_univ _, by + -- This works by `simp`, but has very high variation in heartbeats. + rw [Finset.mem_insert, PSigma.mk.injEq, heq_eq_eq, PSigma.mk.injEq, heq_eq_eq, + PSigma.mk.injEq, heq_eq_eq, PSigma.mk.injEq, heq_eq_eq, eq_self, true_and, eq_self, + true_and, eq_self, true_and, eq_self, true_and, Finset.mem_singleton, eq_self, + true_or] + trivial⟩⟩⟩ clear_value i clear s' i' H kfO k'O O -- We're finally ready to construct the pre-image, and verify it really maps to `x`. @@ -306,7 +304,7 @@ theorem colimitLimitToLimitColimit_surjective : simp only [id.def, ← e, Limits.ι_colimitLimitToLimitColimit_π_apply, colimit_eq_iff.{v, v}, Bifunctor.map_id_comp, types_comp_apply, curry_obj_obj_map, Functor.comp_obj, colim_obj, Limit.π_mk] - refine' ⟨k'', 𝟙 k'', g j ≫ gf (𝟙 j) ≫ i (𝟙 j), _⟩ + refine ⟨k'', 𝟙 k'', g j ≫ gf (𝟙 j) ≫ i (𝟙 j), ?_⟩ -- porting note: the lean 3 proof finished with -- `simp only [Bifunctor.map_id_comp, types_comp_apply, Bifunctor.map_id, types_id_apply]` -- which doesn't work; the corresponding `rw` works fine: @@ -402,3 +400,8 @@ theorem ι_colimitLimitIso_limit_π (F : J ⥤ K ⥤ C) (a) (b) : end end CategoryTheory.Limits + +-- Various pieces of algebra that have previously been spuriously imported here: +assert_not_exists zero_zpow +assert_not_exists div_self +assert_not_exists Field diff --git a/Mathlib/CategoryTheory/Limits/FintypeCat.lean b/Mathlib/CategoryTheory/Limits/FintypeCat.lean index 59de83533f36b..46230405c95b0 100644 --- a/Mathlib/CategoryTheory/Limits/FintypeCat.lean +++ b/Mathlib/CategoryTheory/Limits/FintypeCat.lean @@ -8,7 +8,7 @@ import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits import Mathlib.CategoryTheory.Limits.Types import Mathlib.CategoryTheory.Limits.Creates import Mathlib.CategoryTheory.Limits.Preserves.Finite -import Mathlib.Data.FunLike.Fintype +import Mathlib.Data.Finite.Basic /-! # (Co)limits in the category of finite types diff --git a/Mathlib/CategoryTheory/Limits/Fubini.lean b/Mathlib/CategoryTheory/Limits/Fubini.lean index 6ef5cce2dfcb4..e40087b8a959a 100644 --- a/Mathlib/CategoryTheory/Limits/Fubini.lean +++ b/Mathlib/CategoryTheory/Limits/Fubini.lean @@ -6,6 +6,7 @@ Authors: Scott Morrison import Mathlib.CategoryTheory.Limits.HasLimits import Mathlib.CategoryTheory.Products.Basic import Mathlib.CategoryTheory.Functor.Currying +import Mathlib.CategoryTheory.Products.Bifunctor #align_import category_theory.limits.fubini from "leanprover-community/mathlib"@"59382264386afdbaf1727e617f5fdda511992eb9" diff --git a/Mathlib/CategoryTheory/Limits/HasLimits.lean b/Mathlib/CategoryTheory/Limits/HasLimits.lean index cfa27fa164d4f..66e09d0083c9c 100644 --- a/Mathlib/CategoryTheory/Limits/HasLimits.lean +++ b/Mathlib/CategoryTheory/Limits/HasLimits.lean @@ -6,6 +6,7 @@ Authors: Reid Barton, Mario Carneiro, Scott Morrison, Floris van Doorn import Mathlib.CategoryTheory.Limits.IsLimit import Mathlib.CategoryTheory.Category.ULift import Mathlib.CategoryTheory.EssentiallySmall +import Mathlib.Logic.Equiv.Basic #align_import category_theory.limits.has_limits from "leanprover-community/mathlib"@"2738d2ca56cbc63be80c3bd48e9ed90ad94e947d" diff --git a/Mathlib/CategoryTheory/Limits/Lattice.lean b/Mathlib/CategoryTheory/Limits/Lattice.lean index e41471ade32de..51d130501ac4d 100644 --- a/Mathlib/CategoryTheory/Limits/Lattice.lean +++ b/Mathlib/CategoryTheory/Limits/Lattice.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Justus Springer -/ import Mathlib.Order.CompleteLattice -import Mathlib.Data.Fintype.Lattice +import Mathlib.Data.Finset.Lattice import Mathlib.CategoryTheory.Limits.Shapes.Pullbacks import Mathlib.CategoryTheory.Category.Preorder import Mathlib.CategoryTheory.Limits.Shapes.Products diff --git a/Mathlib/CategoryTheory/Limits/Opposites.lean b/Mathlib/CategoryTheory/Limits/Opposites.lean index b147588969f4c..620470e8cfe94 100644 --- a/Mathlib/CategoryTheory/Limits/Opposites.lean +++ b/Mathlib/CategoryTheory/Limits/Opposites.lean @@ -468,8 +468,8 @@ theorem desc_op_comp_opCoproductIsoProduct_hom {X : C} (π : (a : α) → Z a (Sigma.desc π).op ≫ (opCoproductIsoProduct Z).hom = Pi.lift (fun a ↦ (π a).op) := by convert desc_op_comp_opCoproductIsoProduct'_hom (coproductIsCoproduct Z) (productIsProduct (op <| Z ·)) (Cofan.mk _ π) - · ext; simp [Sigma.desc, colimit.desc, coproductIsCoproduct] - · ext; simp [Pi.lift, limit.lift, productIsProduct] + · ext; simp [Sigma.desc, coproductIsCoproduct] + · ext; simp [Pi.lift, productIsProduct] end OppositeCoproducts @@ -542,8 +542,8 @@ theorem opProductIsoCoproduct_inv_comp_lift {X : C} (π : (a : α) → X ⟶ Z a (opProductIsoCoproduct Z).inv ≫ (Pi.lift π).op = Sigma.desc (fun a ↦ (π a).op) := by convert opProductIsoCoproduct'_inv_comp_lift (productIsProduct Z) (coproductIsCoproduct (op <| Z ·)) (Fan.mk _ π) - · ext; simp [Pi.lift, limit.lift, productIsProduct] - · ext; simp [Sigma.desc, colimit.desc, coproductIsCoproduct] + · ext; simp [Pi.lift, productIsProduct] + · ext; simp [Sigma.desc, coproductIsCoproduct] end OppositeProducts diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean b/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean index 79a179131cb3b..69dfe5000478d 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Dagur Asgeirsson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Dagur Asgeirsson +Authors: Dagur Asgeirsson, Junyan Xu -/ import Mathlib.CategoryTheory.Limits.Creates import Mathlib.CategoryTheory.Limits.Types @@ -10,100 +10,143 @@ import Mathlib.CategoryTheory.Limits.Types # `ULift` creates small (co)limits This file shows that `uliftFunctor.{v, u}` creates (and hence preserves) limits and colimits indexed -by `J` with `[Category.{u, u} J]`. +by `J` with `[Category.{w, u} J]`. -It also shows that `uliftFunctor.{v, u}` *preserves* "all" limits (i.e. of size `max u v`, +It also shows that `uliftFunctor.{v, u}` *preserves* "all" limits, potentially too big to exist in `Type u`). -/ -universe v u +universe v w w' u namespace CategoryTheory.Limits.Types -/-- -The equivalence between the ulift of the explicit limit cone of a functor `K` and the explicit limit -cone of `K ⋙ uliftFunctor`. --/ -def sectionsEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) : - uliftFunctor.{v, u}.obj (Functor.sections K) ≃ - (Functor.sections (K ⋙ uliftFunctor.{v, u})) where - toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩ - invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, fun f => by simp [← hu f]⟩ - left_inv _ := by apply ULift.ext; ext; rfl - right_inv _ := by ext; rfl - -/-- -The functor `uliftFunctor : Type u ⥤ Type (max u v)` creates `u`-small limits. --/ -noncomputable instance : CreatesLimitsOfSize.{u, u} uliftFunctor.{v, u} where - CreatesLimitsOfShape := { - CreatesLimit := fun {K} => - @createsLimitOfFullyFaithfulOfIso _ _ _ _ _ _ K uliftFunctor _ _ _ (limit K) - (uliftFunctor.{v, u}.mapIso (equivEquivIso (isLimitEquivSections.{u, u} - (limit.isLimit K))) ≪≫ (equivEquivIso (sectionsEquiv K)) ≪≫ - (equivEquivIso (isLimitEquivSections.{u, max u v} - (limit.isLimit (K ⋙ uliftFunctor.{v, u})))).symm) } - /-- The equivalence between `K.sections` and `(K ⋙ uliftFunctor.{v, u}).sections`. This is used to show -that `uliftFunctor` preserves limits that are too possibly too large to exist in the source +that `uliftFunctor` preserves limits that are potentially too large to exist in the source category. -/ -def sectionsEquiv' {J : Type*} [Category J] (K : J ⥤ Type u) : +def sectionsEquiv {J : Type*} [Category J] (K : J ⥤ Type u) : K.sections ≃ (K ⋙ uliftFunctor.{v, u}).sections where toFun := fun ⟨u, hu⟩ => ⟨fun j => ⟨u j⟩, fun f => by simp [hu f]⟩ invFun := fun ⟨u, hu⟩ => ⟨fun j => (u j).down, @fun j j' f => by simp [← hu f]⟩ - left_inv _ := by ext; rfl - right_inv _ := by ext; rfl + left_inv _ := rfl + right_inv _ := rfl /-- -The functor `uliftFunctor : Type u ⥤ Type (max u v)` preserves limits. +The functor `uliftFunctor : Type u ⥤ Type (max u v)` preserves limits of arbitrary size. -/ noncomputable -instance : PreservesLimits uliftFunctor.{v, u} where +instance : PreservesLimitsOfSize.{w', w} uliftFunctor.{v, u} where preservesLimitsOfShape {J} := { preservesLimit := fun {K} => { preserves := fun {c} hc => by apply Nonempty.some rw [Types.isLimit_iff ((uliftFunctor.{v, u}).mapCone c)] intro s hs - obtain ⟨x, hx₁, hx₂⟩ := (Types.isLimit_iff c).mp ⟨hc⟩ _ ((sectionsEquiv' K).symm ⟨s, hs⟩).2 + obtain ⟨x, hx₁, hx₂⟩ := (Types.isLimit_iff c).mp ⟨hc⟩ _ ((sectionsEquiv K).symm ⟨s, hs⟩).2 exact ⟨⟨x⟩, fun i => ULift.ext _ _ (hx₁ i), fun y hy => ULift.ext _ _ (hx₂ y.down fun i ↦ (ULift.ext_iff _ _).mp (hy i))⟩ } } /-- -The equivalence between the ulift of the explicit colimit cocone of a functor `K` and the explicit -colimit cocone of `K ⋙ uliftFunctor`. +The functor `uliftFunctor : Type u ⥤ Type (max u v)` creates `u`-small limits. +-/ +noncomputable instance : CreatesLimitsOfSize.{w, u} uliftFunctor.{v, u} where + CreatesLimitsOfShape := { CreatesLimit := fun {_} ↦ createsLimitOfFullyFaithfulOfPreserves } + +variable {J : Type*} [Category J] {K : J ⥤ Type u} {c : Cocone K} (hc : IsColimit c) +variable {lc : Cocone (K ⋙ uliftFunctor.{v, u})} + +/-- Given a subset of the cocone point of a cocone over the lifted functor, + produce a cocone over the original functor. -/ +def coconeOfSet (ls : Set lc.pt) : Cocone K where + pt := ULift Prop + ι := + { app := fun j x ↦ ⟨lc.ι.app j ⟨x⟩ ∈ ls⟩ + naturality := fun i j f ↦ by dsimp only; rw [← lc.w f]; rfl } + +/-- Given a subset of the cocone point of a cocone over the lifted functor, + produce a subset of the cocone point of a colimit cocone over the original functor. -/ +def descSet (ls : Set lc.pt) : Set c.pt := {x | (hc.desc (coconeOfSet ls) x).down} + +/-- Characterization the map `descSet hc`: the image of an element in a vertex of the original + diagram in the cocone point lies in `descSet hc ls` if and only if the image of the corresponding + element in the lifted diagram lie in `ls`. -/ +lemma descSet_spec (s : Set c.pt) (ls : Set lc.pt) : + descSet hc ls = s ↔ ∀ j x, lc.ι.app j ⟨x⟩ ∈ ls ↔ c.ι.app j x ∈ s := by + refine ⟨?_, fun he ↦ funext fun x ↦ ?_⟩ + · rintro rfl j x + exact (congr_arg ULift.down (congr_fun (hc.fac (coconeOfSet ls) j) x).symm).to_iff + · refine (congr_arg ULift.down (congr_fun (hc.uniq (coconeOfSet ls) (⟨· ∈ s⟩) fun j ↦ ?_) x)).symm + ext y; exact congr_arg ULift.up (propext (he j y).symm) + +lemma mem_descSet_singleton {x : lc.pt} {j : J} {y : K.obj j} : + c.ι.app j y ∈ descSet hc {x} ↔ lc.ι.app j ⟨y⟩ = x := + ((descSet_spec hc _ {x}).mp rfl j y).symm + +variable (lc) + +lemma descSet_univ : descSet hc (@Set.univ lc.pt) = Set.univ := by simp [descSet_spec] + +lemma iUnion_descSet_singleton : ⋃ x : lc.pt, descSet hc {x} = Set.univ := by + rw [← descSet_univ hc lc, eq_comm, descSet_spec] + intro j x + erw [true_iff, Set.mem_iUnion] + use lc.ι.app j ⟨x⟩ + rw [mem_descSet_singleton] + +lemma descSet_empty : descSet hc (∅ : Set lc.pt) = ∅ := by simp [descSet_spec] + +lemma descSet_inter_of_ne (x y : lc.pt) (hn : x ≠ y) : descSet hc {x} ∩ descSet hc {y} = ∅ := by + rw [eq_comm, ← descSet_empty hc lc, descSet_spec] + intro j z + erw [false_iff] + rintro ⟨hx, hy⟩ + rw [mem_descSet_singleton] at hx hy + exact hn (hx ▸ hy) + +lemma exists_unique_mem_descSet (x : c.pt) : ∃! y : lc.pt, x ∈ descSet hc {y} := + exists_unique_of_exists_of_unique + (Set.mem_iUnion.mp <| Set.eq_univ_iff_forall.mp (iUnion_descSet_singleton hc lc) x) + fun y₁ y₂ h₁ h₂ ↦ by_contra fun hn ↦ + Set.eq_empty_iff_forall_not_mem.1 (descSet_inter_of_ne hc lc y₁ y₂ hn) x ⟨h₁, h₂⟩ + +/-- Given a colimit cocone in `Type u` and an arbitrary cocone over the diagram lifted to + `Type (max u v)`, produce a function from the cocone point of the colimit cocone to the + cocone point of the other cocone, that witnesses the colimit cocone also being a colimit + in the higher universe. -/ +noncomputable def descFun (x : c.pt) : lc.pt := (exists_unique_mem_descSet hc lc x).exists.choose + +lemma descFun_apply_spec {x : c.pt} {y : lc.pt} : descFun hc lc x = y ↔ x ∈ descSet hc {y} := + have hu := exists_unique_mem_descSet hc lc x + have hm := hu.exists.choose_spec + ⟨fun he ↦ he ▸ hm, hu.unique hm⟩ + +lemma descFun_spec (f : c.pt → lc.pt) : + f = descFun hc lc ↔ ∀ j, f ∘ c.ι.app j = lc.ι.app j ∘ ULift.up := by + refine ⟨?_, fun he ↦ funext fun x ↦ ((descFun_apply_spec hc lc).mpr ?_).symm⟩ + · rintro rfl j; ext + apply (descFun_apply_spec hc lc).mpr + rw [mem_descSet_singleton]; rfl + · rw [← (jointly_surjective_of_isColimit hc x).choose_spec.choose_spec, mem_descSet_singleton] + exact (congr_fun (he _) _).symm + +/-- +The functor `uliftFunctor : Type u ⥤ Type (max u v)` preserves colimits of arbitrary size. -/ -def quotEquiv {J : Type u} [Category.{u, u} J] (K : J ⥤ Type u) : - uliftFunctor.{v, u}.obj (Types.Quot.{u, u} K) ≃ - (Types.Quot.{u, v} (K ⋙ uliftFunctor.{v, u})) where - toFun := fun ⟨u⟩ => Quot.map (fun ⟨j, x⟩ ↦ ⟨j, ⟨x⟩⟩) - (fun _ _ ⟨f, h⟩ => ⟨f, ULift.ext _ _ h⟩) u - invFun := fun u => ⟨Quot.map (fun ⟨j, x⟩ ↦ ⟨j, x.down⟩) - (fun _ _ ⟨f, h⟩ => ⟨f, (ULift.ext_iff.{v, u} _ _).mp h⟩) u⟩ - left_inv := by - intro ⟨x⟩ - apply ULift.ext - simp only [Functor.comp_obj, Quot.map] - rw [← Quot.out_eq x] - right_inv := by - intro x - simp only [Functor.comp_obj, Quot.map] - rw [← Quot.out_eq x] - rfl +noncomputable instance : PreservesColimitsOfSize.{w', w} uliftFunctor.{v, u} where + preservesColimitsOfShape {J _} := + { preservesColimit := fun {F} ↦ + { preserves := fun {c} hc ↦ + { desc := fun lc x ↦ descFun hc lc x.down + fac := fun lc j ↦ by ext ⟨⟩; apply congr_fun ((descFun_spec hc lc _).mp rfl j) + uniq := fun lc f hf ↦ by ext ⟨⟩; apply congr_fun ((descFun_spec hc lc (f ∘ ULift.up)).mpr + fun j ↦ funext fun y ↦ congr_fun (hf j) ⟨y⟩) } } } /-- The functor `uliftFunctor : Type u ⥤ Type (max u v)` creates `u`-small colimits. -/ -noncomputable instance : CreatesColimitsOfSize.{u, u} uliftFunctor.{v, u} where - CreatesColimitsOfShape := { - CreatesColimit := fun {K} => - @createsColimitOfFullyFaithfulOfIso _ _ _ _ _ _ K uliftFunctor.{v, u} _ _ - (Types.hasColimit.{u, max u v} (K ⋙ uliftFunctor.{v, u})) (colimit K) - (uliftFunctor.{v, u}.mapIso (equivEquivIso (colimitEquivQuot.{u, u} K)) ≪≫ - (equivEquivIso (quotEquiv K)) ≪≫ - (equivEquivIso (colimitEquivQuot.{u, v} (K ⋙ uliftFunctor.{v, u}))).symm) } +noncomputable instance : CreatesColimitsOfSize.{w, u} uliftFunctor.{v, u} where + CreatesColimitsOfShape := { CreatesColimit := fun {_} ↦ createsColimitOfFullyFaithfulOfPreserves } end CategoryTheory.Limits.Types diff --git a/Mathlib/CategoryTheory/Limits/Presheaf.lean b/Mathlib/CategoryTheory/Limits/Presheaf.lean index deb4c3082d6ca..eb3ba2db16311 100644 --- a/Mathlib/CategoryTheory/Limits/Presheaf.lean +++ b/Mathlib/CategoryTheory/Limits/Presheaf.lean @@ -390,7 +390,7 @@ noncomputable def natIsoOfNatIsoOnRepresentables (L₁ L₂ : (Cᵒᵖ ⥤ Type · intro P₁ P₂ f apply (isColimitOfPreserves L₁ (colimitOfRepresentable P₁)).hom_ext intro j - dsimp only [id.def, IsColimit.comp_coconePointsIsoOfNatIso_hom, isoWhiskerLeft_hom] + dsimp only [id.def, isoWhiskerLeft_hom] have : (L₁.mapCocone (coconeOfRepresentable P₁)).ι.app j ≫ L₁.map f = (L₁.mapCocone (coconeOfRepresentable P₂)).ι.app diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean index 1960eb96565b9..5a5c6a9e1dff5 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean @@ -1976,6 +1976,21 @@ def isoZeroBiprod {X Y : C} [HasBinaryBiproduct X Y] (hY : IsZero X) : Y ≅ X apply hY.eq_of_tgt #align category_theory.limits.iso_zero_biprod CategoryTheory.Limits.isoZeroBiprod +@[simp] +lemma biprod_isZero_iff (A B : C) [HasBinaryBiproduct A B] : + IsZero (biprod A B) ↔ IsZero A ∧ IsZero B := by + constructor + · intro h + simp only [IsZero.iff_id_eq_zero] at h ⊢ + simp only [show 𝟙 A = biprod.inl ≫ 𝟙 (A ⊞ B) ≫ biprod.fst by simp, + show 𝟙 B = biprod.inr ≫ 𝟙 (A ⊞ B) ≫ biprod.snd by simp, h, zero_comp, comp_zero, + and_self] + · rintro ⟨hA, hB⟩ + rw [IsZero.iff_id_eq_zero] + apply biprod.hom_ext + · apply hA.eq_of_tgt + · apply hB.eq_of_tgt + end IsZero section diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean b/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean index 9581753b7bb12..70c3f56832df7 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean @@ -33,7 +33,7 @@ universe w v u namespace CategoryTheory.Limits.Concrete -attribute [local instance] ConcreteCategory.funLike ConcreteCategory.hasCoeToSort +attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort variable {C : Type u} [Category.{v} C] diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean b/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean new file mode 100644 index 0000000000000..1a93825cb5a47 --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean @@ -0,0 +1,157 @@ +/- +Copyright (c) 2023 Dagur Asgeirsson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Dagur Asgeirsson +-/ +import Mathlib.CategoryTheory.Limits.Final +import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits +import Mathlib.CategoryTheory.Countable +import Mathlib.Data.Countable.Defs +/-! +# Countable limits and colimits + +A typeclass for categories with all countable (co)limits. + +We also prove that all cofiltered limits over countable preorders are isomorphic to sequential +limits, see `sequentialFunctor_initial`. + +## Projects + +* There is a series of `proof_wanted` at the bottom of this file, implying that all cofiltered + limits over countable categories are isomorphic to sequential limits. + +* Prove the dual result for filtered colimits. + +-/ + +open CategoryTheory Opposite CountableCategory + +variable (C : Type*) [Category C] (J : Type*) [Countable J] + +namespace CategoryTheory.Limits + +/-- +A category has all countable limits if every functor `J ⥤ C` with a `CountableCategory J` +instance and `J : Type` has a limit. +-/ +class HasCountableLimits : Prop where + /-- `C` has all limits over any type `J` whose objects and morphisms lie in the same universe + and which has countably many objects and morphisms-/ + out (J : Type) [SmallCategory J] [CountableCategory J] : HasLimitsOfShape J C + +instance (priority := 100) hasFiniteLimits_of_hasCountableLimits [HasCountableLimits C] : + HasFiniteLimits C where + out J := HasCountableLimits.out J + +instance (priority := 100) hasCountableLimits_of_hasLimits [HasLimits C] : + HasCountableLimits C where + out := inferInstance + +universe v in +instance [Category.{v} J] [CountableCategory J] [HasCountableLimits C] : HasLimitsOfShape J C := + have : HasLimitsOfShape (HomAsType J) C := HasCountableLimits.out (HomAsType J) + hasLimitsOfShape_of_equivalence (homAsTypeEquiv J) + +/-- +A category has all countable colimits if every functor `J ⥤ C` with a `CountableCategory J` +instance and `J : Type` has a colimit. +-/ +class HasCountableColimits : Prop where + /-- `C` has all limits over any type `J` whose objects and morphisms lie in the same universe + and which has countably many objects and morphisms-/ + out (J : Type) [SmallCategory J] [CountableCategory J] : HasColimitsOfShape J C + +instance (priority := 100) hasFiniteColimits_of_hasCountableColimits [HasCountableColimits C] : + HasFiniteColimits C where + out J := HasCountableColimits.out J + +instance (priority := 100) hasCountableColimits_of_hasColimits [HasColimits C] : + HasCountableColimits C where + out := inferInstance + +universe v in +instance [Category.{v} J] [CountableCategory J] [HasCountableColimits C] : HasColimitsOfShape J C := + have : HasColimitsOfShape (HomAsType J) C := HasCountableColimits.out (HomAsType J) + hasColimitsOfShape_of_equivalence (homAsTypeEquiv J) + +section Preorder + +attribute [local instance] IsCofiltered.nonempty + +variable {C} [Preorder J] [IsCofiltered J] + +/-- The object part of the initial functor `ℕᵒᵖ ⥤ J` -/ +noncomputable def sequentialFunctor_obj : ℕ → J := fun + | .zero => (exists_surjective_nat _).choose 0 + | .succ n => (IsCofilteredOrEmpty.cone_objs ((exists_surjective_nat _).choose n) + (sequentialFunctor_obj n)).choose + +theorem sequentialFunctor_map : Antitone (sequentialFunctor_obj J) := + antitone_nat_of_succ_le fun n ↦ + leOfHom (IsCofilteredOrEmpty.cone_objs ((exists_surjective_nat _).choose n) + (sequentialFunctor_obj J n)).choose_spec.choose_spec.choose + +/-- +The initial functor `ℕᵒᵖ ⥤ J`, which allows us to turn cofiltered limits over countable preorders +into sequential limits. +-/ +noncomputable def sequentialFunctor : ℕᵒᵖ ⥤ J where + obj n := sequentialFunctor_obj J (unop n) + map h := homOfLE (sequentialFunctor_map J (leOfHom h.unop)) + +theorem sequentialFunctor_initial_aux (j : J) : ∃ (n : ℕ), sequentialFunctor_obj J n ≤ j := by + obtain ⟨m, h⟩ := (exists_surjective_nat _).choose_spec j + refine ⟨m + 1, ?_⟩ + simpa [h] using leOfHom (IsCofilteredOrEmpty.cone_objs ((exists_surjective_nat _).choose m) + (sequentialFunctor_obj J m)).choose_spec.choose + +instance sequentialFunctor_initial : (sequentialFunctor J).Initial where + out d := by + obtain ⟨n, (g : (sequentialFunctor J).obj ⟨n⟩ ≤ d)⟩ := sequentialFunctor_initial_aux J d + have : Nonempty (CostructuredArrow (sequentialFunctor J) d) := + ⟨CostructuredArrow.mk (homOfLE g)⟩ + apply isConnected_of_zigzag + refine fun i j ↦ ⟨[j], ?_⟩ + simp only [List.chain_cons, Zag, List.Chain.nil, and_true, ne_eq, not_false_eq_true, + List.getLast_cons, not_true_eq_false, List.getLast_singleton'] + wlog h : (unop i.left) ≤ (unop j.left) + · exact or_comm.1 (this (C := C) J d n g inferInstance j i (le_of_lt (not_le.mp h))) + · right + exact ⟨CostructuredArrow.homMk (homOfLE h).op rfl⟩ + +/-- +This is proved in https://stacks.math.columbia.edu/tag/0032 +-/ +proof_wanted preorder_of_cofiltered (J : Type*) [Category J] [IsCofiltered J] : + ∃ (I : Type*) (_ : Preorder I) (_ : IsCofiltered I) (F : I ⥤ J), F.Initial + +/-- +The proof of `preorder_of_cofiltered` should give a countable `I` in the case that `J` is a +countable category. +-/ +proof_wanted preorder_of_cofiltered_countable + (J : Type*) [SmallCategory J] [IsCofiltered J] [CountableCategory J] : + ∃ (I : Type) (_ : Preorder I) (_ : Countable I) (_ : IsCofiltered I) (F : I ⥤ J), F.Initial + +/-- +Put together `sequentialFunctor_initial` and `preorder_of_cofiltered_countable`. +-/ +proof_wanted hasCofilteredCountableLimits_of_hasSequentialLimits [HasLimitsOfShape ℕᵒᵖ C] : + ∀ (J : Type) [SmallCategory J] [IsCofiltered J] [CountableCategory J], HasLimitsOfShape J C + +/-- +This is the countable version of `CategoryTheory.Limits.has_limits_of_finite_and_cofiltered`, given +all of the above. +-/ +proof_wanted hasCountableLimits_of_hasFiniteLimits_and_hasSequentialLimits [HasFiniteLimits C] + [HasLimitsOfShape ℕᵒᵖ C] : HasCountableLimits C + +/-- +For this we need to dualize this whole section. +-/ +proof_wanted hasCountableColimits_of_hasFiniteColimits_and_hasSequentialColimits + [HasFiniteColimits C] [HasLimitsOfShape ℕ C] : HasCountableColimits C + +end Preorder + +end CategoryTheory.Limits diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullbacks.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullbacks.lean index 341f3d913d230..34c9076f3718e 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullbacks.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullbacks.lean @@ -616,7 +616,7 @@ theorem equalizer_ext (t : PullbackCone f g) {W : C} {k l : W ⟶ t.pt} (h₀ : (h₁ : k ≫ snd t = l ≫ snd t) : ∀ j : WalkingCospan, k ≫ t.π.app j = l ≫ t.π.app j | some WalkingPair.left => h₀ | some WalkingPair.right => h₁ - | none => by rw [← t.w inl]; dsimp [h₀]; simp only [← Category.assoc, congrArg (· ≫ f) h₀] + | none => by rw [← t.w inl, reassoc_of% h₀] #align category_theory.limits.pullback_cone.equalizer_ext CategoryTheory.Limits.PullbackCone.equalizer_ext theorem IsLimit.hom_ext {t : PullbackCone f g} (ht : IsLimit t) {W : C} {k l : W ⟶ t.pt} diff --git a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean index 9fbb44c2d4926..739046ae22b96 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean @@ -75,7 +75,7 @@ instance : Inhabited (WalkingParallelFamily J) := inductive WalkingParallelFamily.Hom (J : Type w) : WalkingParallelFamily J → WalkingParallelFamily J → Type w | id : ∀ X : WalkingParallelFamily.{w} J, WalkingParallelFamily.Hom J X X - | line : ∀ _ : J, WalkingParallelFamily.Hom J zero one + | line : J → WalkingParallelFamily.Hom J zero one deriving DecidableEq #align category_theory.limits.walking_parallel_family.hom diff --git a/Mathlib/CategoryTheory/Limits/Types.lean b/Mathlib/CategoryTheory/Limits/Types.lean index 5eb0ec094524e..0cfa90d6f231e 100644 --- a/Mathlib/CategoryTheory/Limits/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Types.lean @@ -27,13 +27,13 @@ set_option autoImplicit true open CategoryTheory CategoryTheory.Limits -universe v u +universe v u w namespace CategoryTheory.Limits.Types section limit_characterization -variable {J : Type v} [Category J] {F : J ⥤ Type u} +variable {J : Type v} [Category.{w} J] {F : J ⥤ Type u} /-- Given a section of a functor F into `Type*`, construct a cone over F with `PUnit` as the cone point. -/ @@ -49,7 +49,7 @@ def sectionOfCone (c : Cone F) (x : c.pt) : F.sections := ⟨fun j ↦ c.π.app j x, fun f ↦ congr_fun (c.π.naturality f).symm x⟩ theorem isLimit_iff (c : Cone F) : - Nonempty (IsLimit c) ↔ ∀ s ∈ F.sections, ∃! x : c.pt, ∀ i, c.π.app i x = s i := by + Nonempty (IsLimit c) ↔ ∀ s ∈ F.sections, ∃! x : c.pt, ∀ j, c.π.app j x = s j := by refine ⟨fun ⟨t⟩ s hs ↦ ?_, fun h ↦ ⟨?_⟩⟩ · let cs := coneOfSection hs exact ⟨t.lift cs ⟨⟩, fun j ↦ congr_fun (t.fac cs j) ⟨⟩, @@ -59,8 +59,7 @@ theorem isLimit_iff (c : Cone F) : fun c f hf ↦ funext fun y ↦ (hx c y).2 (f y) (fun j ↦ congr_fun (hf j) y)⟩ /-- The equivalence between a limiting cone of `F` in `Type u` and the "concrete" definition as the -sections of `F`. --/ + sections of `F`. -/ noncomputable def isLimitEquivSections {c : Cone F} (t : IsLimit c) : c.pt ≃ F.sections where toFun := sectionOfCone c @@ -83,7 +82,7 @@ theorem isLimitEquivSections_symm_apply {c : Cone F} (t : IsLimit c) end limit_characterization -variable {J : Type v} [SmallCategory J] +variable {J : Type v} [Category.{w} J] /-! We now provide two distinct implementations in the category of types. @@ -151,7 +150,7 @@ noncomputable def limitCone (F : J ⥤ TypeMax.{v, u}) : Cone F where /-- (internal implementation) the fact that the proposed limit cone is the limit -/ @[simps] -noncomputable def limitConeIsLimit (F : J ⥤ TypeMax.{v, u}) : IsLimit (limitCone.{v, u} F) where +noncomputable def limitConeIsLimit (F : J ⥤ TypeMax.{v, u}) : IsLimit (limitCone F) where lift s v := { val := fun j => s.π.app j v property := fun f => congr_fun (Cone.w s f) _ } @@ -187,7 +186,7 @@ More specifically, when `UnivLE.{v, u}`, the category `Type u` has all `v`-small See . -/ -instance (priority := 1300) hasLimitsOfSize [UnivLE.{v, u}] : HasLimitsOfSize.{v} (Type u) where +instance (priority := 1300) hasLimitsOfSize [UnivLE.{v, u}] : HasLimitsOfSize.{w', v} (Type u) where has_limits_of_shape _ := { } #align category_theory.limits.types.has_limits_of_size CategoryTheory.Limits.Types.hasLimitsOfSize @@ -196,19 +195,19 @@ variable [Small.{u} J] and the "concrete" definition as the sections of `F`. -/ noncomputable def limitEquivSections (F : J ⥤ Type u) : - (@limit _ _ _ _ F (hasLimit.{v, u} F) : Type u) ≃ F.sections := - isLimitEquivSections.{v, u} (limit.isLimit F) + (@limit _ _ _ _ F (hasLimit F) : Type u) ≃ F.sections := + isLimitEquivSections (limit.isLimit F) #align category_theory.limits.types.limit_equiv_sections CategoryTheory.Limits.Types.limitEquivSections @[simp] theorem limitEquivSections_apply (F : J ⥤ Type u) (x : limit F) (j : J) : - ((limitEquivSections.{v, u} F) x : ∀ j, F.obj j) j = limit.π F j x := + ((limitEquivSections F) x : ∀ j, F.obj j) j = limit.π F j x := isLimitEquivSections_apply _ _ _ #align category_theory.limits.types.limit_equiv_sections_apply CategoryTheory.Limits.Types.limitEquivSections_apply @[simp] theorem limitEquivSections_symm_apply (F : J ⥤ Type u) (x : F.sections) (j : J) : - limit.π F j ((limitEquivSections.{v, u} F).symm x) = (x : ∀ j, F.obj j) j := + limit.π F j ((limitEquivSections F).symm x) = (x : ∀ j, F.obj j) j := isLimitEquivSections_symm_apply _ _ _ #align category_theory.limits.types.limit_equiv_sections_symm_apply CategoryTheory.Limits.Types.limitEquivSections_symm_apply @@ -226,13 +225,13 @@ which are "coherent": `∀ (j j') (f : j ⟶ j'), F.map f (x j) = x j'`. -/ noncomputable def Limit.mk (F : J ⥤ Type u) (x : ∀ j, F.obj j) (h : ∀ (j j') (f : j ⟶ j'), F.map f (x j) = x j') : (limit F : Type u) := - (limitEquivSections.{v, u} F).symm ⟨x, h _ _⟩ + (limitEquivSections F).symm ⟨x, h _ _⟩ #align category_theory.limits.types.limit.mk CategoryTheory.Limits.Types.Limit.mk @[simp] theorem Limit.π_mk (F : J ⥤ Type u) (x : ∀ j, F.obj j) (h : ∀ (j j') (f : j ⟶ j'), F.map f (x j) = x j') (j) : - limit.π F j (Limit.mk.{v, u} F x h) = x j := by + limit.π F j (Limit.mk F x h) = x j := by dsimp [Limit.mk] simp #align category_theory.limits.types.limit.π_mk CategoryTheory.Limits.Types.Limit.π_mk @@ -250,7 +249,7 @@ theorem Limit.π_mk (F : J ⥤ Type u) (x : ∀ j, F.obj j) @[ext] theorem limit_ext (F : J ⥤ Type u) (x y : limit F) (w : ∀ j, limit.π F j x = limit.π F j y) : x = y := by - apply (limitEquivSections.{v, u} F).injective + apply (limitEquivSections F).injective ext j simp [w j] #align category_theory.limits.types.limit_ext CategoryTheory.Limits.Types.limit_ext @@ -258,17 +257,17 @@ theorem limit_ext (F : J ⥤ Type u) (x y : limit F) @[ext] theorem limit_ext' (F : J ⥤ Type v) (x y : limit F) (w : ∀ j, limit.π F j x = limit.π F j y) : x = y := - limit_ext.{v, v} F x y w + limit_ext F x y w #align category_theory.limits.types.limit_ext' CategoryTheory.Limits.Types.limit_ext' theorem limit_ext_iff (F : J ⥤ Type u) (x y : limit F) : x = y ↔ ∀ j, limit.π F j x = limit.π F j y := - ⟨fun t _ => t ▸ rfl, limit_ext.{v, u} _ _ _⟩ + ⟨fun t _ => t ▸ rfl, limit_ext _ _ _⟩ #align category_theory.limits.types.limit_ext_iff CategoryTheory.Limits.Types.limit_ext_iff theorem limit_ext_iff' (F : J ⥤ Type v) (x y : limit F) : x = y ↔ ∀ j, limit.π F j x = limit.π F j y := - ⟨fun t _ => t ▸ rfl, limit_ext'.{v} _ _ _⟩ + ⟨fun t _ => t ▸ rfl, limit_ext' _ _ _⟩ #align category_theory.limits.types.limit_ext_iff' CategoryTheory.Limits.Types.limit_ext_iff' -- TODO: are there other limits lemmas that should have `_apply` versions? @@ -342,14 +341,14 @@ as pairs `⟨j, x⟩` where `x : F.obj j`, modulo the equivalence relation gener `⟨j, x⟩ ~ ⟨j', x'⟩` whenever there is a morphism `f : j ⟶ j'` so `F.map f x = x'`. -/ def Quot (F : J ⥤ TypeMax.{v, u}) : TypeMax.{v, u} := - _root_.Quot (Quot.Rel.{v, u} F) + _root_.Quot (Quot.Rel F) #align category_theory.limits.types.quot CategoryTheory.Limits.Types.Quot /-- (internal implementation) the colimit cocone of a functor, implemented as a quotient of a sigma type -/ def colimitCocone (F : J ⥤ TypeMax.{v, u}) : Cocone F where - pt := Quot.{v, u} F + pt := Quot F ι := { app := fun j x => Quot.mk _ ⟨j, x⟩ naturality := fun _ _ f => funext fun _ => Eq.symm (Quot.sound ⟨f, rfl⟩) } @@ -358,7 +357,7 @@ def colimitCocone (F : J ⥤ TypeMax.{v, u}) : Cocone F where --attribute [local elab_with_expected_type] Quot.lift /-- (internal implementation) the fact that the proposed colimit cocone is the colimit -/ -def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone.{v, u} F) where +def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone F) where desc s := Quot.lift (fun p : Σj, F.obj j => s.ι.app p.1 p.2) fun ⟨j, x⟩ ⟨j', x'⟩ ⟨f, hf⟩ => by dsimp at hf @@ -374,7 +373,7 @@ def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone See . -/ -instance hasColimitsOfSize : HasColimitsOfSize.{v} TypeMax.{v, u} where +instance hasColimitsOfSize : HasColimitsOfSize.{w', v} TypeMax.{v, u} where has_colimits_of_shape _ := { has_colimit := fun F => HasColimit.mk @@ -382,11 +381,13 @@ instance hasColimitsOfSize : HasColimitsOfSize.{v} TypeMax.{v, u} where isColimit := colimitCoconeIsColimit F } } #align category_theory.limits.types.has_colimits_of_size CategoryTheory.Limits.Types.hasColimitsOfSize +instance : HasColimitsOfSize.{w', v} (Type v) := hasColimitsOfSize.{v, v} + instance : HasColimits (Type u) := - Types.hasColimitsOfSize.{u, u} + Types.hasColimitsOfSize.{u, u, u} instance hasColimit (F : J ⥤ TypeMax.{v, u}) : HasColimit F := - (Types.hasColimitsOfSize.{v, u}.has_colimits_of_shape J).has_colimit F + (Types.hasColimitsOfSize.has_colimits_of_shape J).has_colimit F instance hasColimit' (F : J ⥤ Type v) : HasColimit F := hasColimit.{v, v} F @@ -394,19 +395,19 @@ instance hasColimit' (F : J ⥤ Type v) : HasColimit F := /-- The equivalence between the abstract colimit of `F` in `Type u` and the "concrete" definition as a quotient. -/ -noncomputable def colimitEquivQuot (F : J ⥤ TypeMax.{v, u}) : colimit F ≃ Quot.{v, u} F := +noncomputable def colimitEquivQuot (F : J ⥤ TypeMax.{v, u}) : colimit F ≃ Quot F := (IsColimit.coconePointUniqueUpToIso (colimit.isColimit F) (colimitCoconeIsColimit F)).toEquiv #align category_theory.limits.types.colimit_equiv_quot CategoryTheory.Limits.Types.colimitEquivQuot @[simp] theorem colimitEquivQuot_symm_apply (F : J ⥤ TypeMax.{v, u}) (j : J) (x : F.obj j) : - (colimitEquivQuot.{v, u} F).symm (Quot.mk _ ⟨j, x⟩) = colimit.ι F j x := + (colimitEquivQuot F).symm (Quot.mk _ ⟨j, x⟩) = colimit.ι F j x := rfl #align category_theory.limits.types.colimit_equiv_quot_symm_apply CategoryTheory.Limits.Types.colimitEquivQuot_symm_apply @[simp] theorem colimitEquivQuot_apply (F : J ⥤ TypeMax.{v, u}) (j : J) (x : F.obj j) : - (colimitEquivQuot.{v, u} F) (colimit.ι F j x) = Quot.mk _ ⟨j, x⟩ := by + (colimitEquivQuot F) (colimit.ι F j x) = Quot.mk _ ⟨j, x⟩ := by apply (colimitEquivQuot F).symm.injective simp #align category_theory.limits.types.colimit_equiv_quot_apply CategoryTheory.Limits.Types.colimitEquivQuot_apply @@ -425,7 +426,7 @@ theorem Colimit.ι_desc_apply (F : J ⥤ TypeMax.{v, u}) (s : Cocone F) (j : J) --porting note: @[simp] was removed because the linter said it was useless theorem Colimit.ι_map_apply {F G : J ⥤ TypeMax.{v, u}} (α : F ⟶ G) (j : J) (x : F.obj j) : - colim.{v, v}.map α (colimit.ι F j x) = colimit.ι G j (α.app j x) := + colim.map α (colimit.ι F j x) = colimit.ι G j (α.app j x) := congr_fun (colimit.ι_map α j) x #align category_theory.limits.types.colimit.ι_map_apply CategoryTheory.Limits.Types.Colimit.ι_map_apply @@ -449,7 +450,7 @@ theorem Colimit.ι_map_apply' {F G : J ⥤ Type v} (α : F ⟶ G) (j : J) (x) : theorem colimit_sound {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : F.obj j'} (f : j ⟶ j') (w : F.map f x = x') : colimit.ι F j x = colimit.ι F j' x' := by - rw [← w, Colimit.w_apply.{v, u}] + rw [← w, Colimit.w_apply] #align category_theory.limits.types.colimit_sound CategoryTheory.Limits.Types.colimit_sound theorem colimit_sound' {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : F.obj j'} {j'' : J} @@ -461,27 +462,29 @@ theorem colimit_sound' {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : theorem colimit_eq {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : F.obj j'} (w : colimit.ι F j x = colimit.ι F j' x') : - EqvGen (Quot.Rel.{v, u} F) ⟨j, x⟩ ⟨j', x'⟩ := by + EqvGen (Quot.Rel F) ⟨j, x⟩ ⟨j', x'⟩ := by apply Quot.eq.1 simpa using congr_arg (colimitEquivQuot.{v, u} F) w #align category_theory.limits.types.colimit_eq CategoryTheory.Limits.Types.colimit_eq +theorem jointly_surjective_of_isColimit {F : J ⥤ Type u} {t : Cocone F} (h : IsColimit t) + (x : t.pt) : ∃ j y, t.ι.app j y = x := by + by_contra hx + simp_rw [not_exists] at hx + apply (_ : (fun _ ↦ ULift.up True) ≠ (⟨· ≠ x⟩)) + · refine h.hom_ext fun j ↦ ?_ + ext y + exact (true_iff _).mpr (hx j y) + · exact fun he ↦ of_eq_true (congr_arg ULift.down <| congr_fun he x).symm rfl + theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) : - ∃ j y, t.ι.app j y = x := by - suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by - have := congr_fun this x - simpa using congr_arg ULift.down this - refine' h.hom_ext _ - intro j - funext y - simp only [Functor.const_obj_obj, types_comp_apply, ULift.up_inj, eq_iff_iff, iff_true] - exact ⟨j, y, rfl⟩ + ∃ j y, t.ι.app j y = x := jointly_surjective_of_isColimit h x #align category_theory.limits.types.jointly_surjective CategoryTheory.Limits.Types.jointly_surjective /-- A variant of `jointly_surjective` for `x : colimit F`. -/ theorem jointly_surjective' {F : J ⥤ TypeMax.{v, u}} (x : colimit F) : - ∃ j y, colimit.ι F j y = x := by - exact jointly_surjective.{v, u} F (colimit.isColimit F) x + ∃ j y, colimit.ι F j y = x := + jointly_surjective F (colimit.isColimit F) x #align category_theory.limits.types.jointly_surjective' CategoryTheory.Limits.Types.jointly_surjective' namespace FilteredColimit @@ -503,12 +506,12 @@ protected def Rel (x y : Σ j, F.obj j) : Prop := #align category_theory.limits.types.filtered_colimit.rel CategoryTheory.Limits.Types.FilteredColimit.Rel theorem rel_of_quot_rel (x y : Σ j, F.obj j) : - Quot.Rel.{v, u} F x y → FilteredColimit.Rel.{v, u} F x y := + Quot.Rel F x y → FilteredColimit.Rel.{v, u} F x y := fun ⟨f, h⟩ => ⟨y.1, f, 𝟙 y.1, by rw [← h, FunctorToTypes.map_id_apply]⟩ #align category_theory.limits.types.filtered_colimit.rel_of_quot_rel CategoryTheory.Limits.Types.FilteredColimit.rel_of_quot_rel theorem eqvGen_quot_rel_of_rel (x y : Σ j, F.obj j) : - FilteredColimit.Rel.{v, u} F x y → EqvGen (Quot.Rel.{v, u} F) x y := fun ⟨k, f, g, h⟩ => by + FilteredColimit.Rel.{v, u} F x y → EqvGen (Quot.Rel F) x y := fun ⟨k, f, g, h⟩ => by refine' EqvGen.trans _ ⟨k, F.map f x.2⟩ _ _ _ · exact (EqvGen.rel _ _ ⟨f, rfl⟩) · exact (EqvGen.symm _ _ (EqvGen.rel _ _ ⟨g, h⟩)) @@ -530,8 +533,8 @@ noncomputable def isColimitOf (t : Cocone F) (hsurj : ∀ x : t.pt, ∃ i xi, x · constructor · show Function.Injective _ intro a b h - rcases jointly_surjective.{v, u} F (colimit.isColimit F) a with ⟨i, xi, rfl⟩ - rcases jointly_surjective.{v, u} F (colimit.isColimit F) b with ⟨j, xj, rfl⟩ + rcases jointly_surjective F (colimit.isColimit F) a with ⟨i, xi, rfl⟩ + rcases jointly_surjective F (colimit.isColimit F) b with ⟨j, xj, rfl⟩ replace h : (colimit.ι F i ≫ colimit.desc F t) xi = (colimit.ι F j ≫ colimit.desc F t) xj := h rw [colimit.ι_desc, colimit.ι_desc] at h rcases hinj i j xi xj h with ⟨k, f, g, h'⟩ @@ -543,7 +546,7 @@ noncomputable def isColimitOf (t : Cocone F) (hsurj : ∀ x : t.pt, ∃ i xi, x intro x rcases hsurj x with ⟨i, xi, rfl⟩ use colimit.ι F i xi - apply Colimit.ι_desc_apply.{v, u} + apply Colimit.ι_desc_apply · intro j apply colimit.ι_desc #align category_theory.limits.types.filtered_colimit.is_colimit_of CategoryTheory.Limits.Types.FilteredColimit.isColimitOf @@ -568,7 +571,7 @@ protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) #align category_theory.limits.types.filtered_colimit.rel_equiv CategoryTheory.Limits.Types.FilteredColimit.rel_equiv protected theorem rel_eq_eqvGen_quot_rel : - FilteredColimit.Rel.{v, u} F = EqvGen (Quot.Rel.{v, u} F) := by + FilteredColimit.Rel.{v, u} F = EqvGen (Quot.Rel F) := by ext ⟨j, x⟩ ⟨j', y⟩ constructor · apply eqvGen_quot_rel_of_rel @@ -588,7 +591,7 @@ theorem isColimit_eq_iff {t : Cocone F} (ht : IsColimit t) {i j : J} {xi : F.obj let t' := colimitCocone.{v, u} F let e : t' ≅ t := IsColimit.uniqueUpToIso (colimitCoconeIsColimit F) ht let e' : t'.pt ≅ t.pt := (Cocones.forget _).mapIso e - refine' Iff.trans _ (colimit_eq_iff_aux.{v, u} F) + refine' Iff.trans _ (colimit_eq_iff_aux F) exact @Equiv.apply_eq_iff_eq _ _ e'.toEquiv ((colimitCocone.{v, u} F).ι.app i xi) ((colimitCocone.{v, u} F).ι.app j xj) #align category_theory.limits.types.filtered_colimit.is_colimit_eq_iff CategoryTheory.Limits.Types.FilteredColimit.isColimit_eq_iff @@ -596,7 +599,7 @@ theorem isColimit_eq_iff {t : Cocone F} (ht : IsColimit t) {i j : J} {xi : F.obj theorem colimit_eq_iff {i j : J} {xi : F.obj i} {xj : F.obj j} : colimit.ι F i xi = colimit.ι F j xj ↔ ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj := - isColimit_eq_iff.{v, u} _ (colimit.isColimit F) + isColimit_eq_iff _ (colimit.isColimit F) #align category_theory.limits.types.filtered_colimit.colimit_eq_iff CategoryTheory.Limits.Types.FilteredColimit.colimit_eq_iff end FilteredColimit diff --git a/Mathlib/CategoryTheory/Limits/VanKampen.lean b/Mathlib/CategoryTheory/Limits/VanKampen.lean index 87dfbdf7ae5a5..4e468365ea3de 100644 --- a/Mathlib/CategoryTheory/Limits/VanKampen.lean +++ b/Mathlib/CategoryTheory/Limits/VanKampen.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.CategoryTheory.Adjunction.FullyFaithful +import Mathlib.CategoryTheory.Adjunction.Limits import Mathlib.CategoryTheory.Limits.Shapes.CommSq -import Mathlib.CategoryTheory.Limits.Shapes.Multiequalizer import Mathlib.CategoryTheory.Limits.Shapes.StrictInitial import Mathlib.CategoryTheory.Limits.FunctorCategory import Mathlib.CategoryTheory.Limits.Constructions.FiniteProductsOfBinaryProducts @@ -322,9 +322,9 @@ theorem IsUniversalColimit.map_reflective haveI : ∀ X, IsIso (Gl.map (adj.unit.app X)) := by simp_rw [hadj] infer_instance - have hα'' : ∀ j, Gl.map (Gr.map $ α'.app j) = adj.counit.app _ ≫ α.app j + have hα'' : ∀ j, Gl.map (Gr.map <| α'.app j) = adj.counit.app _ ≫ α.app j · intro j - rw [← cancel_mono (adj.counit.app $ F.obj j)] + rw [← cancel_mono (adj.counit.app <| F.obj j)] dsimp simp only [Category.comp_id, Adjunction.counit_naturality_assoc, Category.id_comp, Adjunction.counit_naturality, Category.assoc, Functor.map_comp] @@ -333,7 +333,7 @@ theorem IsUniversalColimit.map_reflective let c'' : Cocone (F' ⋙ Gr) · refine { pt := pullback (Gr.map f) (adj.unit.app _) - ι := { app := λ j ↦ pullback.lift (Gr.map $ c'.ι.app j) (Gr.map (α'.app j) ≫ c.ι.app j) ?_ + ι := { app := λ j ↦ pullback.lift (Gr.map <| c'.ι.app j) (Gr.map (α'.app j) ≫ c.ι.app j) ?_ naturality := ?_ } } · rw [← Gr.map_comp, ← hc''] erw [← adj.unit_naturality] @@ -354,8 +354,8 @@ theorem IsUniversalColimit.map_reflective exact c.w _ let cf : (Cocones.precompose β.hom).obj c' ⟶ Gl.mapCocone c'' · refine { hom := pullback.lift ?_ f ?_ ≫ (PreservesPullback.iso _ _ _).inv, w := ?_ } - exact (inv $ adj.counit.app c'.pt) - · rw [IsIso.inv_comp_eq, ← adj.counit_naturality_assoc f, ← cancel_mono (adj.counit.app $ + exact (inv <| adj.counit.app c'.pt) + · rw [IsIso.inv_comp_eq, ← adj.counit_naturality_assoc f, ← cancel_mono (adj.counit.app <| Gl.obj c.pt), Category.assoc, Category.assoc, adj.left_triangle_components] erw [Category.comp_id] rfl @@ -379,7 +379,7 @@ theorem IsUniversalColimit.map_reflective rw [this] infer_instance have ⟨Hc''⟩ := H c'' (whiskerRight α' Gr) pullback.snd ?_ (hα'.whiskerRight Gr) ?_ - · exact ⟨IsColimit.precomposeHomEquiv β c' $ + · exact ⟨IsColimit.precomposeHomEquiv β c' <| (isColimitOfPreserves Gl Hc'').ofIsoColimit (asIso cf).symm⟩ · ext j dsimp @@ -417,16 +417,16 @@ theorem IsVanKampenColimit.map_reflective [HasColimitsOfShape J C] intro ⟨hc'⟩ j let α' := α ≫ (Functor.associator _ _ _).hom ≫ whiskerLeft F adj.counit ≫ F.rightUnitor.hom have hα' : NatTrans.Equifibered α' := hα.comp (NatTrans.equifibered_of_isIso _) - have hα'' : ∀ j, Gl.map (Gr.map $ α'.app j) = adj.counit.app _ ≫ α.app j + have hα'' : ∀ j, Gl.map (Gr.map <| α'.app j) = adj.counit.app _ ≫ α.app j · intro j - rw [← cancel_mono (adj.counit.app $ F.obj j)] + rw [← cancel_mono (adj.counit.app <| F.obj j)] dsimp simp only [Category.comp_id, Adjunction.counit_naturality_assoc, Category.id_comp, Adjunction.counit_naturality, Category.assoc, Functor.map_comp] let β := isoWhiskerLeft F' (asIso adj.counit) ≪≫ F'.rightUnitor let hl := (IsColimit.precomposeHomEquiv β c').symm hc' - let hr := isColimitOfPreserves Gl (colimit.isColimit $ F' ⋙ Gr) - have : α.app j = β.inv.app _ ≫ Gl.map (Gr.map $ α'.app j) + let hr := isColimitOfPreserves Gl (colimit.isColimit <| F' ⋙ Gr) + have : α.app j = β.inv.app _ ≫ Gl.map (Gr.map <| α'.app j) · rw [hα''] simp rw [this] @@ -448,9 +448,9 @@ theorem IsVanKampenColimit.map_reflective [HasColimitsOfShape J C] congr 1 exact (NatTrans.congr_app h j).symm rw [this] - have := ((H (colimit.cocone $ F' ⋙ Gr) (whiskerRight α' Gr) + have := ((H (colimit.cocone <| F' ⋙ Gr) (whiskerRight α' Gr) (colimit.desc _ ⟨_, whiskerRight α' Gr ≫ c.2⟩) ?_ (hα'.whiskerRight Gr)).mp - ⟨(getColimitCocone $ F' ⋙ Gr).2⟩ j).map Gl + ⟨(getColimitCocone <| F' ⋙ Gr).2⟩ j).map Gl convert IsPullback.paste_vert _ this refine IsPullback.of_vert_isIso ⟨?_⟩ rw [← IsIso.inv_comp_eq, ← Category.assoc, NatIso.inv_inv_app] @@ -729,9 +729,9 @@ theorem isPullback_of_cofan_isVanKampen [HasInitial C] {ι : Type*} {X : ι → else eqToHom (if_neg h) ≫ initial.to (X j)) (Cofan.inj c i) (Cofan.inj c j) := by refine (hc (Cofan.mk (X i) (f := fun k ↦ if k = i then X i else ⊥_ C) - (fun k ↦ if h : k = i then (eqToHom $ if_pos h) else (eqToHom $ if_neg h) ≫ initial.to _)) - (Discrete.natTrans (fun k ↦ if h : k.1 = i then (eqToHom $ (if_pos h).trans - (congr_arg X h.symm)) else (eqToHom $ if_neg h) ≫ initial.to _)) + (fun k ↦ if h : k = i then (eqToHom <| if_pos h) else (eqToHom <| if_neg h) ≫ initial.to _)) + (Discrete.natTrans (fun k ↦ if h : k.1 = i then (eqToHom <| (if_pos h).trans + (congr_arg X h.symm)) else (eqToHom <| if_neg h) ≫ initial.to _)) (c.inj i) ?_ (NatTrans.equifibered_of_discrete _)).mp ⟨?_⟩ ⟨j⟩ · ext ⟨k⟩ simp only [Discrete.functor_obj, Functor.const_obj_obj, NatTrans.comp_app, diff --git a/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean b/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean index e9fd0409a60b9..dcec12237a416 100644 --- a/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean +++ b/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.CategoryTheory.Localization.Opposite +import Mathlib.CategoryTheory.MorphismProperty /-! # Calculus of fractions diff --git a/Mathlib/CategoryTheory/Localization/Pi.lean b/Mathlib/CategoryTheory/Localization/Pi.lean index ea98e5396fc93..299145ae67898 100644 --- a/Mathlib/CategoryTheory/Localization/Pi.lean +++ b/Mathlib/CategoryTheory/Localization/Pi.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.CategoryTheory.Localization.Prod +import Mathlib.CategoryTheory.Localization.Equivalence /-! # Localization of product categories diff --git a/Mathlib/CategoryTheory/Localization/Prod.lean b/Mathlib/CategoryTheory/Localization/Prod.lean index d731a294d781f..62762e7f46073 100644 --- a/Mathlib/CategoryTheory/Localization/Prod.lean +++ b/Mathlib/CategoryTheory/Localization/Prod.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.CategoryTheory.Localization.Equivalence +import Mathlib.CategoryTheory.Localization.Predicate /-! # Localization of product categories diff --git a/Mathlib/CategoryTheory/Monad/Types.lean b/Mathlib/CategoryTheory/Monad/Types.lean index 1e958dd0522d1..eb864d4b0a108 100644 --- a/Mathlib/CategoryTheory/Monad/Types.lean +++ b/Mathlib/CategoryTheory/Monad/Types.lean @@ -57,7 +57,7 @@ def eq : KleisliCat m ≌ Kleisli (ofTypeMonad m) where funext t -- Porting note: missing tactic `unfold_projs`, using `change` instead. change _ = joinM (g <$> (f t)) - simp only [joinM, seq_bind_eq, Function.comp.left_id] + simp only [joinM, seq_bind_eq, Function.id_comp] rfl } inverse := { obj := fun X => X @@ -75,7 +75,7 @@ def eq : KleisliCat m ≌ Kleisli (ofTypeMonad m) where dsimp -- Porting note: missing tactic `unfold_projs`, using `change` instead. change joinM (g <$> (f t)) = _ - simp only [joinM, seq_bind_eq, Function.comp.left_id] + simp only [joinM, seq_bind_eq, Function.id_comp] rfl } unitIso := by refine' NatIso.ofComponents (fun X => Iso.refl X) fun f => _ diff --git a/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean b/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean index 1fd3cbf61785c..3bb669914909a 100644 --- a/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean +++ b/Mathlib/CategoryTheory/Monoidal/CoherenceLemmas.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Jendrusch, Scott Morrison, Bhavik Mehta, Jakob von Raumer -/ import Mathlib.Tactic.CategoryTheory.Coherence +import Mathlib.CategoryTheory.Monoidal.Free.Coherence #align_import category_theory.monoidal.coherence_lemmas from "leanprover-community/mathlib"@"b8b8bf3ea0c625fa1f950034a184e07c67f7bcfe" diff --git a/Mathlib/CategoryTheory/Monoidal/Mod_.lean b/Mathlib/CategoryTheory/Monoidal/Mod_.lean index 1e23e1bccecdb..dbb25e46217e9 100644 --- a/Mathlib/CategoryTheory/Monoidal/Mod_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Mod_.lean @@ -114,6 +114,7 @@ set_option linter.uppercaseLean3 false in open CategoryTheory.MonoidalCategory +set_option maxHeartbeats 400000 in /-- A morphism of monoid objects induces a "restriction" or "comap" functor between the categories of module objects. -/ diff --git a/Mathlib/CategoryTheory/Monoidal/Opposite.lean b/Mathlib/CategoryTheory/Monoidal/Opposite.lean index 9f970b0975178..3ad2597b81651 100644 --- a/Mathlib/CategoryTheory/Monoidal/Opposite.lean +++ b/Mathlib/CategoryTheory/Monoidal/Opposite.lean @@ -3,7 +3,8 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.CategoryTheory.Monoidal.CoherenceLemmas +import Mathlib.CategoryTheory.Monoidal.Free.Coherence +import Mathlib.Tactic.CategoryTheory.Coherence #align_import category_theory.monoidal.opposite from "leanprover-community/mathlib"@"14b69e9f3c16630440a2cbd46f1ddad0d561dee7" diff --git a/Mathlib/CategoryTheory/Monoidal/Preadditive.lean b/Mathlib/CategoryTheory/Monoidal/Preadditive.lean index de09694784229..1e7e126bf36c8 100644 --- a/Mathlib/CategoryTheory/Monoidal/Preadditive.lean +++ b/Mathlib/CategoryTheory/Monoidal/Preadditive.lean @@ -15,7 +15,6 @@ A monoidal category is `MonoidalPreadditive` if it is preadditive and tensor pro is linear in both factors. -/ - noncomputable section open Classical @@ -284,7 +283,7 @@ theorem leftDistributor_ext_left {J : Type} [Fintype J] {X Y : C} {f : J → C} ext simp? [leftDistributor_inv, Preadditive.comp_sum_assoc, biproduct.ι_π_assoc, dite_comp] says simp only [leftDistributor_inv, Preadditive.comp_sum_assoc, biproduct.ι_π_assoc, dite_comp, - zero_comp, Finset.sum_dite_eq, Finset.mem_univ, eqToHom_refl, Category.id_comp, ite_true] + zero_comp, Finset.sum_dite_eq, Finset.mem_univ, ↓reduceIte, eqToHom_refl, Category.id_comp] apply w @[ext] @@ -293,10 +292,10 @@ theorem leftDistributor_ext_right {J : Type} [Fintype J] {X Y : C} {f : J → C} apply (cancel_mono (leftDistributor Y f).hom).mp ext simp? [leftDistributor_hom, Preadditive.sum_comp, Preadditive.comp_sum_assoc, biproduct.ι_π, - comp_dite] says - simp only [leftDistributor_hom, Category.assoc, Preadditive.sum_comp, biproduct.ι_π, - comp_dite, comp_zero, Finset.sum_dite_eq', Finset.mem_univ, eqToHom_refl, Category.comp_id, - ite_true] + comp_dite] says + simp only [leftDistributor_hom, Category.assoc, Preadditive.sum_comp, biproduct.ι_π, comp_dite, + comp_zero, Finset.sum_dite_eq', Finset.mem_univ, ↓reduceIte, eqToHom_refl, Category.comp_id] + apply w -- One might wonder how many iterated tensor products we need simp lemmas for. @@ -326,9 +325,9 @@ theorem rightDistributor_ext_left {J : Type} [Fintype J] apply (cancel_epi (rightDistributor f X).inv).mp ext simp? [rightDistributor_inv, Preadditive.comp_sum_assoc, biproduct.ι_π_assoc, dite_comp] says - simp only [rightDistributor_inv, Preadditive.comp_sum_assoc, biproduct.ι_π_assoc, - dite_comp, zero_comp, Finset.sum_dite_eq, Finset.mem_univ, eqToHom_refl, Category.id_comp, - ite_true] + simp only [rightDistributor_inv, Preadditive.comp_sum_assoc, biproduct.ι_π_assoc, dite_comp, + zero_comp, Finset.sum_dite_eq, Finset.mem_univ, ↓reduceIte, eqToHom_refl, Category.id_comp] + apply w @[ext] @@ -338,10 +337,10 @@ theorem rightDistributor_ext_right {J : Type} [Fintype J] apply (cancel_mono (rightDistributor f Y).hom).mp ext simp? [rightDistributor_hom, Preadditive.sum_comp, Preadditive.comp_sum_assoc, biproduct.ι_π, - comp_dite] says - simp only [rightDistributor_hom, Category.assoc, Preadditive.sum_comp, biproduct.ι_π, - comp_dite, comp_zero, Finset.sum_dite_eq', Finset.mem_univ, eqToHom_refl, Category.comp_id, - ite_true] + comp_dite] says + simp only [rightDistributor_hom, Category.assoc, Preadditive.sum_comp, biproduct.ι_π, comp_dite, + comp_zero, Finset.sum_dite_eq', Finset.mem_univ, ↓reduceIte, eqToHom_refl, Category.comp_id] + apply w @[ext] diff --git a/Mathlib/CategoryTheory/MorphismProperty.lean b/Mathlib/CategoryTheory/MorphismProperty.lean index 115c322ddee0a..b394b90fe1e48 100644 --- a/Mathlib/CategoryTheory/MorphismProperty.lean +++ b/Mathlib/CategoryTheory/MorphismProperty.lean @@ -807,7 +807,7 @@ variable [ConcreteCategory C] open Function -attribute [local instance] ConcreteCategory.funLike ConcreteCategory.hasCoeToSort +attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort variable (C) diff --git a/Mathlib/CategoryTheory/Pi/Basic.lean b/Mathlib/CategoryTheory/Pi/Basic.lean index 5fae1ca167314..6bb89536c15b1 100644 --- a/Mathlib/CategoryTheory/Pi/Basic.lean +++ b/Mathlib/CategoryTheory/Pi/Basic.lean @@ -6,7 +6,6 @@ Authors: Simon Hudon, Scott Morrison import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.NatIso import Mathlib.CategoryTheory.Products.Basic -import Mathlib.Data.Sum.Basic #align_import category_theory.pi.basic from "leanprover-community/mathlib"@"dc6c365e751e34d100e80fe6e314c3c3e0fd2988" @@ -373,7 +372,7 @@ def Pi.optionEquivalence (C' : Option J → Type u₁) [∀ i, Category.{v₁} ( inverse := Functor.pi' (fun i => match i with | none => Prod.fst _ _ | some i => Prod.snd _ _ ⋙ (Pi.eval _ i)) - unitIso := NatIso.pi' (fun i => match i with + unitIso := NatIso.pi' (fun i => match i with | none => Iso.refl _ | some i => Iso.refl _) counitIso := by exact Iso.refl _ diff --git a/Mathlib/CategoryTheory/Preadditive/FunctorCategory.lean b/Mathlib/CategoryTheory/Preadditive/FunctorCategory.lean index 90bc801fd4cf8..4729cfd019df2 100644 --- a/Mathlib/CategoryTheory/Preadditive/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Preadditive/FunctorCategory.lean @@ -15,7 +15,6 @@ then `C ⥤ D` is also preadditive. -/ - open BigOperators namespace CategoryTheory @@ -37,30 +36,37 @@ instance functorCategoryPreadditive : Preadditive (C ⥤ D) apply add_assoc zero_add := by intros + dsimp ext apply zero_add add_zero := by intros + dsimp ext apply add_zero add_comm := by intros + dsimp ext apply add_comm sub_eq_add_neg := by intros + dsimp ext apply sub_eq_add_neg add_left_neg := by intros + dsimp ext apply add_left_neg } add_comp := by intros + dsimp ext apply add_comp comp_add := by intros + dsimp ext apply comp_add #align category_theory.functor_category_preadditive CategoryTheory.functorCategoryPreadditive diff --git a/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean b/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean index 50e54f27e52e2..19d209b53d359 100644 --- a/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean +++ b/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel -/ -import Mathlib.CategoryTheory.Limits.Yoneda import Mathlib.CategoryTheory.Preadditive.Opposite import Mathlib.Algebra.Category.ModuleCat.Basic import Mathlib.Algebra.Category.GroupCat.Preadditive diff --git a/Mathlib/CategoryTheory/Preadditive/Yoneda/Limits.lean b/Mathlib/CategoryTheory/Preadditive/Yoneda/Limits.lean index ac6e5c627c868..4379c46eb2258 100644 --- a/Mathlib/CategoryTheory/Preadditive/Yoneda/Limits.lean +++ b/Mathlib/CategoryTheory/Preadditive/Yoneda/Limits.lean @@ -5,6 +5,7 @@ Authors: Markus Himmel -/ import Mathlib.CategoryTheory.Preadditive.Yoneda.Basic import Mathlib.Algebra.Category.ModuleCat.Abelian +import Mathlib.CategoryTheory.Limits.Yoneda #align_import category_theory.preadditive.yoneda.limits from "leanprover-community/mathlib"@"09f981f72d43749f1fa072deade828d9c1e185bb" diff --git a/Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean b/Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean index 9681700de88c2..0bff6fee570e9 100644 --- a/Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean +++ b/Mathlib/CategoryTheory/Preadditive/Yoneda/Projective.lean @@ -6,7 +6,6 @@ Authors: Markus Himmel, Scott Morrison import Mathlib.CategoryTheory.Preadditive.Yoneda.Basic import Mathlib.CategoryTheory.Preadditive.Projective import Mathlib.Algebra.Category.GroupCat.EpiMono -import Mathlib.Algebra.Category.ModuleCat.EpiMono #align_import category_theory.preadditive.yoneda.projective from "leanprover-community/mathlib"@"f8d8465c3c392a93b9ed226956e26dee00975946" diff --git a/Mathlib/CategoryTheory/Quotient.lean b/Mathlib/CategoryTheory/Quotient.lean index 6d6f65b09d557..96ec64a41c801 100644 --- a/Mathlib/CategoryTheory/Quotient.lean +++ b/Mathlib/CategoryTheory/Quotient.lean @@ -104,9 +104,9 @@ instance category : Category (Quotient r) where Hom := Hom r id a := Quot.mk _ (𝟙 a.as) comp := @comp _ _ r - comp_id f := Quot.inductionOn f $ by simp - id_comp f := Quot.inductionOn f $ by simp - assoc f g h := Quot.inductionOn f $ Quot.inductionOn g $ Quot.inductionOn h $ by simp + comp_id f := Quot.inductionOn f <| by simp + id_comp f := Quot.inductionOn f <| by simp + assoc f g h := Quot.inductionOn f <| Quot.inductionOn g <| Quot.inductionOn h <| by simp #align category_theory.quotient.category CategoryTheory.Quotient.category /-- The functor from a category to its quotient. -/ diff --git a/Mathlib/CategoryTheory/Shift/Basic.lean b/Mathlib/CategoryTheory/Shift/Basic.lean index d09a2d1a1cea1..62863ff34b0b9 100644 --- a/Mathlib/CategoryTheory/Shift/Basic.lean +++ b/Mathlib/CategoryTheory/Shift/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Johan Commelin, Andrew Yang -/ +import Mathlib.Algebra.Group.Basic import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Zero import Mathlib.CategoryTheory.Monoidal.End import Mathlib.CategoryTheory.Monoidal.Discrete diff --git a/Mathlib/CategoryTheory/Shift/ShiftSequence.lean b/Mathlib/CategoryTheory/Shift/ShiftSequence.lean index 722ec91df0ef8..2103b0a075264 100644 --- a/Mathlib/CategoryTheory/Shift/ShiftSequence.lean +++ b/Mathlib/CategoryTheory/Shift/ShiftSequence.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.CategoryTheory.Shift.CommShift +import Mathlib.CategoryTheory.Shift.Basic /-! Sequences of functors from a category equipped with a shift diff --git a/Mathlib/CategoryTheory/SingleObj.lean b/Mathlib/CategoryTheory/SingleObj.lean index 3ac73b2f21571..4fea4371e23df 100644 --- a/Mathlib/CategoryTheory/SingleObj.lean +++ b/Mathlib/CategoryTheory/SingleObj.lean @@ -19,19 +19,19 @@ from category theory to monoids and groups. ## Main definitions -Given a type `α` with a monoid structure, `SingleObj α` is `Unit` type with `Category` structure -such that `End (SingleObj α).star` is the monoid `α`. This can be extended to a functor +Given a type `M` with a monoid structure, `SingleObj M` is `Unit` type with `Category` structure +such that `End (SingleObj M).star` is the monoid `M`. This can be extended to a functor `MonCat ⥤ Cat`. -If `α` is a group, then `SingleObj α` is a groupoid. +If `M` is a group, then `SingleObj M` is a groupoid. -An element `x : α` can be reinterpreted as an element of `End (SingleObj.star α)` using +An element `x : M` can be reinterpreted as an element of `End (SingleObj.star M)` using `SingleObj.toEnd`. ## Implementation notes -- `categoryStruct.comp` on `End (SingleObj.star α)` is `flip (*)`, not `(*)`. This way - multiplication on `End` agrees with the multiplication on `α`. +- `categoryStruct.comp` on `End (SingleObj.star M)` is `flip (*)`, not `(*)`. This way + multiplication on `End` agrees with the multiplication on `M`. - By default, Lean puts instances into `CategoryTheory` namespace instead of `CategoryTheory.SingleObj`, so we give all names explicitly. @@ -50,44 +50,46 @@ abbrev SingleObj := namespace SingleObj -variable (α : Type u) +variable (M G : Type u) /-- One and `flip (*)` become `id` and `comp` for morphisms of the single object category. -/ -instance categoryStruct [One α] [Mul α] : CategoryStruct (SingleObj α) +instance categoryStruct [One M] [Mul M] : CategoryStruct (SingleObj M) where - Hom _ _ := α + Hom _ _ := M comp x y := y * x id _ := 1 #align category_theory.single_obj.category_struct CategoryTheory.SingleObj.categoryStruct +variable [Monoid M] [Group G] + /-- Monoid laws become category laws for the single object category. -/ -instance category [Monoid α] : Category (SingleObj α) +instance category : Category (SingleObj M) where comp_id := one_mul id_comp := mul_one assoc x y z := (mul_assoc z y x).symm #align category_theory.single_obj.category CategoryTheory.SingleObj.category -theorem id_as_one [Monoid α] (x : SingleObj α) : 𝟙 x = 1 := +theorem id_as_one (x : SingleObj M) : 𝟙 x = 1 := rfl #align category_theory.single_obj.id_as_one CategoryTheory.SingleObj.id_as_one -theorem comp_as_mul [Monoid α] {x y z : SingleObj α} (f : x ⟶ y) (g : y ⟶ z) : f ≫ g = g * f := +theorem comp_as_mul {x y z : SingleObj M} (f : x ⟶ y) (g : y ⟶ z) : f ≫ g = g * f := rfl #align category_theory.single_obj.comp_as_mul CategoryTheory.SingleObj.comp_as_mul -/-- Groupoid structure on `SingleObj α`. +/-- Groupoid structure on `SingleObj M`. See . -/ -instance groupoid [Group α] : Groupoid (SingleObj α) +instance groupoid : Groupoid (SingleObj G) where inv x := x⁻¹ inv_comp := mul_right_inv comp_inv := mul_left_inv #align category_theory.single_obj.groupoid CategoryTheory.SingleObj.groupoid -theorem inv_as_inv [Group α] {x y : SingleObj α} (f : x ⟶ y) : inv f = f⁻¹ := by +theorem inv_as_inv {x y : SingleObj G} (f : x ⟶ y) : inv f = f⁻¹ := by apply IsIso.inv_eq_of_hom_inv_id rw [comp_as_mul, inv_mul_self, id_as_one] #align category_theory.single_obj.inv_as_inv CategoryTheory.SingleObj.inv_as_inv @@ -95,55 +97,60 @@ theorem inv_as_inv [Group α] {x y : SingleObj α} (f : x ⟶ y) : inv f = f⁻ /-- Abbreviation that allows writing `CategoryTheory.SingleObj.star` rather than `Quiver.SingleObj.star`. -/ -abbrev star : SingleObj α := - Quiver.SingleObj.star α +abbrev star : SingleObj M := + Quiver.SingleObj.star M #align category_theory.single_obj.star CategoryTheory.SingleObj.star -/-- The endomorphisms monoid of the only object in `SingleObj α` is equivalent to the original - monoid α. -/ -def toEnd [Monoid α] : α ≃* End (SingleObj.star α) := - { Equiv.refl α with map_mul' := fun _ _ => rfl } +/-- The endomorphisms monoid of the only object in `SingleObj M` is equivalent to the original + monoid M. -/ +def toEnd : M ≃* End (SingleObj.star M) := + { Equiv.refl M with map_mul' := fun _ _ => rfl } #align category_theory.single_obj.to_End CategoryTheory.SingleObj.toEnd -theorem toEnd_def [Monoid α] (x : α) : toEnd α x = x := +theorem toEnd_def (x : M) : toEnd M x = x := rfl #align category_theory.single_obj.to_End_def CategoryTheory.SingleObj.toEnd_def -/-- There is a 1-1 correspondence between monoid homomorphisms `α → β` and functors between the +variable (N : Type v) [Monoid N] + +/-- There is a 1-1 correspondence between monoid homomorphisms `M → N` and functors between the corresponding single-object categories. It means that `SingleObj` is a fully faithful functor. See -- although we do not characterize when the functor is full or faithful. -/ -def mapHom (α : Type u) (β : Type v) [Monoid α] [Monoid β] : - (α →* β) ≃ SingleObj α ⥤ SingleObj β where +def mapHom : (M →* N) ≃ SingleObj M ⥤ SingleObj N where toFun f := { obj := id map := ⇑f map_id := fun _ => f.map_one map_comp := fun x y => f.map_mul y x } invFun f := - { toFun := fun x => f.map ((toEnd α) x) + { toFun := fun x => f.map ((toEnd M) x) map_one' := f.map_id _ map_mul' := fun x y => f.map_comp y x } left_inv := by aesop_cat right_inv := by aesop_cat #align category_theory.single_obj.map_hom CategoryTheory.SingleObj.mapHom -theorem mapHom_id (α : Type u) [Monoid α] : mapHom α α (MonoidHom.id α) = 𝟭 _ := +theorem mapHom_id : mapHom M M (MonoidHom.id M) = 𝟭 _ := rfl #align category_theory.single_obj.map_hom_id CategoryTheory.SingleObj.mapHom_id -theorem mapHom_comp {α : Type u} {β : Type v} [Monoid α] [Monoid β] (f : α →* β) {γ : Type w} - [Monoid γ] (g : β →* γ) : mapHom α γ (g.comp f) = mapHom α β f ⋙ mapHom β γ g := +variable {M N G} + +theorem mapHom_comp (f : M →* N) {P : Type w} [Monoid P] (g : N →* P) : + mapHom M P (g.comp f) = mapHom M N f ⋙ mapHom N P g := rfl #align category_theory.single_obj.map_hom_comp CategoryTheory.SingleObj.mapHom_comp +variable {C : Type v} [Category.{w} C] + /-- Given a function `f : C → G` from a category to a group, we get a functor `C ⥤ G` sending any morphism `x ⟶ y` to `f y * (f x)⁻¹`. -/ @[simps] -def differenceFunctor {C G} [Category C] [Group G] (f : C → G) : C ⥤ SingleObj G +def differenceFunctor (f : C → G) : C ⥤ SingleObj G where obj _ := () map {x y} _ := f y * (f x)⁻¹ @@ -156,6 +163,23 @@ def differenceFunctor {C G} [Category C] [Group G] (f : C → G) : C ⥤ SingleO rw [SingleObj.comp_as_mul, ← mul_assoc, mul_left_inj, mul_assoc, inv_mul_self, mul_one] #align category_theory.single_obj.difference_functor CategoryTheory.SingleObj.differenceFunctor +/-- A monoid homomorphism `f: M → End X` into the endomorphisms of an object `X` of a category `C` +induces a functor `SingleObj M ⥤ C`. -/ +@[simps] +def functor {X : C} (f : M →* End X) : SingleObj M ⥤ C where + obj _ := X + map a := f a + map_id _ := MonoidHom.map_one f + map_comp a b := MonoidHom.map_mul f b a + +/-- Construct a natural transformation between functors `SingleObj M ⥤ C` by +giving a compatible morphism `SingleObj.star M`. -/ +@[simps] +def natTrans {F G : SingleObj M ⥤ C} (u : F.obj (SingleObj.star M) ⟶ G.obj (SingleObj.star M)) + (h : ∀ a : M, F.map a ≫ u = u ≫ G.map a) : F ⟶ G where + app _ := u + naturality _ _ a := h a + end SingleObj end CategoryTheory @@ -164,49 +188,72 @@ open CategoryTheory namespace MonoidHom -/-- Reinterpret a monoid homomorphism `f : α → β` as a functor `(single_obj α) ⥤ (single_obj β)`. +variable {M : Type u} {N : Type v} [Monoid M] [Monoid N] + +/-- Reinterpret a monoid homomorphism `f : M → N` as a functor `(single_obj M) ⥤ (single_obj N)`. See also `CategoryTheory.SingleObj.mapHom` for an equivalence between these types. -/ @[reducible] -def toFunctor {α : Type u} {β : Type v} [Monoid α] [Monoid β] (f : α →* β) : - SingleObj α ⥤ SingleObj β := - SingleObj.mapHom α β f +def toFunctor (f : M →* N) : SingleObj M ⥤ SingleObj N := + SingleObj.mapHom M N f #align monoid_hom.to_functor MonoidHom.toFunctor @[simp] -theorem id_toFunctor (α : Type u) [Monoid α] : (id α).toFunctor = 𝟭 _ := +theorem comp_toFunctor (f : M →* N) {P : Type w} [Monoid P] (g : N →* P) : + (g.comp f).toFunctor = f.toFunctor ⋙ g.toFunctor := rfl -#align monoid_hom.id_to_functor MonoidHom.id_toFunctor +#align monoid_hom.comp_to_functor MonoidHom.comp_toFunctor + +variable (M) @[simp] -theorem comp_toFunctor {α : Type u} {β : Type v} [Monoid α] [Monoid β] (f : α →* β) {γ : Type w} - [Monoid γ] (g : β →* γ) : (g.comp f).toFunctor = f.toFunctor ⋙ g.toFunctor := +theorem id_toFunctor : (id M).toFunctor = 𝟭 _ := rfl -#align monoid_hom.comp_to_functor MonoidHom.comp_toFunctor +#align monoid_hom.id_to_functor MonoidHom.id_toFunctor end MonoidHom +namespace MulEquiv + +variable {M : Type u} {N : Type v} [Monoid M] [Monoid N] + +/-- Reinterpret a monoid isomorphism `f : M ≃* N` as an equivalence `SingleObj M ≌ SingleObj N`. -/ +@[simps!] +def toSingleObjEquiv (e : M ≃* N) : SingleObj M ≌ SingleObj N where + functor := e.toMonoidHom.toFunctor + inverse := e.symm.toMonoidHom.toFunctor + unitIso := eqToIso (by + rw [← MonoidHom.comp_toFunctor, ← MonoidHom.id_toFunctor] + congr 1 + aesop_cat) + counitIso := eqToIso (by + rw [← MonoidHom.comp_toFunctor, ← MonoidHom.id_toFunctor] + congr 1 + aesop_cat) + +end MulEquiv + namespace Units -variable (α : Type u) [Monoid α] +variable (M : Type u) [Monoid M] -- porting note: it was necessary to add `by exact` in this definition, presumably --- so that Lean4 is not confused by the fact that `α` has two opposite multiplications +-- so that Lean4 is not confused by the fact that `M` has two opposite multiplications /-- The units in a monoid are (multiplicatively) equivalent to the automorphisms of `star` when we think of the monoid as a single-object category. -/ -def toAut : αˣ ≃* Aut (SingleObj.star α) := - MulEquiv.trans (Units.mapEquiv (by exact SingleObj.toEnd α)) - (Aut.unitsEndEquivAut (SingleObj.star α)) +def toAut : Mˣ ≃* Aut (SingleObj.star M) := + MulEquiv.trans (Units.mapEquiv (by exact SingleObj.toEnd M)) + (Aut.unitsEndEquivAut (SingleObj.star M)) set_option linter.uppercaseLean3 false in #align units.to_Aut Units.toAut @[simp] -theorem toAut_hom (x : αˣ) : (toAut α x).hom = SingleObj.toEnd α x := +theorem toAut_hom (x : Mˣ) : (toAut M x).hom = SingleObj.toEnd M x := rfl set_option linter.uppercaseLean3 false in #align units.to_Aut_hom Units.toAut_hom @[simp] -theorem toAut_inv (x : αˣ) : (toAut α x).inv = SingleObj.toEnd α (x⁻¹ : αˣ) := +theorem toAut_inv (x : Mˣ) : (toAut M x).inv = SingleObj.toEnd M (x⁻¹ : Mˣ) := rfl set_option linter.uppercaseLean3 false in #align units.to_Aut_inv Units.toAut_inv diff --git a/Mathlib/CategoryTheory/Sites/Adjunction.lean b/Mathlib/CategoryTheory/Sites/Adjunction.lean index 9348a8deea0ae..1b5326cd15d98 100644 --- a/Mathlib/CategoryTheory/Sites/Adjunction.lean +++ b/Mathlib/CategoryTheory/Sites/Adjunction.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Adam Topaz -/ import Mathlib.CategoryTheory.Adjunction.Whiskering -import Mathlib.CategoryTheory.Sites.ConcreteSheafification import Mathlib.CategoryTheory.Sites.Whiskering +import Mathlib.CategoryTheory.Sites.Sheafification #align_import category_theory.sites.adjunction from "leanprover-community/mathlib"@"70fd9563a21e7b963887c9360bd29b2393e6225a" @@ -21,32 +21,26 @@ namespace CategoryTheory open GrothendieckTopology CategoryTheory Limits Opposite -universe w₁ w₂ v u +universe v u variable {C : Type u} [Category.{v} C] (J : GrothendieckTopology C) -variable {D : Type w₁} [Category.{max v u} D] +variable {D : Type*} [Category D] -variable {E : Type w₂} [Category.{max v u} E] +variable {E : Type*} [Category E] variable {F : D ⥤ E} {G : E ⥤ D} -variable [∀ (X : C) (S : J.Cover X) (P : Cᵒᵖ ⥤ D), PreservesLimit (S.index P).multicospan F] - -variable [ConcreteCategory.{max v u} D] [PreservesLimits (forget D)] +variable [HasWeakSheafify J D] [HasSheafCompose J F] /-- The forgetful functor from `Sheaf J D` to sheaves of types, for a concrete category `D` whose forgetful functor preserves the correct limits. -/ -abbrev sheafForget : Sheaf J D ⥤ SheafOfTypes J := +abbrev sheafForget [ConcreteCategory D] [HasSheafCompose J (forget D)] : + Sheaf J D ⥤ SheafOfTypes J := sheafCompose J (forget D) ⋙ (sheafEquivSheafOfTypes J).functor set_option linter.uppercaseLean3 false in #align category_theory.Sheaf_forget CategoryTheory.sheafForget --- We need to sheafify... -variable [∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : J.Cover X), HasMultiequalizer (S.index P)] - [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ D] - [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget D)] [ReflectsIsomorphisms (forget D)] - namespace Sheaf noncomputable section @@ -63,21 +57,21 @@ set_option linter.uppercaseLean3 false in def composeEquiv (adj : G ⊣ F) (X : Sheaf J E) (Y : Sheaf J D) : ((composeAndSheafify J G).obj X ⟶ Y) ≃ (X ⟶ (sheafCompose J F).obj Y) := let A := adj.whiskerRight Cᵒᵖ - { toFun := fun η => ⟨A.homEquiv _ _ (J.toSheafify _ ≫ η.val)⟩ - invFun := fun γ => ⟨J.sheafifyLift ((A.homEquiv _ _).symm ((sheafToPresheaf _ _).map γ)) Y.2⟩ + { toFun := fun η => ⟨A.homEquiv _ _ (toSheafify J _ ≫ η.val)⟩ + invFun := fun γ => ⟨sheafifyLift J ((A.homEquiv _ _).symm ((sheafToPresheaf _ _).map γ)) Y.2⟩ left_inv := by intro η ext1 dsimp symm - apply J.sheafifyLift_unique + apply sheafifyLift_unique rw [Equiv.symm_apply_apply] right_inv := by intro γ ext1 dsimp -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [J.toSheafify_sheafifyLift, Equiv.apply_symm_apply] } + erw [toSheafify_sheafifyLift, Equiv.apply_symm_apply] } set_option linter.uppercaseLean3 false in #align category_theory.Sheaf.compose_equiv CategoryTheory.Sheaf.composeEquiv @@ -113,6 +107,8 @@ instance [IsRightAdjoint F] : IsRightAdjoint (sheafCompose J F) := section ForgetToType +variable [ConcreteCategory D] [HasSheafCompose J (forget D)] + /-- This is the functor sending a sheaf of types `X` to the sheafification of `X ⋙ G`. -/ abbrev composeAndSheafifyFromTypes (G : Type max v u ⥤ D) : SheafOfTypes J ⥤ Sheaf J D := (sheafEquivSheafOfTypes J).inverse ⋙ composeAndSheafify _ G @@ -132,7 +128,7 @@ theorem adjunctionToTypes_unit_app_val {G : Type max v u ⥤ D} (adj : G ⊣ for (Y : SheafOfTypes J) : ((adjunctionToTypes J adj).unit.app Y).val = (adj.whiskerRight _).unit.app ((sheafOfTypesToPresheaf J).obj Y) ≫ - whiskerRight (J.toSheafify _) (forget D) := by + whiskerRight (toSheafify J _) (forget D) := by dsimp [adjunctionToTypes, Adjunction.comp] simp rfl @@ -143,12 +139,12 @@ set_option linter.uppercaseLean3 false in theorem adjunctionToTypes_counit_app_val {G : Type max v u ⥤ D} (adj : G ⊣ forget D) (X : Sheaf J D) : ((adjunctionToTypes J adj).counit.app X).val = - J.sheafifyLift ((Functor.associator _ _ _).hom ≫ (adj.whiskerRight _).counit.app _) X.2 := by - apply J.sheafifyLift_unique + sheafifyLift J ((Functor.associator _ _ _).hom ≫ (adj.whiskerRight _).counit.app _) X.2 := by + apply sheafifyLift_unique dsimp only [adjunctionToTypes, Adjunction.comp, NatTrans.comp_app, instCategorySheaf_comp_val, instCategorySheaf_id_val] rw [adjunction_counit_app_val] - erw [Category.id_comp, J.sheafifyMap_sheafifyLift, J.toSheafify_sheafifyLift] + erw [Category.id_comp, sheafifyMap_sheafifyLift, toSheafify_sheafifyLift] ext dsimp [sheafEquivSheafOfTypes, Equivalence.symm, Equivalence.toAdjunction, NatIso.ofComponents, Adjunction.whiskerRight, Adjunction.mkOfUnitCounit] diff --git a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean index d610e91cea37a..bd22d27c7c4f4 100644 --- a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean @@ -3,10 +3,8 @@ Copyright (c) 2021 Adam Topaz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Adam Topaz -/ -import Mathlib.CategoryTheory.Adjunction.FullyFaithful import Mathlib.CategoryTheory.Sites.Plus import Mathlib.CategoryTheory.Limits.Shapes.ConcreteCategory -import Mathlib.CategoryTheory.ConcreteCategory.Elementwise #align_import category_theory.sites.sheafification from "leanprover-community/mathlib"@"70fd9563a21e7b963887c9360bd29b2393e6225a" @@ -37,7 +35,7 @@ section variable [ConcreteCategory.{max v u} D] -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike -- porting note: removed @[nolint has_nonempty_instance] /-- A concrete version of the multiequalizer, to be used below. -/ @@ -52,7 +50,7 @@ namespace Meq variable [ConcreteCategory.{max v u} D] -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike instance {X} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) : CoeFun (Meq P S) fun _ => ∀ I : S.Arrow, P.obj (op I.Y) := @@ -145,7 +143,7 @@ namespace Plus variable [ConcreteCategory.{max v u} D] -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike variable [PreservesLimits (forget D)] @@ -525,7 +523,8 @@ noncomputable def toSheafification : 𝟭 _ ⟶ sheafification J D := #align category_theory.grothendieck_topology.to_sheafification CategoryTheory.GrothendieckTopology.toSheafification @[simp] -theorem toSheafification_app (P : Cᵒᵖ ⥤ D) : (J.toSheafification D).app P = J.toSheafify P := +theorem toSheafification_app (P : Cᵒᵖ ⥤ D) : + (J.toSheafification D).app P = J.toSheafify P := rfl #align category_theory.grothendieck_topology.to_sheafification_app CategoryTheory.GrothendieckTopology.toSheafification_app @@ -550,8 +549,7 @@ theorem isoSheafify_hom {P : Cᵒᵖ ⥤ D} (hP : Presheaf.IsSheaf J P) : rfl #align category_theory.grothendieck_topology.iso_sheafify_hom CategoryTheory.GrothendieckTopology.isoSheafify_hom -/-- Given a sheaf `Q` and a morphism `P ⟶ Q`, construct a morphism from -`J.sheafify P` to `Q`. -/ +/-- Given a sheaf `Q` and a morphism `P ⟶ Q`, construct a morphism from `J.sheafify P` to `Q`. -/ noncomputable def sheafifyLift {P Q : Cᵒᵖ ⥤ D} (η : P ⟶ Q) (hQ : Presheaf.IsSheaf J Q) : J.sheafify P ⟶ Q := J.plusLift (J.plusLift η hQ) hQ @@ -613,26 +611,26 @@ variable (D) /-- The sheafification functor, as a functor taking values in `Sheaf`. -/ @[simps] -noncomputable def presheafToSheaf : (Cᵒᵖ ⥤ D) ⥤ Sheaf J D where +noncomputable def plusPlusSheaf : (Cᵒᵖ ⥤ D) ⥤ Sheaf J D where obj P := ⟨J.sheafify P, J.sheafify_isSheaf P⟩ map η := ⟨J.sheafifyMap η⟩ map_id _ := Sheaf.Hom.ext _ _ <| J.sheafifyMap_id _ map_comp _ _ := Sheaf.Hom.ext _ _ <| J.sheafifyMap_comp _ _ set_option linter.uppercaseLean3 false in -#align category_theory.presheaf_to_Sheaf CategoryTheory.presheafToSheaf +#align category_theory.presheaf_to_Sheaf CategoryTheory.plusPlusSheaf -instance presheafToSheaf_preservesZeroMorphisms [Preadditive D] : - (presheafToSheaf J D).PreservesZeroMorphisms where +instance plusPlusSheaf_preservesZeroMorphisms [Preadditive D] : + (plusPlusSheaf J D).PreservesZeroMorphisms where map_zero F G := by ext : 3 refine' colimit.hom_ext (fun j => _) erw [colimit.ι_map, comp_zero, J.plusMap_zero, J.diagramNatTrans_zero, zero_comp] set_option linter.uppercaseLean3 false in -#align category_theory.presheaf_to_Sheaf_preserves_zero_morphisms CategoryTheory.presheafToSheaf_preservesZeroMorphisms +#align category_theory.presheaf_to_Sheaf_preserves_zero_morphisms CategoryTheory.plusPlusSheaf_preservesZeroMorphisms /-- The sheafification functor is left adjoint to the forgetful functor. -/ @[simps! unit_app counit_app_val] -noncomputable def sheafificationAdjunction : presheafToSheaf J D ⊣ sheafToPresheaf J D := +noncomputable def plusPlusAdjunction : plusPlusSheaf J D ⊣ sheafToPresheaf J D := Adjunction.mkOfHomEquiv { homEquiv := fun P Q => { toFun := fun e => J.toSheafify P ≫ e.val @@ -645,10 +643,10 @@ noncomputable def sheafificationAdjunction : presheafToSheaf J D ⊣ sheafToPres homEquiv_naturality_right := fun η γ => by dsimp rw [Category.assoc] } -#align category_theory.sheafification_adjunction CategoryTheory.sheafificationAdjunction +#align category_theory.sheafification_adjunction CategoryTheory.plusPlusAdjunction noncomputable instance sheafToPresheafIsRightAdjoint : IsRightAdjoint (sheafToPresheaf J D) := - ⟨_, sheafificationAdjunction J D⟩ + ⟨_, plusPlusAdjunction J D⟩ set_option linter.uppercaseLean3 false in #align category_theory.Sheaf_to_presheaf_is_right_adjoint CategoryTheory.sheafToPresheafIsRightAdjoint @@ -666,31 +664,7 @@ set_option linter.uppercaseLean3 false in @[simps! hom_app inv_app] noncomputable def GrothendieckTopology.sheafificationIsoPresheafToSheafCompSheafToPreasheaf : - J.sheafification D ≅ presheafToSheaf J D ⋙ sheafToPresheaf J D := + J.sheafification D ≅ plusPlusSheaf J D ⋙ sheafToPresheaf J D := NatIso.ofComponents fun P => Iso.refl _ -variable {J D} - -/-- A sheaf `P` is isomorphic to its own sheafification. -/ -@[simps] -noncomputable def sheafificationIso (P : Sheaf J D) : P ≅ (presheafToSheaf J D).obj P.val where - hom := ⟨(J.isoSheafify P.2).hom⟩ - inv := ⟨(J.isoSheafify P.2).inv⟩ - hom_inv_id := by - ext1 - apply (J.isoSheafify P.2).hom_inv_id - inv_hom_id := by - ext1 - apply (J.isoSheafify P.2).inv_hom_id -#align category_theory.sheafification_iso CategoryTheory.sheafificationIso - -instance isIso_sheafificationAdjunction_counit (P : Sheaf J D) : - IsIso ((sheafificationAdjunction J D).counit.app P) := - isIso_of_fully_faithful (sheafToPresheaf J D) _ -#align category_theory.is_iso_sheafification_adjunction_counit CategoryTheory.isIso_sheafificationAdjunction_counit - -instance sheafification_reflective : IsIso (sheafificationAdjunction J D).counit := - NatIso.isIso_of_isIso_app _ -#align category_theory.sheafification_reflective CategoryTheory.sheafification_reflective - end CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean b/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean index c5037f936904f..d0c7ef731078c 100644 --- a/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean +++ b/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Dagur Asgeirsson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Dagur Asgeirsson -/ -import Mathlib.CategoryTheory.Sites.ConcreteSheafification +import Mathlib.CategoryTheory.Sites.Sheafification /-! @@ -37,10 +37,7 @@ noncomputable def constantPresheafAdj {T : C} (hT : IsTerminal T) : simp } naturality := by intros; ext; simp /- Note: `aesop` works but is kind of slow -/ } } -variable [ConcreteCategory D] [PreservesLimits (forget D)] - [∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : J.Cover X), HasMultiequalizer (S.index P)] - [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ D] - [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget D)] [ReflectsIsomorphisms (forget D)] +variable [HasWeakSheafify J D] /-- The functor which maps an object of `D` to the constant sheaf at that object, i.e. the diff --git a/Mathlib/CategoryTheory/Sites/CoverLifting.lean b/Mathlib/CategoryTheory/Sites/CoverLifting.lean index 7a1c6e3f97d43..ab7716c0eae51 100644 --- a/Mathlib/CategoryTheory/Sites/CoverLifting.lean +++ b/Mathlib/CategoryTheory/Sites/CoverLifting.lean @@ -3,9 +3,9 @@ Copyright (c) 2021 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.CategoryTheory.Sites.ConcreteSheafification import Mathlib.CategoryTheory.Limits.KanExtension import Mathlib.CategoryTheory.Sites.CoverPreserving +import Mathlib.CategoryTheory.Sites.Sheafification #align_import category_theory.sites.cover_lifting from "leanprover-community/mathlib"@"14b69e9f3c16630440a2cbd46f1ddad0d561dee7" @@ -369,13 +369,7 @@ noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K] #align category_theory.sites.pullback_copullback_adjunction CategoryTheory.Functor.sheafAdjunctionCocontinuous variable - [ConcreteCategory.{max v u} A] - [PreservesLimits (forget A)] - [ReflectsIsomorphisms (forget A)] - [∀ (X : C), PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget A)] - [∀ (X : C), HasColimitsOfShape (J.Cover X)ᵒᵖ A] - [∀ (X : D), PreservesColimitsOfShape (K.Cover X)ᵒᵖ (forget A)] - [∀ (X : D), HasColimitsOfShape (K.Cover X)ᵒᵖ A] + [HasWeakSheafify J A] [HasWeakSheafify K A] [G.IsCocontinuous J K] [G.IsContinuous J K] /-- The natural isomorphism exhibiting compatibility between pushforward and sheafification. -/ @@ -393,9 +387,9 @@ def Functor.pushforwardContinuousSheafificationCompatibility : /- Implementation: This is primarily used to prove the lemma `pullbackSheafificationCompatibility_hom_app_val`. -/ lemma Functor.toSheafify_pullbackSheafificationCompatibility (F : Dᵒᵖ ⥤ A) : - J.toSheafify (G.op ⋙ F) ≫ + toSheafify J (G.op ⋙ F) ≫ ((G.pushforwardContinuousSheafificationCompatibility A J K).hom.app F).val = - whiskerLeft _ (K.toSheafify _) := by + whiskerLeft _ (toSheafify K _) := by dsimp [pushforwardContinuousSheafificationCompatibility, Adjunction.leftAdjointUniq] apply Quiver.Hom.op_inj apply coyoneda.map_injective @@ -403,25 +397,24 @@ lemma Functor.toSheafify_pullbackSheafificationCompatibility (F : Dᵒᵖ ⥤ A) dsimp [Functor.preimage, Full.preimage, coyoneda, Adjunction.leftAdjointsCoyonedaEquiv] erw [Adjunction.homEquiv_unit, Adjunction.homEquiv_counit] dsimp [Adjunction.comp] - simp only [sheafificationAdjunction_unit_app, Category.comp_id, Functor.map_id, - whiskerLeft_id', GrothendieckTopology.sheafifyMap_comp, - GrothendieckTopology.sheafifyMap_sheafifyLift, Category.id_comp, - Category.assoc, GrothendieckTopology.toSheafify_sheafifyLift] + simp only [Category.comp_id, map_id, whiskerLeft_id', map_comp, Sheaf.instCategorySheaf_comp_val, + sheafificationAdjunction_counit_app_val, sheafifyMap_sheafifyLift, + Category.id_comp, Category.assoc, toSheafify_sheafifyLift] ext t s : 3 dsimp [sheafPushforwardContinuous] congr 1 simp only [← Category.assoc] convert Category.id_comp (obj := A) _ have := (Ran.adjunction A G.op).left_triangle - apply_fun (fun e => (e.app (K.sheafify F)).app s) at this + apply_fun (fun e => (e.app (sheafify K F)).app s) at this exact this @[simp] lemma Functor.pushforwardContinuousSheafificationCompatibility_hom_app_val (F : Dᵒᵖ ⥤ A) : ((G.pushforwardContinuousSheafificationCompatibility A J K).hom.app F).val = - J.sheafifyLift (whiskerLeft G.op <| K.toSheafify F) + sheafifyLift J (whiskerLeft G.op <| toSheafify K F) ((presheafToSheaf K A ⋙ G.sheafPushforwardContinuous A J K).obj F).cond := by - apply J.sheafifyLift_unique + apply sheafifyLift_unique apply toSheafify_pullbackSheafificationCompatibility end CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/CoverPreserving.lean b/Mathlib/CategoryTheory/Sites/CoverPreserving.lean index 6f29ac9836a05..88882611e28f7 100644 --- a/Mathlib/CategoryTheory/Sites/CoverPreserving.lean +++ b/Mathlib/CategoryTheory/Sites/CoverPreserving.lean @@ -120,7 +120,7 @@ theorem Presieve.FamilyOfElements.Compatible.functorPushforward : theorem CompatiblePreserving.apply_map {Y : C} {f : Y ⟶ Z} (hf : T f) : x.functorPushforward G (G.map f) (image_mem_functorPushforward G T hf) = x f hf := by unfold FamilyOfElements.functorPushforward - rcases e₁ : getFunctorPushforwardStructure (image_mem_functorPushforward G T hf) with + rcases getFunctorPushforwardStructure (image_mem_functorPushforward G T hf) with ⟨X, g, f', hg, eq⟩ simpa using hG.compatible ℱ h f' (𝟙 _) hg hf (by simp [eq]) #align category_theory.compatible_preserving.apply_map CategoryTheory.CompatiblePreserving.apply_map diff --git a/Mathlib/CategoryTheory/Sites/DenseSubsite.lean b/Mathlib/CategoryTheory/Sites/DenseSubsite.lean index 290ec99123a7e..77298a1dbed41 100644 --- a/Mathlib/CategoryTheory/Sites/DenseSubsite.lean +++ b/Mathlib/CategoryTheory/Sites/DenseSubsite.lean @@ -545,14 +545,7 @@ noncomputable def sheafEquivOfCoverPreservingCoverLifting : Sheaf J A ≌ Sheaf set_option linter.uppercaseLean3 false in #align category_theory.cover_dense.Sheaf_equiv_of_cover_preserving_cover_lifting CategoryTheory.Functor.IsCoverDense.sheafEquivOfCoverPreservingCoverLifting -variable - [ConcreteCategory.{max v u} A] - [Limits.PreservesLimits (forget A)] - [ReflectsIsomorphisms (forget A)] - [∀ (X : C), Limits.PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget A)] - [∀ (X : C), Limits.HasColimitsOfShape (J.Cover X)ᵒᵖ A] - [∀ (X : D), Limits.PreservesColimitsOfShape (K.Cover X)ᵒᵖ (forget A)] - [∀ (X : D), Limits.HasColimitsOfShape (K.Cover X)ᵒᵖ A] +variable [HasWeakSheafify J A] [HasWeakSheafify K A] /-- The natural isomorphism exhibiting the compatibility of `sheafEquivOfCoverPreservingCoverLifting` with sheafification. -/ diff --git a/Mathlib/CategoryTheory/Sites/EffectiveEpimorphic.lean b/Mathlib/CategoryTheory/Sites/EffectiveEpimorphic.lean index 4bfcdc1c476e9..05af684ee0372 100644 --- a/Mathlib/CategoryTheory/Sites/EffectiveEpimorphic.lean +++ b/Mathlib/CategoryTheory/Sites/EffectiveEpimorphic.lean @@ -5,7 +5,9 @@ Authors: Adam Topaz -/ import Mathlib.CategoryTheory.Sites.Sieves -import Mathlib.CategoryTheory.Limits.Shapes.KernelPair +import Mathlib.CategoryTheory.Limits.Shapes.FiniteProducts +import Mathlib.CategoryTheory.Limits.Shapes.RegularMono +import Mathlib.CategoryTheory.Limits.Shapes.ZeroObjects import Mathlib.Tactic.ApplyFun /-! diff --git a/Mathlib/CategoryTheory/Sites/Equivalence.lean b/Mathlib/CategoryTheory/Sites/Equivalence.lean new file mode 100644 index 0000000000000..0c1967d0b334c --- /dev/null +++ b/Mathlib/CategoryTheory/Sites/Equivalence.lean @@ -0,0 +1,231 @@ +/- +Copyright (c) 2023 Dagur Asgeirsson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Dagur Asgeirsson +-/ +import Mathlib.CategoryTheory.Sites.InducedTopology +import Mathlib.CategoryTheory.Sites.Whiskering +/-! +# Equivalences of sheaf categories + +Given a site `(C, J)` and a category `D` which is equivalent to `C`, with `C` and `D` possibly large +and possibly in different universes, we transport the Grothendieck topology `J` on `C` to `D` and +prove that the sheaf categories are equivalent. + +We also prove that sheafification and the property `HasSheafCompose` transport nicely over this +equivalence, and apply it to essentially small sites. We also provide instances for existence of +sufficiently small limits in the sheaf category on the essentially small site. + +## Main definitions + +* `CategoryTheory.Equivalence.sheafCongr` is the equivalence of sheaf categories. + +* `CategoryTheory.Equivalence.transportAndSheafify` is the functor which takes a presheaf on `C`, + transports it over the equivalence to `D`, sheafifies there and then transports back to `C`. + +* `CategoryTheory.Equivalence.transportSheafificationAdjunction`: `transportAndSheafify` is + left adjoint to the functor taking a sheaf to its underlying presheaf. + +* `CategoryTheory.smallSheafify` is the functor which takes a presheaf on an essentially small site + `(C, J)`, transports to a small model, sheafifies there and then transports back to `C`. + +* `CategoryTheory.smallSheafificationAdjunction`: `smallSheafify` is left adjoint to the functor + taking a sheaf to its underlying presheaf. + +-/ + +universe u + +namespace CategoryTheory + +open Functor Limits GrothendieckTopology + +namespace Equivalence + +variable {C : Type*} [Category C] (J : GrothendieckTopology C) +variable {D : Type*} [Category D] (e : C ≌ D) +variable (A : Type*) [Category A] + +theorem locallyCoverDense : LocallyCoverDense J e.inverse := by + intro X T + convert T.prop + ext Z f + constructor + · rintro ⟨_, _, g', hg, rfl⟩ + exact T.val.downward_closed hg g' + · intro hf + refine ⟨e.functor.obj Z, (Adjunction.homEquiv e.toAdjunction _ _).symm f, e.unit.app Z, ?_, ?_⟩ + · simp only [Adjunction.homEquiv_counit, Functor.id_obj, Equivalence.toAdjunction_counit, + Sieve.functorPullback_apply, Presieve.functorPullback_mem, Functor.map_comp, + Equivalence.inv_fun_map, Functor.comp_obj, Category.assoc, Equivalence.unit_inverse_comp, + Category.comp_id] + exact T.val.downward_closed hf _ + · simp + +theorem coverPreserving : + CoverPreserving J (e.locallyCoverDense J).inducedTopology e.functor where + cover_preserve {U S} h := by + change _ ∈ J.sieves (e.inverse.obj (e.functor.obj U)) + convert J.pullback_stable (e.unitInv.app U) h + ext Z f + rw [← Sieve.functorPushforward_comp] + simp only [Sieve.functorPushforward_apply, Presieve.functorPushforward, exists_and_left, id_obj, + comp_obj, Sieve.pullback_apply] + constructor + · rintro ⟨W, g, hg, x, rfl⟩ + rw [Category.assoc] + apply S.downward_closed + simpa using S.downward_closed hg _ + · intro hf + exact ⟨_, e.unitInv.app Z ≫ f ≫ e.unitInv.app U, S.downward_closed hf _, + e.unit.app Z ≫ e.unit.app _, (by simp)⟩ + +instance : IsCoverDense e.functor (e.locallyCoverDense J).inducedTopology where + is_cover U := by + change _ ∈ J.sieves _ + convert J.top_mem (e.inverse.obj U) + ext Y f + simp only [Sieve.functorPushforward_apply, Presieve.functorPushforward, exists_and_left, + Sieve.top_apply, iff_true] + exact ⟨e.functor.obj Y, (Adjunction.homEquiv e.toAdjunction _ _).symm f, + Presieve.in_coverByImage _ _, e.unit.app _, (by simp)⟩ + +instance : IsContinuous e.functor J (e.locallyCoverDense J).inducedTopology := + IsCoverDense.isContinuous _ _ _ (e.coverPreserving J) + +instance : IsCoverDense e.inverse J where + is_cover U := by + convert J.top_mem U + ext Y f + simp only [Sieve.functorPushforward_apply, Presieve.functorPushforward, exists_and_left, + Sieve.top_apply, iff_true] + let g : e.inverse.obj _ ⟶ U := (e.unitInv.app Y) ≫ f + have : (Sieve.coverByImage e.inverse U).arrows g := Presieve.in_coverByImage _ g + replace := Sieve.downward_closed _ this (e.unit.app Y) + simpa using this + +instance : IsContinuous e.inverse (e.locallyCoverDense J).inducedTopology J := + IsCoverDense.isContinuous _ _ _ (e.locallyCoverDense J).inducedTopology_coverPreserving + +/-- The functor in the equivalence of sheaf categories. -/ +@[simps!] +def sheafCongr.functor : Sheaf J A ⥤ Sheaf (e.locallyCoverDense J).inducedTopology A where + obj F := ⟨e.inverse.op ⋙ F.val, e.inverse.op_comp_isSheaf _ _ _⟩ + map f := ⟨whiskerLeft e.inverse.op f.val⟩ + +/-- The inverse in the equivalence of sheaf categories. -/ +@[simps!] +def sheafCongr.inverse : Sheaf (e.locallyCoverDense J).inducedTopology A ⥤ Sheaf J A where + obj F := ⟨e.functor.op ⋙ F.val, e.functor.op_comp_isSheaf _ _ _⟩ + map f := ⟨whiskerLeft e.functor.op f.val⟩ + +/-- The unit iso in the equivalence of sheaf categories. -/ +@[simps!] +def sheafCongr.unitIso : 𝟭 (Sheaf J A) ≅ functor J e A ⋙ inverse J e A := + NatIso.ofComponents (fun F ↦ ⟨⟨(isoWhiskerRight e.op.unitIso F.val).hom⟩, + ⟨(isoWhiskerRight e.op.unitIso F.val).inv⟩, + Sheaf.hom_ext _ _ (isoWhiskerRight e.op.unitIso F.val).hom_inv_id, + Sheaf.hom_ext _ _ (isoWhiskerRight e.op.unitIso F.val).inv_hom_id⟩ ) (by aesop) + +/-- The counit iso in the equivalence of sheaf categories. -/ +@[simps!] +def sheafCongr.counitIso : inverse J e A ⋙ functor J e A ≅ 𝟭 (Sheaf _ A) := + NatIso.ofComponents (fun F ↦ ⟨⟨(isoWhiskerRight e.op.counitIso F.val).hom⟩, + ⟨(isoWhiskerRight e.op.counitIso F.val).inv⟩, + Sheaf.hom_ext _ _ (isoWhiskerRight e.op.counitIso F.val).hom_inv_id, + Sheaf.hom_ext _ _ (isoWhiskerRight e.op.counitIso F.val).inv_hom_id⟩ ) (by aesop) + +/-- The equivalence of sheaf categories. -/ +def sheafCongr : Sheaf J A ≌ Sheaf (e.locallyCoverDense J).inducedTopology A where + functor := sheafCongr.functor J e A + inverse := sheafCongr.inverse J e A + unitIso := sheafCongr.unitIso J e A + counitIso := sheafCongr.counitIso J e A + functor_unitIso_comp X := by + ext + simp only [id_obj, sheafCongr.functor_obj_val_obj, comp_obj, Sheaf.instCategorySheaf_comp_val, + NatTrans.comp_app, sheafCongr.inverse_obj_val_obj, Opposite.unop_op, + sheafCongr.functor_map_val_app, sheafCongr.unitIso_hom_app_val_app, + sheafCongr.counitIso_hom_app_val_app, sheafCongr.functor_obj_val_map, Quiver.Hom.unop_op, + Sheaf.instCategorySheaf_id_val, NatTrans.id_app] + simp [← Functor.map_comp, ← op_comp] + +variable [HasSheafify (e.locallyCoverDense J).inducedTopology A] + +/-- Transport a presheaf to the equivalent category and sheafify there. -/ +noncomputable +def transportAndSheafify : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A := + e.op.congrLeft.functor ⋙ presheafToSheaf _ _ ⋙ (e.sheafCongr J A).inverse + +/-- An auxiliary definition for the sheafification adjunction. -/ +noncomputable +def transportIsoSheafToPresheaf : (e.sheafCongr J A).functor ⋙ + sheafToPresheaf (e.locallyCoverDense J).inducedTopology A ⋙ + e.op.congrLeft.inverse ≅ sheafToPresheaf J A := + NatIso.ofComponents (fun F ↦ isoWhiskerRight e.op.unitIso.symm F.val) + (by intros; ext; simp [Equivalence.sheafCongr]) + +/-- Transporting and sheafifying is left adjoint to taking the underlying presheaf. -/ +noncomputable +def transportSheafificationAdjunction : transportAndSheafify J e A ⊣ sheafToPresheaf J A := + ((e.op.congrLeft.toAdjunction.comp (sheafificationAdjunction _ _)).comp + (e.sheafCongr (A := A) J).symm.toAdjunction).ofNatIsoRight (transportIsoSheafToPresheaf _ _ _) + +noncomputable instance : PreservesFiniteLimits <| transportAndSheafify J e A where + preservesFiniteLimits _ := compPreservesLimitsOfShape _ _ + +/-- Transport `HasSheafify` along an equivalence of sites. -/ +theorem hasSheafify : HasSheafify J A := + HasSheafify.mk' J A (transportSheafificationAdjunction J e A) + +variable {A : Type*} [Category A] {B : Type*} [Category B] (F : A ⥤ B) + [(e.locallyCoverDense J).inducedTopology.HasSheafCompose F] + +theorem hasSheafCompose : J.HasSheafCompose F where + isSheaf P hP := by + let K := (e.locallyCoverDense J).inducedTopology + have hP' : Presheaf.IsSheaf K (e.inverse.op ⋙ P ⋙ F) := by + change Presheaf.IsSheaf K ((_ ⋙ _) ⋙ _) + apply HasSheafCompose.isSheaf + exact e.inverse.op_comp_isSheaf K J ⟨P, hP⟩ + replace hP' : Presheaf.IsSheaf J (e.functor.op ⋙ e.inverse.op ⋙ P ⋙ F) := + e.functor.op_comp_isSheaf _ _ ⟨_, hP'⟩ + exact (Presheaf.isSheaf_of_iso_iff ((isoWhiskerRight e.op.unitIso.symm (P ⋙ F)))).mp hP' + +end Equivalence + +variable {C : Type*} [Category C] [EssentiallySmall C] (J : GrothendieckTopology C) +variable (A : Type*) [Category A] +variable (B : Type*) [Category B] (F : A ⥤ B) +variable [HasSheafify ((equivSmallModel C).locallyCoverDense J).inducedTopology A] +variable [((equivSmallModel C).locallyCoverDense J).inducedTopology.HasSheafCompose F] + +/-- Transport to a small model and sheafify there. -/ +noncomputable +def smallSheafify : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A := (equivSmallModel C).transportAndSheafify J A + +/-- +Transporting to a small model and sheafifying there is left adjoint to the underlying presheaf +functor +-/ +noncomputable +def smallSheafificationAdjunction : smallSheafify J A ⊣ sheafToPresheaf J A := + (equivSmallModel C).transportSheafificationAdjunction J A + +noncomputable instance hasSheafifyEssentiallySmallSite : HasSheafify J A := + (equivSmallModel C).hasSheafify J A + +instance hasSheafComposeEssentiallySmallSite : HasSheafCompose J F := + (equivSmallModel C).hasSheafCompose J F + +instance hasLimitsEssentiallySmallSite + [HasLimits <| Sheaf ((equivSmallModel C).locallyCoverDense J).inducedTopology A] : + HasLimitsOfSize <| Sheaf J A := + Adjunction.has_limits_of_equivalence ((equivSmallModel C).sheafCongr J A).functor + +instance hasColimitsEssentiallySmallSite + [HasColimits <| Sheaf ((equivSmallModel C).locallyCoverDense J).inducedTopology A] : + HasColimitsOfSize <| Sheaf J A := + Adjunction.has_colimits_of_equivalence ((equivSmallModel C).sheafCongr J A).functor + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/LeftExact.lean b/Mathlib/CategoryTheory/Sites/LeftExact.lean index e0c2887b7000f..f06f09e2aca51 100644 --- a/Mathlib/CategoryTheory/Sites/LeftExact.lean +++ b/Mathlib/CategoryTheory/Sites/LeftExact.lean @@ -3,11 +3,11 @@ Copyright (c) 2021 Adam Topaz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Adam Topaz -/ -import Mathlib.CategoryTheory.Sites.ConcreteSheafification import Mathlib.CategoryTheory.Sites.Limits import Mathlib.CategoryTheory.Limits.FunctorCategory import Mathlib.CategoryTheory.Limits.FilteredColimitCommutesFiniteLimit import Mathlib.CategoryTheory.Adhesive +import Mathlib.CategoryTheory.Sites.Sheafification #align_import category_theory.sites.left_exact from "leanprover-community/mathlib"@"59382264386afdbaf1727e617f5fdda511992eb9" @@ -243,7 +243,7 @@ variable (K : Type w') variable [SmallCategory K] [FinCategory K] [HasLimitsOfShape K D] instance preservesLimitsOfShape_presheafToSheaf : - PreservesLimitsOfShape K (presheafToSheaf J D) := by + PreservesLimitsOfShape K (plusPlusSheaf J D) := by let e := (FinCategory.equivAsType K).symm.trans (AsSmall.equiv.{0, 0, max v u}) haveI : HasLimitsOfShape (AsSmall.{max v u} (FinCategory.AsType K)) D := Limits.hasLimitsOfShape_of_equivalence e @@ -261,22 +261,42 @@ instance preservesLimitsOfShape_presheafToSheaf : reflectsLimitsOfShapeOfReflectsIsomorphisms -- porting note: the mathlib proof was by `apply is_limit_of_preserves (J.sheafification D) hS` have : PreservesLimitsOfShape (AsSmall.{max v u} (FinCategory.AsType K)) - (presheafToSheaf J D ⋙ sheafToPresheaf J D) := + (plusPlusSheaf J D ⋙ sheafToPresheaf J D) := preservesLimitsOfShapeOfNatIso (J.sheafificationIsoPresheafToSheafCompSheafToPreasheaf D) - exact isLimitOfPreserves (presheafToSheaf J D ⋙ sheafToPresheaf J D) hS + exact isLimitOfPreserves (plusPlusSheaf J D ⋙ sheafToPresheaf J D) hS instance preservesfiniteLimits_presheafToSheaf [HasFiniteLimits D] : - PreservesFiniteLimits (presheafToSheaf J D) := by + PreservesFiniteLimits (plusPlusSheaf J D) := by apply preservesFiniteLimitsOfPreservesFiniteLimitsOfSize.{max v u} intros infer_instance +instance : HasWeakSheafify J D := ⟨sheafToPresheafIsRightAdjoint J D⟩ + +variable (J D) + +/-- `plusPlusSheaf` is isomorphic to an arbitrary choice of left adjoint. -/ +def plusPlusSheafIsoPresheafToSheaf : plusPlusSheaf J D ≅ presheafToSheaf J D := + (plusPlusAdjunction J D).leftAdjointUniq (sheafificationAdjunction J D) + +/-- `plusPlusFunctor` is isomorphic to `sheafification`. -/ +def plusPlusFunctorIsoSheafification : J.sheafification D ≅ sheafification J D := + isoWhiskerRight (plusPlusSheafIsoPresheafToSheaf J D) (sheafToPresheaf J D) + +/-- `plusPlus` is isomorphic to `sheafify`. -/ +def plusPlusIsoSheafify (P : Cᵒᵖ ⥤ D) : J.sheafify P ≅ sheafify J P := + (sheafToPresheaf J D).mapIso ((plusPlusSheafIsoPresheafToSheaf J D).app P) + +instance [HasFiniteLimits D] : HasSheafify J D := HasSheafify.mk' J D (plusPlusAdjunction J D) + +variable {J D} + instance [FinitaryExtensive D] [HasFiniteCoproducts D] [HasPullbacks D] : FinitaryExtensive (Sheaf J D) := - finitaryExtensive_of_reflective (sheafificationAdjunction _ _) + finitaryExtensive_of_reflective (plusPlusAdjunction _ _) instance [Adhesive D] [HasPullbacks D] [HasPushouts D] : Adhesive (Sheaf J D) := - adhesive_of_reflective (sheafificationAdjunction _ _) + adhesive_of_reflective (plusPlusAdjunction _ _) instance SheafOfTypes.finitary_extensive {C : Type u} [SmallCategory C] (J : GrothendieckTopology C) : FinitaryExtensive (Sheaf J (Type u)) := diff --git a/Mathlib/CategoryTheory/Sites/RegularExtensive.lean b/Mathlib/CategoryTheory/Sites/RegularExtensive.lean index 615471555b5a2..24cf691432f95 100644 --- a/Mathlib/CategoryTheory/Sites/RegularExtensive.lean +++ b/Mathlib/CategoryTheory/Sites/RegularExtensive.lean @@ -227,7 +227,7 @@ namespace regularCoverage /-- The map to the explicit equalizer used in the sheaf condition. -/ -def MapToEqualizer (P : Cᵒᵖ ⥤ Type (max u v)) {W X B : C} (f : X ⟶ B) +def MapToEqualizer (P : Cᵒᵖ ⥤ Type*) {W X B : C} (f : X ⟶ B) (g₁ g₂ : W ⟶ X) (w : g₁ ≫ f = g₂ ≫ f) : P.obj (op B) → { x : P.obj (op X) | P.map g₁.op x = P.map g₂.op x } := fun t ↦ ⟨P.map f.op t, by simp only [Set.mem_setOf_eq, ← FunctorToTypes.map_comp_apply, ← op_comp, w]⟩ @@ -235,13 +235,13 @@ def MapToEqualizer (P : Cᵒᵖ ⥤ Type (max u v)) {W X B : C} (f : X ⟶ B) /-- The sheaf condition with respect to regular presieves, given the existence of the relavant pullback. -/ -def EqualizerCondition (P : Cᵒᵖ ⥤ Type (max u v)) : Prop := +def EqualizerCondition (P : Cᵒᵖ ⥤ Type*) : Prop := ∀ (X B : C) (π : X ⟶ B) [EffectiveEpi π] [HasPullback π π], Function.Bijective (MapToEqualizer P π (pullback.fst (f := π) (g := π)) (pullback.snd (f := π) (g := π)) pullback.condition) lemma EqualizerCondition.isSheafFor {B : C} {S : Presieve B} [S.regular] [S.hasPullbacks] - {F : Cᵒᵖ ⥤ Type (max u v)} + {F : Cᵒᵖ ⥤ Type*} (hF : EqualizerCondition F) : S.IsSheafFor F := by obtain ⟨X, π, hS, πsurj⟩ := Presieve.regular.single_epi (R := S) subst hS @@ -256,7 +256,7 @@ lemma EqualizerCondition.isSheafFor {B : C} {S : Presieve B} [S.regular] [S.hasP · simpa [MapToEqualizer] using ht · simpa [MapToEqualizer] using h () -lemma equalizerCondition_of_regular {F : Cᵒᵖ ⥤ Type (max u v)} +lemma equalizerCondition_of_regular {F : Cᵒᵖ ⥤ Type*} (hSF : ∀ {B : C} (S : Presieve B) [S.regular] [S.hasPullbacks], S.IsSheafFor F) : EqualizerCondition F := by intro X B π _ _ @@ -273,7 +273,7 @@ lemma equalizerCondition_of_regular {F : Cᵒᵖ ⥤ Type (max u v)} · simpa [MapToEqualizer] using h lemma isSheafFor_regular_of_projective {X : C} (S : Presieve X) [S.regular] [Projective X] - (F : Cᵒᵖ ⥤ Type (max u v)) : S.IsSheafFor F := by + (F : Cᵒᵖ ⥤ Type*) : S.IsSheafFor F := by obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S) rw [isSheafFor_arrows_iff] refine fun x hx ↦ ⟨F.map (Projective.factorThru (𝟙 _) f).op <| x (), fun _ ↦ ?_, fun y h ↦ ?_⟩ @@ -281,7 +281,7 @@ lemma isSheafFor_regular_of_projective {X : C} (S : Presieve X) [S.regular] [Pro · simp only [← h (), ← FunctorToTypes.map_comp_apply, ← op_comp, Projective.factorThru_comp, op_id, FunctorToTypes.map_id_apply] -lemma EqualizerCondition.isSheaf_iff (F : Cᵒᵖ ⥤ Type (max u v)) +lemma EqualizerCondition.isSheaf_iff (F : Cᵒᵖ ⥤ Type*) [∀ ⦃X Y : C⦄ (π : X ⟶ Y) [EffectiveEpi π], HasPullback π π] [Preregular C] : Presieve.IsSheaf (regularCoverage C).toGrothendieck F ↔ EqualizerCondition F := by rw [Presieve.isSheaf_coverage] @@ -289,7 +289,7 @@ lemma EqualizerCondition.isSheaf_iff (F : Cᵒᵖ ⥤ Type (max u v)) rintro h X S ⟨Y, f, rfl, hf⟩ exact @isSheafFor _ _ _ _ ⟨Y, f, rfl, hf⟩ ⟨fun g _ h ↦ by cases g; cases h; infer_instance⟩ _ h -lemma isSheaf_of_projective (F : Cᵒᵖ ⥤ Type (max u v)) [Preregular C] [∀ (X : C), Projective X] : +lemma isSheaf_of_projective (F : Cᵒᵖ ⥤ Type*) [Preregular C] [∀ (X : C), Projective X] : IsSheaf (regularCoverage C).toGrothendieck F := (isSheaf_coverage _ _).mpr fun S ⟨_, h⟩ ↦ have : S.regular := ⟨_, h⟩ isSheafFor_regular_of_projective _ _ diff --git a/Mathlib/CategoryTheory/Sites/Sheafification.lean b/Mathlib/CategoryTheory/Sites/Sheafification.lean new file mode 100644 index 0000000000000..75dff87a70b28 --- /dev/null +++ b/Mathlib/CategoryTheory/Sites/Sheafification.lean @@ -0,0 +1,231 @@ +/- +Copyright (c) 2023 Dagur Asgeirsson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Dagur Asgeirsson +-/ +import Mathlib.CategoryTheory.Adjunction.Opposites +import Mathlib.CategoryTheory.Adjunction.FullyFaithful +import Mathlib.CategoryTheory.Sites.Sheaf +import Mathlib.CategoryTheory.Limits.Preserves.Finite +/-! + +# Sheafification + +Given a site `(C, J)` we define a typeclass `HasSheafify J A` saying that the inclusion functor from +`A`-valued sheaves on `C` to presheaves admits a left exact left adjoint (sheafification). + +Note: to access the `HasSheafify` instance for suitable concrete categories, import the file +`Mathlib.CategoryTheory.Sites.LeftExact`. +-/ + +universe v₁ v₂ u₁ u₂ + +namespace CategoryTheory + +open Limits + +variable {C : Type u₁} [Category.{v₁} C] (J : GrothendieckTopology C) +variable (A : Type u₂) [Category.{v₂} A] + +/-- +A proposition saying that the inclusion functor from sheaves to presheaves admits a left adjoint. +-/ +abbrev HasWeakSheafify := Nonempty (IsRightAdjoint (sheafToPresheaf J A)) + +/-- +`HasSheafify` means that the inclusion functor from sheaves to presheaves admits a left exact +left adjiont (sheafification). + +Given a finite limit preserving functor `F : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A` and an adjunction +`adj : F ⊣ sheafToPresheaf J A`, use `HasSheafify.mk'` to construct a `HasSheafify` instance. +-/ +class HasSheafify : Prop where + isRightAdjoint : HasWeakSheafify J A + isLeftExact : letI := isRightAdjoint.some + Nonempty (PreservesFiniteLimits (leftAdjoint (sheafToPresheaf J A))) + +instance [HasSheafify J A] : HasWeakSheafify J A := HasSheafify.isRightAdjoint + +instance [IsRightAdjoint <| sheafToPresheaf J A] : HasWeakSheafify J A := ⟨inferInstance⟩ + +noncomputable section + +instance [h : HasWeakSheafify J A] : IsRightAdjoint (sheafToPresheaf J A) := h.some + +instance [HasSheafify J A] : PreservesFiniteLimits (leftAdjoint (sheafToPresheaf J A)) := + HasSheafify.isLeftExact.some + +theorem HasSheafify.mk' {F : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A} (adj : F ⊣ sheafToPresheaf J A) + [PreservesFiniteLimits F] : HasSheafify J A where + isRightAdjoint := ⟨⟨F, adj⟩⟩ + isLeftExact := + let i : (h : IsRightAdjoint (sheafToPresheaf J A) := ⟨F, adj⟩) → + F ≅ leftAdjoint (sheafToPresheaf J A) := fun _ ↦ + adj.leftAdjointUniq (Adjunction.ofRightAdjoint (sheafToPresheaf J A)) + ⟨⟨fun _ ↦ preservesLimitsOfShapeOfNatIso (i _)⟩⟩ + +/-- The sheafification functor, left adjoint to the inclusion. -/ +def presheafToSheaf [HasWeakSheafify J A] : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A := + leftAdjoint (sheafToPresheaf J A) + +instance [HasSheafify J A] : PreservesFiniteLimits (presheafToSheaf J A) := + HasSheafify.isLeftExact.some + +/-- The sheafification-inclusion adjunction. -/ +def sheafificationAdjunction [HasWeakSheafify J A] : + presheafToSheaf J A ⊣ sheafToPresheaf J A := IsRightAdjoint.adj + +instance [HasWeakSheafify J A] : IsLeftAdjoint <| presheafToSheaf J A where + adj := sheafificationAdjunction J A + +end + +variable {D : Type*} [Category D] [HasWeakSheafify J D] + +/-- The sheafification of a presheaf `P`. -/ +noncomputable abbrev sheafify (P : Cᵒᵖ ⥤ D) : Cᵒᵖ ⥤ D := + presheafToSheaf J D |>.obj P |>.val + +/-- The canonical map from `P` to its sheafification. -/ +noncomputable abbrev toSheafify (P : Cᵒᵖ ⥤ D) : P ⟶ sheafify J P := + sheafificationAdjunction J D |>.unit.app P + +@[simp] +theorem sheafificationAdjunction_unit_app (P : Cᵒᵖ ⥤ D) : + (sheafificationAdjunction J D).unit.app P = toSheafify J P := rfl + +/-- The canonical map on sheafifications induced by a morphism. -/ +noncomputable abbrev sheafifyMap {P Q : Cᵒᵖ ⥤ D} (η : P ⟶ Q) : sheafify J P ⟶ sheafify J Q := + presheafToSheaf J D |>.map η |>.val + +@[simp] +theorem sheafifyMap_id (P : Cᵒᵖ ⥤ D) : sheafifyMap J (𝟙 P) = 𝟙 (sheafify J P) := by + simp [sheafifyMap, sheafify] + +@[simp] +theorem sheafifyMap_comp {P Q R : Cᵒᵖ ⥤ D} (η : P ⟶ Q) (γ : Q ⟶ R) : + sheafifyMap J (η ≫ γ) = sheafifyMap J η ≫ sheafifyMap J γ := by + simp [sheafifyMap, sheafify] + +@[reassoc (attr := simp)] +theorem toSheafify_naturality {P Q : Cᵒᵖ ⥤ D} (η : P ⟶ Q) : + η ≫ toSheafify J _ = toSheafify J _ ≫ sheafifyMap J η := + sheafificationAdjunction J D |>.unit.naturality η + +variable (D) + +/-- The sheafification of a presheaf `P`, as a functor. -/ +noncomputable abbrev sheafification : (Cᵒᵖ ⥤ D) ⥤ Cᵒᵖ ⥤ D := + presheafToSheaf J D ⋙ sheafToPresheaf J D + +theorem sheafification_obj (P : Cᵒᵖ ⥤ D) : (sheafification J D).obj P = sheafify J P := + rfl + +theorem sheafification_map {P Q : Cᵒᵖ ⥤ D} (η : P ⟶ Q) : + (sheafification J D).map η = sheafifyMap J η := + rfl + +/-- The canonical map from `P` to its sheafification, as a natural transformation. -/ +noncomputable abbrev toSheafification : 𝟭 _ ⟶ sheafification J D := + sheafificationAdjunction J D |>.unit + +theorem toSheafification_app (P : Cᵒᵖ ⥤ D) : (toSheafification J D).app P = toSheafify J P := + rfl + +variable {D} + +theorem isIso_toSheafify {P : Cᵒᵖ ⥤ D} (hP : Presheaf.IsSheaf J P) : IsIso (toSheafify J P) := by + refine ⟨(sheafificationAdjunction J D |>.counit.app ⟨P, hP⟩).val, ?_, ?_⟩ + · change _ = (𝟙 (sheafToPresheaf J D ⋙ 𝟭 (Cᵒᵖ ⥤ D)) : _).app ⟨P, hP⟩ + rw [← sheafificationAdjunction J D |>.right_triangle] + rfl + · change (sheafToPresheaf _ _).map _ ≫ _ = _ + change _ ≫ (sheafificationAdjunction J D).unit.app ((sheafToPresheaf J D).obj ⟨P, hP⟩) = _ + erw [← inv_counit_map (sheafificationAdjunction J D) (X := ⟨P, hP⟩), comp_inv_eq_id] + +/-- If `P` is a sheaf, then `P` is isomorphic to `sheafify J P`. -/ +noncomputable def isoSheafify {P : Cᵒᵖ ⥤ D} (hP : Presheaf.IsSheaf J P) : P ≅ sheafify J P := + letI := isIso_toSheafify J hP + asIso (toSheafify J P) + +@[simp] +theorem isoSheafify_hom {P : Cᵒᵖ ⥤ D} (hP : Presheaf.IsSheaf J P) : + (isoSheafify J hP).hom = toSheafify J P := + rfl + +/-- Given a sheaf `Q` and a morphism `P ⟶ Q`, construct a morphism from `sheafify J P` to `Q`. -/ +noncomputable def sheafifyLift {P Q : Cᵒᵖ ⥤ D} (η : P ⟶ Q) (hQ : Presheaf.IsSheaf J Q) : + sheafify J P ⟶ Q := + (sheafificationAdjunction J D).homEquiv P ⟨Q, hQ⟩ |>.symm η |>.val + +@[simp] +theorem sheafificationAdjunction_counit_app_val (P : Sheaf J D) : + ((sheafificationAdjunction J D).counit.app P).val = sheafifyLift J (𝟙 P.val) P.cond := by + unfold sheafifyLift + rw [Adjunction.homEquiv_counit] + simp + +@[reassoc (attr := simp)] +theorem toSheafify_sheafifyLift {P Q : Cᵒᵖ ⥤ D} (η : P ⟶ Q) (hQ : Presheaf.IsSheaf J Q) : + toSheafify J P ≫ sheafifyLift J η hQ = η := by + rw [toSheafify, sheafifyLift, Adjunction.homEquiv_counit] + change _ ≫ (sheafToPresheaf J D).map _ ≫ _ = _ + simp only [Adjunction.unit_naturality_assoc] + change _ ≫ (sheafificationAdjunction J D).unit.app ((sheafToPresheaf J D).obj ⟨Q, hQ⟩) ≫ _ = _ + change _ ≫ _ ≫ (sheafToPresheaf J D).map _ = _ + rw [sheafificationAdjunction J D |>.right_triangle_components (Y := ⟨Q, hQ⟩)] + simp + +theorem sheafifyLift_unique {P Q : Cᵒᵖ ⥤ D} (η : P ⟶ Q) (hQ : Presheaf.IsSheaf J Q) + (γ : sheafify J P ⟶ Q) : toSheafify J P ≫ γ = η → γ = sheafifyLift J η hQ := by + intro h + rw [toSheafify] at h + rw [sheafifyLift] + let γ' : (presheafToSheaf J D).obj P ⟶ ⟨Q, hQ⟩ := ⟨γ⟩ + change γ'.val = _ + rw [← Sheaf.Hom.ext_iff, ← Adjunction.homEquiv_apply_eq, Adjunction.homEquiv_unit] + exact h + +@[simp] +theorem isoSheafify_inv {P : Cᵒᵖ ⥤ D} (hP : Presheaf.IsSheaf J P) : + (isoSheafify J hP).inv = sheafifyLift J (𝟙 _) hP := by + apply sheafifyLift_unique + simp [Iso.comp_inv_eq] + +theorem sheafify_hom_ext {P Q : Cᵒᵖ ⥤ D} (η γ : sheafify J P ⟶ Q) (hQ : Presheaf.IsSheaf J Q) + (h : toSheafify J P ≫ η = toSheafify J P ≫ γ) : η = γ := by + rw [sheafifyLift_unique J _ hQ _ h, ← h] + exact (sheafifyLift_unique J _ hQ _ h.symm).symm + +@[reassoc (attr := simp)] +theorem sheafifyMap_sheafifyLift {P Q R : Cᵒᵖ ⥤ D} (η : P ⟶ Q) (γ : Q ⟶ R) + (hR : Presheaf.IsSheaf J R) : + sheafifyMap J η ≫ sheafifyLift J γ hR = sheafifyLift J (η ≫ γ) hR := by + apply sheafifyLift_unique + rw [← Category.assoc, ← toSheafify_naturality, Category.assoc, toSheafify_sheafifyLift] + +variable {J} + +/-- A sheaf `P` is isomorphic to its own sheafification. -/ +@[simps] +noncomputable def sheafificationIso (P : Sheaf J D) : P ≅ (presheafToSheaf J D).obj P.val where + hom := ⟨(isoSheafify J P.2).hom⟩ + inv := ⟨(isoSheafify J P.2).inv⟩ + hom_inv_id := by + ext1 + apply (isoSheafify J P.2).hom_inv_id + inv_hom_id := by + ext1 + apply (isoSheafify J P.2).inv_hom_id +#align category_theory.sheafification_iso CategoryTheory.sheafificationIso + +instance isIso_sheafificationAdjunction_counit (P : Sheaf J D) : + IsIso ((sheafificationAdjunction J D).counit.app P) := + isIso_of_fully_faithful (sheafToPresheaf J D) _ +#align category_theory.is_iso_sheafification_adjunction_counit CategoryTheory.isIso_sheafificationAdjunction_counit + +instance sheafification_reflective : IsIso (sheafificationAdjunction J D).counit := + NatIso.isIso_of_isIso_app _ +#align category_theory.sheafification_reflective CategoryTheory.sheafification_reflective + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/Subsheaf.lean b/Mathlib/CategoryTheory/Sites/Subsheaf.lean index 5835adc936fd3..eb78427fbab9a 100644 --- a/Mathlib/CategoryTheory/Sites/Subsheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Subsheaf.lean @@ -5,8 +5,10 @@ Authors: Andrew Yang -/ import Mathlib.CategoryTheory.Elementwise import Mathlib.CategoryTheory.Adjunction.Evaluation -import Mathlib.CategoryTheory.Sites.ConcreteSheafification import Mathlib.Tactic.CategoryTheory.Elementwise +import Mathlib.CategoryTheory.Adhesive +import Mathlib.CategoryTheory.Sites.ConcreteSheafification +import Mathlib.CategoryTheory.Limits.Preserves.Filtered #align_import category_theory.sites.subsheaf from "leanprover-community/mathlib"@"70fd9563a21e7b963887c9360bd29b2393e6225a" diff --git a/Mathlib/CategoryTheory/Sites/Surjective.lean b/Mathlib/CategoryTheory/Sites/Surjective.lean index 053e385d95f3b..7eaad47420a13 100644 --- a/Mathlib/CategoryTheory/Sites/Surjective.lean +++ b/Mathlib/CategoryTheory/Sites/Surjective.lean @@ -32,7 +32,7 @@ namespace CategoryTheory variable {C : Type u} [Category.{v} C] (J : GrothendieckTopology C) -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike variable {A : Type u'} [Category.{v'} A] [ConcreteCategory.{w'} A] @@ -144,7 +144,7 @@ noncomputable def sheafificationIsoImagePresheaf : J.sheafifyLift (toImagePresheafSheafify J _) ((isSheaf_iff_isSheaf_of_type J _).mpr <| Subpresheaf.sheafify_isSheaf _ <| - (isSheaf_iff_isSheaf_of_type J _).mp <| sheafify_isSheaf J _) + (isSheaf_iff_isSheaf_of_type J _).mp <| GrothendieckTopology.sheafify_isSheaf J _) inv := Subpresheaf.ι _ hom_inv_id := J.sheafify_hom_ext _ _ (J.sheafify_isSheaf _) (by simp [toImagePresheafSheafify]) diff --git a/Mathlib/CategoryTheory/Sites/Types.lean b/Mathlib/CategoryTheory/Sites/Types.lean index 8bda080f4e657..c664375c12ecc 100644 --- a/Mathlib/CategoryTheory/Sites/Types.lean +++ b/Mathlib/CategoryTheory/Sites/Types.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ import Mathlib.CategoryTheory.Sites.Canonical -import Mathlib.CategoryTheory.Sites.EqualizerSheafCondition #align_import category_theory.sites.types from "leanprover-community/mathlib"@"9f9015c645d85695581237cc761981036be8bd37" diff --git a/Mathlib/CategoryTheory/Triangulated/Basic.lean b/Mathlib/CategoryTheory/Triangulated/Basic.lean index c3eb9756dd927..f6bec1774ea29 100644 --- a/Mathlib/CategoryTheory/Triangulated/Basic.lean +++ b/Mathlib/CategoryTheory/Triangulated/Basic.lean @@ -162,6 +162,23 @@ lemma Triangle.hom_ext {A B : Triangle C} (f g : A ⟶ B) (h₁ : f.hom₁ = g.hom₁) (h₂ : f.hom₂ = g.hom₂) (h₃ : f.hom₃ = g.hom₃) : f = g := TriangleMorphism.ext _ _ h₁ h₂ h₃ +@[simp] +lemma id_hom₁ (A : Triangle C) : TriangleMorphism.hom₁ (𝟙 A) = 𝟙 _ := rfl +@[simp] +lemma id_hom₂ (A : Triangle C) : TriangleMorphism.hom₂ (𝟙 A) = 𝟙 _ := rfl +@[simp] +lemma id_hom₃ (A : Triangle C) : TriangleMorphism.hom₃ (𝟙 A) = 𝟙 _ := rfl + +@[simp, reassoc] +lemma comp_hom₁ {X Y Z : Triangle C} (f : X ⟶ Y) (g : Y ⟶ Z) : + (f ≫ g).hom₁ = f.hom₁ ≫ g.hom₁ := rfl +@[simp, reassoc] +lemma comp_hom₂ {X Y Z : Triangle C} (f : X ⟶ Y) (g : Y ⟶ Z) : + (f ≫ g).hom₂ = f.hom₂ ≫ g.hom₂ := rfl +@[simp, reassoc] +lemma comp_hom₃ {X Y Z : Triangle C} (f : X ⟶ Y) (g : Y ⟶ Z) : + (f ≫ g).hom₃ = f.hom₃ ≫ g.hom₃ := rfl + @[simps] def Triangle.homMk (A B : Triangle C) (hom₁ : A.obj₁ ⟶ B.obj₁) (hom₂ : A.obj₂ ⟶ B.obj₂) (hom₃ : A.obj₃ ⟶ B.obj₃) @@ -200,6 +217,26 @@ lemma Triangle.isIso_of_isIsos {A B : Triangle C} (f : A ⟶ B) (by simp) (by simp) (by simp) exact (inferInstance : IsIso e.hom) +@[reassoc (attr := simp)] +lemma _root_.CategoryTheory.Iso.hom_inv_id_triangle_hom₁ {A B : Triangle C} (e : A ≅ B) : + e.hom.hom₁ ≫ e.inv.hom₁ = 𝟙 _ := by rw [← comp_hom₁, e.hom_inv_id, id_hom₁] +@[reassoc (attr := simp)] +lemma _root_.CategoryTheory.Iso.hom_inv_id_triangle_hom₂ {A B : Triangle C} (e : A ≅ B) : + e.hom.hom₂ ≫ e.inv.hom₂ = 𝟙 _ := by rw [← comp_hom₂, e.hom_inv_id, id_hom₂] +@[reassoc (attr := simp)] +lemma _root_.CategoryTheory.Iso.hom_inv_id_triangle_hom₃ {A B : Triangle C} (e : A ≅ B) : + e.hom.hom₃ ≫ e.inv.hom₃ = 𝟙 _ := by rw [← comp_hom₃, e.hom_inv_id, id_hom₃] + +@[reassoc (attr := simp)] +lemma _root_.CategoryTheory.Iso.inv_hom_id_triangle_hom₁ {A B : Triangle C} (e : A ≅ B) : + e.inv.hom₁ ≫ e.hom.hom₁ = 𝟙 _ := by rw [← comp_hom₁, e.inv_hom_id, id_hom₁] +@[reassoc (attr := simp)] +lemma _root_.CategoryTheory.Iso.inv_hom_id_triangle_hom₂ {A B : Triangle C} (e : A ≅ B) : + e.inv.hom₂ ≫ e.hom.hom₂ = 𝟙 _ := by rw [← comp_hom₂, e.inv_hom_id, id_hom₂] +@[reassoc (attr := simp)] +lemma _root_.CategoryTheory.Iso.inv_hom_id_triangle_hom₃ {A B : Triangle C} (e : A ≅ B) : + e.inv.hom₃ ≫ e.hom.hom₃ = 𝟙 _ := by rw [← comp_hom₃, e.inv_hom_id, id_hom₃] + lemma Triangle.eqToHom_hom₁ {A B : Triangle C} (h : A = B) : (eqToHom h).hom₁ = eqToHom (by subst h; rfl) := by subst h; rfl lemma Triangle.eqToHom_hom₂ {A B : Triangle C} (h : A = B) : diff --git a/Mathlib/CategoryTheory/Triangulated/Opposite.lean b/Mathlib/CategoryTheory/Triangulated/Opposite.lean index 6af5abb1100e8..67c5698cac5ce 100644 --- a/Mathlib/CategoryTheory/Triangulated/Opposite.lean +++ b/Mathlib/CategoryTheory/Triangulated/Opposite.lean @@ -5,7 +5,7 @@ Authors: Joël Riou -/ import Mathlib.CategoryTheory.Shift.Opposite import Mathlib.CategoryTheory.Shift.Pullback -import Mathlib.CategoryTheory.Triangulated.Triangulated +import Mathlib.CategoryTheory.Triangulated.Pretriangulated import Mathlib.Tactic.Linarith /-! diff --git a/Mathlib/CategoryTheory/Types.lean b/Mathlib/CategoryTheory/Types.lean index f4131caa22712..54b1945546d4f 100644 --- a/Mathlib/CategoryTheory/Types.lean +++ b/Mathlib/CategoryTheory/Types.lean @@ -5,7 +5,6 @@ Authors: Stephen Morgan, Scott Morrison, Johannes Hölzl -/ import Mathlib.CategoryTheory.EpiMono import Mathlib.CategoryTheory.Functor.FullyFaithful -import Mathlib.Logic.Equiv.Basic import Mathlib.Data.Set.Basic import Mathlib.Tactic.PPWithUniv diff --git a/Mathlib/CategoryTheory/Yoneda.lean b/Mathlib/CategoryTheory/Yoneda.lean index 0546dfc31cd1b..f818456e97afc 100644 --- a/Mathlib/CategoryTheory/Yoneda.lean +++ b/Mathlib/CategoryTheory/Yoneda.lean @@ -337,6 +337,23 @@ theorem yonedaPairing_map (P Q : Cᵒᵖ × (Cᵒᵖ ⥤ Type v₁)) (α : P ⟶ rfl #align category_theory.yoneda_pairing_map CategoryTheory.yonedaPairing_map +variable {C} in +/-- A bijection `(yoneda.obj X ⋙ uliftFunctor ⟶ F) ≃ F.obj (op X)` which is a variant +of `yonedaEquiv` with heterogeneous universes. -/ +def yonedaCompUliftFunctorEquiv (F : Cᵒᵖ ⥤ Type max v₁ w) (X : C) : + (yoneda.obj X ⋙ uliftFunctor.{w} ⟶ F) ≃ F.obj (op X) where + toFun φ := φ.app (op X) (ULift.up (𝟙 _)) + invFun f := + { app := fun Y x => F.map (ULift.down x).op f } + left_inv φ := by + ext Y f + dsimp + rw [← FunctorToTypes.naturality] + dsimp + rw [Category.comp_id] + rfl + right_inv f := by aesop_cat + /-- The Yoneda lemma asserts that the Yoneda pairing `(X : Cᵒᵖ, F : Cᵒᵖ ⥤ Type) ↦ (yoneda.obj (unop X) ⟶ F)` is naturally isomorphic to the evaluation `(X, F) ↦ F.obj X`. diff --git a/Mathlib/Combinatorics/Additive/Behrend.lean b/Mathlib/Combinatorics/Additive/Behrend.lean index 80aef26aa015e..c565e14b3ec5a 100644 --- a/Mathlib/Combinatorics/Additive/Behrend.lean +++ b/Mathlib/Combinatorics/Additive/Behrend.lean @@ -421,7 +421,7 @@ theorem le_N (hN : 2 ≤ N) : (2 * dValue N - 1) ^ nValue N ≤ N := by rw [cast_ne_zero] apply (nValue_pos hN).ne' rw [← le_div_iff'] - · exact floor_le (div_nonneg (rpow_nonneg_of_nonneg (cast_nonneg _) _) zero_le_two) + · exact floor_le (div_nonneg (rpow_nonneg (cast_nonneg _) _) zero_le_two) apply zero_lt_two set_option linter.uppercaseLean3 false in #align behrend.le_N Behrend.le_N @@ -462,14 +462,14 @@ theorem roth_lower_bound_explicit (hN : 4096 ≤ N) : have hn : 0 < (n : ℝ) := cast_pos.2 (nValue_pos <| hN.trans' <| by norm_num1) have hd : 0 < dValue N := dValue_pos (hN.trans' <| by norm_num1) have hN₀ : 0 < (N : ℝ) := cast_pos.2 (hN.trans' <| by norm_num1) - have hn₂ : 2 < n := three_le_nValue $ hN.trans' $ by norm_num1 + have hn₂ : 2 < n := three_le_nValue <| hN.trans' <| by norm_num1 have : (2 * dValue N - 1) ^ n ≤ N := le_N (hN.trans' <| by norm_num1) calc _ ≤ (N ^ (nValue N : ℝ)⁻¹ / rexp 1 : ℝ) ^ (n - 2) / n := ?_ _ < _ := by gcongr; exacts [(tsub_pos_of_lt hn₂).ne', bound hN] _ ≤ rothNumberNat ((2 * dValue N - 1) ^ n) := bound_aux hd.ne' hn₂.le _ ≤ rothNumberNat N := mod_cast rothNumberNat.mono this - rw [← rpow_nat_cast, div_rpow (rpow_nonneg_of_nonneg hN₀.le _) (exp_pos _).le, ← rpow_mul hN₀.le, + rw [← rpow_nat_cast, div_rpow (rpow_nonneg hN₀.le _) (exp_pos _).le, ← rpow_mul hN₀.le, inv_mul_eq_div, cast_sub hn₂.le, cast_two, same_sub_div hn.ne', exp_one_rpow, div_div, rpow_sub hN₀, rpow_one, div_div, div_eq_mul_inv] refine' mul_le_mul_of_nonneg_left _ (cast_nonneg _) @@ -479,7 +479,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≤ N) : norm_num rw [this] refine' mul_le_mul _ (exp_neg_two_mul_le <| Real.sqrt_pos.2 <| log_pos _).le (exp_pos _).le <| - rpow_nonneg_of_nonneg (cast_nonneg _) _ + rpow_nonneg (cast_nonneg _) _ · rw [← le_log_iff_exp_le (rpow_pos_of_pos hN₀ _), log_rpow hN₀, ← le_div_iff, mul_div_assoc, div_sqrt, neg_mul, neg_le_neg_iff, div_mul_eq_mul_div, div_le_iff hn] · exact mul_le_mul_of_nonneg_left (le_ceil _) zero_le_two diff --git a/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean b/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean index 3341bd2d1636e..81820d0326f85 100644 --- a/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean +++ b/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean @@ -7,6 +7,7 @@ import Mathlib.Combinatorics.DoubleCounting import Mathlib.Data.Finset.Pointwise import Mathlib.Data.Rat.NNRat import Mathlib.Tactic.GCongr +import Mathlib.Algebra.GroupPower.Order #align_import combinatorics.additive.pluennecke_ruzsa from "leanprover-community/mathlib"@"4aab2abced69a9e579b1e6dc2856ed3db48e2cbd" diff --git a/Mathlib/Combinatorics/Additive/SalemSpencer.lean b/Mathlib/Combinatorics/Additive/SalemSpencer.lean index a59f7cb0eeb76..54679ac3846f1 100644 --- a/Mathlib/Combinatorics/Additive/SalemSpencer.lean +++ b/Mathlib/Combinatorics/Additive/SalemSpencer.lean @@ -118,7 +118,7 @@ section CommMonoid variable [CommMonoid α] [CommMonoid β] {s : Set α} {a : α} @[to_additive] -theorem MulSalemSpencer.of_image [FunLike F α fun _ => β] [FreimanHomClass F s β 2] (f : F) +theorem MulSalemSpencer.of_image [FunLike F α β] [FreimanHomClass F s β 2] (f : F) (hf : s.InjOn f) (h : MulSalemSpencer (f '' s)) : MulSalemSpencer s := fun _ _ _ ha hb hc habc => hf ha hb <| h (mem_image_of_mem _ ha) (mem_image_of_mem _ hb) (mem_image_of_mem _ hc) <| diff --git a/Mathlib/Combinatorics/Catalan.lean b/Mathlib/Combinatorics/Catalan.lean index 1bd5673e2c062..a98406743d623 100644 --- a/Mathlib/Combinatorics/Catalan.lean +++ b/Mathlib/Combinatorics/Catalan.lean @@ -10,6 +10,7 @@ import Mathlib.Data.Finset.NatAntidiagonal import Mathlib.Data.Nat.Choose.Central import Mathlib.Data.Tree import Mathlib.Tactic.FieldSimp +import Mathlib.Tactic.GCongr #align_import combinatorics.catalan from "leanprover-community/mathlib"@"26b40791e4a5772a4e53d0e28e4df092119dc7da" @@ -171,9 +172,8 @@ def treesOfNumNodesEq : ℕ → Finset (Tree Unit) pairwiseNode (treesOfNumNodesEq ijh.1.1) (treesOfNumNodesEq ijh.1.2) -- Porting note: Add this to satisfy the linter. decreasing_by - simp_wf - try exact Nat.lt_succ_of_le (fst_le ijh.2) - try exact Nat.lt_succ_of_le (snd_le ijh.2) + · simp_wf; have := fst_le ijh.2; omega + · simp_wf; have := snd_le ijh.2; omega #align tree.trees_of_num_nodes_eq Tree.treesOfNumNodesEq @[simp] diff --git a/Mathlib/Combinatorics/Colex.lean b/Mathlib/Combinatorics/Colex.lean index 6fb4153f4a31a..850666e37735f 100644 --- a/Mathlib/Combinatorics/Colex.lean +++ b/Mathlib/Combinatorics/Colex.lean @@ -266,6 +266,8 @@ instance instLinearOrder : LinearOrder (Colex α) where decidableLE := instDecidableLE decidableLT := instDecidableLT +open scoped symmDiff + private lemma max_mem_aux {s t : Colex α} (hst : s ≠ t) : (ofColex s ∆ ofColex t).Nonempty := by simpa @@ -315,7 +317,7 @@ lemma toColex_image_lt_toColex_image (hf : StrictMono f) : lt_iff_lt_of_le_iff_le <| toColex_image_le_toColex_image hf lemma toColex_image_ofColex_strictMono (hf : StrictMono f) : - StrictMono fun s ↦ toColex $ image f $ ofColex s := + StrictMono fun s ↦ toColex <| image f <| ofColex s := fun _s _t ↦ (toColex_image_lt_toColex_image hf).2 /-! ### Initial segments -/ @@ -402,7 +404,7 @@ lemma geomSum_ofColex_strictMono (hn : 2 ≤ n) : StrictMono fun s ↦ ∑ k in rw [toColex_lt_toColex_iff_exists_forall_lt] at hst obtain ⟨a, hat, has, ha⟩ := hst rw [← sum_sdiff_lt_sum_sdiff] - exact (Nat.geomSum_lt hn $ by simpa).trans_le <| single_le_sum (fun _ _ ↦ by positivity) <| + exact (Nat.geomSum_lt hn <| by simpa).trans_le <| single_le_sum (fun _ _ ↦ by positivity) <| mem_sdiff.2 ⟨hat, has⟩ /-- For finsets of naturals of naturals, the colexicographic order is equivalent to the order diff --git a/Mathlib/Combinatorics/Composition.lean b/Mathlib/Combinatorics/Composition.lean index d0edb88ba5d96..cd6865296cfa8 100644 --- a/Mathlib/Combinatorics/Composition.lean +++ b/Mathlib/Combinatorics/Composition.lean @@ -801,7 +801,7 @@ def compositionAsSetEquiv (n : ℕ) : CompositionAsSet n ≃ Finset (Fin (n - 1) · simp only [or_iff_not_imp_left] intro i_mem i_ne_zero i_ne_last simp? [Fin.ext_iff] at i_ne_zero i_ne_last says - simp only [Fin.ext_iff, Fin.val_zero, Fin.val_last] at i_ne_zero i_ne_last + simp only [Fin.isValue, Fin.ext_iff, Fin.val_zero, Fin.val_last] at i_ne_zero i_ne_last have A : (1 + (i - 1) : ℕ) = (i : ℕ) := by rw [add_comm] exact Nat.succ_pred_eq_of_pos (pos_iff_ne_zero.mpr i_ne_zero) @@ -996,9 +996,7 @@ theorem Composition.toCompositionAsSet_blocks (c : Composition n) : c.toCompositionAsSet.blocks = c.blocks := by let d := c.toCompositionAsSet change d.blocks = c.blocks - have length_eq : d.blocks.length = c.blocks.length := by - convert c.toCompositionAsSet_length - simp [CompositionAsSet.blocks] + have length_eq : d.blocks.length = c.blocks.length := by simp [blocks_length] suffices H : ∀ i ≤ d.blocks.length, (d.blocks.take i).sum = (c.blocks.take i).sum exact eq_of_sum_take_eq length_eq H intro i hi diff --git a/Mathlib/Combinatorics/Configuration.lean b/Mathlib/Combinatorics/Configuration.lean index 85825f46b961f..ed129a2c31d18 100644 --- a/Mathlib/Combinatorics/Configuration.lean +++ b/Mathlib/Combinatorics/Configuration.lean @@ -263,7 +263,7 @@ theorem HasLines.exists_bijective_of_card_eq [HasLines P L] [Fintype P] [Fintype obtain ⟨f, hf1, hf2⟩ := Nondegenerate.exists_injective_of_card_le (ge_of_eq h) have hf3 := (Fintype.bijective_iff_injective_and_card f).mpr ⟨hf1, h.symm⟩ exact ⟨f, hf3, fun l ↦ (sum_eq_sum_iff_of_le fun l _ ↦ pointCount_le_lineCount (hf2 l)).1 - ((hf3.sum_comp _).trans (sum_lineCount_eq_sum_pointCount P L)).symm _ $ mem_univ _⟩ + ((hf3.sum_comp _).trans (sum_lineCount_eq_sum_pointCount P L)).symm _ <| mem_univ _⟩ #align configuration.has_lines.exists_bijective_of_card_eq Configuration.HasLines.exists_bijective_of_card_eq theorem HasLines.lineCount_eq_pointCount [HasLines P L] [Fintype P] [Fintype L] diff --git a/Mathlib/Combinatorics/Derangements/Finite.lean b/Mathlib/Combinatorics/Derangements/Finite.lean index eab83e05742e8..d35387ca62d5c 100644 --- a/Mathlib/Combinatorics/Derangements/Finite.lean +++ b/Mathlib/Combinatorics/Derangements/Finite.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Henry Swanson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Henry Swanson -/ +import Mathlib.Algebra.BigOperators.Ring import Mathlib.Combinatorics.Derangements.Basic import Mathlib.Data.Fintype.BigOperators import Mathlib.Tactic.Ring @@ -115,7 +116,7 @@ theorem card_derangements_eq_numDerangements (α : Type*) [Fintype α] [Decidabl theorem numDerangements_sum (n : ℕ) : (numDerangements n : ℤ) = - ∑ k in Finset.range (n + 1), (-1 : ℤ) ^ k * Nat.ascFactorial k (n - k) := by + ∑ k in Finset.range (n + 1), (-1 : ℤ) ^ k * Nat.ascFactorial (k + 1) (n - k) := by induction' n with n hn; · rfl rw [Finset.sum_range_succ, numDerangements_succ, hn, Finset.mul_sum, tsub_self, Nat.ascFactorial_zero, Int.ofNat_one, mul_one, pow_succ, neg_one_mul, sub_eq_add_neg, @@ -123,6 +124,6 @@ theorem numDerangements_sum (n : ℕ) : -- show that (n + 1) * (-1)^x * asc_fac x (n - x) = (-1)^x * asc_fac x (n.succ - x) intro x hx have h_le : x ≤ n := Finset.mem_range_succ_iff.mp hx - rw [Nat.succ_sub h_le, Nat.ascFactorial_succ, add_tsub_cancel_of_le h_le, Int.ofNat_mul, - Int.ofNat_succ, mul_left_comm] + rw [Nat.succ_sub h_le, Nat.ascFactorial_succ, add_right_comm, add_tsub_cancel_of_le h_le, + Int.ofNat_mul, Int.ofNat_succ, mul_left_comm] #align num_derangements_sum numDerangements_sum diff --git a/Mathlib/Combinatorics/Hall/Finite.lean b/Mathlib/Combinatorics/Hall/Finite.lean index ee952b778c794..1c454f5c3e9b5 100644 --- a/Mathlib/Combinatorics/Hall/Finite.lean +++ b/Mathlib/Combinatorics/Hall/Finite.lean @@ -52,7 +52,7 @@ theorem hall_cond_of_erase {x : ι} (a : α) (s' : Finset { x' : ι | x' ≠ x }) : s'.card ≤ (s'.biUnion fun x' => (t x').erase a).card := by haveI := Classical.decEq ι specialize ha (s'.image fun z => z.1) - rw [Nonempty.image_iff, Finset.card_image_of_injective s' Subtype.coe_injective] at ha + rw [image_nonempty, Finset.card_image_of_injective s' Subtype.coe_injective] at ha by_cases he : s'.Nonempty · have ha' : s'.card < (s'.biUnion fun x => t x).card := by convert ha he fun h => by simpa [← h] using mem_univ x using 2 diff --git a/Mathlib/Combinatorics/Optimization/ValuedCSP.lean b/Mathlib/Combinatorics/Optimization/ValuedCSP.lean index 0ca7be351031a..db71f15dcab63 100644 --- a/Mathlib/Combinatorics/Optimization/ValuedCSP.lean +++ b/Mathlib/Combinatorics/Optimization/ValuedCSP.lean @@ -14,12 +14,12 @@ General-Valued CSP is a very broad class of problems in discrete optimization. General-Valued CSP subsumes Min-Cost-Hom (including 3-SAT for example) and Finite-Valued CSP. ## Main definitions -* `ValuedCsp`: A VCSP template; fixes a domain, a codomain, and allowed cost functions. -* `ValuedCsp.Term`: One summand in a VCSP instance; calls a concrete function from given template. -* `ValuedCsp.Term.evalSolution`: An evaluation of the VCSP term for given solution. -* `ValuedCsp.Instance`: An instance of a VCSP problem over given template. -* `ValuedCsp.Instance.evalSolution`: An evaluation of the VCSP instance for given solution. -* `ValuedCsp.Instance.IsOptimumSolution`: Is given solution a minimum of the VCSP instance? +* `ValuedCSP`: A VCSP template; fixes a domain, a codomain, and allowed cost functions. +* `ValuedCSP.Term`: One summand in a VCSP instance; calls a concrete function from given template. +* `ValuedCSP.Term.evalSolution`: An evaluation of the VCSP term for given solution. +* `ValuedCSP.Instance`: An instance of a VCSP problem over given template. +* `ValuedCSP.Instance.evalSolution`: An evaluation of the VCSP instance for given solution. +* `ValuedCSP.Instance.IsOptimumSolution`: Is given solution a minimum of the VCSP instance? ## References * [D. A. Cohen, M. C. Cooper, P. Creed, P. G. Jeavons, S. Živný, @@ -31,13 +31,13 @@ General-Valued CSP subsumes Min-Cost-Hom (including 3-SAT for example) and Finit Regarding `C` we want to support `Bool`, `Nat`, `ENat`, `Int`, `Rat`, `NNRat`, `Real`, `NNReal`, `EReal`, `ENNReal`, and tuples made of any of those types. -/ @[nolint unusedArguments] -abbrev ValuedCsp (D C : Type*) [OrderedAddCommMonoid C] := +abbrev ValuedCSP (D C : Type*) [OrderedAddCommMonoid C] := Set (Σ (n : ℕ), (Fin n → D) → C) -- Cost functions `D^n → C` for any `n` variable {D C : Type*} [OrderedAddCommMonoid C] /-- A term in a valued CSP instance over the template `Γ`. -/ -structure ValuedCsp.Term (Γ : ValuedCsp D C) (ι : Type*) where +structure ValuedCSP.Term (Γ : ValuedCSP D C) (ι : Type*) where /-- Arity of the function -/ n : ℕ /-- Which cost function is instantiated -/ @@ -48,20 +48,20 @@ structure ValuedCsp.Term (Γ : ValuedCsp D C) (ι : Type*) where app : Fin n → ι /-- Evaluation of a `Γ` term `t` for given solution `x`. -/ -def ValuedCsp.Term.evalSolution {Γ : ValuedCsp D C} {ι : Type*} +def ValuedCSP.Term.evalSolution {Γ : ValuedCSP D C} {ι : Type*} (t : Γ.Term ι) (x : ι → D) : C := t.f (x ∘ t.app) /-- A valued CSP instance over the template `Γ` with variables indexed by `ι`.-/ -abbrev ValuedCsp.Instance (Γ : ValuedCsp D C) (ι : Type*) : Type _ := +abbrev ValuedCSP.Instance (Γ : ValuedCSP D C) (ι : Type*) : Type _ := Multiset (Γ.Term ι) /-- Evaluation of a `Γ` instance `I` for given solution `x`. -/ -def ValuedCsp.Instance.evalSolution {Γ : ValuedCsp D C} {ι : Type*} +def ValuedCSP.Instance.evalSolution {Γ : ValuedCSP D C} {ι : Type*} (I : Γ.Instance ι) (x : ι → D) : C := (I.map (·.evalSolution x)).sum /-- Condition for `x` being an optimum solution (min) to given `Γ` instance `I`.-/ -def ValuedCsp.Instance.IsOptimumSolution {Γ : ValuedCsp D C} {ι : Type*} +def ValuedCSP.Instance.IsOptimumSolution {Γ : ValuedCSP D C} {ι : Type*} (I : Γ.Instance ι) (x : ι → D) : Prop := ∀ y : ι → D, I.evalSolution x ≤ I.evalSolution y diff --git a/Mathlib/Combinatorics/Quiver/Arborescence.lean b/Mathlib/Combinatorics/Quiver/Arborescence.lean index 373cb7dc56e57..8697b5a03f4e8 100644 --- a/Mathlib/Combinatorics/Quiver/Arborescence.lean +++ b/Mathlib/Combinatorics/Quiver/Arborescence.lean @@ -3,10 +3,10 @@ Copyright (c) 2021 David Wärn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Wärn -/ -import Mathlib.Order.WellFounded -import Mathlib.Data.Nat.Basic -import Mathlib.Combinatorics.Quiver.Subquiver import Mathlib.Combinatorics.Quiver.Path +import Mathlib.Combinatorics.Quiver.Subquiver +import Mathlib.Data.Nat.Defs +import Mathlib.Order.WellFounded #align_import combinatorics.quiver.arborescence from "leanprover-community/mathlib"@"fc2ed6f838ce7c9b7c7171e58d78eaf7b438fb0e" diff --git a/Mathlib/Combinatorics/Quiver/Subquiver.lean b/Mathlib/Combinatorics/Quiver/Subquiver.lean index 0525a8049c787..cfe298fa7136e 100644 --- a/Mathlib/Combinatorics/Quiver/Subquiver.lean +++ b/Mathlib/Combinatorics/Quiver/Subquiver.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 David Wärn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Wärn -/ -import Mathlib.Order.BoundedOrder +import Mathlib.Order.Notation import Mathlib.Combinatorics.Quiver.Basic #align_import combinatorics.quiver.subquiver from "leanprover-community/mathlib"@"70d50ecfd4900dd6d328da39ab7ebd516abe4025" diff --git a/Mathlib/Combinatorics/Quiver/Symmetric.lean b/Mathlib/Combinatorics/Quiver/Symmetric.lean index 93484db807053..471274fb68487 100644 --- a/Mathlib/Combinatorics/Quiver/Symmetric.lean +++ b/Mathlib/Combinatorics/Quiver/Symmetric.lean @@ -5,7 +5,6 @@ Authors: David Wärn, Antoine Labelle, Rémi Bottinelli -/ import Mathlib.Combinatorics.Quiver.Path import Mathlib.Combinatorics.Quiver.Push -import Mathlib.Data.Sum.Basic #align_import combinatorics.quiver.symmetric from "leanprover-community/mathlib"@"706d88f2b8fdfeb0b22796433d7a6c1a010af9f2" diff --git a/Mathlib/Combinatorics/Schnirelmann.lean b/Mathlib/Combinatorics/Schnirelmann.lean index 2c286d7b988ec..503af8a8ff3f9 100644 --- a/Mathlib/Combinatorics/Schnirelmann.lean +++ b/Mathlib/Combinatorics/Schnirelmann.lean @@ -5,6 +5,7 @@ Authors: Yaël Dillies, Bhavik Mehta, Doga Can Sertbas -/ import Mathlib.Data.Nat.Interval import Mathlib.Data.Nat.Parity +import Mathlib.Data.Nat.Prime import Mathlib.Data.Real.Archimedean /-! @@ -206,10 +207,10 @@ lemma schnirelmannDensity_finite {A : Set ℕ} [DecidablePred (· ∈ A)] (hA : (schnirelmannDensity_eq_one_iff_of_zero_mem (by simp)).2 (by simp) lemma schnirelmannDensity_setOf_even : schnirelmannDensity (setOf Even) = 0 := - schnirelmannDensity_eq_zero_of_one_not_mem $ by simp + schnirelmannDensity_eq_zero_of_one_not_mem <| by simp lemma schnirelmannDensity_setOf_prime : schnirelmannDensity (setOf Nat.Prime) = 0 := - schnirelmannDensity_eq_zero_of_one_not_mem $ by simp [Nat.not_prime_one] + schnirelmannDensity_eq_zero_of_one_not_mem <| by simp [Nat.not_prime_one] /-- The Schnirelmann density of the set of naturals which are `1 mod m` is `m⁻¹`, for any `m ≠ 1`. @@ -223,9 +224,9 @@ lemma schnirelmannDensity_setOf_mod_eq_one {m : ℕ} (hm : m ≠ 1) : refine schnirelmannDensity_finite ?_ simp apply le_antisymm (schnirelmannDensity_le_of_le m hm'.ne' _) _ - · rw [← one_div] - apply div_le_div_of_le (Nat.cast_nonneg _) - simp only [Set.mem_setOf_eq, Nat.cast_le_one, card_le_one_iff_subset_singleton, subset_iff, + · rw [← one_div, ← @Nat.cast_one ℝ] + gcongr + simp only [Set.mem_setOf_eq, card_le_one_iff_subset_singleton, subset_iff, mem_filter, mem_Ioc, mem_singleton, and_imp] use 1 intro x _ hxm h diff --git a/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean b/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean new file mode 100644 index 0000000000000..3eb47dfb92762 --- /dev/null +++ b/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean @@ -0,0 +1,420 @@ +/- +Copyright (c) 2023 Yaël Dillies, Vladimir Ivanov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Vladimir Ivanov +-/ +import Mathlib.Algebra.BigOperators.Intervals +import Mathlib.Algebra.BigOperators.Order +import Mathlib.Algebra.BigOperators.Ring +import Mathlib.Data.Finset.Sups +import Mathlib.Order.Hom.Lattice +import Mathlib.Tactic.FieldSimp +import Mathlib.Tactic.Ring + +/-! +# The Ahlswede-Zhang identity + +This file proves the Ahlswede-Zhang identity, which is a nontrivial relation between the size of the +"truncated unions" of a set family. It sharpens the Lubell-Yamamoto-Meshalkin inequality +`Finset.sum_card_slice_div_choose_le_one`, by making explicit the correction term. + +For a set family `𝒜` over a ground set of size `n`, the Ahlswede-Zhang identity states that the sum +of `|⋂ B ∈ 𝒜, B ⊆ A, B|/(|A| * n.choose |A|)` over all set `A` is exactly `1`. This implies the LYM +inequality since for an antichain `𝒜` and every `A ∈ 𝒜` we have +`|⋂ B ∈ 𝒜, B ⊆ A, B|/(|A| * n.choose |A|) = 1 / n.choose |A|`. + +## Main declarations + +* `Finset.truncatedSup`: `s.truncatedSup a` is the supremum of all `b ≥ a` in `𝒜` if there are + some, or `⊤` if there are none. +* `Finset.truncatedInf`: `s.truncatedInf a` is the infimum of all `b ≤ a` in `𝒜` if there are + some, or `⊥` if there are none. +* `AhlswedeZhang.infSum`: LHS of the Ahlswede-Zhang identity. +* `AhlswedeZhang.le_infSum`: The sum of `1 / n.choose |A|` over an antichain is less than the RHS of + the Ahlswede-Zhang identity. +* `AhlswedeZhang.infSum_eq_one`: Ahlswede-Zhang identity. + +## References + +* [R. Ahlswede, Z. Zhang, *An identity in combinatorial extremal theory*](https://doi.org/10.1016/0001-8708(90)90023-G) +* [D. T. Tru, *An AZ-style identity and Bollobás deficiency*](https://doi.org/10.1016/j.jcta.2007.03.005) +-/ + +section +variable (α : Type*) [Fintype α] [Nonempty α] {m n : ℕ} + +open Finset Fintype Nat +open scoped BigOperators + +private lemma binomial_sum_eq (h : n < m) : + ∑ i in range (n + 1), (n.choose i * (m - n) / ((m - i) * m.choose i) : ℚ) = 1 := by + set f : ℕ → ℚ := fun i ↦ n.choose i * (m.choose i : ℚ)⁻¹ with hf + suffices : ∀ i ∈ range (n + 1), f i - f (i + 1) = n.choose i * (m - n) / ((m - i) * m.choose i) + · rw [← sum_congr rfl this, sum_range_sub', hf] + simp [choose_self, choose_zero_right, choose_eq_zero_of_lt h] + intro i h₁ + rw [mem_range] at h₁ + have h₁ := le_of_lt_succ h₁ + have h₂ := h₁.trans_lt h + have h₃ := h₂.le + have hi₄ : (i + 1 : ℚ) ≠ 0 := i.cast_add_one_ne_zero + have := congr_arg ((↑) : ℕ → ℚ) (choose_succ_right_eq m i) + push_cast at this + dsimp [hf] + rw [(eq_mul_inv_iff_mul_eq₀ hi₄).mpr this] + have := congr_arg ((↑) : ℕ → ℚ) (choose_succ_right_eq n i) + push_cast at this + rw [(eq_mul_inv_iff_mul_eq₀ hi₄).mpr this] + have : (m - i : ℚ) ≠ 0 := sub_ne_zero_of_ne (cast_lt.mpr h₂).ne' + have : (m.choose i : ℚ) ≠ 0 := cast_ne_zero.2 (choose_pos h₂.le).ne' + field_simp + ring + +private lemma Fintype.sum_div_mul_card_choose_card : + ∑ s : Finset α, (card α / ((card α - s.card) * (card α).choose s.card) : ℚ) = + card α * ∑ k in range (card α), (↑k)⁻¹ + 1 := by + rw [← powerset_univ, powerset_card_disjiUnion, sum_disjiUnion] + have : ∀ {x : ℕ}, ∀ s ∈ powersetCard x (univ : Finset α), + (card α / ((card α - Finset.card s) * (card α).choose (Finset.card s)) : ℚ) = + card α / ((card α - x) * (card α).choose x) + · intros n s hs + rw [mem_powersetCard_univ.1 hs] + simp_rw [sum_congr rfl this, sum_const, card_powersetCard, card_univ, nsmul_eq_mul, mul_div, + mul_comm, ← mul_div] + rw [← mul_sum, ← mul_inv_cancel (cast_ne_zero.mpr card_ne_zero : (card α : ℚ) ≠ 0), ← mul_add, + add_comm _ ((card α)⁻¹ : ℚ), ← sum_insert (f := fun x : ℕ ↦ (x⁻¹ : ℚ)) not_mem_range_self, + ← range_succ] + have (n) (hn : n ∈ range (card α + 1)) : + ((card α).choose n / ((card α - n) * (card α).choose n) : ℚ) = (card α - n : ℚ)⁻¹ + · rw [div_mul_left] + · simp + · exact cast_ne_zero.2 (choose_pos $ mem_range_succ_iff.1 hn).ne' + simp only [sum_congr rfl this, mul_eq_mul_left_iff, cast_eq_zero] + convert Or.inl $ sum_range_reflect _ _ with a ha + rw [add_tsub_cancel_right, cast_sub (mem_range_succ_iff.mp ha)] + +end + +open scoped FinsetFamily + +namespace Finset +variable {α β : Type*} + +/-! ### Truncated supremum, truncated infimum -/ + +section SemilatticeSup +variable [SemilatticeSup α] [OrderTop α] [@DecidableRel α (· ≤ ·)] [SemilatticeSup β] + [BoundedOrder β] [@DecidableRel β (· ≤ ·)] {s t : Finset α} {a b : α} + +private lemma sup_aux : a ∈ lowerClosure s → (s.filter fun b ↦ a ≤ b).Nonempty := + fun ⟨b, hb, hab⟩ ↦ ⟨b, mem_filter.2 ⟨hb, hab⟩⟩ + +/-- The supremum of the elements of `s` less than `a` if there are some, otherwise `⊤`. -/ +def truncatedSup (s : Finset α) (a : α) : α := + if h : a ∈ lowerClosure s then (s.filter fun b ↦ a ≤ b).sup' (sup_aux h) id else ⊤ + +lemma truncatedSup_of_mem (h : a ∈ lowerClosure s) : + truncatedSup s a = (s.filter fun b ↦ a ≤ b).sup' (sup_aux h) id := dif_pos h + +lemma truncatedSup_of_not_mem (h : a ∉ lowerClosure s) : truncatedSup s a = ⊤ := dif_neg h + +@[simp] lemma truncatedSup_empty (a : α) : truncatedSup ∅ a = ⊤ := truncatedSup_of_not_mem $ by simp + +@[simp] lemma truncatedSup_singleton (b a : α) : truncatedSup {b} a = if a ≤ b then b else ⊤ := by + simp [truncatedSup]; split_ifs <;> simp [*] + +lemma le_truncatedSup : a ≤ truncatedSup s a := by + rw [truncatedSup] + split_ifs with h + · obtain ⟨ℬ, hb, h⟩ := h + exact h.trans $ le_sup' id $ mem_filter.2 ⟨hb, h⟩ + · exact le_top + +lemma map_truncatedSup (e : α ≃o β) (s : Finset α) (a : α) : + e (truncatedSup s a) = truncatedSup (s.map e.toEquiv.toEmbedding) (e a) := by + have : e a ∈ lowerClosure (s.map e.toEquiv.toEmbedding : Set β) ↔ a ∈ lowerClosure s + · simp + simp_rw [truncatedSup, apply_dite e, map_finset_sup', map_top, this] + congr with h + simp only [filter_map, Function.comp, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, + OrderIso.le_iff_le, id.def] + rw [sup'_map] + -- TODO: Why can't `simp` use `Finset.sup'_map`? + simp only [sup'_map, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, Function.comp_apply] + +variable [DecidableEq α] + +private lemma lower_aux : a ∈ lowerClosure ↑(s ∪ t) ↔ a ∈ lowerClosure s ∨ a ∈ lowerClosure t := by + rw [coe_union, lowerClosure_union, LowerSet.mem_sup_iff] + +lemma truncatedSup_union (hs : a ∈ lowerClosure s) (ht : a ∈ lowerClosure t) : + truncatedSup (s ∪ t) a = truncatedSup s a ⊔ truncatedSup t a := by + simpa only [truncatedSup_of_mem, hs, ht, lower_aux.2 (Or.inl hs), filter_union] using + sup'_union _ _ _ + +lemma truncatedSup_union_left (hs : a ∈ lowerClosure s) (ht : a ∉ lowerClosure t) : + truncatedSup (s ∪ t) a = truncatedSup s a := by + simp only [mem_lowerClosure, mem_coe, exists_prop, not_exists, not_and] at ht + simp only [truncatedSup_of_mem, hs, filter_union, filter_false_of_mem ht, union_empty, + lower_aux.2 (Or.inl hs), ht] + +lemma truncatedSup_union_right (hs : a ∉ lowerClosure s) (ht : a ∈ lowerClosure t) : + truncatedSup (s ∪ t) a = truncatedSup t a := by rw [union_comm, truncatedSup_union_left ht hs] + +lemma truncatedSup_union_of_not_mem (hs : a ∉ lowerClosure s) (ht : a ∉ lowerClosure t) : + truncatedSup (s ∪ t) a = ⊤ := truncatedSup_of_not_mem fun h ↦ (lower_aux.1 h).elim hs ht + +lemma truncatedSup_of_isAntichain (hs : IsAntichain (· ≤ ·) (s : Set α)) (ha : a ∈ s) : + truncatedSup s a = a := by + refine' le_antisymm _ le_truncatedSup + simp_rw [truncatedSup_of_mem (subset_lowerClosure ha), sup'_le_iff, mem_filter] + rintro b ⟨hb, hab⟩ + exact (hs.eq ha hb hab).ge + +end SemilatticeSup + +section SemilatticeInf +variable [SemilatticeInf α] [BoundedOrder α] [@DecidableRel α (· ≤ ·)] [SemilatticeInf β] + [BoundedOrder β] [@DecidableRel β (· ≤ ·)] {s t : Finset α} {a : α} + +private lemma inf_aux : a ∈ upperClosure s → (s.filter (· ≤ a)).Nonempty := + fun ⟨b, hb, hab⟩ ↦ ⟨b, mem_filter.2 ⟨hb, hab⟩⟩ + +/-- The infimum of the elements of `s` less than `a` if there are some, otherwise `⊥`. -/ +def truncatedInf (s : Finset α) (a : α) : α := + if h : a ∈ upperClosure s then (s.filter (· ≤ a)).inf' (inf_aux h) id else ⊥ + +lemma truncatedInf_of_mem (h : a ∈ upperClosure s) : + truncatedInf s a = (s.filter (· ≤ a)).inf' (inf_aux h) id := dif_pos h + +lemma truncatedInf_of_not_mem (h : a ∉ upperClosure s) : truncatedInf s a = ⊥ := dif_neg h + +lemma truncatedInf_le : truncatedInf s a ≤ a := by + unfold truncatedInf + split_ifs with h + · obtain ⟨b, hb, hba⟩ := h + exact hba.trans' $ inf'_le id $ mem_filter.2 ⟨hb, ‹_›⟩ + · exact bot_le + +@[simp] lemma truncatedInf_empty (a : α) : truncatedInf ∅ a = ⊥ := truncatedInf_of_not_mem $ by simp + +@[simp] lemma truncatedInf_singleton (b a : α) : truncatedInf {b} a = if b ≤ a then b else ⊥ := by + simp only [truncatedInf, coe_singleton, upperClosure_singleton, UpperSet.mem_Ici_iff, + filter_congr_decidable, id_eq] + split_ifs <;> simp [*] + +lemma map_truncatedInf (e : α ≃o β) (s : Finset α) (a : α) : + e (truncatedInf s a) = truncatedInf (s.map e.toEquiv.toEmbedding) (e a) := by + have : e a ∈ upperClosure (s.map e.toEquiv.toEmbedding) ↔ a ∈ upperClosure s := by simp + simp_rw [truncatedInf, apply_dite e, map_finset_inf', map_bot, this] + congr with h + simp only [filter_map, Function.comp, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, + OrderIso.le_iff_le, id.def, inf'_map] + +variable [DecidableEq α] + +private lemma upper_aux : a ∈ upperClosure ↑(s ∪ t) ↔ a ∈ upperClosure s ∨ a ∈ upperClosure t := by + rw [coe_union, upperClosure_union, UpperSet.mem_inf_iff] + +lemma truncatedInf_union (hs : a ∈ upperClosure s) (ht : a ∈ upperClosure t) : + truncatedInf (s ∪ t) a = truncatedInf s a ⊓ truncatedInf t a := by + simpa only [truncatedInf_of_mem, hs, ht, upper_aux.2 (Or.inl hs), filter_union] using + inf'_union _ _ _ + +lemma truncatedInf_union_left (hs : a ∈ upperClosure s) (ht : a ∉ upperClosure t) : + truncatedInf (s ∪ t) a = truncatedInf s a := by + simp only [mem_upperClosure, mem_coe, exists_prop, not_exists, not_and] at ht + simp only [truncatedInf_of_mem, hs, filter_union, filter_false_of_mem ht, union_empty, + upper_aux.2 (Or.inl hs), ht] + +lemma truncatedInf_union_right (hs : a ∉ upperClosure s) (ht : a ∈ upperClosure t) : + truncatedInf (s ∪ t) a = truncatedInf t a := by + rw [union_comm, truncatedInf_union_left ht hs] + +lemma truncatedInf_union_of_not_mem (hs : a ∉ upperClosure s) (ht : a ∉ upperClosure t) : + truncatedInf (s ∪ t) a = ⊥ := + truncatedInf_of_not_mem $ by rw [coe_union, upperClosure_union]; exact fun h ↦ h.elim hs ht + +lemma truncatedInf_of_isAntichain (hs : IsAntichain (· ≤ ·) (s : Set α)) (ha : a ∈ s) : + truncatedInf s a = a := by + refine' le_antisymm truncatedInf_le _ + simp_rw [truncatedInf_of_mem (subset_upperClosure ha), le_inf'_iff, mem_filter] + rintro b ⟨hb, hba⟩ + exact (hs.eq hb ha hba).ge + +end SemilatticeInf + +section DistribLattice +variable [DistribLattice α] [BoundedOrder α] [DecidableEq α] [@DecidableRel α (· ≤ ·)] + {s t : Finset α} {a : α} + +private lemma infs_aux : a ∈ lowerClosure ↑(s ⊼ t) ↔ a ∈ lowerClosure s ∧ a ∈ lowerClosure t := by + rw [coe_infs, lowerClosure_infs, LowerSet.mem_inf_iff] + +private lemma sups_aux : a ∈ upperClosure ↑(s ⊻ t) ↔ a ∈ upperClosure s ∧ a ∈ upperClosure t := by + rw [coe_sups, upperClosure_sups, UpperSet.mem_sup_iff] + +lemma truncatedSup_infs (hs : a ∈ lowerClosure s) (ht : a ∈ lowerClosure t) : + truncatedSup (s ⊼ t) a = truncatedSup s a ⊓ truncatedSup t a := by + simp only [truncatedSup_of_mem, hs, ht, infs_aux.2 ⟨hs, ht⟩, sup'_inf_sup', filter_infs_le] + simp_rw [← image_inf_product] + rw [sup'_image] + simp [Function.uncurry_def] + +lemma truncatedInf_sups (hs : a ∈ upperClosure s) (ht : a ∈ upperClosure t) : + truncatedInf (s ⊻ t) a = truncatedInf s a ⊔ truncatedInf t a := by + simp only [truncatedInf_of_mem, hs, ht, sups_aux.2 ⟨hs, ht⟩, inf'_sup_inf', filter_sups_le] + simp_rw [← image_sup_product] + rw [inf'_image] + simp [Function.uncurry_def] + +lemma truncatedSup_infs_of_not_mem (ha : a ∉ lowerClosure s ⊓ lowerClosure t) : + truncatedSup (s ⊼ t) a = ⊤ := + truncatedSup_of_not_mem $ by rwa [coe_infs, lowerClosure_infs] + +lemma truncatedInf_sups_of_not_mem (ha : a ∉ upperClosure s ⊔ upperClosure t) : + truncatedInf (s ⊻ t) a = ⊥ := + truncatedInf_of_not_mem $ by rwa [coe_sups, upperClosure_sups] + +end DistribLattice + +section BooleanAlgebra +variable [BooleanAlgebra α] [@DecidableRel α (· ≤ ·)] {s : Finset α} {a : α} + +@[simp] lemma compl_truncatedSup (s : Finset α) (a : α) : + (truncatedSup s a)ᶜ = truncatedInf sᶜˢ aᶜ := map_truncatedSup (OrderIso.compl α) _ _ + +@[simp] lemma compl_truncatedInf (s : Finset α) (a : α) : + (truncatedInf s a)ᶜ = truncatedSup sᶜˢ aᶜ := map_truncatedInf (OrderIso.compl α) _ _ + +end BooleanAlgebra + +variable [DecidableEq α] [Fintype α] + +lemma card_truncatedSup_union_add_card_truncatedSup_infs (𝒜 ℬ : Finset (Finset α)) (s : Finset α) : + (truncatedSup (𝒜 ∪ ℬ) s).card + (truncatedSup (𝒜 ⊼ ℬ) s).card = + (truncatedSup 𝒜 s).card + (truncatedSup ℬ s).card := by + by_cases h𝒜 : s ∈ lowerClosure (𝒜 : Set $ Finset α) <;> + by_cases hℬ : s ∈ lowerClosure (ℬ : Set $ Finset α) + · rw [truncatedSup_union h𝒜 hℬ, truncatedSup_infs h𝒜 hℬ] + exact card_union_add_card_inter _ _ + · rw [truncatedSup_union_left h𝒜 hℬ, truncatedSup_of_not_mem hℬ, + truncatedSup_infs_of_not_mem fun h ↦ hℬ h.2] + · rw [truncatedSup_union_right h𝒜 hℬ, truncatedSup_of_not_mem h𝒜, + truncatedSup_infs_of_not_mem fun h ↦ h𝒜 h.1, add_comm] + · rw [truncatedSup_of_not_mem h𝒜, truncatedSup_of_not_mem hℬ, + truncatedSup_union_of_not_mem h𝒜 hℬ, truncatedSup_infs_of_not_mem fun h ↦ h𝒜 h.1] + +lemma card_truncatedInf_union_add_card_truncatedInf_sups (𝒜 ℬ : Finset (Finset α)) (s : Finset α) : + (truncatedInf (𝒜 ∪ ℬ) s).card + (truncatedInf (𝒜 ⊻ ℬ) s).card = + (truncatedInf 𝒜 s).card + (truncatedInf ℬ s).card := by + by_cases h𝒜 : s ∈ upperClosure (𝒜 : Set $ Finset α) <;> + by_cases hℬ : s ∈ upperClosure (ℬ : Set $ Finset α) + · rw [truncatedInf_union h𝒜 hℬ, truncatedInf_sups h𝒜 hℬ] + exact card_inter_add_card_union _ _ + · rw [truncatedInf_union_left h𝒜 hℬ, truncatedInf_of_not_mem hℬ, + truncatedInf_sups_of_not_mem fun h ↦ hℬ h.2] + · rw [truncatedInf_union_right h𝒜 hℬ, truncatedInf_of_not_mem h𝒜, + truncatedInf_sups_of_not_mem fun h ↦ h𝒜 h.1, add_comm] + · rw [truncatedInf_of_not_mem h𝒜, truncatedInf_of_not_mem hℬ, + truncatedInf_union_of_not_mem h𝒜 hℬ, truncatedInf_sups_of_not_mem fun h ↦ h𝒜 h.1] + +end Finset + +open Finset hiding card +open Fintype Nat +open scoped BigOperators + +namespace AhlswedeZhang +variable {α : Type*} [Fintype α] [DecidableEq α] {𝒜 ℬ : Finset (Finset α)} {s : Finset α} + +/-- Weighted sum of the size of the truncated infima of a set family. Relevant to the +Ahlswede-Zhang identity. -/ +def infSum (𝒜 : Finset (Finset α)) : ℚ := + ∑ s, (truncatedInf 𝒜 s).card / (s.card * (card α).choose s.card) + +/-- Weighted sum of the size of the truncated suprema of a set family. Relevant to the +Ahlswede-Zhang identity. -/ +def supSum (𝒜 : Finset (Finset α)) : ℚ := + ∑ s, (truncatedSup 𝒜 s).card / ((card α - s.card) * (card α).choose s.card) + +lemma supSum_union_add_supSum_infs (𝒜 ℬ : Finset (Finset α)) : + supSum (𝒜 ∪ ℬ) + supSum (𝒜 ⊼ ℬ) = supSum 𝒜 + supSum ℬ := by + unfold supSum + rw [← sum_add_distrib, ← sum_add_distrib, sum_congr rfl fun s _ ↦ _] + simp_rw [div_add_div_same, ← Nat.cast_add, card_truncatedSup_union_add_card_truncatedSup_infs] + simp + +lemma infSum_union_add_infSum_sups (𝒜 ℬ : Finset (Finset α)) : + infSum (𝒜 ∪ ℬ) + infSum (𝒜 ⊻ ℬ) = infSum 𝒜 + infSum ℬ := by + unfold infSum + rw [← sum_add_distrib, ← sum_add_distrib, sum_congr rfl fun s _ ↦ _] + simp_rw [div_add_div_same, ← Nat.cast_add, card_truncatedInf_union_add_card_truncatedInf_sups] + simp + +lemma IsAntichain.le_infSum (h𝒜 : IsAntichain (· ⊆ ·) (𝒜 : Set (Finset α))) (h𝒜₀ : ∅ ∉ 𝒜) : + ∑ s in 𝒜, ((card α).choose s.card : ℚ)⁻¹ ≤ infSum 𝒜 := by + calc + _ = ∑ s in 𝒜, (truncatedInf 𝒜 s).card / (s.card * (card α).choose s.card : ℚ) := ?_ + _ ≤ _ := sum_le_univ_sum_of_nonneg fun s ↦ by positivity + refine' sum_congr rfl fun s hs ↦ _ + rw [truncatedInf_of_isAntichain h𝒜 hs, div_mul_right, one_div] + have := (nonempty_iff_ne_empty.2 $ ne_of_mem_of_not_mem hs h𝒜₀).card_pos + positivity + +variable [Nonempty α] + +@[simp] lemma supSum_singleton (hs : s ≠ univ) : + supSum ({s} : Finset (Finset α)) = card α * ∑ k in range (card α), (k : ℚ)⁻¹ := by + have : ∀ t : Finset α, + (card α - (truncatedSup {s} t).card : ℚ) / ((card α - t.card) * (card α).choose t.card) = + if t ⊆ s then (card α - s.card : ℚ) / ((card α - t.card) * (card α).choose t.card) else 0 + · rintro t + simp_rw [truncatedSup_singleton, le_iff_subset] + split_ifs <;> simp [card_univ] + simp_rw [← sub_eq_of_eq_add (Fintype.sum_div_mul_card_choose_card α), eq_sub_iff_add_eq, + ← eq_sub_iff_add_eq', supSum, ← sum_sub_distrib, ← sub_div] + rw [sum_congr rfl fun t _ ↦ this t, sum_ite, sum_const_zero, add_zero, filter_subset_univ, + sum_powerset, ← binomial_sum_eq ((card_lt_iff_ne_univ _).2 hs), eq_comm] + refine' sum_congr rfl fun n _ ↦ _ + rw [mul_div_assoc, ← nsmul_eq_mul] + exact sum_powersetCard n s fun m ↦ (card α - s.card : ℚ) / ((card α - m) * (card α).choose m) + +/-- The **Ahlswede-Zhang Identity**. -/ +lemma infSum_compls_add_supSum (𝒜 : Finset (Finset α)) : + infSum 𝒜ᶜˢ + supSum 𝒜 = card α * ∑ k in range (card α), (k : ℚ)⁻¹ + 1 := by + unfold infSum supSum + rw [← @map_univ_of_surjective (Finset α) _ _ _ ⟨compl, compl_injective⟩ compl_surjective, sum_map] + simp only [Function.Embedding.coeFn_mk, univ_map_embedding, ← compl_truncatedSup, + ← sum_add_distrib, card_compl, cast_sub (card_le_univ _), choose_symm (card_le_univ _), + div_add_div_same, sub_add_cancel, Fintype.sum_div_mul_card_choose_card] + +lemma supSum_of_not_univ_mem (h𝒜₁ : 𝒜.Nonempty) (h𝒜₂ : univ ∉ 𝒜) : + supSum 𝒜 = card α * ∑ k in range (card α), (k : ℚ)⁻¹ := by + set m := 𝒜.card with hm + clear_value m + induction' m using Nat.strong_induction_on with m ih generalizing 𝒜 + replace ih := fun 𝒜 h𝒜 h𝒜₁ h𝒜₂ ↦ @ih _ h𝒜 𝒜 h𝒜₁ h𝒜₂ rfl + obtain ⟨a, rfl⟩ | h𝒜₃ := h𝒜₁.exists_eq_singleton_or_nontrivial + · refine' supSum_singleton _ + simpa [eq_comm] using h𝒜₂ + cases m + · cases h𝒜₁.card_pos.ne hm + obtain ⟨s, 𝒜, hs, rfl, rfl⟩ := card_eq_succ.1 hm.symm + have h𝒜 : 𝒜.Nonempty := nonempty_iff_ne_empty.2 (by rintro rfl; simp at h𝒜₃) + rw [insert_eq, eq_sub_of_add_eq (supSum_union_add_supSum_infs _ _), singleton_infs, + supSum_singleton (ne_of_mem_of_not_mem (mem_insert_self _ _) h𝒜₂), ih, ih, add_sub_cancel] + · exact card_image_le.trans_lt (lt_add_one _) + · exact h𝒜.image _ + · simpa using fun _ ↦ ne_of_mem_of_not_mem (mem_insert_self _ _) h𝒜₂ + · exact lt_add_one _ + · exact h𝒜 + · exact fun h ↦ h𝒜₂ (mem_insert_of_mem h) + +/-- The **Ahlswede-Zhang Identity**. -/ +lemma infSum_eq_one (h𝒜₁ : 𝒜.Nonempty) (h𝒜₀ : ∅ ∉ 𝒜) : infSum 𝒜 = 1 := by + rw [← compls_compls 𝒜, eq_sub_of_add_eq (infSum_compls_add_supSum _), + supSum_of_not_univ_mem h𝒜₁.compls, add_sub_cancel'] + simpa + +end AhlswedeZhang diff --git a/Mathlib/Combinatorics/SetFamily/CauchyDavenport.lean b/Mathlib/Combinatorics/SetFamily/CauchyDavenport.lean index b7e75eff1a216..80169b65bdfef 100644 --- a/Mathlib/Combinatorics/SetFamily/CauchyDavenport.lean +++ b/Mathlib/Combinatorics/SetFamily/CauchyDavenport.lean @@ -144,7 +144,7 @@ lemma Finset.min_le_card_mul (hs : s.Nonempty) (ht : t.Nonempty) : -- as wanted. obtain hsg | hsg := eq_or_ne (op g • s) s · have hS : (zpowers g : Set α) ⊆ a⁻¹ • (s : Set α) := by - refine forall_mem_zpowers.2 $ @zpow_induction_right _ _ _ (· ∈ a⁻¹ • (s : Set α)) + refine forall_mem_zpowers.2 <| @zpow_induction_right _ _ _ (· ∈ a⁻¹ • (s : Set α)) ⟨_, ha, inv_mul_self _⟩ (fun c hc ↦ ?_) fun c hc ↦ ?_ · rw [← hsg, coe_smul_finset, smul_comm] exact Set.smul_mem_smul_set hc @@ -161,8 +161,8 @@ lemma Finset.min_le_card_mul (hs : s.Nonempty) (ht : t.Nonempty) : -- `(s'', t'')` is strictly smaller than `(s, t)` according to `DevosMulRel`. replace hsg : (s ∩ op g • s).card < s.card := card_lt_card ⟨inter_subset_left _ _, fun h ↦ hsg <| eq_of_superset_of_card_ge (h.trans <| inter_subset_right _ _) (card_smul_finset _ _).le⟩ - replace aux1 := card_mono $ mulETransformLeft.fst_mul_snd_subset g (s, t) - replace aux2 := card_mono $ mulETransformRight.fst_mul_snd_subset g (s, t) + replace aux1 := card_mono <| mulETransformLeft.fst_mul_snd_subset g (s, t) + replace aux2 := card_mono <| mulETransformRight.fst_mul_snd_subset g (s, t) -- If the left translate of `t` by `g⁻¹` is disjoint from `t`, then we're easily done. obtain hgt | hgt := disjoint_or_nonempty_inter t (g⁻¹ • t) · rw [← card_smul_finset g⁻¹ t] diff --git a/Mathlib/Combinatorics/SetFamily/Compression/UV.lean b/Mathlib/Combinatorics/SetFamily/Compression/UV.lean index a7dc5260daf15..9f834bd7f4011 100644 --- a/Mathlib/Combinatorics/SetFamily/Compression/UV.lean +++ b/Mathlib/Combinatorics/SetFamily/Compression/UV.lean @@ -408,7 +408,7 @@ theorem shadow_compression_subset_compression_shadow (u v : Finset α) exact disjoint_sdiff convert this using 1 rw [insert_union_comm, insert_erase ‹w ∈ u›, - sdiff_union_of_subset (hus.trans $ subset_union_left _ _), + sdiff_union_of_subset (hus.trans <| subset_union_left _ _), sdiff_erase (mem_union_right _ ‹z ∈ v›), union_sdiff_cancel_right hsv] -- If `w ∉ u`, we contradict `m` again rw [mem_sdiff, ← not_imp, Classical.not_not] at hwB diff --git a/Mathlib/Combinatorics/SetFamily/FourFunctions.lean b/Mathlib/Combinatorics/SetFamily/FourFunctions.lean index ede2be843716e..d79a2bc619dd8 100644 --- a/Mathlib/Combinatorics/SetFamily/FourFunctions.lean +++ b/Mathlib/Combinatorics/SetFamily/FourFunctions.lean @@ -81,7 +81,7 @@ private lemma ineq {a₀ a₁ b₀ b₁ c₀ c₁ d₀ d₁ : β} _ ≤ a₀ * b₁ * (a₁ * b₀) + c₀ * d₁ * (c₀ * d₁) := mul_add_mul_le_mul_add_mul h₀₁ h₁₀ _ = a₀ * b₀ * (a₁ * b₁) + c₀ * d₁ * (c₀ * d₁) := by ring _ ≤ c₀ * d₀ * (c₁ * d₁) + c₀ * d₁ * (c₀ * d₁) := - add_le_add_right (mul_le_mul h₀₀ h₁₁ (by positivity) $ by positivity) _ + add_le_add_right (mul_le_mul h₀₀ h₁₁ (by positivity) <| by positivity) _ _ = (c₀ * d₁ + c₁ * d₀) * (c₀ * d₁) := by ring private def collapse (𝒜 : Finset (Finset α)) (a : α) (f : Finset α → β) (s : Finset α) : β := @@ -115,14 +115,14 @@ lemma le_collapse_of_mem (ha : a ∉ s) (hf : 0 ≤ f) (hts : t = s) (ht : t ∈ subst hts rw [collapse_eq ha, if_pos ht] split_ifs - · exact le_add_of_nonneg_right $ hf _ + · exact le_add_of_nonneg_right <| hf _ · rw [add_zero] lemma le_collapse_of_insert_mem (ha : a ∉ s) (hf : 0 ≤ f) (hts : t = insert a s) (ht : t ∈ 𝒜) : f t ≤ collapse 𝒜 a f s := by rw [collapse_eq ha, ← hts, if_pos ht] split_ifs - · exact le_add_of_nonneg_left $ hf _ + · exact le_add_of_nonneg_left <| hf _ · rw [zero_add] lemma collapse_nonneg (hf : 0 ≤ f) : 0 ≤ collapse 𝒜 a f := fun _s ↦ sum_nonneg fun _t _ ↦ hf _ @@ -134,8 +134,8 @@ lemma collapse_modular (hu : a ∉ u) (h₁ : 0 ≤ f₁) (h₂ : 0 ≤ f₂) (h collapse (𝒜 ⊼ ℬ) a f₃ (s ∩ t) * collapse (𝒜 ⊻ ℬ) a f₄ (s ∪ t) := by rintro s hsu t htu -- Gather a bunch of facts we'll need a lot - have := hsu.trans $ subset_insert a _ - have := htu.trans $ subset_insert a _ + have := hsu.trans <| subset_insert a _ + have := htu.trans <| subset_insert a _ have := insert_subset_insert a hsu have := insert_subset_insert a htu have has := not_mem_mono hsu hu @@ -154,59 +154,60 @@ lemma collapse_modular (hu : a ∉ u) (h₁ : 0 ≤ f₁) (h₂ : 0 ≤ f₂) (h · simpa [*] using h ‹s ⊆ _› ‹insert a t ⊆ _› · simpa [*] using h ‹insert a s ⊆ _› ‹insert a t ⊆ _› · rw [add_zero, add_mul] - refine' (add_le_add (h ‹_› ‹_›) $ h ‹_› ‹_›).trans _ + refine' (add_le_add (h ‹_› ‹_›) <| h ‹_› ‹_›).trans _ rw [collapse_of_mem ‹_› (union_mem_sups ‹_› ‹_›) (union_mem_sups ‹_› ‹_›) rfl (insert_union _ _ _), insert_inter_of_not_mem ‹_›, ← mul_add] - exact mul_le_mul_of_nonneg_right (le_collapse_of_mem ‹_› h₃ rfl $ inter_mem_infs ‹_› ‹_›) $ - add_nonneg (h₄ _) $ h₄ _ + exact mul_le_mul_of_nonneg_right (le_collapse_of_mem ‹_› h₃ rfl <| inter_mem_infs ‹_› ‹_›) <| + add_nonneg (h₄ _) <| h₄ _ · rw [zero_add, add_mul] - refine' (add_le_add (h ‹_› ‹_›) $ h ‹_› ‹_›).trans _ + refine' (add_le_add (h ‹_› ‹_›) <| h ‹_› ‹_›).trans _ rw [collapse_of_mem ‹_› (inter_mem_infs ‹_› ‹_›) (inter_mem_infs ‹_› ‹_›) (inter_insert_of_not_mem ‹_›) (insert_inter_distrib _ _ _).symm, union_insert, insert_union_distrib, ← add_mul] exact mul_le_mul_of_nonneg_left (le_collapse_of_insert_mem ‹_› h₄ - (insert_union_distrib _ _ _).symm $ union_mem_sups ‹_› ‹_›) $ add_nonneg (h₃ _) $ h₃ _ + (insert_union_distrib _ _ _).symm <| union_mem_sups ‹_› ‹_›) <| add_nonneg (h₃ _) <| h₃ _ · rw [add_zero, mul_zero] - exact mul_nonneg (collapse_nonneg h₃ _) $ collapse_nonneg h₄ _ + exact mul_nonneg (collapse_nonneg h₃ _) <| collapse_nonneg h₄ _ · rw [add_zero, collapse_eq hat, mul_add] split_ifs - · refine' (add_le_add (h ‹_› ‹_›) $ h ‹_› ‹_›).trans _ + · refine' (add_le_add (h ‹_› ‹_›) <| h ‹_› ‹_›).trans _ rw [collapse_of_mem ‹_› (union_mem_sups ‹_› ‹_›) (union_mem_sups ‹_› ‹_›) rfl (union_insert _ _ _), inter_insert_of_not_mem ‹_›, ← mul_add] - exact mul_le_mul_of_nonneg_right (le_collapse_of_mem ‹_› h₃ rfl $ inter_mem_infs ‹_› ‹_›) $ - add_nonneg (h₄ _) $ h₄ _ + exact mul_le_mul_of_nonneg_right (le_collapse_of_mem ‹_› h₃ rfl <| inter_mem_infs ‹_› ‹_›) <| + add_nonneg (h₄ _) <| h₄ _ · rw [mul_zero, add_zero] - exact (h ‹_› ‹_›).trans $ mul_le_mul (le_collapse_of_mem ‹_› h₃ rfl $ - inter_mem_infs ‹_› ‹_›) (le_collapse_of_mem ‹_› h₄ rfl $ union_mem_sups ‹_› ‹_›) - (h₄ _) $ collapse_nonneg h₃ _ + exact (h ‹_› ‹_›).trans <| mul_le_mul (le_collapse_of_mem ‹_› h₃ rfl <| + inter_mem_infs ‹_› ‹_›) (le_collapse_of_mem ‹_› h₄ rfl <| union_mem_sups ‹_› ‹_›) + (h₄ _) <| collapse_nonneg h₃ _ · rw [mul_zero, zero_add] - refine' (h ‹_› ‹_›).trans $ mul_le_mul _ (le_collapse_of_insert_mem ‹_› h₄ - (union_insert _ _ _) $ union_mem_sups ‹_› ‹_›) (h₄ _) $ collapse_nonneg h₃ _ + refine' (h ‹_› ‹_›).trans <| mul_le_mul _ (le_collapse_of_insert_mem ‹_› h₄ + (union_insert _ _ _) <| union_mem_sups ‹_› ‹_›) (h₄ _) <| collapse_nonneg h₃ _ exact le_collapse_of_mem (not_mem_mono (inter_subset_left _ _) ‹_›) h₃ - (inter_insert_of_not_mem ‹_›) $ inter_mem_infs ‹_› ‹_› + (inter_insert_of_not_mem ‹_›) <| inter_mem_infs ‹_› ‹_› · simp_rw [mul_zero, add_zero] - exact mul_nonneg (collapse_nonneg h₃ _) $ collapse_nonneg h₄ _ + exact mul_nonneg (collapse_nonneg h₃ _) <| collapse_nonneg h₄ _ · rw [zero_add, collapse_eq hat, mul_add] split_ifs - · refine' (add_le_add (h ‹_› ‹_›) $ h ‹_› ‹_›).trans _ + · refine' (add_le_add (h ‹_› ‹_›) <| h ‹_› ‹_›).trans _ rw [collapse_of_mem ‹_› (inter_mem_infs ‹_› ‹_›) (inter_mem_infs ‹_› ‹_›) (insert_inter_of_not_mem ‹_›) (insert_inter_distrib _ _ _).symm, insert_inter_of_not_mem ‹_›, ← insert_inter_distrib, insert_union, insert_union_distrib, ← add_mul] exact mul_le_mul_of_nonneg_left (le_collapse_of_insert_mem ‹_› h₄ - (insert_union_distrib _ _ _).symm $ union_mem_sups ‹_› ‹_›) $ add_nonneg (h₃ _) $ h₃ _ + (insert_union_distrib _ _ _).symm <| union_mem_sups ‹_› ‹_›) <| add_nonneg (h₃ _) <| h₃ _ · rw [mul_zero, add_zero] - refine' (h ‹_› ‹_›).trans $ mul_le_mul (le_collapse_of_mem ‹_› h₃ - (insert_inter_of_not_mem ‹_›) $ inter_mem_infs ‹_› ‹_›) (le_collapse_of_insert_mem ‹_› h₄ - (insert_union _ _ _) $ union_mem_sups ‹_› ‹_›) (h₄ _) $ collapse_nonneg h₃ _ + refine' (h ‹_› ‹_›).trans <| mul_le_mul (le_collapse_of_mem ‹_› h₃ + (insert_inter_of_not_mem ‹_›) <| inter_mem_infs ‹_› ‹_›) (le_collapse_of_insert_mem ‹_› h₄ + (insert_union _ _ _) <| union_mem_sups ‹_› ‹_›) (h₄ _) <| collapse_nonneg h₃ _ · rw [mul_zero, zero_add] - exact (h ‹_› ‹_›).trans $ mul_le_mul (le_collapse_of_insert_mem ‹_› h₃ - (insert_inter_distrib _ _ _).symm $ inter_mem_infs ‹_› ‹_›) (le_collapse_of_insert_mem ‹_› - h₄ (insert_union_distrib _ _ _).symm $ union_mem_sups ‹_› ‹_›) (h₄ _) $ collapse_nonneg h₃ _ + exact (h ‹_› ‹_›).trans <| mul_le_mul (le_collapse_of_insert_mem ‹_› h₃ + (insert_inter_distrib _ _ _).symm <| inter_mem_infs ‹_› ‹_›) (le_collapse_of_insert_mem ‹_› + h₄ (insert_union_distrib _ _ _).symm <| union_mem_sups ‹_› ‹_›) (h₄ _) <| + collapse_nonneg h₃ _ · simp_rw [mul_zero, add_zero] - exact mul_nonneg (collapse_nonneg h₃ _) $ collapse_nonneg h₄ _ + exact mul_nonneg (collapse_nonneg h₃ _) <| collapse_nonneg h₄ _ · simp_rw [add_zero, zero_mul] - exact mul_nonneg (collapse_nonneg h₃ _) $ collapse_nonneg h₄ _ + exact mul_nonneg (collapse_nonneg h₃ _) <| collapse_nonneg h₄ _ lemma sum_collapse (h𝒜 : 𝒜 ⊆ (insert a u).powerset) (hu : a ∉ u) : ∑ s in u.powerset, collapse 𝒜 a f s = ∑ s in 𝒜, f s := by @@ -221,12 +222,13 @@ lemma sum_collapse (h𝒜 : 𝒜 ⊆ (insert a u).powerset) (hu : a ∉ u) : simp only [mem_image, mem_powerset, mem_sdiff, subset_insert_iff] refine' ⟨_, fun h ↦ ⟨_, h.1, _⟩⟩ · rintro ⟨s, hs, rfl⟩ - exact ⟨subset_insert_iff.1 $ insert_subset_insert _ hs, fun h ↦ hu $ h $ mem_insert_self _ _⟩ + exact ⟨subset_insert_iff.1 <| insert_subset_insert _ hs, fun h ↦ + hu <| h <| mem_insert_self _ _⟩ · rw [insert_erase (erase_ne_self.1 fun hs ↦ ?_)] rw [hs] at h exact h.2 h.1 · rw [← sum_union (disjoint_sdiff_self_right.mono inf_le_left inf_le_left), ← inter_distrib_right, - union_sdiff_of_subset (powerset_mono.2 $ subset_insert _ _), inter_eq_right.2 h𝒜] + union_sdiff_of_subset (powerset_mono.2 <| subset_insert _ _), inter_eq_right.2 h𝒜] /-- The **Four Functions Theorem** on a powerset algebra. See `four_functions_theorem` for the finite distributive lattice generalisation. -/ @@ -268,14 +270,14 @@ lemma four_functions_theorem (h₁ : 0 ≤ f₁) (h₂ : 0 ≤ f₂) (h₃ : 0 set L : Sublattice α := ⟨latticeClosure (s ∪ t), isSublattice_latticeClosure.1, isSublattice_latticeClosure.2⟩ have : Finite L := (s.finite_toSet.union t.finite_toSet).latticeClosure.to_subtype - set s' : Finset L := s.preimage (↑) $ Subtype.coe_injective.injOn _ - set t' : Finset L := t.preimage (↑) $ Subtype.coe_injective.injOn _ + set s' : Finset L := s.preimage (↑) <| Subtype.coe_injective.injOn _ + set t' : Finset L := t.preimage (↑) <| Subtype.coe_injective.injOn _ have hs' : s'.map ⟨L.subtype, Subtype.coe_injective⟩ = s := by simp [map_eq_image, image_preimage, filter_eq_self] - exact fun a ha ↦ subset_latticeClosure $ Set.subset_union_left _ _ ha + exact fun a ha ↦ subset_latticeClosure <| Set.subset_union_left _ _ ha have ht' : t'.map ⟨L.subtype, Subtype.coe_injective⟩ = t := by simp [map_eq_image, image_preimage, filter_eq_self] - exact fun a ha ↦ subset_latticeClosure $ Set.subset_union_right _ _ ha + exact fun a ha ↦ subset_latticeClosure <| Set.subset_union_right _ _ ha clear_value s' t' obtain ⟨β, _, _, g, hg⟩ := exists_birkhoff_representation L have := four_functions_theorem_aux (extend g (f₁ ∘ (↑)) 0) (extend g (f₂ ∘ (↑)) 0) @@ -325,18 +327,18 @@ lemma holley (hμ₀ : 0 ≤ μ) (hf : 0 ≤ f) (hg : 0 ≤ g) (hμ : Monotone · simpa [hfg, sum_pos hg] using this · simp_rw [Pi.mul_apply, mul_left_comm _ (μ _), mul_comm (g _)] rw [sup_comm, inf_comm] - exact mul_le_mul (hμ le_sup_left) (h _ _) (mul_nonneg (hf.le _) $ hg.le _) $ hμ₀ _ + exact mul_le_mul (hμ le_sup_left) (h _ _) (mul_nonneg (hf.le _) <| hg.le _) <| hμ₀ _ /-- The **Fortuin-Kastelyn-Ginibre Inequality**. -/ lemma fkg (hμ₀ : 0 ≤ μ) (hf₀ : 0 ≤ f) (hg₀ : 0 ≤ g) (hf : Monotone f) (hg : Monotone g) (hμ : ∀ a b, μ a * μ b ≤ μ (a ⊓ b) * μ (a ⊔ b)) : (∑ a, μ a * f a) * ∑ a, μ a * g a ≤ (∑ a, μ a) * ∑ a, μ a * (f a * g a) := by refine' four_functions_theorem_univ (μ * f) (μ * g) μ _ (mul_nonneg hμ₀ hf₀) (mul_nonneg hμ₀ hg₀) - hμ₀ (mul_nonneg hμ₀ $ mul_nonneg hf₀ hg₀) (fun a b ↦ _) + hμ₀ (mul_nonneg hμ₀ <| mul_nonneg hf₀ hg₀) (fun a b ↦ _) dsimp rw [mul_mul_mul_comm, ← mul_assoc (μ (a ⊓ b))] - exact mul_le_mul (hμ _ _) (mul_le_mul (hf le_sup_left) (hg le_sup_right) (hg₀ _) $ hf₀ _) - (mul_nonneg (hf₀ _) $ hg₀ _) $ mul_nonneg (hμ₀ _) $ hμ₀ _ + exact mul_le_mul (hμ _ _) (mul_le_mul (hf le_sup_left) (hg le_sup_right) (hg₀ _) <| hf₀ _) + (mul_nonneg (hf₀ _) <| hg₀ _) <| mul_nonneg (hμ₀ _) <| hμ₀ _ end DistribLattice @@ -358,5 +360,5 @@ lemma Finset.le_card_diffs_mul_card_diffs (s t : Finset α) : /-- The **Marica-Schönheim Inequality**. -/ lemma Finset.card_le_card_diffs (s : Finset α) : s.card ≤ (s \\ s).card := - le_of_pow_le_pow_left two_ne_zero (zero_le _) $ by + le_of_pow_le_pow_left two_ne_zero (zero_le _) <| by simpa [← sq] using s.le_card_diffs_mul_card_diffs s diff --git a/Mathlib/Combinatorics/SetFamily/HarrisKleitman.lean b/Mathlib/Combinatorics/SetFamily/HarrisKleitman.lean index 653905311681f..b621b885d3f0a 100644 --- a/Mathlib/Combinatorics/SetFamily/HarrisKleitman.lean +++ b/Mathlib/Combinatorics/SetFamily/HarrisKleitman.lean @@ -5,7 +5,7 @@ Authors: Yaël Dillies -/ import Mathlib.Combinatorics.SetFamily.Compression.Down import Mathlib.Order.UpperLower.Basic -import Mathlib.Data.Fintype.BigOperators +import Mathlib.Data.Fintype.Powerset #align_import combinatorics.set_family.harris_kleitman from "leanprover-community/mathlib"@"b363547b3113d350d053abdf2884e9850a56b205" @@ -29,8 +29,6 @@ correlate in the uniform measure. open Finset -open BigOperators - variable {α : Type*} [DecidableEq α] {𝒜 ℬ : Finset (Finset α)} {s : Finset α} {a : α} theorem IsLowerSet.nonMemberSubfamily (h : IsLowerSet (𝒜 : Set (Finset α))) : diff --git a/Mathlib/Combinatorics/SetFamily/Shadow.lean b/Mathlib/Combinatorics/SetFamily/Shadow.lean index 65c4b131cc20f..9c72b39e744c8 100644 --- a/Mathlib/Combinatorics/SetFamily/Shadow.lean +++ b/Mathlib/Combinatorics/SetFamily/Shadow.lean @@ -101,12 +101,12 @@ theorem erase_mem_shadow (hs : s ∈ 𝒜) (ha : a ∈ s) : erase s a ∈ ∂ See also `Finset.mem_shadow_iff_exists_mem_card_add_one`. -/ lemma mem_shadow_iff_exists_sdiff : t ∈ ∂ 𝒜 ↔ ∃ s ∈ 𝒜, t ⊆ s ∧ (s \ t).card = 1 := by - simp_rw [mem_shadow_iff, ← covby_iff_card_sdiff_eq_one, covby_iff_exists_erase] + simp_rw [mem_shadow_iff, ← covBy_iff_card_sdiff_eq_one, covBy_iff_exists_erase] /-- `t` is in the shadow of `𝒜` iff we can add an element to it so that the resulting finset is in `𝒜`. -/ lemma mem_shadow_iff_insert_mem : t ∈ ∂ 𝒜 ↔ ∃ a, a ∉ t ∧ insert a t ∈ 𝒜 := by - simp_rw [mem_shadow_iff_exists_sdiff, ← covby_iff_card_sdiff_eq_one, covby_iff_exists_insert] + simp_rw [mem_shadow_iff_exists_sdiff, ← covBy_iff_card_sdiff_eq_one, covBy_iff_exists_insert] aesop #align finset.mem_shadow_iff_insert_mem Finset.mem_shadow_iff_insert_mem @@ -115,7 +115,7 @@ lemma mem_shadow_iff_insert_mem : t ∈ ∂ 𝒜 ↔ ∃ a, a ∉ t ∧ insert a See also `Finset.mem_shadow_iff_exists_sdiff`. -/ lemma mem_shadow_iff_exists_mem_card_add_one : t ∈ ∂ 𝒜 ↔ ∃ s ∈ 𝒜, t ⊆ s ∧ s.card = t.card + 1 := by - refine mem_shadow_iff_exists_sdiff.trans $ exists_congr fun t ↦ and_congr_right fun _ ↦ + refine mem_shadow_iff_exists_sdiff.trans <| exists_congr fun t ↦ and_congr_right fun _ ↦ and_congr_right fun hst ↦ ?_ rw [card_sdiff hst, tsub_eq_iff_eq_add_of_le, add_comm] exact card_mono hst @@ -145,7 +145,7 @@ lemma mem_shadow_iterate_iff_exists_sdiff : t ∈ ∂^[k] 𝒜 ↔ ∃ s ∈ See also `Finset.mem_shadow_iterate_iff_exists_sdiff`. -/ lemma mem_shadow_iterate_iff_exists_mem_card_add : t ∈ ∂^[k] 𝒜 ↔ ∃ s ∈ 𝒜, t ⊆ s ∧ s.card = t.card + k := by - refine mem_shadow_iterate_iff_exists_sdiff.trans $ exists_congr fun t ↦ and_congr_right fun _ ↦ + refine mem_shadow_iterate_iff_exists_sdiff.trans <| exists_congr fun t ↦ and_congr_right fun _ ↦ and_congr_right fun hst ↦ ?_ rw [card_sdiff hst, tsub_eq_iff_eq_add_of_le, add_comm] exact card_mono hst @@ -223,12 +223,12 @@ theorem insert_mem_upShadow (hs : s ∈ 𝒜) (ha : a ∉ s) : insert a s ∈ See also `Finset.mem_upShadow_iff_exists_mem_card_add_one`. -/ lemma mem_upShadow_iff_exists_sdiff : t ∈ ∂⁺ 𝒜 ↔ ∃ s ∈ 𝒜, s ⊆ t ∧ (t \ s).card = 1 := by - simp_rw [mem_upShadow_iff, ← covby_iff_card_sdiff_eq_one, covby_iff_exists_insert] + simp_rw [mem_upShadow_iff, ← covBy_iff_card_sdiff_eq_one, covBy_iff_exists_insert] /-- `t` is in the upper shadow of `𝒜` iff we can remove an element from it so that the resulting finset is in `𝒜`. -/ lemma mem_upShadow_iff_erase_mem : t ∈ ∂⁺ 𝒜 ↔ ∃ a, a ∈ t ∧ erase t a ∈ 𝒜 := by - simp_rw [mem_upShadow_iff_exists_sdiff, ← covby_iff_card_sdiff_eq_one, covby_iff_exists_erase] + simp_rw [mem_upShadow_iff_exists_sdiff, ← covBy_iff_card_sdiff_eq_one, covBy_iff_exists_erase] aesop #align finset.mem_up_shadow_iff_erase_mem Finset.mem_upShadow_iff_erase_mem @@ -237,7 +237,7 @@ lemma mem_upShadow_iff_erase_mem : t ∈ ∂⁺ 𝒜 ↔ ∃ a, a ∈ t ∧ eras See also `Finset.mem_upShadow_iff_exists_sdiff`. -/ lemma mem_upShadow_iff_exists_mem_card_add_one : t ∈ ∂⁺ 𝒜 ↔ ∃ s ∈ 𝒜, s ⊆ t ∧ t.card = s.card + 1 := by - refine mem_upShadow_iff_exists_sdiff.trans $ exists_congr fun t ↦ and_congr_right fun _ ↦ + refine mem_upShadow_iff_exists_sdiff.trans <| exists_congr fun t ↦ and_congr_right fun _ ↦ and_congr_right fun hst ↦ ?_ rw [card_sdiff hst, tsub_eq_iff_eq_add_of_le, add_comm] exact card_mono hst @@ -273,7 +273,7 @@ lemma mem_upShadow_iterate_iff_exists_sdiff : See also `Finset.mem_upShadow_iterate_iff_exists_sdiff`. -/ lemma mem_upShadow_iterate_iff_exists_mem_card_add : t ∈ ∂⁺^[k] 𝒜 ↔ ∃ s ∈ 𝒜, s ⊆ t ∧ t.card = s.card + k := by - refine mem_upShadow_iterate_iff_exists_sdiff.trans $ exists_congr fun t ↦ and_congr_right fun _ ↦ + refine mem_upShadow_iterate_iff_exists_sdiff.trans <| exists_congr fun t ↦ and_congr_right fun _ ↦ and_congr_right fun hst ↦ ?_ rw [card_sdiff hst, tsub_eq_iff_eq_add_of_le, add_comm] exact card_mono hst diff --git a/Mathlib/Combinatorics/SetFamily/Shatter.lean b/Mathlib/Combinatorics/SetFamily/Shatter.lean index 50e97a018bb22..0caea132eb5bb 100644 --- a/Mathlib/Combinatorics/SetFamily/Shatter.lean +++ b/Mathlib/Combinatorics/SetFamily/Shatter.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Data.Finset.Sort import Mathlib.Data.Nat.Interval import Mathlib.Order.UpperLower.Basic import Mathlib.Combinatorics.SetFamily.Compression.Down diff --git a/Mathlib/Combinatorics/SimpleGraph/AdjMatrix.lean b/Mathlib/Combinatorics/SimpleGraph/AdjMatrix.lean index 39aeb09947857..e280ac8f92672 100644 --- a/Mathlib/Combinatorics/SimpleGraph/AdjMatrix.lean +++ b/Mathlib/Combinatorics/SimpleGraph/AdjMatrix.lean @@ -243,14 +243,14 @@ theorem trace_adjMatrix [AddCommMonoid α] [One α] : Matrix.trace (G.adjMatrix variable {α} theorem adjMatrix_mul_self_apply_self [NonAssocSemiring α] (i : V) : - (G.adjMatrix α * G.adjMatrix α) i i = degree G i := by simp [degree] + (G.adjMatrix α * G.adjMatrix α) i i = degree G i := by simp #align simple_graph.adj_matrix_mul_self_apply_self SimpleGraph.adjMatrix_mul_self_apply_self variable {G} -- @[simp] -- Porting note: simp can prove this theorem adjMatrix_mulVec_const_apply [Semiring α] {a : α} {v : V} : - (G.adjMatrix α).mulVec (Function.const _ a) v = G.degree v * a := by simp [degree] + (G.adjMatrix α).mulVec (Function.const _ a) v = G.degree v * a := by simp #align simple_graph.adj_matrix_mul_vec_const_apply SimpleGraph.adjMatrix_mulVec_const_apply theorem adjMatrix_mulVec_const_apply_of_regular [Semiring α] {d : ℕ} {a : α} diff --git a/Mathlib/Combinatorics/SimpleGraph/Basic.lean b/Mathlib/Combinatorics/SimpleGraph/Basic.lean index 2a5e9e6e87070..3e4e3ae28c9b3 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Basic.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Basic.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson, Jalex Stark, Kyle Miller, Alena Gusakov, Hunter Monroe -/ import Mathlib.Combinatorics.SimpleGraph.Init -import Mathlib.Data.FunLike.Fintype import Mathlib.Data.Rel import Mathlib.Data.Set.Finite import Mathlib.Data.Sym.Card @@ -96,7 +95,7 @@ to standard `aesop`: macro (name := aesop_graph) "aesop_graph" c:Aesop.tactic_clause* : tactic => `(tactic| aesop $c* - (options := { introsTransparency? := some .default, terminal := true }) + (config := { introsTransparency? := some .default, terminal := true }) (rule_sets [$(Lean.mkIdent `SimpleGraph):ident])) /-- @@ -105,7 +104,7 @@ Use `aesop_graph?` to pass along a `Try this` suggestion when using `aesop_graph macro (name := aesop_graph?) "aesop_graph?" c:Aesop.tactic_clause* : tactic => `(tactic| aesop $c* - (options := { introsTransparency? := some .default, terminal := true }) + (config := { introsTransparency? := some .default, terminal := true }) (rule_sets [$(Lean.mkIdent `SimpleGraph):ident])) /-- @@ -116,7 +115,7 @@ nonterminal `simp`. macro (name := aesop_graph_nonterminal) "aesop_graph_nonterminal" c:Aesop.tactic_clause* : tactic => `(tactic| aesop $c* - (options := { introsTransparency? := some .default, warnOnNonterminal := false }) + (config := { introsTransparency? := some .default, warnOnNonterminal := false }) (rule_sets [$(Lean.mkIdent `SimpleGraph):ident])) open Finset Function @@ -1308,183 +1307,6 @@ theorem DeleteFar.mono (h : G.DeleteFar p r₂) (hr : r₁ ≤ r₂) : G.DeleteF end DeleteFar -/-! ## Map and comap -/ - - -/-- Given an injective function, there is a covariant induced map on graphs by pushing forward -the adjacency relation. - -This is injective (see `SimpleGraph.map_injective`). -/ -protected def map (f : V ↪ W) (G : SimpleGraph V) : SimpleGraph W where - Adj := Relation.Map G.Adj f f - symm a b := by -- porting note: `obviously` used to handle this - rintro ⟨v, w, h, rfl, rfl⟩ - use w, v, h.symm, rfl - loopless a := by -- porting note: `obviously` used to handle this - rintro ⟨v, w, h, rfl, h'⟩ - exact h.ne (f.injective h'.symm) -#align simple_graph.map SimpleGraph.map - -instance instDecidableMapAdj {f : V ↪ W} {a b} [Decidable (Relation.Map G.Adj f f a b)] : - Decidable ((G.map f).Adj a b) := ‹Decidable (Relation.Map G.Adj f f a b)› -#align simple_graph.decidable_map SimpleGraph.instDecidableMapAdj - -@[simp] -theorem map_adj (f : V ↪ W) (G : SimpleGraph V) (u v : W) : - (G.map f).Adj u v ↔ ∃ u' v' : V, G.Adj u' v' ∧ f u' = u ∧ f v' = v := - Iff.rfl -#align simple_graph.map_adj SimpleGraph.map_adj - -lemma map_adj_apply {G : SimpleGraph V} {f : V ↪ W} {a b : V} : - (G.map f).Adj (f a) (f b) ↔ G.Adj a b := by simp -#align simple_graph.map_adj_apply SimpleGraph.map_adj_apply - -theorem map_monotone (f : V ↪ W) : Monotone (SimpleGraph.map f) := by - rintro G G' h _ _ ⟨u, v, ha, rfl, rfl⟩ - exact ⟨_, _, h ha, rfl, rfl⟩ -#align simple_graph.map_monotone SimpleGraph.map_monotone - -@[simp] lemma map_id : G.map (Function.Embedding.refl _) = G := - SimpleGraph.ext _ _ $ Relation.map_id_id _ -#align simple_graph.map_id SimpleGraph.map_id - -@[simp] lemma map_map (f : V ↪ W) (g : W ↪ X) : (G.map f).map g = G.map (f.trans g) := - SimpleGraph.ext _ _ $ Relation.map_map _ _ _ _ _ -#align simple_graph.map_map SimpleGraph.map_map - -/-- Given a function, there is a contravariant induced map on graphs by pulling back the -adjacency relation. -This is one of the ways of creating induced graphs. See `SimpleGraph.induce` for a wrapper. - -This is surjective when `f` is injective (see `SimpleGraph.comap_surjective`).-/ -protected def comap (f : V → W) (G : SimpleGraph W) : SimpleGraph V where - Adj u v := G.Adj (f u) (f v) - symm _ _ h := h.symm - loopless _ := G.loopless _ -#align simple_graph.comap SimpleGraph.comap - -@[simp] lemma comap_adj {G : SimpleGraph W} {f : V → W} : - (G.comap f).Adj u v ↔ G.Adj (f u) (f v) := Iff.rfl - -@[simp] lemma comap_id {G : SimpleGraph V} : G.comap id = G := SimpleGraph.ext _ _ rfl -#align simple_graph.comap_id SimpleGraph.comap_id - -@[simp] lemma comap_comap {G : SimpleGraph X} (f : V → W) (g : W → X) : - (G.comap g).comap f = G.comap (g ∘ f) := rfl -#align simple_graph.comap_comap SimpleGraph.comap_comap - -instance instDecidableComapAdj (f : V → W) (G : SimpleGraph W) [DecidableRel G.Adj] : - DecidableRel (G.comap f).Adj := fun _ _ ↦ ‹DecidableRel G.Adj› _ _ - -lemma comap_symm (G : SimpleGraph V) (e : V ≃ W) : - G.comap e.symm.toEmbedding = G.map e.toEmbedding := by - ext; simp only [Equiv.apply_eq_iff_eq_symm_apply, comap_adj, map_adj, Equiv.toEmbedding_apply, - exists_eq_right_right, exists_eq_right] -#align simple_graph.comap_symm SimpleGraph.comap_symm - -lemma map_symm (G : SimpleGraph W) (e : V ≃ W) : - G.map e.symm.toEmbedding = G.comap e.toEmbedding := by rw [← comap_symm, e.symm_symm] -#align simple_graph.map_symm SimpleGraph.map_symm - -theorem comap_monotone (f : V ↪ W) : Monotone (SimpleGraph.comap f) := by - intro G G' h _ _ ha - exact h ha -#align simple_graph.comap_monotone SimpleGraph.comap_monotone - -@[simp] -theorem comap_map_eq (f : V ↪ W) (G : SimpleGraph V) : (G.map f).comap f = G := by - ext - simp -#align simple_graph.comap_map_eq SimpleGraph.comap_map_eq - -theorem leftInverse_comap_map (f : V ↪ W) : - Function.LeftInverse (SimpleGraph.comap f) (SimpleGraph.map f) := - comap_map_eq f -#align simple_graph.left_inverse_comap_map SimpleGraph.leftInverse_comap_map - -theorem map_injective (f : V ↪ W) : Function.Injective (SimpleGraph.map f) := - (leftInverse_comap_map f).injective -#align simple_graph.map_injective SimpleGraph.map_injective - -theorem comap_surjective (f : V ↪ W) : Function.Surjective (SimpleGraph.comap f) := - (leftInverse_comap_map f).surjective -#align simple_graph.comap_surjective SimpleGraph.comap_surjective - -theorem map_le_iff_le_comap (f : V ↪ W) (G : SimpleGraph V) (G' : SimpleGraph W) : - G.map f ≤ G' ↔ G ≤ G'.comap f := - ⟨fun h u v ha => h ⟨_, _, ha, rfl, rfl⟩, by - rintro h _ _ ⟨u, v, ha, rfl, rfl⟩ - exact h ha⟩ -#align simple_graph.map_le_iff_le_comap SimpleGraph.map_le_iff_le_comap - -theorem map_comap_le (f : V ↪ W) (G : SimpleGraph W) : (G.comap f).map f ≤ G := by - rw [map_le_iff_le_comap] -#align simple_graph.map_comap_le SimpleGraph.map_comap_le - -lemma le_comap_of_subsingleton (f : V → W) [Subsingleton V] : G ≤ G'.comap f := by - intros v w; simp [Subsingleton.elim v w] - -lemma map_le_of_subsingleton (f : V ↪ W) [Subsingleton V] : G.map f ≤ G' := by - rw [map_le_iff_le_comap]; apply le_comap_of_subsingleton - -/-- Given a family of vertex types indexed by `ι`, pulling back from `⊤ : SimpleGraph ι` -yields the complete multipartite graph on the family. -Two vertices are adjacent if and only if their indices are not equal. -/ -abbrev completeMultipartiteGraph {ι : Type*} (V : ι → Type*) : SimpleGraph (Σ i, V i) := - SimpleGraph.comap Sigma.fst ⊤ - -/-- Equivalent types have equivalent simple graphs. -/ -@[simps apply] -protected def _root_.Equiv.simpleGraph (e : V ≃ W) : SimpleGraph V ≃ SimpleGraph W where - toFun := SimpleGraph.comap e.symm - invFun := SimpleGraph.comap e - left_inv _ := by simp - right_inv _ := by simp -#align equiv.simple_graph Equiv.simpleGraph - -@[simp] lemma _root_.Equiv.simpleGraph_refl : (Equiv.refl V).simpleGraph = Equiv.refl _ := by - ext; rfl - -@[simp] lemma _root_.Equiv.simpleGraph_trans (e₁ : V ≃ W) (e₂ : W ≃ X) : - (e₁.trans e₂).simpleGraph = e₁.simpleGraph.trans e₂.simpleGraph := rfl -#align equiv.simple_graph_trans Equiv.simpleGraph_trans - -@[simp] -lemma _root_.Equiv.symm_simpleGraph (e : V ≃ W) : e.simpleGraph.symm = e.symm.simpleGraph := rfl -#align equiv.symm_simple_graph Equiv.symm_simpleGraph - -/-! ## Induced graphs -/ - -/- Given a set `s` of vertices, we can restrict a graph to those vertices by restricting its -adjacency relation. This gives a map between `SimpleGraph V` and `SimpleGraph s`. - -There is also a notion of induced subgraphs (see `SimpleGraph.subgraph.induce`). -/ -/-- Restrict a graph to the vertices in the set `s`, deleting all edges incident to vertices -outside the set. This is a wrapper around `SimpleGraph.comap`. -/ -@[reducible] -def induce (s : Set V) (G : SimpleGraph V) : SimpleGraph s := - G.comap (Function.Embedding.subtype _) -#align simple_graph.induce SimpleGraph.induce - -@[simp] lemma induce_singleton_eq_top (v : V) : G.induce {v} = ⊤ := by - rw [eq_top_iff]; apply le_comap_of_subsingleton - -/-- Given a graph on a set of vertices, we can make it be a `SimpleGraph V` by -adding in the remaining vertices without adding in any additional edges. -This is a wrapper around `SimpleGraph.map`. -/ -@[reducible] -def spanningCoe {s : Set V} (G : SimpleGraph s) : SimpleGraph V := - G.map (Function.Embedding.subtype _) -#align simple_graph.spanning_coe SimpleGraph.spanningCoe - -theorem induce_spanningCoe {s : Set V} {G : SimpleGraph s} : G.spanningCoe.induce s = G := - comap_map_eq _ _ -#align simple_graph.induce_spanning_coe SimpleGraph.induce_spanningCoe - -theorem spanningCoe_induce_le (s : Set V) : (G.induce s).spanningCoe ≤ G := - map_comap_le _ _ -#align simple_graph.spanning_coe_induce_le SimpleGraph.spanningCoe_induce_le - section FiniteAt /-! @@ -1799,451 +1621,4 @@ theorem card_commonNeighbors_top [DecidableEq V] {v w : V} (h : v ≠ w) : end Finite -section Maps - -/-- A graph homomorphism is a map on vertex sets that respects adjacency relations. - -The notation `G →g G'` represents the type of graph homomorphisms. -/ -abbrev Hom := - RelHom G.Adj G'.Adj -#align simple_graph.hom SimpleGraph.Hom - -/-- A graph embedding is an embedding `f` such that for vertices `v w : V`, -`G.Adj (f v) (f w) ↔ G.Adj v w`. Its image is an induced subgraph of G'. - -The notation `G ↪g G'` represents the type of graph embeddings. -/ -abbrev Embedding := - RelEmbedding G.Adj G'.Adj -#align simple_graph.embedding SimpleGraph.Embedding - -/-- A graph isomorphism is a bijective map on vertex sets that respects adjacency relations. - -The notation `G ≃g G'` represents the type of graph isomorphisms. --/ -abbrev Iso := - RelIso G.Adj G'.Adj -#align simple_graph.iso SimpleGraph.Iso - --- mathport name: «expr →g » -infixl:50 " →g " => Hom - --- mathport name: «expr ↪g » -infixl:50 " ↪g " => Embedding - --- mathport name: «expr ≃g » -infixl:50 " ≃g " => Iso - -namespace Hom - -variable {G G'} {G₁ G₂ : SimpleGraph V} {H : SimpleGraph W} (f : G →g G') - -/-- The identity homomorphism from a graph to itself. -/ -protected abbrev id : G →g G := - RelHom.id _ -#align simple_graph.hom.id SimpleGraph.Hom.id - -@[simp, norm_cast] lemma coe_id : ⇑(Hom.id : G →g G) = id := rfl -#align simple_graph.hom.coe_id SimpleGraph.Hom.coe_id - -instance [Subsingleton (V → W)] : Subsingleton (G →g H) := FunLike.coe_injective.subsingleton - -instance [IsEmpty V] : Unique (G →g H) where - default := ⟨isEmptyElim, fun {a} ↦ isEmptyElim a⟩ - uniq _ := Subsingleton.elim _ _ - -instance instFintype [DecidableEq V] [Fintype V] [Fintype W] [DecidableRel G.Adj] - [DecidableRel H.Adj] : Fintype (G →g H) := - Fintype.ofEquiv {f : V → W // ∀ {a b}, G.Adj a b → H.Adj (f a) (f b)} - { toFun := fun f ↦ ⟨f.1, f.2⟩, invFun := fun f ↦ ⟨f.1, f.2⟩, - left_inv := fun _ ↦ rfl, right_inv := fun _ ↦ rfl } - -instance [Finite V] [Finite W] : Finite (G →g H) := FunLike.finite _ - -theorem map_adj {v w : V} (h : G.Adj v w) : G'.Adj (f v) (f w) := - f.map_rel' h -#align simple_graph.hom.map_adj SimpleGraph.Hom.map_adj - -theorem map_mem_edgeSet {e : Sym2 V} (h : e ∈ G.edgeSet) : e.map f ∈ G'.edgeSet := - Sym2.ind (fun _ _ => f.map_rel') e h -#align simple_graph.hom.map_mem_edge_set SimpleGraph.Hom.map_mem_edgeSet - -theorem apply_mem_neighborSet {v w : V} (h : w ∈ G.neighborSet v) : f w ∈ G'.neighborSet (f v) := - map_adj f h -#align simple_graph.hom.apply_mem_neighbor_set SimpleGraph.Hom.apply_mem_neighborSet - -/-- The map between edge sets induced by a homomorphism. -The underlying map on edges is given by `Sym2.map`. -/ -@[simps] -def mapEdgeSet (e : G.edgeSet) : G'.edgeSet := - ⟨Sym2.map f e, f.map_mem_edgeSet e.property⟩ -#align simple_graph.hom.map_edge_set SimpleGraph.Hom.mapEdgeSet - -/-- The map between neighbor sets induced by a homomorphism. -/ -@[simps] -def mapNeighborSet (v : V) (w : G.neighborSet v) : G'.neighborSet (f v) := - ⟨f w, f.apply_mem_neighborSet w.property⟩ -#align simple_graph.hom.map_neighbor_set SimpleGraph.Hom.mapNeighborSet - -/-- The map between darts induced by a homomorphism. -/ -def mapDart (d : G.Dart) : G'.Dart := - ⟨d.1.map f f, f.map_adj d.2⟩ -#align simple_graph.hom.map_dart SimpleGraph.Hom.mapDart - -@[simp] -theorem mapDart_apply (d : G.Dart) : f.mapDart d = ⟨d.1.map f f, f.map_adj d.2⟩ := - rfl -#align simple_graph.hom.map_dart_apply SimpleGraph.Hom.mapDart_apply - -/-- The induced map for spanning subgraphs, which is the identity on vertices. -/ -@[simps] -def mapSpanningSubgraphs {G G' : SimpleGraph V} (h : G ≤ G') : G →g G' where - toFun x := x - map_rel' ha := h ha -#align simple_graph.hom.map_spanning_subgraphs SimpleGraph.Hom.mapSpanningSubgraphs - -theorem mapEdgeSet.injective (hinj : Function.Injective f) : Function.Injective f.mapEdgeSet := by - rintro ⟨e₁, h₁⟩ ⟨e₂, h₂⟩ - dsimp [Hom.mapEdgeSet] - repeat' rw [Subtype.mk_eq_mk] - apply Sym2.map.injective hinj -#align simple_graph.hom.map_edge_set.injective SimpleGraph.Hom.mapEdgeSet.injective - -/-- Every graph homomorphism from a complete graph is injective. -/ -theorem injective_of_top_hom (f : (⊤ : SimpleGraph V) →g G') : Function.Injective f := by - intro v w h - contrapose! h - exact G'.ne_of_adj (map_adj _ ((top_adj _ _).mpr h)) -#align simple_graph.hom.injective_of_top_hom SimpleGraph.Hom.injective_of_top_hom - -/-- There is a homomorphism to a graph from a comapped graph. -When the function is injective, this is an embedding (see `SimpleGraph.Embedding.comap`). -/ -@[simps] -protected def comap (f : V → W) (G : SimpleGraph W) : G.comap f →g G where - toFun := f - map_rel' := by simp -#align simple_graph.hom.comap SimpleGraph.Hom.comap - -variable {G'' : SimpleGraph X} - -/-- Composition of graph homomorphisms. -/ -abbrev comp (f' : G' →g G'') (f : G →g G') : G →g G'' := - RelHom.comp f' f -#align simple_graph.hom.comp SimpleGraph.Hom.comp - -@[simp] -theorem coe_comp (f' : G' →g G'') (f : G →g G') : ⇑(f'.comp f) = f' ∘ f := - rfl -#align simple_graph.hom.coe_comp SimpleGraph.Hom.coe_comp - -/-- The graph homomorphism from a smaller graph to a bigger one. -/ -def ofLe (h : G₁ ≤ G₂) : G₁ →g G₂ := ⟨id, @h⟩ -#align simple_graph.hom.of_le SimpleGraph.Hom.ofLe - -@[simp, norm_cast] lemma coe_ofLe (h : G₁ ≤ G₂) : ⇑(ofLe h) = id := rfl -#align simple_graph.hom.coe_of_le SimpleGraph.Hom.coe_ofLe - -end Hom - -namespace Embedding - -variable {G G'} {H : SimpleGraph W} (f : G ↪g G') - -/-- The identity embedding from a graph to itself. -/ -abbrev refl : G ↪g G := - RelEmbedding.refl _ -#align simple_graph.embedding.refl SimpleGraph.Embedding.refl - -/-- An embedding of graphs gives rise to a homomorphism of graphs. -/ -abbrev toHom : G →g G' := - f.toRelHom -#align simple_graph.embedding.to_hom SimpleGraph.Embedding.toHom - -@[simp] lemma coe_toHom (f : G ↪g H) : ⇑f.toHom = f := rfl -#align simple_graph.embedding.coe_to_hom SimpleGraph.Embedding.coe_toHom - -@[simp] theorem map_adj_iff {v w : V} : G'.Adj (f v) (f w) ↔ G.Adj v w := - f.map_rel_iff -#align simple_graph.embedding.map_adj_iff SimpleGraph.Embedding.map_adj_iff - -theorem map_mem_edgeSet_iff {e : Sym2 V} : e.map f ∈ G'.edgeSet ↔ e ∈ G.edgeSet := - Sym2.ind (fun _ _ => f.map_adj_iff) e -#align simple_graph.embedding.map_mem_edge_set_iff SimpleGraph.Embedding.map_mem_edgeSet_iff - -theorem apply_mem_neighborSet_iff {v w : V} : f w ∈ G'.neighborSet (f v) ↔ w ∈ G.neighborSet v := - map_adj_iff f -#align simple_graph.embedding.apply_mem_neighbor_set_iff SimpleGraph.Embedding.apply_mem_neighborSet_iff - -/-- A graph embedding induces an embedding of edge sets. -/ -@[simps] -def mapEdgeSet : G.edgeSet ↪ G'.edgeSet where - toFun := Hom.mapEdgeSet f - inj' := Hom.mapEdgeSet.injective f f.injective -#align simple_graph.embedding.map_edge_set SimpleGraph.Embedding.mapEdgeSet - -/-- A graph embedding induces an embedding of neighbor sets. -/ -@[simps] -def mapNeighborSet (v : V) : G.neighborSet v ↪ G'.neighborSet (f v) - where - toFun w := ⟨f w, f.apply_mem_neighborSet_iff.mpr w.2⟩ - inj' := by - rintro ⟨w₁, h₁⟩ ⟨w₂, h₂⟩ h - rw [Subtype.mk_eq_mk] at h ⊢ - exact f.inj' h -#align simple_graph.embedding.map_neighbor_set SimpleGraph.Embedding.mapNeighborSet - -/-- Given an injective function, there is an embedding from the comapped graph into the original -graph. -/ --- porting note: @[simps] does not work here since `f` is not a constructor application. --- `@[simps toEmbedding]` could work, but Floris suggested writing `comap_apply` for now. -protected def comap (f : V ↪ W) (G : SimpleGraph W) : G.comap f ↪g G := - { f with map_rel_iff' := by simp } -#align simple_graph.embedding.comap SimpleGraph.Embedding.comap - -@[simp] -theorem comap_apply (f : V ↪ W) (G : SimpleGraph W) (v : V) : - SimpleGraph.Embedding.comap f G v = f v := rfl -#align simple_graph.embedding.comap_apply SimpleGraph.Embedding.comap_apply - -/-- Given an injective function, there is an embedding from a graph into the mapped graph. -/ --- porting note: @[simps] does not work here since `f` is not a constructor application. --- `@[simps toEmbedding]` could work, but Floris suggested writing `map_apply` for now. -protected def map (f : V ↪ W) (G : SimpleGraph V) : G ↪g G.map f := - { f with map_rel_iff' := by simp } -#align simple_graph.embedding.map SimpleGraph.Embedding.map - -@[simp] -theorem map_apply (f : V ↪ W) (G : SimpleGraph V) (v : V) : - SimpleGraph.Embedding.map f G v = f v := rfl -#align simple_graph.embedding.map_apply SimpleGraph.Embedding.map_apply - -/-- Induced graphs embed in the original graph. - -Note that if `G.induce s = ⊤` (i.e., if `s` is a clique) then this gives the embedding of a -complete graph. -/ -@[reducible] -protected def induce (s : Set V) : G.induce s ↪g G := - SimpleGraph.Embedding.comap (Function.Embedding.subtype _) G -#align simple_graph.embedding.induce SimpleGraph.Embedding.induce - -/-- Graphs on a set of vertices embed in their `spanningCoe`. -/ -@[reducible] -protected def spanningCoe {s : Set V} (G : SimpleGraph s) : G ↪g G.spanningCoe := - SimpleGraph.Embedding.map (Function.Embedding.subtype _) G -#align simple_graph.embedding.spanning_coe SimpleGraph.Embedding.spanningCoe - -/-- Embeddings of types induce embeddings of complete graphs on those types. -/ -protected def completeGraph {α β : Type*} (f : α ↪ β) : - (⊤ : SimpleGraph α) ↪g (⊤ : SimpleGraph β) := - { f with map_rel_iff' := by simp } -#align simple_graph.embedding.complete_graph SimpleGraph.Embedding.completeGraph - -variable {G'' : SimpleGraph X} - -/-- Composition of graph embeddings. -/ -abbrev comp (f' : G' ↪g G'') (f : G ↪g G') : G ↪g G'' := - f.trans f' -#align simple_graph.embedding.comp SimpleGraph.Embedding.comp - -@[simp] -theorem coe_comp (f' : G' ↪g G'') (f : G ↪g G') : ⇑(f'.comp f) = f' ∘ f := - rfl -#align simple_graph.embedding.coe_comp SimpleGraph.Embedding.coe_comp - -end Embedding - -section induceHom - -variable {G G'} {G'' : SimpleGraph X} {s : Set V} {t : Set W} {r : Set X} - (φ : G →g G') (φst : Set.MapsTo φ s t) (ψ : G' →g G'') (ψtr : Set.MapsTo ψ t r) - -/-- The restriction of a morphism of graphs to induced subgraphs. -/ -def induceHom : G.induce s →g G'.induce t where - toFun := Set.MapsTo.restrict φ s t φst - map_rel' := φ.map_rel' -#align simple_graph.induce_hom SimpleGraph.induceHom - -@[simp, norm_cast] lemma coe_induceHom : ⇑(induceHom φ φst) = Set.MapsTo.restrict φ s t φst := - rfl -#align simple_graph.coe_induce_hom SimpleGraph.coe_induceHom - -@[simp] lemma induceHom_id (G : SimpleGraph V) (s) : - induceHom (Hom.id : G →g G) (Set.mapsTo_id s) = Hom.id := by - ext x - rfl -#align simple_graph.induce_hom_id SimpleGraph.induceHom_id - -@[simp] lemma induceHom_comp : - (induceHom ψ ψtr).comp (induceHom φ φst) = induceHom (ψ.comp φ) (ψtr.comp φst) := by - ext x - rfl -#align simple_graph.induce_hom_comp SimpleGraph.induceHom_comp - -lemma induceHom_injective (hi : Set.InjOn φ s) : - Function.Injective (induceHom φ φst) := by - erw [Set.MapsTo.restrict_inj] <;> assumption - -end induceHom - -section induceHomLE -variable {s s' : Set V} (h : s ≤ s') - -/-- Given an inclusion of vertex subsets, the induced embedding on induced graphs. -This is not an abbreviation for `induceHom` since we get an embedding in this case. -/ -def induceHomOfLE (h : s ≤ s') : G.induce s ↪g G.induce s' where - toEmbedding := Set.embeddingOfSubset s s' h - map_rel_iff' := by simp - -@[simp] lemma induceHomOfLE_apply (v : s) : (G.induceHomOfLE h) v = Set.inclusion h v := rfl - -@[simp] lemma induceHomOfLE_toHom : - (G.induceHomOfLE h).toHom = induceHom (.id : G →g G) ((Set.mapsTo_id s).mono_right h) := by - ext; simp - -end induceHomLE - -namespace Iso - -variable {G G'} (f : G ≃g G') - -/-- The identity isomorphism of a graph with itself. -/ -abbrev refl : G ≃g G := - RelIso.refl _ -#align simple_graph.iso.refl SimpleGraph.Iso.refl - -/-- An isomorphism of graphs gives rise to an embedding of graphs. -/ -abbrev toEmbedding : G ↪g G' := - f.toRelEmbedding -#align simple_graph.iso.to_embedding SimpleGraph.Iso.toEmbedding - -/-- An isomorphism of graphs gives rise to a homomorphism of graphs. -/ -abbrev toHom : G →g G' := - f.toEmbedding.toHom -#align simple_graph.iso.to_hom SimpleGraph.Iso.toHom - -/-- The inverse of a graph isomorphism. -/ -abbrev symm : G' ≃g G := - RelIso.symm f -#align simple_graph.iso.symm SimpleGraph.Iso.symm - -theorem map_adj_iff {v w : V} : G'.Adj (f v) (f w) ↔ G.Adj v w := - f.map_rel_iff -#align simple_graph.iso.map_adj_iff SimpleGraph.Iso.map_adj_iff - -theorem map_mem_edgeSet_iff {e : Sym2 V} : e.map f ∈ G'.edgeSet ↔ e ∈ G.edgeSet := - Sym2.ind (fun _ _ => f.map_adj_iff) e -#align simple_graph.iso.map_mem_edge_set_iff SimpleGraph.Iso.map_mem_edgeSet_iff - -theorem apply_mem_neighborSet_iff {v w : V} : f w ∈ G'.neighborSet (f v) ↔ w ∈ G.neighborSet v := - map_adj_iff f -#align simple_graph.iso.apply_mem_neighbor_set_iff SimpleGraph.Iso.apply_mem_neighborSet_iff - -/-- An isomorphism of graphs induces an equivalence of edge sets. -/ -@[simps] -def mapEdgeSet : G.edgeSet ≃ G'.edgeSet - where - toFun := Hom.mapEdgeSet f - invFun := Hom.mapEdgeSet f.symm - left_inv := by - rintro ⟨e, h⟩ - simp only [Hom.mapEdgeSet, RelEmbedding.toRelHom, Embedding.toFun_eq_coe, - RelEmbedding.coe_toEmbedding, RelIso.coe_toRelEmbedding, Sym2.map_map, comp_apply, - Subtype.mk.injEq] - convert congr_fun Sym2.map_id e - exact RelIso.symm_apply_apply _ _ - right_inv := by - rintro ⟨e, h⟩ - simp only [Hom.mapEdgeSet, RelEmbedding.toRelHom, Embedding.toFun_eq_coe, - RelEmbedding.coe_toEmbedding, RelIso.coe_toRelEmbedding, Sym2.map_map, comp_apply, - Subtype.mk.injEq] - convert congr_fun Sym2.map_id e - exact RelIso.apply_symm_apply _ _ -#align simple_graph.iso.map_edge_set SimpleGraph.Iso.mapEdgeSet - -/-- A graph isomorphism induces an equivalence of neighbor sets. -/ -@[simps] -def mapNeighborSet (v : V) : G.neighborSet v ≃ G'.neighborSet (f v) - where - toFun w := ⟨f w, f.apply_mem_neighborSet_iff.mpr w.2⟩ - invFun w := - ⟨f.symm w, by - simpa [RelIso.symm_apply_apply] using f.symm.apply_mem_neighborSet_iff.mpr w.2⟩ - left_inv w := by simp - right_inv w := by simp -#align simple_graph.iso.map_neighbor_set SimpleGraph.Iso.mapNeighborSet - -theorem card_eq_of_iso [Fintype V] [Fintype W] (f : G ≃g G') : Fintype.card V = Fintype.card W := by - rw [← Fintype.ofEquiv_card f.toEquiv] - -- porting note: need to help it to find the typeclass instances from the target expression - apply @Fintype.card_congr' _ _ (_) (_) rfl -#align simple_graph.iso.card_eq_of_iso SimpleGraph.Iso.card_eq_of_iso - -/-- Given a bijection, there is an embedding from the comapped graph into the original -graph. -/ --- porting note: `@[simps]` does not work here anymore since `f` is not a constructor application. --- `@[simps toEmbedding]` could work, but Floris suggested writing `comap_apply` for now. -protected def comap (f : V ≃ W) (G : SimpleGraph W) : G.comap f.toEmbedding ≃g G := - { f with map_rel_iff' := by simp } -#align simple_graph.iso.comap SimpleGraph.Iso.comap - -@[simp] -lemma comap_apply (f : V ≃ W) (G : SimpleGraph W) (v : V) : - SimpleGraph.Iso.comap f G v = f v := rfl -#align simple_graph.iso.comap_apply SimpleGraph.Iso.comap_apply - -@[simp] -lemma comap_symm_apply (f : V ≃ W) (G : SimpleGraph W) (w : W) : - (SimpleGraph.Iso.comap f G).symm w = f.symm w := rfl -#align simple_graph.iso.comap_symm_apply SimpleGraph.Iso.comap_symm_apply - -/-- Given an injective function, there is an embedding from a graph into the mapped graph. -/ --- porting note: `@[simps]` does not work here anymore since `f` is not a constructor application. --- `@[simps toEmbedding]` could work, but Floris suggested writing `map_apply` for now. -protected def map (f : V ≃ W) (G : SimpleGraph V) : G ≃g G.map f.toEmbedding := - { f with map_rel_iff' := by simp } -#align simple_graph.iso.map SimpleGraph.Iso.map - -@[simp] -lemma map_apply (f : V ≃ W) (G : SimpleGraph V) (v : V) : - SimpleGraph.Iso.map f G v = f v := rfl -#align simple_graph.iso.map_apply SimpleGraph.Iso.map_apply - -@[simp] -lemma map_symm_apply (f : V ≃ W) (G : SimpleGraph V) (w : W) : - (SimpleGraph.Iso.map f G).symm w = f.symm w := rfl -#align simple_graph.iso.map_symm_apply SimpleGraph.Iso.map_symm_apply - -/-- Equivalences of types induce isomorphisms of complete graphs on those types. -/ -protected def completeGraph {α β : Type*} (f : α ≃ β) : - (⊤ : SimpleGraph α) ≃g (⊤ : SimpleGraph β) := - { f with map_rel_iff' := by simp } -#align simple_graph.iso.complete_graph SimpleGraph.Iso.completeGraph - -theorem toEmbedding_completeGraph {α β : Type*} (f : α ≃ β) : - (Iso.completeGraph f).toEmbedding = Embedding.completeGraph f.toEmbedding := - rfl -#align simple_graph.iso.to_embedding_complete_graph SimpleGraph.Iso.toEmbedding_completeGraph - -variable {G'' : SimpleGraph X} - -/-- Composition of graph isomorphisms. -/ -abbrev comp (f' : G' ≃g G'') (f : G ≃g G') : G ≃g G'' := - f.trans f' -#align simple_graph.iso.comp SimpleGraph.Iso.comp - -@[simp] -theorem coe_comp (f' : G' ≃g G'') (f : G ≃g G') : ⇑(f'.comp f) = f' ∘ f := - rfl -#align simple_graph.iso.coe_comp SimpleGraph.Iso.coe_comp - -end Iso - -end Maps - -/-- The graph induced on `Set.univ` is isomorphic to the original graph. -/ -@[simps!] -def induceUnivIso (G : SimpleGraph V) : G.induce Set.univ ≃g G where - toEquiv := Equiv.Set.univ V - map_rel_iff' := by simp only [Equiv.Set.univ, Equiv.coe_fn_mk, comap_adj, Embedding.coe_subtype, - Subtype.forall, Set.mem_univ, forall_true_left, implies_true] - end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/Clique.lean b/Mathlib/Combinatorics/SimpleGraph/Clique.lean index cf0d783247864..d2885c05fcef6 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Clique.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Clique.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 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 Mathlib.Combinatorics.SimpleGraph.Maps import Mathlib.Combinatorics.SimpleGraph.Operations import Mathlib.Data.Finset.Pairwise import Mathlib.Data.Finset.Preimage @@ -280,6 +281,11 @@ theorem CliqueFree.anti (h : G ≤ H) : H.CliqueFree n → G.CliqueFree n := forall_imp fun _ ↦ mt <| IsNClique.mono h #align simple_graph.clique_free.anti SimpleGraph.CliqueFree.anti +/-- If a graph is cliquefree, any graph that embeds into it is also cliquefree. -/ +theorem CliqueFree.comap {H : SimpleGraph β} (f : H ↪g G) : G.CliqueFree n → H.CliqueFree n := by + intro h; contrapose h + exact not_cliqueFree_of_top_embedding <| f.comp (topEmbeddingOfNotCliqueFree h) + /-- See `SimpleGraph.cliqueFree_of_chromaticNumber_lt` for a tighter bound. -/ theorem cliqueFree_of_card_lt [Fintype α] (hc : card α < n) : G.CliqueFree n := by by_contra h @@ -298,41 +304,28 @@ theorem cliqueFree_completeMultipartiteGraph {ι : Type*} [Fintype ι] (V : ι exact absurd he hn /-- Clique-freeness is preserved by `replaceVertex`. -/ -theorem cliqueFree_of_replaceVertex_cliqueFree [DecidableEq α] (s t : α) (h : G.CliqueFree n) : +protected theorem CliqueFree.replaceVertex [DecidableEq α] (h : G.CliqueFree n) (s t : α) : (G.replaceVertex s t).CliqueFree n := by contrapose h - obtain ⟨⟨f, hi⟩, ha⟩ := topEmbeddingOfNotCliqueFree h - simp only [Function.Embedding.coeFn_mk, top_adj, ne_eq] at ha + obtain ⟨φ, hφ⟩ := topEmbeddingOfNotCliqueFree h rw [not_cliqueFree_iff] - by_cases mt : t ∈ Set.range f + by_cases mt : t ∈ Set.range φ · obtain ⟨x, hx⟩ := mt - by_cases ms : s ∈ Set.range f + by_cases ms : s ∈ Set.range φ · obtain ⟨y, hy⟩ := ms - by_cases hst : s = t - · simp_all [not_cliqueFree_iff] - · replace ha := @ha x y; simp_all - · use ⟨fun v => if v = x then s else f v, ?_⟩ - swap - · intro a b - dsimp only - split_ifs - · simp_all - · intro; simp_all - · intro; simp_all - · apply hi + have e := @hφ x y + simp_rw [hx, hy, adj_comm, not_adj_replaceVertex_same, top_adj, false_iff, not_ne_iff] at e + rwa [← hx, e, hy, replaceVertex_self, not_cliqueFree_iff] at h + · unfold replaceVertex at hφ + use φ.setValue x s intro a b - simp only [Function.Embedding.coeFn_mk, top_adj, ne_eq] - split_ifs with h1 h2 h2 - · simp_all - · have := (@ha b x).mpr h2 - split_ifs at this; subst h1; tauto - · have := (@ha a x).mpr h1 - split_ifs at this; subst h2; tauto - · rw [← @ha a b] - have := (@hi a x).mt h1 - have := (@hi b x).mt h2 - simp_all - · use ⟨f, hi⟩; simp_all + simp only [Embedding.coeFn_mk, Embedding.setValue, not_exists.mp ms, ite_false] + rw [apply_ite (G.Adj · _), apply_ite (G.Adj _ ·), apply_ite (G.Adj _ ·)] + convert @hφ a b <;> simp only [← φ.apply_eq_iff_eq, SimpleGraph.irrefl, hx] + · use φ + simp_rw [Set.mem_range, not_exists, ← ne_eq] at mt + conv at hφ => enter [a, b]; rw [G.adj_replaceVertex_iff_of_ne _ (mt a) (mt b)] + exact hφ @[simp] theorem cliqueFree_two : G.CliqueFree 2 ↔ G = ⊥ := by @@ -344,6 +337,34 @@ theorem cliqueFree_two : G.CliqueFree 2 ↔ G = ⊥ := by exact cliqueFree_bot le_rfl #align simple_graph.clique_free_two SimpleGraph.cliqueFree_two +/-- Adding an edge increases the clique number by at most one. -/ +protected theorem CliqueFree.addEdge (h : G.CliqueFree n) (v w) : + (G.addEdge v w).CliqueFree (n + 1) := by + contrapose h + obtain ⟨f, ha⟩ := topEmbeddingOfNotCliqueFree h + simp only [ne_eq, top_adj] at ha + rw [not_cliqueFree_iff] + by_cases mw : w ∈ Set.range f + · obtain ⟨x, hx⟩ := mw + use ⟨f ∘ x.succAboveEmb, (f.2.of_comp_iff _).mpr (RelEmbedding.injective _)⟩ + intro a b + simp_rw [Embedding.coeFn_mk, comp_apply, Fin.succAboveEmb_apply, top_adj] + have hs := @ha (x.succAbove a) (x.succAbove b) + have ia : w ≠ f (x.succAbove a) := + (hx ▸ f.apply_eq_iff_eq x (x.succAbove a)).ne.mpr (x.succAbove_ne a).symm + have ib : w ≠ f (x.succAbove b) := + (hx ▸ f.apply_eq_iff_eq x (x.succAbove b)).ne.mpr (x.succAbove_ne b).symm + simp only [addEdge, ia, ib, and_false, false_and, or_false] at hs + rw [hs, Fin.succAbove_right_inj] + · use ⟨f ∘ Fin.succEmbedding n, (f.2.of_comp_iff _).mpr (RelEmbedding.injective _)⟩ + intro a b + simp only [Fin.val_succEmbedding, Embedding.coeFn_mk, comp_apply, top_adj] + have hs := @ha a.succ b.succ + have ia : f a.succ ≠ w := by simp_all + have ib : f b.succ ≠ w := by simp_all + simp only [addEdge, ia.symm, ib.symm, and_false, false_and, or_false] at hs + rw [hs, Fin.succ_inj] + end CliqueFree section CliqueFreeOn diff --git a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean index 5e3813ebb0c5a..f335c0cc0f412 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino, Kyle Miller -/ import Mathlib.Combinatorics.SimpleGraph.Clique +import Mathlib.Data.ENat.Lattice import Mathlib.Data.Nat.Lattice import Mathlib.Data.Setoid.Partition import Mathlib.Order.Antichain @@ -30,8 +31,10 @@ a complete graph, whose vertices represent the colors. is whether there exists a coloring with at most *n* colors. * `G.chromaticNumber` is the minimal `n` such that `G` is - `n`-colorable, or `0` if it cannot be colored with finitely many + `n`-colorable, or `⊤` if it cannot be colored with finitely many colors. + (Cardinal-valued chromatic numbers are more niche, so we stick to `ℕ∞`.) + We write `G.chromaticNumber ≠ ⊤` to mean a graph is colorable with finitely many colors. * `C.colorClass c` is the set of vertices colored by `c : α` in the coloring `C : G.Coloring α`. @@ -157,11 +160,24 @@ def selfColoring : G.Coloring V := Coloring.mk id fun {_ _} => G.ne_of_adj #align simple_graph.self_coloring SimpleGraph.selfColoring /-- The chromatic number of a graph is the minimal number of colors needed to color it. -If `G` isn't colorable with finitely many colors, this will be 0. -/ -noncomputable def chromaticNumber : ℕ := - sInf { n : ℕ | G.Colorable n } +This is `⊤` (infinity) iff `G` isn't colorable with finitely many colors. + +If `G` is colorable, then `ENat.toNat G.chromaticNumber` is the `ℕ`-valued chromatic number. -/ +noncomputable def chromaticNumber : ℕ∞ := ⨅ n ∈ setOf G.Colorable, (n : ℕ∞) #align simple_graph.chromatic_number SimpleGraph.chromaticNumber +lemma chromaticNumber_eq_biInf {G : SimpleGraph V} : + G.chromaticNumber = ⨅ n ∈ setOf G.Colorable, (n : ℕ∞) := rfl + +lemma chromaticNumber_eq_iInf {G : SimpleGraph V} : + G.chromaticNumber = ⨅ n : {m | G.Colorable m}, (n : ℕ∞) := by + rw [chromaticNumber, iInf_subtype] + +lemma Colorable.chromaticNumber_eq_sInf {G : SimpleGraph V} {n} (h : G.Colorable n) : + G.chromaticNumber = sInf {n' : ℕ | G.Colorable n'} := by + rw [ENat.coe_sInf, chromaticNumber] + exact ⟨_, h⟩ + /-- Given an embedding, there is an induced embedding of colorings. -/ def recolorOfEmbedding {α β : Type*} (f : α ↪ β) : G.Coloring α ↪ G.Coloring β where toFun C := (Embedding.completeGraph f).toHom.comp C @@ -200,12 +216,12 @@ theorem Colorable.mono {n m : ℕ} (h : n ≤ m) (hc : G.Colorable n) : G.Colora ⟨G.recolorOfCardLE (by simp [h]) hc.some⟩ #align simple_graph.colorable.mono SimpleGraph.Colorable.mono -theorem Coloring.to_colorable [Fintype α] (C : G.Coloring α) : G.Colorable (Fintype.card α) := +theorem Coloring.colorable [Fintype α] (C : G.Coloring α) : G.Colorable (Fintype.card α) := ⟨G.recolorOfCardLE (by simp) C⟩ -#align simple_graph.coloring.to_colorable SimpleGraph.Coloring.to_colorable +#align simple_graph.coloring.to_colorable SimpleGraph.Coloring.colorable theorem colorable_of_fintype (G : SimpleGraph V) [Fintype V] : G.Colorable (Fintype.card V) := - G.selfColoring.to_colorable + G.selfColoring.colorable #align simple_graph.colorable_of_fintype SimpleGraph.colorable_of_fintype /-- Noncomputably get a coloring from colorability. -/ @@ -247,47 +263,63 @@ theorem chromaticNumber_bddBelow : BddBelow { n : ℕ | G.Colorable n } := ⟨0, fun _ _ => zero_le _⟩ #align simple_graph.chromatic_number_bdd_below SimpleGraph.chromaticNumber_bddBelow -theorem chromaticNumber_le_of_colorable {n : ℕ} (hc : G.Colorable n) : G.chromaticNumber ≤ n := by - rw [chromaticNumber] +theorem Colorable.chromaticNumber_le {n : ℕ} (hc : G.Colorable n) : G.chromaticNumber ≤ n := by + rw [hc.chromaticNumber_eq_sInf] + norm_cast apply csInf_le chromaticNumber_bddBelow - constructor - exact Classical.choice hc -#align simple_graph.chromatic_number_le_of_colorable SimpleGraph.chromaticNumber_le_of_colorable + exact hc +#align simple_graph.chromatic_number_le_of_colorable SimpleGraph.Colorable.chromaticNumber_le + +theorem chromaticNumber_ne_top_iff_exists : G.chromaticNumber ≠ ⊤ ↔ ∃ n, G.Colorable n := by + rw [chromaticNumber] + convert_to ⨅ n : {m | G.Colorable m}, (n : ℕ∞) ≠ ⊤ ↔ _ + · rw [iInf_subtype] + rw [← lt_top_iff_ne_top, ENat.iInf_coe_lt_top] + simp + +theorem chromaticNumber_le_iff_colorable {n : ℕ} : G.chromaticNumber ≤ n ↔ G.Colorable n := by + refine ⟨fun h ↦ ?_, Colorable.chromaticNumber_le⟩ + have : G.chromaticNumber ≠ ⊤ := (trans h (WithTop.coe_lt_top n)).ne + rw [chromaticNumber_ne_top_iff_exists] at this + obtain ⟨m, hm⟩ := this + rw [hm.chromaticNumber_eq_sInf, Nat.cast_le] at h + have := Nat.sInf_mem (⟨m, hm⟩ : {n' | G.Colorable n'}.Nonempty) + rw [Set.mem_setOf_eq] at this + exact this.mono h theorem chromaticNumber_le_card [Fintype α] (C : G.Coloring α) : - G.chromaticNumber ≤ Fintype.card α := - csInf_le chromaticNumber_bddBelow C.to_colorable + G.chromaticNumber ≤ Fintype.card α := by + rw [C.colorable.chromaticNumber_eq_sInf] + norm_cast + exact csInf_le chromaticNumber_bddBelow C.colorable #align simple_graph.chromatic_number_le_card SimpleGraph.chromaticNumber_le_card -theorem colorable_chromaticNumber {m : ℕ} (hc : G.Colorable m) : G.Colorable G.chromaticNumber := by +theorem colorable_chromaticNumber {m : ℕ} (hc : G.Colorable m) : + G.Colorable (ENat.toNat G.chromaticNumber) := by classical - dsimp only [chromaticNumber] - rw [Nat.sInf_def] + rw [hc.chromaticNumber_eq_sInf, Nat.sInf_def] apply Nat.find_spec exact colorable_set_nonempty_of_colorable hc #align simple_graph.colorable_chromatic_number SimpleGraph.colorable_chromaticNumber theorem colorable_chromaticNumber_of_fintype (G : SimpleGraph V) [Finite V] : - G.Colorable G.chromaticNumber := by + G.Colorable (ENat.toNat G.chromaticNumber) := by cases nonempty_fintype V exact colorable_chromaticNumber G.colorable_of_fintype #align simple_graph.colorable_chromatic_number_of_fintype SimpleGraph.colorable_chromaticNumber_of_fintype theorem chromaticNumber_le_one_of_subsingleton (G : SimpleGraph V) [Subsingleton V] : G.chromaticNumber ≤ 1 := by - rw [chromaticNumber] - apply csInf_le chromaticNumber_bddBelow - constructor - refine' Coloring.mk (fun _ => 0) _ - intro v w - rw [Subsingleton.elim v w] + rw [← Nat.cast_one, chromaticNumber_le_iff_colorable] + refine ⟨Coloring.mk (fun _ => 0) ?_⟩ + intros v w + cases Subsingleton.elim v w simp #align simple_graph.chromatic_number_le_one_of_subsingleton SimpleGraph.chromaticNumber_le_one_of_subsingleton theorem chromaticNumber_eq_zero_of_isempty (G : SimpleGraph V) [IsEmpty V] : G.chromaticNumber = 0 := by - rw [← nonpos_iff_eq_zero] - apply csInf_le chromaticNumber_bddBelow + rw [← nonpos_iff_eq_zero, ← Nat.cast_zero, chromaticNumber_le_iff_colorable] apply colorable_of_isEmpty #align simple_graph.chromatic_number_eq_zero_of_isempty SimpleGraph.chromaticNumber_eq_zero_of_isempty @@ -299,6 +331,7 @@ theorem isEmpty_of_chromaticNumber_eq_zero (G : SimpleGraph V) [Finite V] #align simple_graph.is_empty_of_chromatic_number_eq_zero SimpleGraph.isEmpty_of_chromaticNumber_eq_zero theorem chromaticNumber_pos [Nonempty V] {n : ℕ} (hc : G.Colorable n) : 0 < G.chromaticNumber := by + rw [hc.chromaticNumber_eq_sInf, Nat.cast_pos] apply le_csInf (colorable_set_nonempty_of_colorable hc) intro m hm by_contra h' @@ -308,43 +341,48 @@ theorem chromaticNumber_pos [Nonempty V] {n : ℕ} (hc : G.Colorable n) : 0 < G. exact Nat.not_lt_zero _ h₁ #align simple_graph.chromatic_number_pos SimpleGraph.chromaticNumber_pos -theorem colorable_of_chromaticNumber_pos (h : 0 < G.chromaticNumber) : - G.Colorable G.chromaticNumber := by - obtain ⟨h, hn⟩ := Nat.nonempty_of_pos_sInf h +theorem colorable_of_chromaticNumber_ne_top (h : G.chromaticNumber ≠ ⊤) : + G.Colorable (ENat.toNat G.chromaticNumber) := by + rw [chromaticNumber_ne_top_iff_exists] at h + obtain ⟨n, hn⟩ := h exact colorable_chromaticNumber hn -#align simple_graph.colorable_of_chromatic_number_pos SimpleGraph.colorable_of_chromaticNumber_pos +#align simple_graph.colorable_of_chromatic_number_pos SimpleGraph.colorable_of_chromaticNumber_ne_top theorem Colorable.mono_left {G' : SimpleGraph V} (h : G ≤ G') {n : ℕ} (hc : G'.Colorable n) : G.Colorable n := ⟨hc.some.comp (Hom.mapSpanningSubgraphs h)⟩ #align simple_graph.colorable.mono_left SimpleGraph.Colorable.mono_left -theorem Colorable.chromaticNumber_le_of_forall_imp {V' : Type*} {G' : SimpleGraph V'} {m : ℕ} - (hc : G'.Colorable m) (h : ∀ n, G'.Colorable n → G.Colorable n) : +theorem chromaticNumber_le_of_forall_imp {V' : Type*} {G' : SimpleGraph V'} + (h : ∀ n, G'.Colorable n → G.Colorable n) : G.chromaticNumber ≤ G'.chromaticNumber := by - apply csInf_le chromaticNumber_bddBelow - apply h - apply colorable_chromaticNumber hc -#align simple_graph.colorable.chromatic_number_le_of_forall_imp SimpleGraph.Colorable.chromaticNumber_le_of_forall_imp - -theorem Colorable.chromaticNumber_mono (G' : SimpleGraph V) {m : ℕ} (hc : G'.Colorable m) + rw [chromaticNumber, chromaticNumber] + simp only [Set.mem_setOf_eq, le_iInf_iff] + intro m hc + have := h _ hc + rw [← chromaticNumber_le_iff_colorable] at this + exact this +#align simple_graph.colorable.chromatic_number_le_of_forall_imp SimpleGraph.chromaticNumber_le_of_forall_imp + +theorem chromaticNumber_mono (G' : SimpleGraph V) (h : G ≤ G') : G.chromaticNumber ≤ G'.chromaticNumber := - hc.chromaticNumber_le_of_forall_imp fun _ => Colorable.mono_left h -#align simple_graph.colorable.chromatic_number_mono SimpleGraph.Colorable.chromaticNumber_mono + chromaticNumber_le_of_forall_imp fun _ => Colorable.mono_left h +#align simple_graph.colorable.chromatic_number_mono SimpleGraph.chromaticNumber_mono -theorem Colorable.chromaticNumber_mono_of_embedding {V' : Type*} {G' : SimpleGraph V'} {n : ℕ} - (h : G'.Colorable n) (f : G ↪g G') : G.chromaticNumber ≤ G'.chromaticNumber := - h.chromaticNumber_le_of_forall_imp fun _ => Colorable.of_embedding f -#align simple_graph.colorable.chromatic_number_mono_of_embedding SimpleGraph.Colorable.chromaticNumber_mono_of_embedding +theorem chromaticNumber_mono_of_embedding {V' : Type*} {G' : SimpleGraph V'} + (f : G ↪g G') : G.chromaticNumber ≤ G'.chromaticNumber := + chromaticNumber_le_of_forall_imp fun _ => Colorable.of_embedding f +#align simple_graph.colorable.chromatic_number_mono_of_embedding SimpleGraph.chromaticNumber_mono_of_embedding theorem chromaticNumber_eq_card_of_forall_surj [Fintype α] (C : G.Coloring α) (h : ∀ C' : G.Coloring α, Function.Surjective C') : G.chromaticNumber = Fintype.card α := by apply le_antisymm · apply chromaticNumber_le_card C - · by_contra hc + · rw [C.colorable.chromaticNumber_eq_sInf, Nat.cast_le] + by_contra hc rw [not_le] at hc obtain ⟨n, cn, hc⟩ := - exists_lt_of_csInf_lt (colorable_set_nonempty_of_colorable C.to_colorable) hc + exists_lt_of_csInf_lt (colorable_set_nonempty_of_colorable C.colorable) hc rw [← Fintype.card_fin n] at hc have f := (Function.Embedding.nonempty_of_card_le (le_of_lt hc)).some have C' := cn.some @@ -359,7 +397,8 @@ theorem chromaticNumber_bot [Nonempty V] : (⊥ : SimpleGraph V).chromaticNumber Coloring.mk (fun _ => 0) fun {v w} h => False.elim h apply le_antisymm · exact chromaticNumber_le_card C - · exact chromaticNumber_pos C.to_colorable + · rw [ENat.one_le_iff_pos] + exact chromaticNumber_pos C.colorable #align simple_graph.chromatic_number_bot SimpleGraph.chromaticNumber_bot @[simp] @@ -373,19 +412,13 @@ theorem chromaticNumber_top [Fintype V] : (⊤ : SimpleGraph V).chromaticNumber exact C.valid h #align simple_graph.chromatic_number_top SimpleGraph.chromaticNumber_top -theorem chromaticNumber_top_eq_zero_of_infinite (V : Type*) [Infinite V] : - (⊤ : SimpleGraph V).chromaticNumber = 0 := by - let n := (⊤ : SimpleGraph V).chromaticNumber +theorem chromaticNumber_top_eq_top_of_infinite (V : Type*) [Infinite V] : + (⊤ : SimpleGraph V).chromaticNumber = ⊤ := by by_contra hc - replace hc := pos_iff_ne_zero.mpr hc - apply Nat.not_succ_le_self n - convert_to (⊤ : SimpleGraph { m | m < n + 1 }).chromaticNumber ≤ _ - · rw [SimpleGraph.chromaticNumber_top, Fintype.card_ofFinset, - Finset.card_range, Nat.succ_eq_add_one] - refine' (colorable_of_chromaticNumber_pos hc).chromaticNumber_mono_of_embedding _ - apply Embedding.completeGraph - exact (Function.Embedding.subtype _).trans (Infinite.natEmbedding V) -#align simple_graph.chromatic_number_top_eq_zero_of_infinite SimpleGraph.chromaticNumber_top_eq_zero_of_infinite + rw [← Ne.def, chromaticNumber_ne_top_iff_exists] at hc + obtain ⟨n, ⟨hn⟩⟩ := hc + exact not_injective_infinite_finite _ hn.injective_of_top_hom +#align simple_graph.chromatic_number_top_eq_zero_of_infinite SimpleGraph.chromaticNumber_top_eq_top_of_infinite /-- The bicoloring of a complete bipartite graph using whether a vertex is on the left or on the right. -/ @@ -433,12 +466,17 @@ theorem IsClique.card_le_of_colorable {s : Finset V} (h : G.IsClique s) {n : ℕ simp #align simple_graph.is_clique.card_le_of_colorable SimpleGraph.IsClique.card_le_of_colorable --- TODO eliminate `Finite V` constraint once chromatic numbers are refactored. --- This is just to ensure the chromatic number exists. -theorem IsClique.card_le_chromaticNumber [Finite V] {s : Finset V} (h : G.IsClique s) : +theorem IsClique.card_le_chromaticNumber {s : Finset V} (h : G.IsClique s) : s.card ≤ G.chromaticNumber := by - cases nonempty_fintype V - exact h.card_le_of_colorable G.colorable_chromaticNumber_of_fintype + obtain (hc | hc) := eq_or_ne G.chromaticNumber ⊤ + · rw [hc] + exact le_top + · have hc' := hc + rw [chromaticNumber_ne_top_iff_exists] at hc' + obtain ⟨n, c⟩ := hc' + rw [← ENat.coe_toNat_eq_self] at hc + rw [← hc, Nat.cast_le] + exact h.card_le_of_colorable (colorable_chromaticNumber c) #align simple_graph.is_clique.card_le_chromatic_number SimpleGraph.IsClique.card_le_chromaticNumber protected theorem Colorable.cliqueFree {n m : ℕ} (hc : G.Colorable n) (hm : n < m) : @@ -449,11 +487,15 @@ protected theorem Colorable.cliqueFree {n m : ℕ} (hc : G.Colorable n) (hm : n exact Nat.lt_le_asymm hm (h.card_le_of_colorable hc) #align simple_graph.colorable.clique_free SimpleGraph.Colorable.cliqueFree --- TODO eliminate `Finite V` constraint once chromatic numbers are refactored. --- This is just to ensure the chromatic number exists. -theorem cliqueFree_of_chromaticNumber_lt [Finite V] {n : ℕ} (hc : G.chromaticNumber < n) : - G.CliqueFree n := - G.colorable_chromaticNumber_of_fintype.cliqueFree hc +theorem cliqueFree_of_chromaticNumber_lt {n : ℕ} (hc : G.chromaticNumber < n) : + G.CliqueFree n := by + have hne : G.chromaticNumber ≠ ⊤ := hc.ne_top + obtain ⟨m, hc'⟩ := chromaticNumber_ne_top_iff_exists.mp hne + have := colorable_chromaticNumber hc' + refine this.cliqueFree ?_ + rw [← ENat.coe_toNat_eq_self] at hne + rw [← hne] at hc + simpa using hc #align simple_graph.clique_free_of_chromatic_number_lt SimpleGraph.cliqueFree_of_chromaticNumber_lt end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean b/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean index 4cd23b04915e2..899eef0002350 100644 --- a/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean +++ b/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean @@ -6,7 +6,7 @@ Authors: Iván Renison import Mathlib.Combinatorics.SimpleGraph.Coloring import Mathlib.Combinatorics.SimpleGraph.Hasse import Mathlib.Data.Nat.Parity -import Mathlib.Data.ZMod.Basic +import Mathlib.Order.OmegaCompletePartialOrder /-! # Concrete colorings of common graphs @@ -38,14 +38,14 @@ def pathGraph_two_embedding (n : ℕ) (h : 2 ≤ n) : pathGraph 2 ↪g pathGraph exact Fin.ext map_rel_iff' := by intro v w - fin_cases v <;> fin_cases w <;> simp [pathGraph, ← Fin.coe_covby_iff] + fin_cases v <;> fin_cases w <;> simp [pathGraph, ← Fin.coe_covBy_iff] theorem chromaticNumber_pathGraph (n : ℕ) (h : 2 ≤ n) : (pathGraph n).chromaticNumber = 2 := by - have hc := (pathGraph.bicoloring n).to_colorable + have hc := (pathGraph.bicoloring n).colorable apply le_antisymm - · exact chromaticNumber_le_of_colorable hc + · exact hc.chromaticNumber_le · simpa only [pathGraph_two_eq_top, chromaticNumber_top] using - hc.chromaticNumber_mono_of_embedding (pathGraph_two_embedding n h) + chromaticNumber_mono_of_embedding (pathGraph_two_embedding n h) end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean b/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean index 49502ecec6844..82318cf9cdaba 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean @@ -196,7 +196,7 @@ lemma induce_connected_adj_union {s t : Set V} simp [Set.insert_subset_iff, Set.singleton_subset_iff, hv, hw] lemma induce_connected_of_patches {s : Set V} (u : V) (hu : u ∈ s) - (patches : ∀ {v} (_ : v ∈ s), ∃ (s' : Set V) (_ : s' ⊆ s) (hu' : u ∈ s') (hv' : v ∈ s'), + (patches : ∀ {v}, v ∈ s → ∃ s' ⊆ s, ∃ (hu' : u ∈ s') (hv' : v ∈ s'), (G.induce s').Reachable ⟨u, hu'⟩ ⟨v, hv'⟩) : (G.induce s).Connected := by rw [connected_iff_exists_forall_reachable] refine ⟨⟨u, hu⟩, ?_⟩ diff --git a/Mathlib/Combinatorics/SimpleGraph/Density.lean b/Mathlib/Combinatorics/SimpleGraph/Density.lean index e117a9e930cf8..761f1ea369f4b 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Density.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Density.lean @@ -6,7 +6,6 @@ Authors: Yaël Dillies, Bhavik Mehta import Mathlib.Combinatorics.SimpleGraph.Basic import Mathlib.Order.Partition.Finpartition import Mathlib.Data.Rat.Cast.Order -import Mathlib.Tactic.Positivity import Mathlib.Tactic.Ring import Mathlib.Tactic.NormNum import Mathlib.Tactic.GCongr diff --git a/Mathlib/Combinatorics/SimpleGraph/Hasse.lean b/Mathlib/Combinatorics/SimpleGraph/Hasse.lean index 5a7d715f64431..7912d71f64ad4 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Hasse.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Hasse.lean @@ -5,15 +5,16 @@ Authors: Yaël Dillies -/ import Mathlib.Combinatorics.SimpleGraph.Prod import Mathlib.Data.Fin.SuccPred -import Mathlib.Data.ZMod.Basic +import Mathlib.Data.Nat.SuccPred import Mathlib.Order.SuccPred.Relation +import Mathlib.Tactic.FinCases #align_import combinatorics.simple_graph.hasse from "leanprover-community/mathlib"@"8a38a697305292b37a61650e2c3bd3502d98c805" /-! # The Hasse diagram as a graph -This file defines the Hasse diagram of an order (graph of `Covby`, the covering relation) and the +This file defines the Hasse diagram of an order (graph of `CovBy`, the covering relation) and the path graph on `n` vertices. ## Main declarations @@ -71,7 +72,7 @@ variable [PartialOrder α] [PartialOrder β] @[simp] theorem hasse_prod : hasse (α × β) = hasse α □ hasse β := by ext x y - simp_rw [boxProd_adj, hasse_adj, Prod.covby_iff, or_and_right, @eq_comm _ y.1, @eq_comm _ y.2, + simp_rw [boxProd_adj, hasse_adj, Prod.covBy_iff, or_and_right, @eq_comm _ y.1, @eq_comm _ y.2, or_or_or_comm] #align simple_graph.hasse_prod SimpleGraph.hasse_prod @@ -85,16 +86,16 @@ theorem hasse_preconnected_of_succ [SuccOrder α] [IsSuccArchimedean α] : (hass fun a b => by rw [reachable_iff_reflTransGen] exact - reflTransGen_of_succ _ (fun c hc => Or.inl <| covby_succ_of_not_isMax hc.2.not_isMax) - fun c hc => Or.inr <| covby_succ_of_not_isMax hc.2.not_isMax + reflTransGen_of_succ _ (fun c hc => Or.inl <| covBy_succ_of_not_isMax hc.2.not_isMax) + fun c hc => Or.inr <| covBy_succ_of_not_isMax hc.2.not_isMax #align simple_graph.hasse_preconnected_of_succ SimpleGraph.hasse_preconnected_of_succ theorem hasse_preconnected_of_pred [PredOrder α] [IsPredArchimedean α] : (hasse α).Preconnected := fun a b => by rw [reachable_iff_reflTransGen, ← reflTransGen_swap] exact - reflTransGen_of_pred _ (fun c hc => Or.inl <| pred_covby_of_not_isMin hc.1.not_isMin) - fun c hc => Or.inr <| pred_covby_of_not_isMin hc.1.not_isMin + reflTransGen_of_pred _ (fun c hc => Or.inl <| pred_covBy_of_not_isMin hc.1.not_isMin) + fun c hc => Or.inr <| pred_covBy_of_not_isMin hc.1.not_isMin #align simple_graph.hasse_preconnected_of_pred SimpleGraph.hasse_preconnected_of_pred end LinearOrder @@ -107,7 +108,7 @@ def pathGraph (n : ℕ) : SimpleGraph (Fin n) := theorem pathGraph_adj {n : ℕ} {u v : Fin n} : (pathGraph n).Adj u v ↔ u.val + 1 = v.val ∨ v.val + 1 = u.val := by simp only [pathGraph, hasse] - simp_rw [← Fin.coe_covby_iff, Nat.covby_iff_succ_eq] + simp_rw [← Fin.coe_covBy_iff, Nat.covBy_iff_succ_eq] theorem pathGraph_preconnected (n : ℕ) : (pathGraph n).Preconnected := hasse_preconnected_of_succ _ @@ -119,6 +120,6 @@ theorem pathGraph_connected (n : ℕ) : (pathGraph (n + 1)).Connected := theorem pathGraph_two_eq_top : pathGraph 2 = ⊤ := by ext u v - fin_cases u <;> fin_cases v <;> simp [pathGraph, ← Fin.coe_covby_iff, Nat.covby_iff_succ_eq] + fin_cases u <;> fin_cases v <;> simp [pathGraph, ← Fin.coe_covBy_iff, Nat.covBy_iff_succ_eq] end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/Maps.lean b/Mathlib/Combinatorics/SimpleGraph/Maps.lean new file mode 100644 index 0000000000000..f5bc856716dc9 --- /dev/null +++ b/Mathlib/Combinatorics/SimpleGraph/Maps.lean @@ -0,0 +1,676 @@ +/- +Copyright (c) 2021 Hunter Monroe. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Hunter Monroe, Kyle Miller +-/ +import Mathlib.Combinatorics.SimpleGraph.Basic +import Mathlib.Data.FunLike.Fintype + +/-! +# Maps between graphs + +This file defines two functions and three structures relating graphs. +The structures directly correspond to the classification of functions as +injective, surjective and bijective, and have corresponding notation. + +## Main definitions + +* `SimpleGraph.map`: the graph obtained by pushing the adjacency relation through + an injective function between vertex types. +* `SimpleGraph.comap`: the graph obtained by pulling the adjacency relation behind + an arbitrary function between vertex types. +* `SimpleGraph.induce`: the subgraph induced by the given vertex set, a wrapper around `comap`. +* `SimpleGraph.spanningCoe`: the supergraph without any additional edges, a wrapper around `map`. +* `SimpleGraph.Hom`, `G →g H`: a graph homomorphism from `G` to `H`. +* `SimpleGraph.Embedding`, `G ↪g H`: a graph embedding of `G` in `H`. +* `SimpleGraph.Iso`, `G ≃g H`: a graph isomorphism between `G` and `H`. +-/ + + +open Function + +namespace SimpleGraph + +variable {V W X : Type*} (G : SimpleGraph V) (G' : SimpleGraph W) {u v : V} + +/-! ## Map and comap -/ + + +/-- Given an injective function, there is a covariant induced map on graphs by pushing forward +the adjacency relation. + +This is injective (see `SimpleGraph.map_injective`). -/ +protected def map (f : V ↪ W) (G : SimpleGraph V) : SimpleGraph W where + Adj := Relation.Map G.Adj f f + symm a b := by -- porting note: `obviously` used to handle this + rintro ⟨v, w, h, rfl, rfl⟩ + use w, v, h.symm, rfl + loopless a := by -- porting note: `obviously` used to handle this + rintro ⟨v, w, h, rfl, h'⟩ + exact h.ne (f.injective h'.symm) +#align simple_graph.map SimpleGraph.map + +instance instDecidableMapAdj {f : V ↪ W} {a b} [Decidable (Relation.Map G.Adj f f a b)] : + Decidable ((G.map f).Adj a b) := ‹Decidable (Relation.Map G.Adj f f a b)› +#align simple_graph.decidable_map SimpleGraph.instDecidableMapAdj + +@[simp] +theorem map_adj (f : V ↪ W) (G : SimpleGraph V) (u v : W) : + (G.map f).Adj u v ↔ ∃ u' v' : V, G.Adj u' v' ∧ f u' = u ∧ f v' = v := + Iff.rfl +#align simple_graph.map_adj SimpleGraph.map_adj + +lemma map_adj_apply {G : SimpleGraph V} {f : V ↪ W} {a b : V} : + (G.map f).Adj (f a) (f b) ↔ G.Adj a b := by simp +#align simple_graph.map_adj_apply SimpleGraph.map_adj_apply + +theorem map_monotone (f : V ↪ W) : Monotone (SimpleGraph.map f) := by + rintro G G' h _ _ ⟨u, v, ha, rfl, rfl⟩ + exact ⟨_, _, h ha, rfl, rfl⟩ +#align simple_graph.map_monotone SimpleGraph.map_monotone + +@[simp] lemma map_id : G.map (Function.Embedding.refl _) = G := + SimpleGraph.ext _ _ <| Relation.map_id_id _ +#align simple_graph.map_id SimpleGraph.map_id + +@[simp] lemma map_map (f : V ↪ W) (g : W ↪ X) : (G.map f).map g = G.map (f.trans g) := + SimpleGraph.ext _ _ <| Relation.map_map _ _ _ _ _ +#align simple_graph.map_map SimpleGraph.map_map + +/-- Given a function, there is a contravariant induced map on graphs by pulling back the +adjacency relation. +This is one of the ways of creating induced graphs. See `SimpleGraph.induce` for a wrapper. + +This is surjective when `f` is injective (see `SimpleGraph.comap_surjective`).-/ +protected def comap (f : V → W) (G : SimpleGraph W) : SimpleGraph V where + Adj u v := G.Adj (f u) (f v) + symm _ _ h := h.symm + loopless _ := G.loopless _ +#align simple_graph.comap SimpleGraph.comap + +@[simp] lemma comap_adj {G : SimpleGraph W} {f : V → W} : + (G.comap f).Adj u v ↔ G.Adj (f u) (f v) := Iff.rfl + +@[simp] lemma comap_id {G : SimpleGraph V} : G.comap id = G := SimpleGraph.ext _ _ rfl +#align simple_graph.comap_id SimpleGraph.comap_id + +@[simp] lemma comap_comap {G : SimpleGraph X} (f : V → W) (g : W → X) : + (G.comap g).comap f = G.comap (g ∘ f) := rfl +#align simple_graph.comap_comap SimpleGraph.comap_comap + +instance instDecidableComapAdj (f : V → W) (G : SimpleGraph W) [DecidableRel G.Adj] : + DecidableRel (G.comap f).Adj := fun _ _ ↦ ‹DecidableRel G.Adj› _ _ + +lemma comap_symm (G : SimpleGraph V) (e : V ≃ W) : + G.comap e.symm.toEmbedding = G.map e.toEmbedding := by + ext; simp only [Equiv.apply_eq_iff_eq_symm_apply, comap_adj, map_adj, Equiv.toEmbedding_apply, + exists_eq_right_right, exists_eq_right] +#align simple_graph.comap_symm SimpleGraph.comap_symm + +lemma map_symm (G : SimpleGraph W) (e : V ≃ W) : + G.map e.symm.toEmbedding = G.comap e.toEmbedding := by rw [← comap_symm, e.symm_symm] +#align simple_graph.map_symm SimpleGraph.map_symm + +theorem comap_monotone (f : V ↪ W) : Monotone (SimpleGraph.comap f) := by + intro G G' h _ _ ha + exact h ha +#align simple_graph.comap_monotone SimpleGraph.comap_monotone + +@[simp] +theorem comap_map_eq (f : V ↪ W) (G : SimpleGraph V) : (G.map f).comap f = G := by + ext + simp +#align simple_graph.comap_map_eq SimpleGraph.comap_map_eq + +theorem leftInverse_comap_map (f : V ↪ W) : + Function.LeftInverse (SimpleGraph.comap f) (SimpleGraph.map f) := + comap_map_eq f +#align simple_graph.left_inverse_comap_map SimpleGraph.leftInverse_comap_map + +theorem map_injective (f : V ↪ W) : Function.Injective (SimpleGraph.map f) := + (leftInverse_comap_map f).injective +#align simple_graph.map_injective SimpleGraph.map_injective + +theorem comap_surjective (f : V ↪ W) : Function.Surjective (SimpleGraph.comap f) := + (leftInverse_comap_map f).surjective +#align simple_graph.comap_surjective SimpleGraph.comap_surjective + +theorem map_le_iff_le_comap (f : V ↪ W) (G : SimpleGraph V) (G' : SimpleGraph W) : + G.map f ≤ G' ↔ G ≤ G'.comap f := + ⟨fun h u v ha => h ⟨_, _, ha, rfl, rfl⟩, by + rintro h _ _ ⟨u, v, ha, rfl, rfl⟩ + exact h ha⟩ +#align simple_graph.map_le_iff_le_comap SimpleGraph.map_le_iff_le_comap + +theorem map_comap_le (f : V ↪ W) (G : SimpleGraph W) : (G.comap f).map f ≤ G := by + rw [map_le_iff_le_comap] +#align simple_graph.map_comap_le SimpleGraph.map_comap_le + +lemma le_comap_of_subsingleton (f : V → W) [Subsingleton V] : G ≤ G'.comap f := by + intros v w; simp [Subsingleton.elim v w] + +lemma map_le_of_subsingleton (f : V ↪ W) [Subsingleton V] : G.map f ≤ G' := by + rw [map_le_iff_le_comap]; apply le_comap_of_subsingleton + +/-- Given a family of vertex types indexed by `ι`, pulling back from `⊤ : SimpleGraph ι` +yields the complete multipartite graph on the family. +Two vertices are adjacent if and only if their indices are not equal. -/ +abbrev completeMultipartiteGraph {ι : Type*} (V : ι → Type*) : SimpleGraph (Σ i, V i) := + SimpleGraph.comap Sigma.fst ⊤ + +/-- Equivalent types have equivalent simple graphs. -/ +@[simps apply] +protected def _root_.Equiv.simpleGraph (e : V ≃ W) : SimpleGraph V ≃ SimpleGraph W where + toFun := SimpleGraph.comap e.symm + invFun := SimpleGraph.comap e + left_inv _ := by simp + right_inv _ := by simp +#align equiv.simple_graph Equiv.simpleGraph + +@[simp] lemma _root_.Equiv.simpleGraph_refl : (Equiv.refl V).simpleGraph = Equiv.refl _ := by + ext; rfl + +@[simp] lemma _root_.Equiv.simpleGraph_trans (e₁ : V ≃ W) (e₂ : W ≃ X) : + (e₁.trans e₂).simpleGraph = e₁.simpleGraph.trans e₂.simpleGraph := rfl +#align equiv.simple_graph_trans Equiv.simpleGraph_trans + +@[simp] +lemma _root_.Equiv.symm_simpleGraph (e : V ≃ W) : e.simpleGraph.symm = e.symm.simpleGraph := rfl +#align equiv.symm_simple_graph Equiv.symm_simpleGraph + +/-! ## Induced graphs -/ + + +/- Given a set `s` of vertices, we can restrict a graph to those vertices by restricting its +adjacency relation. This gives a map between `SimpleGraph V` and `SimpleGraph s`. + +There is also a notion of induced subgraphs (see `SimpleGraph.subgraph.induce`). -/ +/-- Restrict a graph to the vertices in the set `s`, deleting all edges incident to vertices +outside the set. This is a wrapper around `SimpleGraph.comap`. -/ +@[reducible] +def induce (s : Set V) (G : SimpleGraph V) : SimpleGraph s := + G.comap (Function.Embedding.subtype _) +#align simple_graph.induce SimpleGraph.induce + +@[simp] lemma induce_singleton_eq_top (v : V) : G.induce {v} = ⊤ := by + rw [eq_top_iff]; apply le_comap_of_subsingleton + +/-- Given a graph on a set of vertices, we can make it be a `SimpleGraph V` by +adding in the remaining vertices without adding in any additional edges. +This is a wrapper around `SimpleGraph.map`. -/ +@[reducible] +def spanningCoe {s : Set V} (G : SimpleGraph s) : SimpleGraph V := + G.map (Function.Embedding.subtype _) +#align simple_graph.spanning_coe SimpleGraph.spanningCoe + +theorem induce_spanningCoe {s : Set V} {G : SimpleGraph s} : G.spanningCoe.induce s = G := + comap_map_eq _ _ +#align simple_graph.induce_spanning_coe SimpleGraph.induce_spanningCoe + +theorem spanningCoe_induce_le (s : Set V) : (G.induce s).spanningCoe ≤ G := + map_comap_le _ _ +#align simple_graph.spanning_coe_induce_le SimpleGraph.spanningCoe_induce_le + +/-! ## Homomorphisms, embeddings and isomorphisms -/ + + +/-- A graph homomorphism is a map on vertex sets that respects adjacency relations. + +The notation `G →g G'` represents the type of graph homomorphisms. -/ +abbrev Hom := + RelHom G.Adj G'.Adj +#align simple_graph.hom SimpleGraph.Hom + +/-- A graph embedding is an embedding `f` such that for vertices `v w : V`, +`G.Adj (f v) (f w) ↔ G.Adj v w`. Its image is an induced subgraph of G'. + +The notation `G ↪g G'` represents the type of graph embeddings. -/ +abbrev Embedding := + RelEmbedding G.Adj G'.Adj +#align simple_graph.embedding SimpleGraph.Embedding + +/-- A graph isomorphism is a bijective map on vertex sets that respects adjacency relations. + +The notation `G ≃g G'` represents the type of graph isomorphisms. +-/ +abbrev Iso := + RelIso G.Adj G'.Adj +#align simple_graph.iso SimpleGraph.Iso + +infixl:50 " →g " => Hom +infixl:50 " ↪g " => Embedding +infixl:50 " ≃g " => Iso + +namespace Hom + +variable {G G'} {G₁ G₂ : SimpleGraph V} {H : SimpleGraph W} (f : G →g G') + +/-- The identity homomorphism from a graph to itself. -/ +protected abbrev id : G →g G := + RelHom.id _ +#align simple_graph.hom.id SimpleGraph.Hom.id + +@[simp, norm_cast] lemma coe_id : ⇑(Hom.id : G →g G) = id := rfl +#align simple_graph.hom.coe_id SimpleGraph.Hom.coe_id + +instance [Subsingleton (V → W)] : Subsingleton (G →g H) := DFunLike.coe_injective.subsingleton + +instance [IsEmpty V] : Unique (G →g H) where + default := ⟨isEmptyElim, fun {a} ↦ isEmptyElim a⟩ + uniq _ := Subsingleton.elim _ _ + +instance instFintype [DecidableEq V] [Fintype V] [Fintype W] [DecidableRel G.Adj] + [DecidableRel H.Adj] : Fintype (G →g H) := + Fintype.ofEquiv {f : V → W // ∀ {a b}, G.Adj a b → H.Adj (f a) (f b)} + { toFun := fun f ↦ ⟨f.1, f.2⟩, invFun := fun f ↦ ⟨f.1, f.2⟩, + left_inv := fun _ ↦ rfl, right_inv := fun _ ↦ rfl } + +instance [Finite V] [Finite W] : Finite (G →g H) := DFunLike.finite _ + +theorem map_adj {v w : V} (h : G.Adj v w) : G'.Adj (f v) (f w) := + f.map_rel' h +#align simple_graph.hom.map_adj SimpleGraph.Hom.map_adj + +theorem map_mem_edgeSet {e : Sym2 V} (h : e ∈ G.edgeSet) : e.map f ∈ G'.edgeSet := + Sym2.ind (fun _ _ => f.map_rel') e h +#align simple_graph.hom.map_mem_edge_set SimpleGraph.Hom.map_mem_edgeSet + +theorem apply_mem_neighborSet {v w : V} (h : w ∈ G.neighborSet v) : f w ∈ G'.neighborSet (f v) := + map_adj f h +#align simple_graph.hom.apply_mem_neighbor_set SimpleGraph.Hom.apply_mem_neighborSet + +/-- The map between edge sets induced by a homomorphism. +The underlying map on edges is given by `Sym2.map`. -/ +@[simps] +def mapEdgeSet (e : G.edgeSet) : G'.edgeSet := + ⟨Sym2.map f e, f.map_mem_edgeSet e.property⟩ +#align simple_graph.hom.map_edge_set SimpleGraph.Hom.mapEdgeSet + +/-- The map between neighbor sets induced by a homomorphism. -/ +@[simps] +def mapNeighborSet (v : V) (w : G.neighborSet v) : G'.neighborSet (f v) := + ⟨f w, f.apply_mem_neighborSet w.property⟩ +#align simple_graph.hom.map_neighbor_set SimpleGraph.Hom.mapNeighborSet + +/-- The map between darts induced by a homomorphism. -/ +def mapDart (d : G.Dart) : G'.Dart := + ⟨d.1.map f f, f.map_adj d.2⟩ +#align simple_graph.hom.map_dart SimpleGraph.Hom.mapDart + +@[simp] +theorem mapDart_apply (d : G.Dart) : f.mapDart d = ⟨d.1.map f f, f.map_adj d.2⟩ := + rfl +#align simple_graph.hom.map_dart_apply SimpleGraph.Hom.mapDart_apply + +/-- The induced map for spanning subgraphs, which is the identity on vertices. -/ +@[simps] +def mapSpanningSubgraphs {G G' : SimpleGraph V} (h : G ≤ G') : G →g G' where + toFun x := x + map_rel' ha := h ha +#align simple_graph.hom.map_spanning_subgraphs SimpleGraph.Hom.mapSpanningSubgraphs + +theorem mapEdgeSet.injective (hinj : Function.Injective f) : Function.Injective f.mapEdgeSet := by + rintro ⟨e₁, h₁⟩ ⟨e₂, h₂⟩ + dsimp [Hom.mapEdgeSet] + repeat' rw [Subtype.mk_eq_mk] + apply Sym2.map.injective hinj +#align simple_graph.hom.map_edge_set.injective SimpleGraph.Hom.mapEdgeSet.injective + +/-- Every graph homomorphism from a complete graph is injective. -/ +theorem injective_of_top_hom (f : (⊤ : SimpleGraph V) →g G') : Function.Injective f := by + intro v w h + contrapose! h + exact G'.ne_of_adj (map_adj _ ((top_adj _ _).mpr h)) +#align simple_graph.hom.injective_of_top_hom SimpleGraph.Hom.injective_of_top_hom + +/-- There is a homomorphism to a graph from a comapped graph. +When the function is injective, this is an embedding (see `SimpleGraph.Embedding.comap`). -/ +@[simps] +protected def comap (f : V → W) (G : SimpleGraph W) : G.comap f →g G where + toFun := f + map_rel' := by simp +#align simple_graph.hom.comap SimpleGraph.Hom.comap + +variable {G'' : SimpleGraph X} + +/-- Composition of graph homomorphisms. -/ +abbrev comp (f' : G' →g G'') (f : G →g G') : G →g G'' := + RelHom.comp f' f +#align simple_graph.hom.comp SimpleGraph.Hom.comp + +@[simp] +theorem coe_comp (f' : G' →g G'') (f : G →g G') : ⇑(f'.comp f) = f' ∘ f := + rfl +#align simple_graph.hom.coe_comp SimpleGraph.Hom.coe_comp + +/-- The graph homomorphism from a smaller graph to a bigger one. -/ +def ofLE (h : G₁ ≤ G₂) : G₁ →g G₂ := ⟨id, @h⟩ +#align simple_graph.hom.of_le SimpleGraph.Hom.ofLE + +@[simp, norm_cast] lemma coe_ofLE (h : G₁ ≤ G₂) : ⇑(ofLE h) = id := rfl +#align simple_graph.hom.coe_of_le SimpleGraph.Hom.coe_ofLE + +end Hom + +namespace Embedding + +variable {G G'} {H : SimpleGraph W} (f : G ↪g G') + +/-- The identity embedding from a graph to itself. -/ +abbrev refl : G ↪g G := + RelEmbedding.refl _ +#align simple_graph.embedding.refl SimpleGraph.Embedding.refl + +/-- An embedding of graphs gives rise to a homomorphism of graphs. -/ +abbrev toHom : G →g G' := + f.toRelHom +#align simple_graph.embedding.to_hom SimpleGraph.Embedding.toHom + +@[simp] lemma coe_toHom (f : G ↪g H) : ⇑f.toHom = f := rfl +#align simple_graph.embedding.coe_to_hom SimpleGraph.Embedding.coe_toHom + +@[simp] theorem map_adj_iff {v w : V} : G'.Adj (f v) (f w) ↔ G.Adj v w := + f.map_rel_iff +#align simple_graph.embedding.map_adj_iff SimpleGraph.Embedding.map_adj_iff + +theorem map_mem_edgeSet_iff {e : Sym2 V} : e.map f ∈ G'.edgeSet ↔ e ∈ G.edgeSet := + Sym2.ind (fun _ _ => f.map_adj_iff) e +#align simple_graph.embedding.map_mem_edge_set_iff SimpleGraph.Embedding.map_mem_edgeSet_iff + +theorem apply_mem_neighborSet_iff {v w : V} : f w ∈ G'.neighborSet (f v) ↔ w ∈ G.neighborSet v := + map_adj_iff f +#align simple_graph.embedding.apply_mem_neighbor_set_iff SimpleGraph.Embedding.apply_mem_neighborSet_iff + +/-- A graph embedding induces an embedding of edge sets. -/ +@[simps] +def mapEdgeSet : G.edgeSet ↪ G'.edgeSet where + toFun := Hom.mapEdgeSet f + inj' := Hom.mapEdgeSet.injective f f.injective +#align simple_graph.embedding.map_edge_set SimpleGraph.Embedding.mapEdgeSet + +/-- A graph embedding induces an embedding of neighbor sets. -/ +@[simps] +def mapNeighborSet (v : V) : G.neighborSet v ↪ G'.neighborSet (f v) + where + toFun w := ⟨f w, f.apply_mem_neighborSet_iff.mpr w.2⟩ + inj' := by + rintro ⟨w₁, h₁⟩ ⟨w₂, h₂⟩ h + rw [Subtype.mk_eq_mk] at h ⊢ + exact f.inj' h +#align simple_graph.embedding.map_neighbor_set SimpleGraph.Embedding.mapNeighborSet + +/-- Given an injective function, there is an embedding from the comapped graph into the original +graph. -/ +-- porting note: @[simps] does not work here since `f` is not a constructor application. +-- `@[simps toEmbedding]` could work, but Floris suggested writing `comap_apply` for now. +protected def comap (f : V ↪ W) (G : SimpleGraph W) : G.comap f ↪g G := + { f with map_rel_iff' := by simp } +#align simple_graph.embedding.comap SimpleGraph.Embedding.comap + +@[simp] +theorem comap_apply (f : V ↪ W) (G : SimpleGraph W) (v : V) : + SimpleGraph.Embedding.comap f G v = f v := rfl +#align simple_graph.embedding.comap_apply SimpleGraph.Embedding.comap_apply + +/-- Given an injective function, there is an embedding from a graph into the mapped graph. -/ +-- porting note: @[simps] does not work here since `f` is not a constructor application. +-- `@[simps toEmbedding]` could work, but Floris suggested writing `map_apply` for now. +protected def map (f : V ↪ W) (G : SimpleGraph V) : G ↪g G.map f := + { f with map_rel_iff' := by simp } +#align simple_graph.embedding.map SimpleGraph.Embedding.map + +@[simp] +theorem map_apply (f : V ↪ W) (G : SimpleGraph V) (v : V) : + SimpleGraph.Embedding.map f G v = f v := rfl +#align simple_graph.embedding.map_apply SimpleGraph.Embedding.map_apply + +/-- Induced graphs embed in the original graph. + +Note that if `G.induce s = ⊤` (i.e., if `s` is a clique) then this gives the embedding of a +complete graph. -/ +@[reducible] +protected def induce (s : Set V) : G.induce s ↪g G := + SimpleGraph.Embedding.comap (Function.Embedding.subtype _) G +#align simple_graph.embedding.induce SimpleGraph.Embedding.induce + +/-- Graphs on a set of vertices embed in their `spanningCoe`. -/ +@[reducible] +protected def spanningCoe {s : Set V} (G : SimpleGraph s) : G ↪g G.spanningCoe := + SimpleGraph.Embedding.map (Function.Embedding.subtype _) G +#align simple_graph.embedding.spanning_coe SimpleGraph.Embedding.spanningCoe + +/-- Embeddings of types induce embeddings of complete graphs on those types. -/ +protected def completeGraph {α β : Type*} (f : α ↪ β) : + (⊤ : SimpleGraph α) ↪g (⊤ : SimpleGraph β) := + { f with map_rel_iff' := by simp } +#align simple_graph.embedding.complete_graph SimpleGraph.Embedding.completeGraph + +variable {G'' : SimpleGraph X} + +/-- Composition of graph embeddings. -/ +abbrev comp (f' : G' ↪g G'') (f : G ↪g G') : G ↪g G'' := + f.trans f' +#align simple_graph.embedding.comp SimpleGraph.Embedding.comp + +@[simp] +theorem coe_comp (f' : G' ↪g G'') (f : G ↪g G') : ⇑(f'.comp f) = f' ∘ f := + rfl +#align simple_graph.embedding.coe_comp SimpleGraph.Embedding.coe_comp + +end Embedding + +section induceHom + +variable {G G'} {G'' : SimpleGraph X} {s : Set V} {t : Set W} {r : Set X} + (φ : G →g G') (φst : Set.MapsTo φ s t) (ψ : G' →g G'') (ψtr : Set.MapsTo ψ t r) + +/-- The restriction of a morphism of graphs to induced subgraphs. -/ +def induceHom : G.induce s →g G'.induce t where + toFun := Set.MapsTo.restrict φ s t φst + map_rel' := φ.map_rel' +#align simple_graph.induce_hom SimpleGraph.induceHom + +@[simp, norm_cast] lemma coe_induceHom : ⇑(induceHom φ φst) = Set.MapsTo.restrict φ s t φst := + rfl +#align simple_graph.coe_induce_hom SimpleGraph.coe_induceHom + +@[simp] lemma induceHom_id (G : SimpleGraph V) (s) : + induceHom (Hom.id : G →g G) (Set.mapsTo_id s) = Hom.id := by + ext x + rfl +#align simple_graph.induce_hom_id SimpleGraph.induceHom_id + +@[simp] lemma induceHom_comp : + (induceHom ψ ψtr).comp (induceHom φ φst) = induceHom (ψ.comp φ) (ψtr.comp φst) := by + ext x + rfl +#align simple_graph.induce_hom_comp SimpleGraph.induceHom_comp + +lemma induceHom_injective (hi : Set.InjOn φ s) : + Function.Injective (induceHom φ φst) := by + erw [Set.MapsTo.restrict_inj] <;> assumption + +end induceHom + +section induceHomLE +variable {s s' : Set V} (h : s ≤ s') + +/-- Given an inclusion of vertex subsets, the induced embedding on induced graphs. +This is not an abbreviation for `induceHom` since we get an embedding in this case. -/ +def induceHomOfLE (h : s ≤ s') : G.induce s ↪g G.induce s' where + toEmbedding := Set.embeddingOfSubset s s' h + map_rel_iff' := by simp + +@[simp] lemma induceHomOfLE_apply (v : s) : (G.induceHomOfLE h) v = Set.inclusion h v := rfl + +@[simp] lemma induceHomOfLE_toHom : + (G.induceHomOfLE h).toHom = induceHom (.id : G →g G) ((Set.mapsTo_id s).mono_right h) := by + ext; simp + +end induceHomLE + +namespace Iso + +variable {G G'} (f : G ≃g G') + +/-- The identity isomorphism of a graph with itself. -/ +abbrev refl : G ≃g G := + RelIso.refl _ +#align simple_graph.iso.refl SimpleGraph.Iso.refl + +/-- An isomorphism of graphs gives rise to an embedding of graphs. -/ +abbrev toEmbedding : G ↪g G' := + f.toRelEmbedding +#align simple_graph.iso.to_embedding SimpleGraph.Iso.toEmbedding + +/-- An isomorphism of graphs gives rise to a homomorphism of graphs. -/ +abbrev toHom : G →g G' := + f.toEmbedding.toHom +#align simple_graph.iso.to_hom SimpleGraph.Iso.toHom + +/-- The inverse of a graph isomorphism. -/ +abbrev symm : G' ≃g G := + RelIso.symm f +#align simple_graph.iso.symm SimpleGraph.Iso.symm + +theorem map_adj_iff {v w : V} : G'.Adj (f v) (f w) ↔ G.Adj v w := + f.map_rel_iff +#align simple_graph.iso.map_adj_iff SimpleGraph.Iso.map_adj_iff + +theorem map_mem_edgeSet_iff {e : Sym2 V} : e.map f ∈ G'.edgeSet ↔ e ∈ G.edgeSet := + Sym2.ind (fun _ _ => f.map_adj_iff) e +#align simple_graph.iso.map_mem_edge_set_iff SimpleGraph.Iso.map_mem_edgeSet_iff + +theorem apply_mem_neighborSet_iff {v w : V} : f w ∈ G'.neighborSet (f v) ↔ w ∈ G.neighborSet v := + map_adj_iff f +#align simple_graph.iso.apply_mem_neighbor_set_iff SimpleGraph.Iso.apply_mem_neighborSet_iff + +/-- An isomorphism of graphs induces an equivalence of edge sets. -/ +@[simps] +def mapEdgeSet : G.edgeSet ≃ G'.edgeSet + where + toFun := Hom.mapEdgeSet f + invFun := Hom.mapEdgeSet f.symm + left_inv := by + rintro ⟨e, h⟩ + simp only [Hom.mapEdgeSet, RelEmbedding.toRelHom, Embedding.toFun_eq_coe, + RelEmbedding.coe_toEmbedding, RelIso.coe_toRelEmbedding, Sym2.map_map, comp_apply, + Subtype.mk.injEq] + convert congr_fun Sym2.map_id e + exact RelIso.symm_apply_apply _ _ + right_inv := by + rintro ⟨e, h⟩ + simp only [Hom.mapEdgeSet, RelEmbedding.toRelHom, Embedding.toFun_eq_coe, + RelEmbedding.coe_toEmbedding, RelIso.coe_toRelEmbedding, Sym2.map_map, comp_apply, + Subtype.mk.injEq] + convert congr_fun Sym2.map_id e + exact RelIso.apply_symm_apply _ _ +#align simple_graph.iso.map_edge_set SimpleGraph.Iso.mapEdgeSet + +/-- A graph isomorphism induces an equivalence of neighbor sets. -/ +@[simps] +def mapNeighborSet (v : V) : G.neighborSet v ≃ G'.neighborSet (f v) + where + toFun w := ⟨f w, f.apply_mem_neighborSet_iff.mpr w.2⟩ + invFun w := + ⟨f.symm w, by + simpa [RelIso.symm_apply_apply] using f.symm.apply_mem_neighborSet_iff.mpr w.2⟩ + left_inv w := by simp + right_inv w := by simp +#align simple_graph.iso.map_neighbor_set SimpleGraph.Iso.mapNeighborSet + +theorem card_eq [Fintype V] [Fintype W] : Fintype.card V = Fintype.card W := by + rw [← Fintype.ofEquiv_card f.toEquiv] + convert rfl +#align simple_graph.iso.card_eq_of_iso SimpleGraph.Iso.card_eq + +theorem card_edgeFinset_eq [Fintype G.edgeSet] [Fintype G'.edgeSet] : + G.edgeFinset.card = G'.edgeFinset.card := by + apply Finset.card_eq_of_equiv + simp only [Set.mem_toFinset] + exact f.mapEdgeSet + +/-- Given a bijection, there is an embedding from the comapped graph into the original +graph. -/ +-- porting note: `@[simps]` does not work here anymore since `f` is not a constructor application. +-- `@[simps toEmbedding]` could work, but Floris suggested writing `comap_apply` for now. +protected def comap (f : V ≃ W) (G : SimpleGraph W) : G.comap f.toEmbedding ≃g G := + { f with map_rel_iff' := by simp } +#align simple_graph.iso.comap SimpleGraph.Iso.comap + +@[simp] +lemma comap_apply (f : V ≃ W) (G : SimpleGraph W) (v : V) : + SimpleGraph.Iso.comap f G v = f v := rfl +#align simple_graph.iso.comap_apply SimpleGraph.Iso.comap_apply + +@[simp] +lemma comap_symm_apply (f : V ≃ W) (G : SimpleGraph W) (w : W) : + (SimpleGraph.Iso.comap f G).symm w = f.symm w := rfl +#align simple_graph.iso.comap_symm_apply SimpleGraph.Iso.comap_symm_apply + +/-- Given an injective function, there is an embedding from a graph into the mapped graph. -/ +-- porting note: `@[simps]` does not work here anymore since `f` is not a constructor application. +-- `@[simps toEmbedding]` could work, but Floris suggested writing `map_apply` for now. +protected def map (f : V ≃ W) (G : SimpleGraph V) : G ≃g G.map f.toEmbedding := + { f with map_rel_iff' := by simp } +#align simple_graph.iso.map SimpleGraph.Iso.map + +@[simp] +lemma map_apply (f : V ≃ W) (G : SimpleGraph V) (v : V) : + SimpleGraph.Iso.map f G v = f v := rfl +#align simple_graph.iso.map_apply SimpleGraph.Iso.map_apply + +@[simp] +lemma map_symm_apply (f : V ≃ W) (G : SimpleGraph V) (w : W) : + (SimpleGraph.Iso.map f G).symm w = f.symm w := rfl +#align simple_graph.iso.map_symm_apply SimpleGraph.Iso.map_symm_apply + +/-- Equivalences of types induce isomorphisms of complete graphs on those types. -/ +protected def completeGraph {α β : Type*} (f : α ≃ β) : + (⊤ : SimpleGraph α) ≃g (⊤ : SimpleGraph β) := + { f with map_rel_iff' := by simp } +#align simple_graph.iso.complete_graph SimpleGraph.Iso.completeGraph + +theorem toEmbedding_completeGraph {α β : Type*} (f : α ≃ β) : + (Iso.completeGraph f).toEmbedding = Embedding.completeGraph f.toEmbedding := + rfl +#align simple_graph.iso.to_embedding_complete_graph SimpleGraph.Iso.toEmbedding_completeGraph + +variable {G'' : SimpleGraph X} + +/-- Composition of graph isomorphisms. -/ +abbrev comp (f' : G' ≃g G'') (f : G ≃g G') : G ≃g G'' := + f.trans f' +#align simple_graph.iso.comp SimpleGraph.Iso.comp + +@[simp] +theorem coe_comp (f' : G' ≃g G'') (f : G ≃g G') : ⇑(f'.comp f) = f' ∘ f := + rfl +#align simple_graph.iso.coe_comp SimpleGraph.Iso.coe_comp + +end Iso + +/-- The graph induced on `Set.univ` is isomorphic to the original graph. -/ +@[simps!] +def induceUnivIso (G : SimpleGraph V) : G.induce Set.univ ≃g G where + toEquiv := Equiv.Set.univ V + map_rel_iff' := by simp only [Equiv.Set.univ, Equiv.coe_fn_mk, comap_adj, Embedding.coe_subtype, + Subtype.forall, Set.mem_univ, forall_true_left, implies_true] + +section Finite + +variable [Fintype V] {n : ℕ} + +/-- Given a graph over a finite vertex type `V` and a proof `hc` that `Fintype.card V = n`, +`G.overFin n` is an isomorphic (as shown in `overFinIso`) graph over `Fin n`. -/ +def overFin (hc : Fintype.card V = n) : SimpleGraph (Fin n) where + Adj x y := G.Adj ((Fintype.equivFinOfCardEq hc).symm x) ((Fintype.equivFinOfCardEq hc).symm y) + symm x y := by simp_rw [adj_comm, imp_self] + +/-- The isomorphism between `G` and `G.overFin hc`. -/ +noncomputable def overFinIso (hc : Fintype.card V = n) : G ≃g G.overFin hc := by + use Fintype.equivFinOfCardEq hc; simp [overFin] + +end Finite + +end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/Operations.lean b/Mathlib/Combinatorics/SimpleGraph/Operations.lean index 03f3af6ab940b..101a41126c11d 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Operations.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Operations.lean @@ -16,6 +16,7 @@ we also prove theorems about the number of edges in the modified graphs. * `G.replaceVertex s t` is `G` with `t` replaced by a copy of `s`, removing the `s-t` edge if present. +* `G.addEdge s t` is `G` with the `s-t` edge added, if that is a valid edge. -/ @@ -29,30 +30,125 @@ section ReplaceVertex /-- The graph formed by forgetting `t`'s neighbours and instead giving it those of `s`. The `s-t` edge is removed if present. -/ -abbrev replaceVertex : SimpleGraph V where +def replaceVertex : SimpleGraph V where Adj v w := if v = t then if w = t then False else G.Adj s w else if w = t then G.Adj v s else G.Adj v w symm v w := by dsimp only; split_ifs <;> simp [adj_comm] /-- There is never an `s-t` edge in `G.replaceVertex s t`. -/ -theorem not_adj_replaceVertex_same : ¬(G.replaceVertex s t).Adj s t := by simp +lemma not_adj_replaceVertex_same : ¬(G.replaceVertex s t).Adj s t := by simp [replaceVertex] @[simp] -theorem replaceVertex_self : G.replaceVertex s s = G := by - ext; dsimp only; split_ifs <;> simp_all [adj_comm] +lemma replaceVertex_self : G.replaceVertex s s = G := by ext; unfold replaceVertex; aesop + +variable {t} /-- Except possibly for `t`, the neighbours of `s` in `G.replaceVertex s t` are its neighbours in `G`. -/ lemma adj_replaceVertex_iff_of_ne_left {w : V} (hw : w ≠ t) : - (G.replaceVertex s t).Adj s w ↔ G.Adj s w := by simp [hw] + (G.replaceVertex s t).Adj s w ↔ G.Adj s w := by simp [replaceVertex, hw] /-- Except possibly for itself, the neighbours of `t` in `G.replaceVertex s t` are the neighbours of `s` in `G`. -/ lemma adj_replaceVertex_iff_of_ne_right {w : V} (hw : w ≠ t) : - (G.replaceVertex s t).Adj t w ↔ G.Adj s w := by simp [hw] + (G.replaceVertex s t).Adj t w ↔ G.Adj s w := by simp [replaceVertex, hw] /-- Adjacency in `G.replaceVertex s t` which does not involve `t` is the same as that of `G`. -/ lemma adj_replaceVertex_iff_of_ne {v w : V} (hv : v ≠ t) (hw : w ≠ t) : - (G.replaceVertex s t).Adj v w ↔ G.Adj v w := by simp [hv, hw] + (G.replaceVertex s t).Adj v w ↔ G.Adj v w := by simp [replaceVertex, hv, hw] + +variable {s} + +theorem edgeSet_replaceVertex_of_not_adj (hn : ¬G.Adj s t) : (G.replaceVertex s t).edgeSet = + G.edgeSet \ G.incidenceSet t ∪ (s(·, t)) '' (G.neighborSet s) := by + ext e; refine' e.inductionOn _ + simp only [replaceVertex, mem_edgeSet, Set.mem_union, Set.mem_diff, mk'_mem_incidenceSet_iff] + intros; split_ifs; exacts [by simp_all, by aesop, by rw [adj_comm]; aesop, by aesop] + +theorem edgeSet_replaceVertex_of_adj (ha : G.Adj s t) : (G.replaceVertex s t).edgeSet = + (G.edgeSet \ G.incidenceSet t ∪ (s(·, t)) '' (G.neighborSet s)) \ {s(t, t)} := by + ext e; refine' e.inductionOn _ + simp only [replaceVertex, mem_edgeSet, Set.mem_union, Set.mem_diff, mk'_mem_incidenceSet_iff] + intros; split_ifs; exacts [by simp_all, by aesop, by rw [adj_comm]; aesop, by aesop] + +variable [Fintype V] [DecidableRel G.Adj] + +instance : DecidableRel (G.replaceVertex s t).Adj := by unfold replaceVertex; infer_instance + +theorem edgeFinset_replaceVertex_of_not_adj (hn : ¬G.Adj s t) : (G.replaceVertex s t).edgeFinset = + G.edgeFinset \ G.incidenceFinset t ∪ (G.neighborFinset s).image (s(·, t)) := by + simp only [incidenceFinset, neighborFinset, ← Set.toFinset_diff, ← Set.toFinset_image, + ← Set.toFinset_union] + exact Set.toFinset_congr (G.edgeSet_replaceVertex_of_not_adj hn) + +theorem edgeFinset_replaceVertex_of_adj (ha : G.Adj s t) : (G.replaceVertex s t).edgeFinset = + (G.edgeFinset \ G.incidenceFinset t ∪ (G.neighborFinset s).image (s(·, t))) \ {s(t, t)} := by + simp only [incidenceFinset, neighborFinset, ← Set.toFinset_diff, ← Set.toFinset_image, + ← Set.toFinset_union, ← Set.toFinset_singleton] + exact Set.toFinset_congr (G.edgeSet_replaceVertex_of_adj ha) + +lemma disjoint_sdiff_neighborFinset_image : + Disjoint (G.edgeFinset \ G.incidenceFinset t) ((G.neighborFinset s).image (s(·, t))) := by + rw [disjoint_iff_ne] + intro e he + have : t ∉ e := by + rw [mem_sdiff, mem_incidenceFinset] at he + obtain ⟨_, h⟩ := he + contrapose! h + simp_all [incidenceSet] + aesop + +theorem card_edgeFinset_replaceVertex_of_not_adj (hn : ¬G.Adj s t) : + (G.replaceVertex s t).edgeFinset.card = G.edgeFinset.card + G.degree s - G.degree t := by + have inc : G.incidenceFinset t ⊆ G.edgeFinset := by simp [incidenceFinset, incidenceSet_subset] + rw [G.edgeFinset_replaceVertex_of_not_adj hn, + card_disjoint_union G.disjoint_sdiff_neighborFinset_image, card_sdiff inc, + tsub_add_eq_add_tsub <| card_le_card inc, card_incidenceFinset_eq_degree] + congr 2 + rw [card_image_of_injective, card_neighborFinset_eq_degree] + unfold Function.Injective + aesop + +theorem card_edgeFinset_replaceVertex_of_adj (ha : G.Adj s t) : + (G.replaceVertex s t).edgeFinset.card = G.edgeFinset.card + G.degree s - G.degree t - 1 := by + have inc : G.incidenceFinset t ⊆ G.edgeFinset := by simp [incidenceFinset, incidenceSet_subset] + rw [G.edgeFinset_replaceVertex_of_adj ha, card_sdiff (by simp [ha]), + card_disjoint_union G.disjoint_sdiff_neighborFinset_image, card_sdiff inc, + tsub_add_eq_add_tsub <| card_le_card inc, card_incidenceFinset_eq_degree] + congr 2 + rw [card_image_of_injective, card_neighborFinset_eq_degree] + unfold Function.Injective + aesop end ReplaceVertex + +section AddEdge + +/-- Given a vertex pair, add the corresponding edge to the graph's edge set if not present. -/ +def addEdge : SimpleGraph V where + Adj v w := G.Adj v w ∨ s ≠ t ∧ (s = v ∧ t = w ∨ s = w ∧ t = v) + symm v w := by simp_rw [adj_comm]; (conv_lhs => arg 2; arg 2; rw [or_comm]); exact id + +@[simp] +lemma addEdge_self : G.addEdge s s = G := by ext; simp [addEdge] + +variable {s t} + +lemma addEdge_of_adj (h : G.Adj s t) : G.addEdge s t = G := by + ext + simp only [addEdge, ne_eq, G.ne_of_adj h, not_false_eq_true, true_and, or_iff_left_iff_imp] + rintro (_ | _) <;> simp_all [adj_comm] + +variable [Fintype V] [DecidableRel G.Adj] + +instance : DecidableRel (G.addEdge s t).Adj := by unfold addEdge; infer_instance + +theorem edgeFinset_addEdge (hn : ¬G.Adj s t) (h : s ≠ t) : + (G.addEdge s t).edgeFinset = G.edgeFinset.cons s(s, t) (by simp_all) := by + ext e; refine' e.inductionOn _; unfold addEdge; aesop + +theorem card_edgeFinset_addEdge (hn : ¬G.Adj s t) (h : s ≠ t) : + (G.addEdge s t).edgeFinset.card = G.edgeFinset.card + 1 := by + rw [G.edgeFinset_addEdge hn h, card_cons] + +end AddEdge diff --git a/Mathlib/Combinatorics/SimpleGraph/Partition.lean b/Mathlib/Combinatorics/SimpleGraph/Partition.lean index ef96ce03f370a..388409935cccc 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Partition.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Partition.lean @@ -115,9 +115,9 @@ def toColoring' : G.Coloring (Set V) := Coloring.mk P.partOfVertex fun hvw ↦ P.partOfVertex_ne_of_adj hvw #align simple_graph.partition.to_coloring' SimpleGraph.Partition.toColoring' -theorem to_colorable [Fintype P.parts] : G.Colorable (Fintype.card P.parts) := - P.toColoring.to_colorable -#align simple_graph.partition.to_colorable SimpleGraph.Partition.to_colorable +theorem colorable [Fintype P.parts] : G.Colorable (Fintype.card P.parts) := + P.toColoring.colorable +#align simple_graph.partition.to_colorable SimpleGraph.Partition.colorable end Partition @@ -143,7 +143,7 @@ theorem partitionable_iff_colorable {n : ℕ} : G.Partitionable n ↔ G.Colorabl · rintro ⟨P, hf, hc⟩ have : Fintype P.parts := hf.fintype rw [Set.Finite.card_toFinset hf] at hc - apply P.to_colorable.mono hc + apply P.colorable.mono hc · rintro ⟨C⟩ refine' ⟨C.toPartition, C.colorClasses_finite, le_trans _ (Fintype.card_fin n).le⟩ generalize_proofs h diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean index 913cb8c960844..80bc35ef1eec6 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean @@ -42,7 +42,8 @@ def stepBound (n : ℕ) : ℕ := n * 4 ^ n #align szemeredi_regularity.step_bound SzemerediRegularity.stepBound -theorem le_stepBound : id ≤ stepBound := fun n => Nat.le_mul_of_pos_right <| pow_pos (by norm_num) n +theorem le_stepBound : id ≤ stepBound := fun n => + Nat.le_mul_of_pos_right _ <| pow_pos (by norm_num) n #align szemeredi_regularity.le_step_bound SzemerediRegularity.le_stepBound theorem stepBound_mono : Monotone stepBound := fun a b h => @@ -130,11 +131,10 @@ theorem eps_pos (hPε : 100 ≤ (4 : ℝ) ^ P.parts.card * ε ^ 5) : 0 < ε := theorem hundred_div_ε_pow_five_le_m [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ card α) (hPε : 100 ≤ (4 : ℝ) ^ P.parts.card * ε ^ 5) : 100 / ε ^ 5 ≤ m := - (div_le_of_nonneg_of_le_mul (eps_pow_five_pos hPε).le (by positivity) hPε).trans - (by - norm_cast - rwa [Nat.le_div_iff_mul_le' (stepBound_pos (P.parts_nonempty <| - univ_nonempty.ne_empty).card_pos), stepBound, mul_left_comm, ← mul_pow]) + (div_le_of_nonneg_of_le_mul (eps_pow_five_pos hPε).le (by positivity) hPε).trans <| by + norm_cast + rwa [Nat.le_div_iff_mul_le' (stepBound_pos (P.parts_nonempty <| + univ_nonempty.ne_empty).card_pos), stepBound, mul_left_comm, ← mul_pow] #align szemeredi_regularity.hundred_div_ε_pow_five_le_m SzemerediRegularity.hundred_div_ε_pow_five_le_m theorem hundred_le_m [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ card α) @@ -215,7 +215,7 @@ noncomputable def bound : ℕ := #align szemeredi_regularity.bound SzemerediRegularity.bound theorem initialBound_le_bound : initialBound ε l ≤ bound ε l := - (id_le_iterate_of_id_le le_stepBound _ _).trans <| Nat.le_mul_of_pos_right <| by positivity + (id_le_iterate_of_id_le le_stepBound _ _).trans <| Nat.le_mul_of_pos_right _ <| by positivity #align szemeredi_regularity.initial_bound_le_bound SzemerediRegularity.initialBound_le_bound theorem le_bound : l ≤ bound ε l := diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean index 909563bd62209..544f3546554b1 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean @@ -342,7 +342,7 @@ private theorem average_density_near_total_density [Nonempty α] suffices (G.edgeDensity (A.biUnion id) (B.biUnion id) : ℝ) - (∑ ab in A.product B, (G.edgeDensity ab.1 ab.2 : ℝ)) / (A.card * B.card) ≤ ε ^ 5 / 50 by apply this.trans - exact div_le_div_of_le_left (by sz_positivity) (by norm_num) (by norm_num) + gcongr <;> [sz_positivity; norm_num] rw [sub_le_iff_le_add, ← sub_le_iff_le_add'] apply density_sub_eps_le_sum_density_div_card hPα hPε hA hB diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean index 92fd8bf443629..402d1657d693c 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean @@ -68,10 +68,11 @@ theorem equitabilise_aux (hs : a * m + b * (m + 1) = s.card) : ite (0 < a) (a - 1) a * m + ite (0 < a) b (b - 1) * (m + 1) = s.card - n := by rw [hn, ← hs] split_ifs with h <;> rw [tsub_mul, one_mul] - · refine' ⟨m_pos, le_succ _, le_add_right (le_mul_of_pos_left ‹0 < a›), _⟩ - rw [tsub_add_eq_add_tsub (le_mul_of_pos_left h)] - · refine' ⟨succ_pos', le_rfl, le_add_left (le_mul_of_pos_left <| hab.resolve_left ‹¬0 < a›), _⟩ - rw [← add_tsub_assoc_of_le (le_mul_of_pos_left <| hab.resolve_left ‹¬0 < a›)] + · refine' ⟨m_pos, le_succ _, le_add_right (Nat.le_mul_of_pos_left _ ‹0 < a›), _⟩ + rw [tsub_add_eq_add_tsub (Nat.le_mul_of_pos_left _ h)] + · refine' ⟨succ_pos', le_rfl, + le_add_left (Nat.le_mul_of_pos_left _ <| hab.resolve_left ‹¬0 < a›), _⟩ + rw [← add_tsub_assoc_of_le (Nat.le_mul_of_pos_left _ <| hab.resolve_left ‹¬0 < a›)] /- We will call the inductive hypothesis on a partition of `s \ t` for a carefully chosen `t ⊆ s`. To decide which, however, we must distinguish the case where all parts of `P` have size `m` (in which case we take `t` to be an arbitrary subset of `s` of size `n`) from the case where at diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Increment.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Increment.lean index fddea8a59efcf..8352d16887eac 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Increment.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Increment.lean @@ -112,7 +112,7 @@ private lemma pairwiseDisjoint_distinctPairs : rw [mem_offDiag] at hs ht obtain ⟨a, ha⟩ := Finpartition.nonempty_of_mem_parts _ huv₁.1 obtain ⟨b, hb⟩ := Finpartition.nonempty_of_mem_parts _ huv₁.2 - exact hst $ Subtype.ext_val <| Prod.ext + exact hst <| Subtype.ext_val <| Prod.ext (P.disjoint.elim_finset hs.1 ht.1 a (Finpartition.le _ huv₁.1 ha) <| Finpartition.le _ huv₂.1 ha) <| P.disjoint.elim_finset hs.2.1 ht.2.1 b (Finpartition.le _ huv₁.2 hb) <| diff --git a/Mathlib/Combinatorics/SimpleGraph/StronglyRegular.lean b/Mathlib/Combinatorics/SimpleGraph/StronglyRegular.lean index 9cc0a4f495c4f..b5cf2ef13d717 100644 --- a/Mathlib/Combinatorics/SimpleGraph/StronglyRegular.lean +++ b/Mathlib/Combinatorics/SimpleGraph/StronglyRegular.lean @@ -190,8 +190,11 @@ theorem IsSRGWith.param_eq (h : G.IsSRGWith n k ℓ μ) (hn : 0 < n) : · simp [h.compl.regular v] · intro w hw rw [mem_neighborFinset] at hw - simp_rw [bipartiteAbove, show G.Adj w = fun a => G.Adj w a by rfl, ← mem_neighborFinset, - filter_mem_eq_inter] + simp_rw [bipartiteAbove] + -- This used to be part of the enclosing `simp_rw` chain, + -- but after leanprover/lean4#3124 it caused a maximum recursion depth error. + change Finset.card (filter (fun a => Adj G w a) _) = _ + simp_rw [← mem_neighborFinset, filter_mem_eq_inter] have s : {v} ⊆ G.neighborFinset w \ G.neighborFinset v := by rw [singleton_subset_iff, mem_sdiff, mem_neighborFinset] exact ⟨hw.symm, G.not_mem_neighborFinset_self v⟩ diff --git a/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean b/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean index df9247de59504..7ea36c839daa7 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean @@ -3,7 +3,8 @@ Copyright (c) 2021 Hunter Monroe. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Hunter Monroe, Kyle Miller, Alena Gusakov -/ -import Mathlib.Combinatorics.SimpleGraph.Basic +import Mathlib.Init.Core +import Mathlib.Combinatorics.SimpleGraph.Maps #align_import combinatorics.simple_graph.subgraph from "leanprover-community/mathlib"@"c6ef6387ede9983aee397d442974e61f89dfd87b" @@ -720,7 +721,7 @@ def inclusion {x y : Subgraph G} (h : x ≤ y) : x.coe →g y.coe where theorem inclusion.injective {x y : Subgraph G} (h : x ≤ y) : Function.Injective (inclusion h) := by intro v w h - rw [inclusion, FunLike.coe, Subtype.mk_eq_mk] at h + rw [inclusion, DFunLike.coe, Subtype.mk_eq_mk] at h exact Subtype.ext h #align simple_graph.subgraph.inclusion.injective SimpleGraph.Subgraph.inclusion.injective diff --git a/Mathlib/Combinatorics/Young/SemistandardTableau.lean b/Mathlib/Combinatorics/Young/SemistandardTableau.lean index 7f4e688394948..de1dbdfea40e1 100644 --- a/Mathlib/Combinatorics/Young/SemistandardTableau.lean +++ b/Mathlib/Combinatorics/Young/SemistandardTableau.lean @@ -63,13 +63,13 @@ structure Ssyt (μ : YoungDiagram) where namespace Ssyt -instance funLike {μ : YoungDiagram} : FunLike (Ssyt μ) ℕ fun _ ↦ ℕ → ℕ where +instance instFunLike {μ : YoungDiagram} : FunLike (Ssyt μ) ℕ (ℕ → ℕ) where coe := Ssyt.entry coe_injective' T T' h := by cases T cases T' congr -#align ssyt.fun_like Ssyt.funLike +#align ssyt.fun_like Ssyt.instFunLike /-- Helper instance for when there's too many metavariables to apply `CoeFun.coe` directly. -/ instance {μ : YoungDiagram} : CoeFun (Ssyt μ) fun _ ↦ ℕ → ℕ → ℕ := @@ -82,7 +82,7 @@ theorem to_fun_eq_coe {μ : YoungDiagram} {T : Ssyt μ} : T.entry = (T : ℕ → @[ext] theorem ext {μ : YoungDiagram} {T T' : Ssyt μ} (h : ∀ i j, T i j = T' i j) : T = T' := - FunLike.ext T T' fun _ ↦ by + DFunLike.ext T T' fun _ ↦ by funext apply h #align ssyt.ext Ssyt.ext @@ -105,7 +105,7 @@ theorem coe_copy {μ : YoungDiagram} (T : Ssyt μ) (entry' : ℕ → ℕ → ℕ theorem copy_eq {μ : YoungDiagram} (T : Ssyt μ) (entry' : ℕ → ℕ → ℕ) (h : entry' = T) : T.copy entry' h = T := - FunLike.ext' h + DFunLike.ext' h #align ssyt.copy_eq Ssyt.copy_eq theorem row_weak {μ : YoungDiagram} (T : Ssyt μ) {i j1 j2 : ℕ} (hj : j1 < j2) diff --git a/Mathlib/Computability/Ackermann.lean b/Mathlib/Computability/Ackermann.lean index 436e1d581b3a1..dc471878ab842 100644 --- a/Mathlib/Computability/Ackermann.lean +++ b/Mathlib/Computability/Ackermann.lean @@ -6,6 +6,7 @@ Authors: Violeta Hernández Palacios import Mathlib.Computability.Primrec import Mathlib.Tactic.Ring import Mathlib.Tactic.Linarith +import Mathlib.Algebra.GroupPower.Order #align_import computability.ackermann from "leanprover-community/mathlib"@"9b2660e1b25419042c8da10bf411aa3c67f14383" @@ -63,7 +64,7 @@ def ack : ℕ → ℕ → ℕ | 0, n => n + 1 | m + 1, 0 => ack m 1 | m + 1, n + 1 => ack m (ack (m + 1) n) - termination_by ack m n => (m, n) + termination_by m n => (m, n) #align ack ack @[simp] @@ -101,6 +102,7 @@ theorem ack_three (n : ℕ) : ack 3 n = 2 ^ (n + 3) - 3 := by Nat.mul_sub_left_distrib, ← Nat.sub_add_comm, two_mul 3, Nat.add_sub_add_right] have H : 2 * 3 ≤ 2 * 2 ^ 3 := by norm_num apply H.trans + set_option simprocs false in simp [pow_le_pow_right (show 1 ≤ 2 by norm_num)] #align ack_three ack_three @@ -142,7 +144,7 @@ theorem ack_strictMono_right : ∀ m, StrictMono (ack m) rw [ack_succ_succ, ack_succ_succ] apply ack_strictMono_right _ (ack_strictMono_right _ _) rwa [add_lt_add_iff_right] at h - termination_by ack_strictMono_right m x y h => (m, x) + termination_by m x y h => (m, x) #align ack_strict_mono_right ack_strictMono_right theorem ack_mono_right (m : ℕ) : Monotone (ack m) := @@ -183,7 +185,7 @@ theorem add_lt_ack : ∀ m n, m + n < ack m n ack_mono_right m <| le_of_eq_of_le (by rw [succ_eq_add_one]; ring_nf) <| succ_le_of_lt <| add_lt_ack (m + 1) n _ = ack (m + 1) (n + 1) := (ack_succ_succ m n).symm - termination_by add_lt_ack m n => (m, n) + termination_by m n => (m, n) #align add_lt_ack add_lt_ack theorem add_add_one_le_ack (m n : ℕ) : m + n + 1 ≤ ack m n := @@ -213,7 +215,7 @@ private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack exact (ack_strict_mono_left' _ <| (add_lt_add_iff_right 1).1 h).trans (ack_strictMono_right _ <| ack_strict_mono_left' n h) - termination_by ack_strict_mono_left' x y => (x, y) + termination_by _ m n => (m, n) theorem ack_strictMono_left (n : ℕ) : StrictMono fun m => ack m n := fun _m₁ _m₂ => ack_strict_mono_left' n diff --git a/Mathlib/Computability/AkraBazzi/AkraBazzi.lean b/Mathlib/Computability/AkraBazzi/AkraBazzi.lean index 9c3fe167173bb..a5441271cb6b4 100644 --- a/Mathlib/Computability/AkraBazzi/AkraBazzi.lean +++ b/Mathlib/Computability/AkraBazzi/AkraBazzi.lean @@ -5,6 +5,7 @@ Authors: Frédéric Dupuis -/ import Mathlib.Computability.AkraBazzi.GrowsPolynomially +import Mathlib.Analysis.Calculus.Deriv.Inv import Mathlib.Analysis.Calculus.MeanValue import Mathlib.Analysis.SpecialFunctions.Pow.Deriv @@ -591,7 +592,7 @@ lemma asympBound_pos (n : ℕ) (hn : 0 < n) : 0 < asympBound g a b n := by simp only [asympBound_def'] gcongr n^p a b * (1 + ?_) have := R.g_nonneg - aesop (add safe Real.rpow_nonneg_of_nonneg, + aesop (add safe Real.rpow_nonneg, safe div_nonneg, safe Finset.sum_nonneg) diff --git a/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean b/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean index cccf395c85a0b..a1570e66cbca0 100644 --- a/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean +++ b/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean @@ -424,7 +424,7 @@ lemma GrowsPolynomially.add_isLittleO {f g : ℝ → ℝ} (hf : GrowsPolynomiall _ = 3/2 * f x := by ring have hx_lb : 1/2 * f x ≤ f x + g x := by calc f x + g x ≥ f x - ‖g x‖ := by - rw [sub_eq_add_neg, norm_eq_abs]; gcongr; exact neg_abs_le_self (g x) + rw [sub_eq_add_neg, norm_eq_abs]; gcongr; exact neg_abs_le (g x) _ ≥ f x - 1/2 * f x := by gcongr _ = 1/2 * f x := by ring intro u ⟨hu_lb, hu_ub⟩ @@ -435,7 +435,7 @@ lemma GrowsPolynomially.add_isLittleO {f g : ℝ → ℝ} (hf : GrowsPolynomiall refine ⟨?lb, ?ub⟩ case lb => calc f u + g u ≥ f u - ‖g u‖ := by - rw [sub_eq_add_neg, norm_eq_abs]; gcongr; exact neg_abs_le_self _ + rw [sub_eq_add_neg, norm_eq_abs]; gcongr; exact neg_abs_le _ _ ≥ f u - 1/2 * f u := by gcongr _ = 1/2 * f u := by ring _ ≥ 1/2 * (c₁ * f x) := by gcongr; exact (hf₁ u ⟨hu_lb, hu_ub⟩).1 @@ -468,7 +468,7 @@ lemma GrowsPolynomially.add_isLittleO {f g : ℝ → ℝ} (hf : GrowsPolynomiall _ = 1/2 * f x := by ring have hx_lb : 3/2 * f x ≤ f x + g x := by calc f x + g x ≥ f x - ‖g x‖ := by - rw [sub_eq_add_neg, norm_eq_abs]; gcongr; exact neg_abs_le_self (g x) + rw [sub_eq_add_neg, norm_eq_abs]; gcongr; exact neg_abs_le (g x) _ ≥ f x + 1/2 * f x := by rw [sub_eq_add_neg] gcongr @@ -484,7 +484,7 @@ lemma GrowsPolynomially.add_isLittleO {f g : ℝ → ℝ} (hf : GrowsPolynomiall refine ⟨?lb, ?ub⟩ case lb => calc f u + g u ≥ f u - ‖g u‖ := by - rw [sub_eq_add_neg, norm_eq_abs]; gcongr; exact neg_abs_le_self _ + rw [sub_eq_add_neg, norm_eq_abs]; gcongr; exact neg_abs_le _ _ ≥ f u + 1/2 * f u := by rw [sub_eq_add_neg] gcongr diff --git a/Mathlib/Computability/ContextFreeGrammar.lean b/Mathlib/Computability/ContextFreeGrammar.lean index 2a162da4e6029..cdb4b8cacf28a 100644 --- a/Mathlib/Computability/ContextFreeGrammar.lean +++ b/Mathlib/Computability/ContextFreeGrammar.lean @@ -176,7 +176,7 @@ lemma Derives.append_left {v w : List (Symbol T g.NT)} g.Derives (p ++ v) (p ++ w) := by induction hvw with | refl => rfl - | tail _ last ih => exact ih.trans_produces $ last.append_left p + | tail _ last ih => exact ih.trans_produces <| last.append_left p /-- Add extra prefix to context-free deriving. -/ lemma Derives.append_right {v w : List (Symbol T g.NT)} @@ -184,6 +184,6 @@ lemma Derives.append_right {v w : List (Symbol T g.NT)} g.Derives (v ++ p) (w ++ p) := by induction hvw with | refl => rfl - | tail _ last ih => exact ih.trans_produces $ last.append_right p + | tail _ last ih => exact ih.trans_produces <| last.append_right p end ContextFreeGrammar diff --git a/Mathlib/Computability/Encoding.lean b/Mathlib/Computability/Encoding.lean index 5bce82a7da600..137189b06b7c3 100644 --- a/Mathlib/Computability/Encoding.lean +++ b/Mathlib/Computability/Encoding.lean @@ -5,6 +5,7 @@ Authors: Pim Spelier, Daan van Gent -/ import Mathlib.Data.Fintype.Basic import Mathlib.Data.Num.Lemmas +import Mathlib.Data.Option.Basic import Mathlib.SetTheory.Cardinal.Ordinal #align_import computability.encoding from "leanprover-community/mathlib"@"b6395b3a5acd655b16385fa0cdbf1961d6c34b3e" diff --git a/Mathlib/Computability/Language.lean b/Mathlib/Computability/Language.lean index af50e1601fa07..9158693a1d18e 100644 --- a/Mathlib/Computability/Language.lean +++ b/Mathlib/Computability/Language.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Fox Thomson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Fox Thomson +Authors: Fox Thomson, Martin Dvorak -/ import Mathlib.Algebra.Order.Kleene import Mathlib.Algebra.Ring.Hom.Defs @@ -14,10 +14,12 @@ import Mathlib.Tactic.DeriveFintype /-! # Languages -This file contains the definition and operations on formal languages over an alphabet. Note strings -are implemented as lists over the alphabet. -The operations in this file define a [Kleene algebra](https://en.wikipedia.org/wiki/Kleene_algebra) +This file contains the definition and operations on formal languages over an alphabet. +Note that "strings" are implemented as lists over the alphabet. +Union and concatenation define a [Kleene algebra](https://en.wikipedia.org/wiki/Kleene_algebra) over the languages. +In addition to that, we define a reversal of a language and prove that it behaves well +with respect to other language operations. -/ @@ -300,6 +302,76 @@ instance : KleeneAlgebra (Language α) := rw [pow_succ, ← mul_assoc m l (l^n)] exact le_trans (le_mul_congr h le_rfl) ih } +/-- Language `l.reverse` is defined as the set of words from `l` backwards. -/ +def reverse (l : Language α) : Language α := { w : List α | w.reverse ∈ l } + +@[simp] +lemma mem_reverse : a ∈ l.reverse ↔ a.reverse ∈ l := Iff.rfl + +lemma reverse_mem_reverse : a.reverse ∈ l.reverse ↔ a ∈ l := by + rw [mem_reverse, List.reverse_reverse] + +lemma reverse_eq_image (l : Language α) : l.reverse = List.reverse '' l := + ((List.reverse_involutive.toPerm _).image_eq_preimage _).symm + +@[simp] +lemma reverse_zero : (0 : Language α).reverse = 0 := rfl + +@[simp] +lemma reverse_one : (1 : Language α).reverse = 1 := by + simp [reverse, ← one_def] + +lemma reverse_involutive : Function.Involutive (reverse : Language α → _) := + List.reverse_involutive.preimage + +lemma reverse_bijective : Function.Bijective (reverse : Language α → _) := + reverse_involutive.bijective + +lemma reverse_injective : Function.Injective (reverse : Language α → _) := + reverse_involutive.injective + +lemma reverse_surjective : Function.Surjective (reverse : Language α → _) := + reverse_involutive.surjective + +@[simp] +lemma reverse_reverse (l : Language α) : l.reverse.reverse = l := reverse_involutive l + +@[simp] +lemma reverse_add (l m : Language α) : (l + m).reverse = l.reverse + m.reverse := rfl + +@[simp] +lemma reverse_mul (l m : Language α) : (l * m).reverse = m.reverse * l.reverse := by + simp only [mul_def, reverse_eq_image, image2_image_left, image2_image_right, image_image2, + List.reverse_append] + apply image2_swap + +@[simp] +lemma reverse_iSup {ι : Sort*} (l : ι → Language α) : (⨆ i, l i).reverse = ⨆ i, (l i).reverse := + preimage_iUnion + +@[simp] +lemma reverse_iInf {ι : Sort*} (l : ι → Language α) : (⨅ i, l i).reverse = ⨅ i, (l i).reverse := + preimage_iInter + +variable (α) in +/-- `Language.reverse` as a ring isomorphism to the opposite ring. -/ +@[simps] +def reverseIso : Language α ≃+* (Language α)ᵐᵒᵖ where + toFun l := .op l.reverse + invFun l' := l'.unop.reverse + left_inv := reverse_reverse + right_inv l' := MulOpposite.unop_injective <| reverse_reverse l'.unop + map_mul' l₁ l₂ := MulOpposite.unop_injective <| reverse_mul l₁ l₂ + map_add' l₁ l₂ := MulOpposite.unop_injective <| reverse_add l₁ l₂ + +@[simp] +lemma reverse_pow (l : Language α) (n : ℕ) : (l ^ n).reverse = l.reverse ^ n := + MulOpposite.op_injective (map_pow (reverseIso α) l n) + +@[simp] +lemma reverse_kstar (l : Language α) : l∗.reverse = l.reverse∗ := by + simp only [kstar_eq_iSup_pow, reverse_iSup, reverse_pow] + end Language /-- Symbols for use by all kinds of grammars. -/ diff --git a/Mathlib/Computability/PartrecCode.lean b/Mathlib/Computability/PartrecCode.lean index a729b0bdfeb41..b311029adaa6c 100644 --- a/Mathlib/Computability/PartrecCode.lean +++ b/Mathlib/Computability/PartrecCode.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Computability.Partrec +import Mathlib.Data.Option.Basic #align_import computability.partrec_code from "leanprover-community/mathlib"@"6155d4351090a6fad236e3d2e4e0e4e7342668e8" @@ -695,7 +696,8 @@ theorem smn : ⟨curry, Primrec₂.to_comp curry_prim, eval_curry⟩ #align nat.partrec.code.smn Nat.Partrec.Code.smn -/-- A function is partial recursive if and only if there is a code implementing it. -/ +/-- A function is partial recursive if and only if there is a code implementing it. Therefore, +`eval` is a **universal partial recursive function**. -/ theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f := by refine ⟨fun h => ?_, ?_⟩ · induction h with @@ -768,8 +770,8 @@ def evaln : ℕ → Code → ℕ → Option ℕ pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)) - termination_by evaln k c => (k, c) - decreasing_by { decreasing_with simp (config := { arith := true }) [Zero.zero]; done } + termination_by k c => (k, c) + decreasing_by all_goals { decreasing_with (dsimp; omega) } #align nat.partrec.code.evaln Nat.Partrec.Code.evaln theorem evaln_bound : ∀ {k c n x}, x ∈ evaln k c n → n < k diff --git a/Mathlib/Computability/RegularExpressions.lean b/Mathlib/Computability/RegularExpressions.lean index 7185404a5d691..9c81f4f0545a1 100644 --- a/Mathlib/Computability/RegularExpressions.lean +++ b/Mathlib/Computability/RegularExpressions.lean @@ -343,7 +343,7 @@ theorem star_rmatch_iff (P : RegularExpression α) : refine' ⟨U, rfl, fun t h => helem t _⟩ right assumption - termination_by star_rmatch_iff P t => (P,t.length) + termination_by t => (P,t.length) #align regular_expression.star_rmatch_iff RegularExpression.star_rmatch_iff @[simp] diff --git a/Mathlib/Computability/TuringMachine.lean b/Mathlib/Computability/TuringMachine.lean index fd523cfeab727..eb7821ef167b6 100644 --- a/Mathlib/Computability/TuringMachine.lean +++ b/Mathlib/Computability/TuringMachine.lean @@ -105,7 +105,7 @@ def BlankExtends.above {Γ} [Inhabited Γ] {l l₁ l₂ : List Γ} (h₁ : Blank theorem BlankExtends.above_of_le {Γ} [Inhabited Γ] {l l₁ l₂ : List Γ} : BlankExtends l₁ l → BlankExtends l₂ l → l₁.length ≤ l₂.length → BlankExtends l₁ l₂ := by rintro ⟨i, rfl⟩ ⟨j, e⟩ h; use i - j - refine' List.append_right_cancel (e.symm.trans _) + refine' List.append_cancel_right (e.symm.trans _) rw [List.append_assoc, ← List.replicate_add, tsub_add_cancel_of_le] apply_fun List.length at e simp only [List.length_append, List.length_replicate] at e diff --git a/Mathlib/Condensed/Discrete.lean b/Mathlib/Condensed/Discrete.lean index 1b89b57919f4b..5e03fc14fa581 100644 --- a/Mathlib/Condensed/Discrete.lean +++ b/Mathlib/Condensed/Discrete.lean @@ -21,14 +21,7 @@ universe u v w open CategoryTheory Limits Opposite GrothendieckTopology -variable (C : Type w) [Category.{u+1} C] [ConcreteCategory C] - [PreservesLimits (forget C)] [ReflectsIsomorphisms (forget C)] - [∀ (P : CompHausᵒᵖ ⥤ C) X (S : Cover (coherentTopology CompHaus) X), - HasMultiequalizer (Cover.index S P)] - [∀ X, HasColimitsOfShape (Cover (coherentTopology CompHaus) X)ᵒᵖ C] - [∀ X, PreservesColimitsOfShape (Cover (coherentTopology CompHaus) X)ᵒᵖ (forget C)] --- These conditions are satisfied by the category of abelian groups, and other "algebraic" --- categories. +variable (C : Type w) [Category.{u+1} C] [HasWeakSheafify (coherentTopology CompHaus) C] /-- The discrete condensed object associated to an object of `C` is the constant sheaf at that object. diff --git a/Mathlib/Condensed/Equivalence.lean b/Mathlib/Condensed/Equivalence.lean index 7424208af47fa..e97dd90c15c07 100644 --- a/Mathlib/Condensed/Equivalence.lean +++ b/Mathlib/Condensed/Equivalence.lean @@ -8,7 +8,6 @@ import Mathlib.Topology.Category.Stonean.EffectiveEpi import Mathlib.Condensed.Basic import Mathlib.CategoryTheory.Sites.DenseSubsite import Mathlib.CategoryTheory.Sites.InducedTopology -import Mathlib.CategoryTheory.Sites.Closed /-! # Sheaves on CompHaus are equivalent to sheaves on Stonean diff --git a/Mathlib/Condensed/Explicit.lean b/Mathlib/Condensed/Explicit.lean index 191d57b9867c9..0c1b24ac63044 100644 --- a/Mathlib/Condensed/Explicit.lean +++ b/Mathlib/Condensed/Explicit.lean @@ -34,7 +34,7 @@ open CategoryTheory Limits Opposite Functor Presieve regularCoverage namespace CategoryTheory variable {C : Type u} [Category.{v} C] (F : Cᵒᵖ ⥤ Type (max u v)) [Preregular C] - [FinitaryPreExtensive C] [Precoherent C] + [FinitaryPreExtensive C] theorem isSheaf_coherent_iff_regular_and_extensive : IsSheaf (coherentTopology C) F ↔ IsSheaf (extensiveCoverage C).toGrothendieck F ∧ diff --git a/Mathlib/Condensed/Functors.lean b/Mathlib/Condensed/Functors.lean index 38baeee1c06db..888db5ea38112 100644 --- a/Mathlib/Condensed/Functors.lean +++ b/Mathlib/Condensed/Functors.lean @@ -5,7 +5,8 @@ Authors: Dagur Asgeirsson -/ import Mathlib.CategoryTheory.Limits.Preserves.Ulift import Mathlib.CategoryTheory.Sites.Whiskering -import Mathlib.Condensed.Equivalence +import Mathlib.Condensed.Basic +import Mathlib.Topology.Category.Stonean.Basic /-! # Functors from categories of topological spaces to condensed sets diff --git a/Mathlib/Control/Basic.lean b/Mathlib/Control/Basic.lean index 99f1c499ad700..946c948077c1e 100644 --- a/Mathlib/Control/Basic.lean +++ b/Mathlib/Control/Basic.lean @@ -7,7 +7,6 @@ import Mathlib.Init.Control.Combinators import Mathlib.Init.Function import Mathlib.Tactic.CasesM import Mathlib.Tactic.Attr.Core -import Std.Data.List.Basic #align_import control.basic from "leanprover-community/mathlib"@"48fb5b5280e7c81672afc9524185ae994553ebf4" diff --git a/Mathlib/Control/Bifunctor.lean b/Mathlib/Control/Bifunctor.lean index 9f107de0db10c..267950a812916 100644 --- a/Mathlib/Control/Bifunctor.lean +++ b/Mathlib/Control/Bifunctor.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ import Mathlib.Control.Functor -import Mathlib.Data.Sum.Basic import Mathlib.Tactic.Common #align_import control.bifunctor from "leanprover-community/mathlib"@"dc1525fb3ef6eb4348fb1749c302d8abc303d34a" diff --git a/Mathlib/Control/Bitraversable/Instances.lean b/Mathlib/Control/Bitraversable/Instances.lean index de7eb37ee5abd..4e49b699f6ac8 100644 --- a/Mathlib/Control/Bitraversable/Instances.lean +++ b/Mathlib/Control/Bitraversable/Instances.lean @@ -46,7 +46,7 @@ instance : Bitraversable Prod where bitraverse := @Prod.bitraverse instance : LawfulBitraversable Prod := by constructor <;> intros <;> casesm _ × _ <;> - simp [bitraverse, Prod.bitraverse, functor_norm, -ApplicativeTransformation.app_eq_coe] <;> rfl + simp [bitraverse, Prod.bitraverse, functor_norm] <;> rfl open Functor @@ -60,7 +60,7 @@ instance : Bitraversable Sum where bitraverse := @Sum.bitraverse instance : LawfulBitraversable Sum := by constructor <;> intros <;> casesm _ ⊕ _ <;> - simp [bitraverse, Sum.bitraverse, functor_norm, -ApplicativeTransformation.app_eq_coe] <;> rfl + simp [bitraverse, Sum.bitraverse, functor_norm] <;> rfl set_option linter.unusedVariables false in @@ -102,9 +102,9 @@ instance (priority := 10) Bitraversable.traversable {α} : Traversable (t α) wh instance (priority := 10) Bitraversable.isLawfulTraversable [LawfulBitraversable t] {α} : LawfulTraversable (t α) := by constructor <;> intros <;> - simp [traverse, comp_tsnd, functor_norm, -ApplicativeTransformation.app_eq_coe] + simp [traverse, comp_tsnd, functor_norm] · simp [tsnd_eq_snd_id]; rfl - · simp [tsnd, binaturality, Function.comp, functor_norm, -ApplicativeTransformation.app_eq_coe] + · simp [tsnd, binaturality, Function.comp, functor_norm] #align bitraversable.is_lawful_traversable Bitraversable.isLawfulTraversable end @@ -129,7 +129,7 @@ instance [LawfulTraversable F] [LawfulTraversable G] [LawfulBitraversable t] : LawfulBitraversable (bicompl t F G) := by constructor <;> intros <;> simp [bitraverse, Bicompl.bitraverse, bimap, traverse_id, bitraverse_id_id, comp_bitraverse, - functor_norm, -ApplicativeTransformation.app_eq_coe] + functor_norm] · simp [traverse_eq_map_id', bitraverse_eq_bimap_id] · dsimp only [bicompl] simp [binaturality, naturality_pf] @@ -150,8 +150,7 @@ instance : Bitraversable (bicompr F t) where bitraverse := @Bicompr.bitraverse t instance [LawfulTraversable F] [LawfulBitraversable t] : LawfulBitraversable (bicompr F t) := by constructor <;> intros <;> - simp [bitraverse, Bicompr.bitraverse, bitraverse_id_id, functor_norm, - -ApplicativeTransformation.app_eq_coe] + simp [bitraverse, Bicompr.bitraverse, bitraverse_id_id, functor_norm] · simp [bitraverse_eq_bimap_id', traverse_eq_map_id']; rfl · dsimp only [bicompr] simp [naturality, binaturality'] diff --git a/Mathlib/Control/EquivFunctor.lean b/Mathlib/Control/EquivFunctor.lean index 4c345d4342bfb..59001f2f53c02 100644 --- a/Mathlib/Control/EquivFunctor.lean +++ b/Mathlib/Control/EquivFunctor.lean @@ -73,7 +73,7 @@ theorem mapEquiv_refl (α) : mapEquiv f (Equiv.refl α) = Equiv.refl (f α) := b @[simp] theorem mapEquiv_symm : (mapEquiv f e).symm = mapEquiv f e.symm := - Equiv.ext $ mapEquiv_symm_apply f e + Equiv.ext <| mapEquiv_symm_apply f e #align equiv_functor.map_equiv_symm EquivFunctor.mapEquiv_symm /-- The composition of `mapEquiv`s is carried over the `EquivFunctor`. diff --git a/Mathlib/Control/Functor.lean b/Mathlib/Control/Functor.lean index df9c171e3c2a7..7c02734eb078a 100644 --- a/Mathlib/Control/Functor.lean +++ b/Mathlib/Control/Functor.lean @@ -5,7 +5,7 @@ Authors: Simon Hudon -/ import Mathlib.Control.Basic import Mathlib.Init.Set -import Mathlib.Tactic.Basic +import Mathlib.Tactic.TypeStar import Std.Tactic.Lint #align_import control.functor from "leanprover-community/mathlib"@"70d50ecfd4900dd6d328da39ab7ebd516abe4025" diff --git a/Mathlib/Control/Monad/Basic.lean b/Mathlib/Control/Monad/Basic.lean index 22e20fd0569d5..e94d4f0f8fb31 100644 --- a/Mathlib/Control/Monad/Basic.lean +++ b/Mathlib/Control/Monad/Basic.lean @@ -3,9 +3,7 @@ Copyright (c) 2019 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ -import Mathlib.Init.Control.Lawful import Mathlib.Logic.Equiv.Defs -import Mathlib.Tactic.Common #align_import control.monad.basic from "leanprover-community/mathlib"@"48fb5b5280e7c81672afc9524185ae994553ebf4" @@ -40,7 +38,7 @@ functor, applicative, monad, simp set_option autoImplicit true -attribute [ext] ReaderT.ext StateT.ext ExceptT.ext OptionT.ext +attribute [ext] ReaderT.ext StateT.ext ExceptT.ext @[monad_norm] theorem map_eq_bind_pure_comp (m : Type u → Type v) [Monad m] [LawfulMonad m] diff --git a/Mathlib/Control/Monad/Writer.lean b/Mathlib/Control/Monad/Writer.lean index e19f0a18912ea..8643d857885cd 100644 --- a/Mathlib/Control/Monad/Writer.lean +++ b/Mathlib/Control/Monad/Writer.lean @@ -72,16 +72,16 @@ This is used to derive instances for both `[EmptyCollection ω] [Append ω]` and -/ @[reducible, inline] def monad (empty : ω) (append : ω → ω → ω) : Monad (WriterT ω M) where - map := fun f (cmd : M _) ↦ WriterT.mk $ (fun (a,w) ↦ (f a, w)) <$> cmd + map := fun f (cmd : M _) ↦ WriterT.mk <| (fun (a,w) ↦ (f a, w)) <$> cmd pure := fun a ↦ pure (f := M) (a, empty) bind := fun (cmd : M _) f ↦ - WriterT.mk $ cmd >>= fun (a, w₁) ↦ + WriterT.mk <| cmd >>= fun (a, w₁) ↦ (fun (b, w₂) ↦ (b, append w₁ w₂)) <$> (f a) /-- Lift an `M` to a `WriterT ω M`, using the given `empty` as the monoid unit. -/ @[inline] protected def liftTell (empty : ω) : MonadLift M (WriterT ω M) where - monadLift := fun cmd ↦ WriterT.mk $ (fun a ↦ (a, empty)) <$> cmd + monadLift := fun cmd ↦ WriterT.mk <| (fun a ↦ (a, empty)) <$> cmd instance [EmptyCollection ω] [Append ω] : Monad (WriterT ω M) := monad ∅ (· ++ ·) instance [EmptyCollection ω] : MonadLift M (WriterT ω M) := WriterT.liftTell ∅ @@ -96,13 +96,13 @@ instance [Monoid ω] [LawfulMonad M] : LawfulMonad (WriterT ω M) := LawfulMonad (bind_assoc := by intros; simp [Bind.bind, mul_assoc, WriterT.mk, ← bind_pure_comp]) instance : MonadWriter ω (WriterT ω M) where - tell := fun w ↦ WriterT.mk $ pure (⟨⟩, w) - listen := fun cmd ↦ WriterT.mk $ (fun (a,w) ↦ ((a,w), w)) <$> cmd - pass := fun cmd ↦ WriterT.mk $ (fun ((a,f), w) ↦ (a, f w)) <$> cmd + tell := fun w ↦ WriterT.mk <| pure (⟨⟩, w) + listen := fun cmd ↦ WriterT.mk <| (fun (a,w) ↦ ((a,w), w)) <$> cmd + pass := fun cmd ↦ WriterT.mk <| (fun ((a,f), w) ↦ (a, f w)) <$> cmd instance [MonadExcept ε M] : MonadExcept ε (WriterT ω M) where - throw := fun e ↦ WriterT.mk $ throw e - tryCatch := fun cmd c ↦ WriterT.mk $ tryCatch cmd fun e ↦ (c e).run + throw := fun e ↦ WriterT.mk <| throw e + tryCatch := fun cmd c ↦ WriterT.mk <| tryCatch cmd fun e ↦ (c e).run instance [MonadLiftT M (WriterT ω M)] : MonadControl M (WriterT ω M) where stM := fun α ↦ α × ω @@ -110,11 +110,11 @@ instance [MonadLiftT M (WriterT ω M)] : MonadControl M (WriterT ω M) where restoreM := WriterT.mk instance : MonadFunctor M (WriterT ω M) where - monadMap := fun k (w : M _) ↦ WriterT.mk $ k w + monadMap := fun k (w : M _) ↦ WriterT.mk <| k w @[inline] protected def adapt {ω' : Type u} {α : Type u} (f : ω → ω') : WriterT ω M α → WriterT ω' M α := - fun cmd ↦ WriterT.mk $ Prod.map id f <$> cmd + fun cmd ↦ WriterT.mk <| Prod.map id f <$> cmd end WriterT @@ -144,7 +144,7 @@ their underlying monad -/ def WriterT.equiv {m₁ : Type u₀ → Type v₀} {m₂ : Type u₁ → Type v₁} {α₁ ω₁ : Type u₀} {α₂ ω₂ : Type u₁} (F : (m₁ (α₁ × ω₁)) ≃ (m₂ (α₂ × ω₂))) : WriterT ω₁ m₁ α₁ ≃ WriterT ω₂ m₂ α₂ where - toFun (f : m₁ _) := WriterT.mk $ F f - invFun (f : m₂ _) := WriterT.mk $ F.symm f - left_inv (f : m₁ _) := congr_arg WriterT.mk $ F.left_inv f - right_inv (f : m₂ _) := congr_arg WriterT.mk $ F.right_inv f + toFun (f : m₁ _) := WriterT.mk <| F f + invFun (f : m₂ _) := WriterT.mk <| F.symm f + left_inv (f : m₁ _) := congr_arg WriterT.mk <| F.left_inv f + right_inv (f : m₂ _) := congr_arg WriterT.mk <| F.right_inv f diff --git a/Mathlib/Control/Random.lean b/Mathlib/Control/Random.lean index e904a25a471b4..a1bf61d6875f1 100644 --- a/Mathlib/Control/Random.lean +++ b/Mathlib/Control/Random.lean @@ -3,15 +3,8 @@ Copyright (c) 2022 Henrik Böving. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Henrik Böving -/ - -import Mathlib.Init.Order.Defs -import Mathlib.Init.Data.Nat.Lemmas -import Mathlib.Init.Data.Int.Order import Mathlib.Control.ULiftable import Mathlib.Data.Fin.Basic -import Mathlib.Data.Nat.Basic -import Mathlib.Order.ULift -import Mathlib.Logic.Equiv.Functor #align_import control.random from "leanprover-community/mathlib"@"fdc286cc6967a012f41b87f76dcd2797b53152af" @@ -126,13 +119,13 @@ instance : BoundedRandom m Nat where instance : BoundedRandom m Int where randomR lo hi h _ := do - let ⟨z, _, h2⟩ ← randBound Nat 0 (Int.natAbs $ hi - lo) (Nat.zero_le _) + let ⟨z, _, h2⟩ ← randBound Nat 0 (Int.natAbs <| hi - lo) (Nat.zero_le _) pure ⟨ z + lo, Int.le_add_of_nonneg_left (Int.ofNat_zero_le z), - Int.add_le_of_le_sub_right $ Int.le_trans + Int.add_le_of_le_sub_right <| Int.le_trans (Int.ofNat_le.mpr h2) - (le_of_eq $ Int.natAbs_of_nonneg $ Int.sub_nonneg_of_le h)⟩ + (le_of_eq <| Int.natAbs_of_nonneg <| Int.sub_nonneg_of_le h)⟩ instance {n : Nat} : BoundedRandom m (Fin n) where randomR lo hi h _ := do @@ -168,6 +161,6 @@ def runRand (cmd : RandT m α) : m α := do pure res def runRandWith (seed : Nat) (cmd : RandT m α) : m α := do - pure $ (← cmd.run (ULift.up $ mkStdGen seed)).1 + pure <| (← cmd.run (ULift.up <| mkStdGen seed)).1 end IO diff --git a/Mathlib/Control/Traversable/Basic.lean b/Mathlib/Control/Traversable/Basic.lean index 11f2d973974e4..0be94c9c400b8 100644 --- a/Mathlib/Control/Traversable/Basic.lean +++ b/Mathlib/Control/Traversable/Basic.lean @@ -3,8 +3,8 @@ Copyright (c) 2018 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ -import Mathlib.Data.List.Defs import Mathlib.Data.Option.Defs +import Mathlib.Control.Functor #align_import control.traversable.basic from "leanprover-community/mathlib"@"1fc36cc9c8264e6e81253f88be7fb2cb6c92d76a" @@ -91,7 +91,7 @@ instance : CoeFun (ApplicativeTransformation F G) fun _ => ∀ {α}, F α → G variable {F G} -@[simp] +-- This cannot be a `simp` lemma, as the RHS is a coercion which contains `η.app`. theorem app_eq_coe (η : ApplicativeTransformation F G) : η.app = η := rfl #align applicative_transformation.app_eq_coe ApplicativeTransformation.app_eq_coe diff --git a/Mathlib/Data/Analysis/Filter.lean b/Mathlib/Data/Analysis/Filter.lean index 23dc5adbe4e1e..c21461b6a3742 100644 --- a/Mathlib/Data/Analysis/Filter.lean +++ b/Mathlib/Data/Analysis/Filter.lean @@ -53,7 +53,7 @@ instance : CoeFun (CFilter α σ) fun _ ↦ σ → α := ⟨CFilter.f⟩ /- Porting note: Due to the CoeFun instance, the lhs of this lemma has a variable (f) as its head -symbol (simpnf linter problem). Replacing it with a FunLike instance would not be mathematically +symbol (simpnf linter problem). Replacing it with a DFunLike instance would not be mathematically meaningful here, since the coercion to f cannot be injective, hence need to remove @[simp]. -/ -- @[simp] theorem coe_mk (f pt inf h₁ h₂ a) : (@CFilter.mk α σ _ f pt inf h₁ h₂) a = f a := diff --git a/Mathlib/Data/Array/Basic.lean b/Mathlib/Data/Array/Basic.lean index 74d015ebb414c..7460f775a36ec 100644 --- a/Mathlib/Data/Array/Basic.lean +++ b/Mathlib/Data/Array/Basic.lean @@ -1,5 +1,4 @@ -import Std.Tactic.HaveI -import Mathlib.Data.List.Basic +import Std.Tactic.Alias attribute [simp] Array.toArrayAux_eq diff --git a/Mathlib/Data/Array/Defs.lean b/Mathlib/Data/Array/Defs.lean index 8a660571b102b..b909aa6fdca70 100644 --- a/Mathlib/Data/Array/Defs.lean +++ b/Mathlib/Data/Array/Defs.lean @@ -4,8 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino, Floris van Doorn -/ -import Lean - /-! ## Definitions on Arrays diff --git a/Mathlib/Data/BinaryHeap.lean b/Mathlib/Data/BinaryHeap.lean index 4b86e27cc2484..3ee7e7e862d06 100644 --- a/Mathlib/Data/BinaryHeap.lean +++ b/Mathlib/Data/BinaryHeap.lean @@ -35,7 +35,7 @@ def heapifyDown (lt : α → α → Bool) (a : Array α) (i : Fin a.size) : rw [a.size_swap i j]; exact Nat.sub_lt_sub_left i.2 <| Nat.lt_of_le_of_ne j.2 h let ⟨a₂, h₂⟩ := heapifyDown lt a' j' ⟨a₂, h₂.trans (a.size_swap i j)⟩ -termination_by _ => a.size - i +termination_by a.size - i decreasing_by assumption @[simp] theorem size_heapifyDown (lt : α → α → Bool) (a : Array α) (i : Fin a.size) : @@ -61,7 +61,7 @@ Given an array which is a max-heap, push item `i` up to restore the max-heap pro def heapifyUp (lt : α → α → Bool) (a : Array α) (i : Fin a.size) : {a' : Array α // a'.size = a.size} := if i0 : i.1 = 0 then ⟨a, rfl⟩ else - have : (i.1 - 1) / 2 < i := Nat.lt_of_le_of_lt (Nat.div_le_self ..) $ + have : (i.1 - 1) / 2 < i := Nat.lt_of_le_of_lt (Nat.div_le_self ..) <| Nat.sub_lt (Nat.pos_of_ne_zero i0) Nat.zero_lt_one let j := ⟨(i.1 - 1) / 2, Nat.lt_trans this i.2⟩ if lt (a.get j) (a.get i) then @@ -69,7 +69,7 @@ if i0 : i.1 = 0 then ⟨a, rfl⟩ else let ⟨a₂, h₂⟩ := heapifyUp lt a' ⟨j.1, by rw [a.size_swap i j]; exact j.2⟩ ⟨a₂, h₂.trans (a.size_swap i j)⟩ else ⟨a, rfl⟩ -termination_by _ => i.1 +termination_by i.1 decreasing_by assumption @[simp] theorem size_heapifyUp (lt : α → α → Bool) (a : Array α) (i : Fin a.size) : @@ -172,6 +172,6 @@ def Array.toBinaryHeap (lt : α → α → Bool) (a : Array α) : BinaryHeap α have : a.popMax.size < a.size := by simp; exact Nat.sub_lt (BinaryHeap.size_pos_of_max e) Nat.zero_lt_one loop a.popMax (out.push x) + termination_by a.size + decreasing_by assumption loop (a.toBinaryHeap gt) #[] -termination_by _ => a.size -decreasing_by assumption diff --git a/Mathlib/Data/Bool/Basic.lean b/Mathlib/Data/Bool/Basic.lean index a9dfbd43d4cd1..af475ab553284 100644 --- a/Mathlib/Data/Bool/Basic.lean +++ b/Mathlib/Data/Bool/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2014 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad -/ -import Mathlib.Init.Data.Bool.Lemmas import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Init.Function @@ -33,8 +32,8 @@ theorem decide_False {h} : @decide False h = false := @[simp] theorem decide_coe (b : Bool) {h} : @decide b h = b := by cases b - · exact decide_eq_false $ λ j => by cases j - · exact decide_eq_true $ rfl + · exact decide_eq_false <| λ j => by cases j + · exact decide_eq_true <| rfl #align bool.to_bool_coe Bool.decide_coe theorem coe_decide (p : Prop) [d : Decidable p] : decide p ↔ p := diff --git a/Mathlib/Data/Bracket.lean b/Mathlib/Data/Bracket.lean index db726be4ed98b..4d3fee3f79801 100644 --- a/Mathlib/Data/Bracket.lean +++ b/Mathlib/Data/Bracket.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Lutz, Oliver Nash -/ import Mathlib.Mathport.Rename -import Mathlib.Tactic.Basic +import Mathlib.Tactic.TypeStar #align_import data.bracket from "leanprover-community/mathlib"@"c4658a649d216f57e99621708b09dcb3dcccbd23" diff --git a/Mathlib/Data/Bundle.lean b/Mathlib/Data/Bundle.lean index 7789779c19d5f..95df202944a7f 100644 --- a/Mathlib/Data/Bundle.lean +++ b/Mathlib/Data/Bundle.lean @@ -3,7 +3,7 @@ Copyright © 2021 Nicolò Cavalleri. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Nicolò Cavalleri -/ -import Mathlib.Algebra.Module.Basic +import Mathlib.Data.Set.Basic #align_import data.bundle from "leanprover-community/mathlib"@"e473c3198bb41f68560cab68a0529c854b618833" diff --git a/Mathlib/Data/ByteArray.lean b/Mathlib/Data/ByteArray.lean index 503831960c155..fcef05c3ca795 100644 --- a/Mathlib/Data/ByteArray.lean +++ b/Mathlib/Data/ByteArray.lean @@ -58,7 +58,7 @@ def forIn.loop [Monad m] (f : UInt8 → β → m (ForInStep β)) | ForInStep.done b => pure b | ForInStep.yield b => have := Nat.Up.next h; loop f arr off _end (i+1) b else pure b -termination_by _ => _end - i +termination_by _end - i instance : ForIn m ByteSlice UInt8 := ⟨fun ⟨arr, off, len⟩ b f ↦ forIn.loop f arr off (off + len) off b⟩ @@ -82,8 +82,8 @@ def String.toAsciiByteArray (s : String) : ByteArray := Nat.sub_lt_sub_left (Nat.lt_of_not_le <| mt decide_eq_true h) (Nat.lt_add_of_pos_right (String.csize_pos _)) loop (s.next p) (out.push c.toUInt8) + termination_by utf8ByteSize s - p.byteIdx loop 0 ByteArray.empty -termination_by _ => utf8ByteSize s - p.byteIdx /-- Convert a byte slice into a string. This does not handle non-ASCII characters correctly: every byte will become a unicode character with codepoint < 256. -/ diff --git a/Mathlib/Data/Complex/Abs.lean b/Mathlib/Data/Complex/Abs.lean index bf53caf8c9510..80b27a5f27f64 100644 --- a/Mathlib/Data/Complex/Abs.lean +++ b/Mathlib/Data/Complex/Abs.lean @@ -110,6 +110,9 @@ theorem sq_abs_sub_sq_im (z : ℂ) : Complex.abs z ^ 2 - z.im ^ 2 = z.re ^ 2 := rw [← sq_abs_sub_sq_re, sub_sub_cancel] #align complex.sq_abs_sub_sq_im Complex.sq_abs_sub_sq_im +lemma abs_add_mul_I (x y : ℝ) : abs (x + y * I) = (x ^ 2 + y ^ 2).sqrt := by + rw [← normSq_add_mul_I]; rfl + @[simp] theorem abs_I : Complex.abs I = 1 := by simp [Complex.abs] set_option linter.uppercaseLean3 false in @@ -251,7 +254,7 @@ theorem range_normSq : range normSq = Ici 0 := /-! ### Cauchy sequences -/ -local notation "abs'" => Abs.abs +local notation "abs'" => _root_.abs theorem isCauSeq_re (f : CauSeq ℂ Complex.abs) : IsCauSeq abs' fun n => (f n).re := fun ε ε0 => (f.cauchy ε0).imp fun i H j ij => @@ -259,8 +262,8 @@ theorem isCauSeq_re (f : CauSeq ℂ Complex.abs) : IsCauSeq abs' fun n => (f n). #align complex.is_cau_seq_re Complex.isCauSeq_re theorem isCauSeq_im (f : CauSeq ℂ Complex.abs) : IsCauSeq abs' fun n => (f n).im := fun ε ε0 => - (f.cauchy ε0).imp fun i H j ij => - lt_of_le_of_lt (by simpa using abs_im_le_abs (f j - f i)) (H _ ij) + (f.cauchy ε0).imp fun i H j ij ↦ by + simpa only [← ofReal_sub, abs_ofReal, sub_re] using (abs_im_le_abs _).trans_lt $ H _ ij #align complex.is_cau_seq_im Complex.isCauSeq_im /-- The real part of a complex Cauchy sequence, as a real Cauchy sequence. -/ diff --git a/Mathlib/Data/Complex/Basic.lean b/Mathlib/Data/Complex/Basic.lean index f93455b764cda..aa9c3b48b0656 100644 --- a/Mathlib/Data/Complex/Basic.lean +++ b/Mathlib/Data/Complex/Basic.lean @@ -5,6 +5,7 @@ Authors: Kevin Buzzard, Mario Carneiro -/ import Mathlib.Data.Real.Basic import Mathlib.Algebra.GroupWithZero.Bitwise +import Mathlib.Data.Set.Image #align_import data.complex.basic from "leanprover-community/mathlib"@"31c24aa72e7b3e5ed97a8412470e904f82b81004" @@ -275,14 +276,17 @@ theorem ofReal_mul (r s : ℝ) : ((r * s : ℝ) : ℂ) = r * s := ext_iff.2 <| by simp [ofReal'] #align complex.of_real_mul Complex.ofReal_mul -theorem ofReal_mul_re (r : ℝ) (z : ℂ) : (↑r * z).re = r * z.re := by simp [ofReal'] -#align complex.of_real_mul_re Complex.ofReal_mul_re +theorem re_ofReal_mul (r : ℝ) (z : ℂ) : (r * z).re = r * z.re := by simp [ofReal'] +#align complex.of_real_mul_re Complex.re_ofReal_mul -theorem ofReal_mul_im (r : ℝ) (z : ℂ) : (↑r * z).im = r * z.im := by simp [ofReal'] -#align complex.of_real_mul_im Complex.ofReal_mul_im +theorem im_ofReal_mul (r : ℝ) (z : ℂ) : (r * z).im = r * z.im := by simp [ofReal'] +#align complex.of_real_mul_im Complex.im_ofReal_mul + +lemma re_mul_ofReal (z : ℂ) (r : ℝ) : (z * r).re = z.re * r := by simp [ofReal'] +lemma im_mul_ofReal (z : ℂ) (r : ℝ) : (z * r).im = z.im * r := by simp [ofReal'] theorem ofReal_mul' (r : ℝ) (z : ℂ) : ↑r * z = ⟨r * z.re, r * z.im⟩ := - ext (ofReal_mul_re _ _) (ofReal_mul_im _ _) + ext (re_ofReal_mul _ _) (im_ofReal_mul _ _) #align complex.of_real_mul' Complex.ofReal_mul' /-! ### The imaginary unit, `I` -/ @@ -317,8 +321,7 @@ theorem I_mul (z : ℂ) : I * z = ⟨-z.im, z.re⟩ := set_option linter.uppercaseLean3 false in #align complex.I_mul Complex.I_mul -theorem I_ne_zero : (I : ℂ) ≠ 0 := - mt (congr_arg im) zero_ne_one.symm +@[simp] lemma I_ne_zero : (I : ℂ) ≠ 0 := mt (congr_arg im) zero_ne_one.symm set_option linter.uppercaseLean3 false in #align complex.I_ne_zero Complex.I_ne_zero @@ -731,6 +734,9 @@ theorem I_sq : I ^ 2 = -1 := by rw [sq, I_mul_I] set_option linter.uppercaseLean3 false in #align complex.I_sq Complex.I_sq +@[simp] +theorem I_pow_four : I ^ 4 = 1 := by rw [(by norm_num : 4 = 2 * 2), pow_mul, I_sq, neg_one_sq] + @[simp] theorem sub_re (z w : ℂ) : (z - w).re = z.re - w.re := rfl @@ -831,6 +837,9 @@ theorem rat_cast_re (q : ℚ) : (q : ℂ).re = (q : ℝ) := rfl theorem rat_cast_im (q : ℚ) : (q : ℂ).im = 0 := rfl #align complex.rat_cast_im Complex.rat_cast_im +@[norm_cast] lemma ofReal_nsmul (n : ℕ) (r : ℝ) : ↑(n • r) = n • (r : ℂ) := by simp +@[norm_cast] lemma ofReal_zsmul (n : ℤ) (r : ℝ) : ↑(n • r) = n • (r : ℂ) := by simp + /-! ### Field instance and lemmas -/ noncomputable instance instField : Field ℂ := diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index 22c0b65c9f658..10781afe3ab24 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -18,10 +18,6 @@ hyperbolic sine, hyperbolic cosine, and hyperbolic tangent functions. -/ - -@[inherit_doc] -local notation "abs'" => Abs.abs - open IsAbsoluteValue open Classical BigOperators ComplexConjugate @@ -331,7 +327,7 @@ open CauSeq namespace Complex theorem isCauSeq_abs_exp (z : ℂ) : - IsCauSeq Abs.abs fun n => ∑ m in range n, abs (z ^ m / m.factorial) := + IsCauSeq _root_.abs fun n => ∑ m in range n, abs (z ^ m / m.factorial) := let ⟨n, hn⟩ := exists_nat_gt (abs z) have hn0 : (0 : ℝ) < n := lt_of_le_of_lt (abs.nonneg _) hn series_ratio_test n (abs z / n) (div_nonneg (abs.nonneg _) (le_of_lt hn0)) @@ -553,7 +549,7 @@ theorem exp_conj : exp (conj x) = conj (exp x) := by dsimp [exp] rw [← lim_conj] refine' congr_arg CauSeq.lim (CauSeq.ext fun _ => _) - dsimp [exp', Function.comp_def, isCauSeq_conj, cauSeqConj] + dsimp [exp', Function.comp_def, cauSeqConj] rw [(starRingEnd _).map_sum] refine' sum_congr rfl fun n _ => _ rw [map_div₀, map_pow, ← ofReal_nat_cast, conj_ofReal] @@ -1453,7 +1449,7 @@ open IsAbsoluteValue Nat theorem sum_le_exp_of_nonneg {x : ℝ} (hx : 0 ≤ x) (n : ℕ) : ∑ i in range n, x ^ i / i ! ≤ exp x := calc - ∑ i in range n, x ^ i / i ! ≤ lim (⟨_, isCauSeq_re (exp' x)⟩ : CauSeq ℝ Abs.abs) := by + ∑ i in range n, x ^ i / i ! ≤ lim (⟨_, isCauSeq_re (exp' x)⟩ : CauSeq ℝ abs) := by refine' le_lim (CauSeq.le_of_exists ⟨n, fun j hj => _⟩) simp only [exp', const_apply, re_sum] norm_cast @@ -1592,7 +1588,7 @@ theorem sum_div_factorial_le {α : Type*} [LinearOrderedField α] (n j : ℕ) (h · rw [← Nat.cast_pow, ← Nat.cast_mul, Nat.cast_le, add_comm] exact Nat.factorial_mul_pow_le_factorial _ = (n.factorial : α)⁻¹ * ∑ m in range (j - n), (n.succ : α)⁻¹ ^ m := by - simp [mul_inv, mul_sum.symm, sum_mul.symm, mul_comm, inv_pow] + simp [mul_inv, ← mul_sum, ← sum_mul, mul_comm, inv_pow] _ = ((n.succ : α) - n.succ * (n.succ : α)⁻¹ ^ (j - n)) / (n.factorial * n) := by have h₁ : (n.succ : α) ≠ 1 := @Nat.cast_one α _ ▸ mt Nat.cast_inj.1 (mt Nat.succ.inj (pos_iff_ne_zero.1 hn)) @@ -1631,7 +1627,7 @@ theorem exp_bound {x : ℂ} (hx : abs x ≤ 1) {n : ℕ} (hn : 0 < n) : · rw [abv_pow abs] exact pow_le_one _ (abs.nonneg _) hx _ = abs x ^ n * ∑ m in (range j).filter fun k => n ≤ k, (1 / m.factorial : ℝ) := by - simp [abs_mul, abv_pow abs, abs_div, mul_sum.symm] + simp [abs_mul, abv_pow abs, abs_div, ← mul_sum] _ ≤ abs x ^ n * (n.succ * (n.factorial * n : ℝ)⁻¹) := by gcongr exact sum_div_factorial_le _ _ hn @@ -1719,7 +1715,7 @@ theorem exp_bound' {x : ℝ} (h1 : 0 ≤ x) (h2 : x ≤ 1) {n : ℕ} (hn : 0 < n #align real.exp_bound' Real.exp_bound' theorem abs_exp_sub_one_le {x : ℝ} (hx : |x| ≤ 1) : |exp x - 1| ≤ 2 * |x| := by - have : abs' x ≤ 1 := mod_cast hx + have : |x| ≤ 1 := mod_cast hx --Porting note: was --exact_mod_cast Complex.abs_exp_sub_one_le (x := x) this have := Complex.abs_exp_sub_one_le (x := x) (by simpa using this) @@ -1775,7 +1771,7 @@ theorem exp_approx_succ {n} {x a₁ b₁ : ℝ} (m : ℕ) (e₁ : n + 1 = m) (a |exp x - expNear n x a₁| ≤ |x| ^ n / n.factorial * b₁ := by refine' (abs_sub_le _ _ _).trans ((add_le_add_right h _).trans _) subst e₁; rw [expNear_succ, expNear_sub, abs_mul] - convert mul_le_mul_of_nonneg_left (a := abs' x ^ n / ↑(Nat.factorial n)) + convert mul_le_mul_of_nonneg_left (a := |x| ^ n / ↑(Nat.factorial n)) (le_sub_iff_add_le'.1 e) ?_ using 1 · simp [mul_add, pow_succ', div_eq_mul_inv, abs_mul, abs_inv, ← pow_abs, mul_inv, Nat.factorial] ac_rfl @@ -1972,10 +1968,10 @@ theorem add_one_le_exp (x : ℝ) : x + 1 ≤ Real.exp x := by #align real.add_one_le_exp_of_nonneg Real.add_one_le_exp lemma one_sub_lt_exp_neg {x : ℝ} (hx : x ≠ 0) : 1 - x < exp (-x) := - (sub_eq_neg_add _ _).trans_lt $ add_one_lt_exp $ neg_ne_zero.2 hx + (sub_eq_neg_add _ _).trans_lt <| add_one_lt_exp <| neg_ne_zero.2 hx lemma one_sub_le_exp_neg (x : ℝ) : 1 - x ≤ exp (-x) := - (sub_eq_neg_add _ _).trans_le $ add_one_le_exp _ + (sub_eq_neg_add _ _).trans_le <| add_one_le_exp _ #align real.one_sub_le_exp_minus_of_pos Real.one_sub_le_exp_neg #align real.one_sub_le_exp_minus_of_nonneg Real.one_sub_le_exp_neg diff --git a/Mathlib/Data/Complex/Module.lean b/Mathlib/Data/Complex/Module.lean index 7d850874f1faa..45637d58054dc 100644 --- a/Mathlib/Data/Complex/Module.lean +++ b/Mathlib/Data/Complex/Module.lean @@ -472,7 +472,7 @@ theorem realPart_I_smul (a : A) : ℜ (I • a) = -ℑ a := by ext -- Porting note: was -- simp [smul_comm I, smul_sub, sub_eq_add_neg, add_comm] - rw [realPart_apply_coe, AddSubgroupClass.coe_neg, imaginaryPart_apply_coe, neg_smul, neg_neg, + rw [realPart_apply_coe, NegMemClass.coe_neg, imaginaryPart_apply_coe, neg_smul, neg_neg, smul_comm I, star_smul, star_def, conj_I, smul_sub, neg_smul, sub_eq_add_neg] set_option linter.uppercaseLean3 false in #align real_part_I_smul realPart_I_smul diff --git a/Mathlib/Data/Complex/Order.lean b/Mathlib/Data/Complex/Order.lean index f5b8f6e368754..0eb62e43a646d 100644 --- a/Mathlib/Data/Complex/Order.lean +++ b/Mathlib/Data/Complex/Order.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.Data.Complex.Module import Mathlib.Data.Complex.Abs /-! diff --git a/Mathlib/Data/Countable/Defs.lean b/Mathlib/Data/Countable/Defs.lean index 7bec5e9fd701d..65c8e0cdb4503 100644 --- a/Mathlib/Data/Countable/Defs.lean +++ b/Mathlib/Data/Countable/Defs.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Data.Finite.Defs +import Mathlib.Data.Bool.Basic import Mathlib.Init.Data.Fin.Basic import Mathlib.Tactic.Common diff --git a/Mathlib/Data/DFinsupp/Basic.lean b/Mathlib/Data/DFinsupp/Basic.lean index b7092d2244060..92075d7773518 100644 --- a/Mathlib/Data/DFinsupp/Basic.lean +++ b/Mathlib/Data/DFinsupp/Basic.lean @@ -82,14 +82,14 @@ section Basic variable [∀ i, Zero (β i)] [∀ i, Zero (β₁ i)] [∀ i, Zero (β₂ i)] -instance funLike : FunLike (Π₀ i, β i) ι β := +instance instDFunLike : DFunLike (Π₀ i, β i) ι β := ⟨fun f => f.toFun, fun ⟨f₁, s₁⟩ ⟨f₂, s₁⟩ ↦ fun (h : f₁ = f₂) ↦ by subst h congr apply Subsingleton.elim ⟩ -#align dfinsupp.fun_like DFinsupp.funLike +#align dfinsupp.fun_like DFinsupp.instDFunLike -/-- Helper instance for when there are too many metavariables to apply `FunLike.coeFunForall` +/-- Helper instance for when there are too many metavariables to apply `DFunLike.coeFunForall` directly. -/ instance : CoeFun (Π₀ i, β i) fun _ => ∀ i, β i := inferInstance @@ -101,19 +101,19 @@ theorem toFun_eq_coe (f : Π₀ i, β i) : f.toFun = f := @[ext] theorem ext {f g : Π₀ i, β i} (h : ∀ i, f i = g i) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align dfinsupp.ext DFinsupp.ext -@[deprecated FunLike.ext_iff] +@[deprecated DFunLike.ext_iff] theorem ext_iff {f g : Π₀ i, β i} : f = g ↔ ∀ i, f i = g i := - FunLike.ext_iff + DFunLike.ext_iff #align dfinsupp.ext_iff DFinsupp.ext_iff -lemma ne_iff {f g : Π₀ i, β i} : f ≠ g ↔ ∃ i, f i ≠ g i := FunLike.ne_iff +lemma ne_iff {f g : Π₀ i, β i} : f ≠ g ↔ ∃ i, f i ≠ g i := DFunLike.ne_iff -@[deprecated FunLike.coe_injective] +@[deprecated DFunLike.coe_injective] theorem coeFn_injective : @Function.Injective (Π₀ i, β i) (∀ i, β i) (⇑) := - FunLike.coe_injective + DFunLike.coe_injective #align dfinsupp.coe_fn_injective DFinsupp.coeFn_injective instance : Zero (Π₀ i, β i) := @@ -243,15 +243,15 @@ theorem coe_add [∀ i, AddZeroClass (β i)] (g₁ g₂ : Π₀ i, β i) : ⇑(g #align dfinsupp.coe_add DFinsupp.coe_add instance addZeroClass [∀ i, AddZeroClass (β i)] : AddZeroClass (Π₀ i, β i) := - FunLike.coe_injective.addZeroClass _ coe_zero coe_add + DFunLike.coe_injective.addZeroClass _ coe_zero coe_add instance instIsLeftCancelAdd [∀ i, AddZeroClass (β i)] [∀ i, IsLeftCancelAdd (β i)] : IsLeftCancelAdd (Π₀ i, β i) where - add_left_cancel _ _ _ h := ext fun x => add_left_cancel <| FunLike.congr_fun h x + add_left_cancel _ _ _ h := ext fun x => add_left_cancel <| DFunLike.congr_fun h x instance instIsRightCancelAdd [∀ i, AddZeroClass (β i)] [∀ i, IsRightCancelAdd (β i)] : IsRightCancelAdd (Π₀ i, β i) where - add_right_cancel _ _ _ h := ext fun x => add_right_cancel <| FunLike.congr_fun h x + add_right_cancel _ _ _ h := ext fun x => add_right_cancel <| DFunLike.congr_fun h x instance instIsCancelAdd [∀ i, AddZeroClass (β i)] [∀ i, IsCancelAdd (β i)] : IsCancelAdd (Π₀ i, β i) where @@ -272,7 +272,7 @@ theorem coe_nsmul [∀ i, AddMonoid (β i)] (b : ℕ) (v : Π₀ i, β i) : ⇑( #align dfinsupp.coe_nsmul DFinsupp.coe_nsmul instance [∀ i, AddMonoid (β i)] : AddMonoid (Π₀ i, β i) := - FunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => coe_nsmul _ _ + DFunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => coe_nsmul _ _ /-- Coercion from a `DFinsupp` to a pi type is an `AddMonoidHom`. -/ def coeFnAddMonoidHom [∀ i, AddZeroClass (β i)] : (Π₀ i, β i) →+ ∀ i, β i @@ -289,7 +289,7 @@ def evalAddMonoidHom [∀ i, AddZeroClass (β i)] (i : ι) : (Π₀ i, β i) → #align dfinsupp.eval_add_monoid_hom DFinsupp.evalAddMonoidHom instance addCommMonoid [∀ i, AddCommMonoid (β i)] : AddCommMonoid (Π₀ i, β i) := - FunLike.coe_injective.addCommMonoid _ coe_zero coe_add fun _ _ => coe_nsmul _ _ + DFunLike.coe_injective.addCommMonoid _ coe_zero coe_add fun _ _ => coe_nsmul _ _ @[simp, norm_cast] theorem coe_finset_sum {α} [∀ i, AddCommMonoid (β i)] (s : Finset α) (g : α → Π₀ i, β i) : @@ -341,11 +341,11 @@ theorem coe_zsmul [∀ i, AddGroup (β i)] (b : ℤ) (v : Π₀ i, β i) : ⇑(b #align dfinsupp.coe_zsmul DFinsupp.coe_zsmul instance [∀ i, AddGroup (β i)] : AddGroup (Π₀ i, β i) := - FunLike.coe_injective.addGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => coe_nsmul _ _) + DFunLike.coe_injective.addGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => coe_nsmul _ _) fun _ _ => coe_zsmul _ _ instance addCommGroup [∀ i, AddCommGroup (β i)] : AddCommGroup (Π₀ i, β i) := - FunLike.coe_injective.addCommGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => coe_nsmul _ _) + DFunLike.coe_injective.addCommGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => coe_nsmul _ _) fun _ _ => coe_zsmul _ _ /-- Dependent functions with finite support inherit a semiring action from an action on each @@ -383,7 +383,7 @@ instance isCentralScalar [Monoid γ] [∀ i, AddMonoid (β i)] [∀ i, DistribMu structure on each coordinate. -/ instance distribMulAction [Monoid γ] [∀ i, AddMonoid (β i)] [∀ i, DistribMulAction γ (β i)] : DistribMulAction γ (Π₀ i, β i) := - Function.Injective.distribMulAction coeFnAddMonoidHom FunLike.coe_injective coe_smul + Function.Injective.distribMulAction coeFnAddMonoidHom DFunLike.coe_injective coe_smul /-- Dependent functions with finite support inherit a module structure from such a structure on each coordinate. -/ @@ -511,14 +511,14 @@ theorem subtypeDomain_apply [∀ i, Zero (β i)] {p : ι → Prop} [DecidablePre @[simp] theorem subtypeDomain_add [∀ i, AddZeroClass (β i)] {p : ι → Prop} [DecidablePred p] (v v' : Π₀ i, β i) : (v + v').subtypeDomain p = v.subtypeDomain p + v'.subtypeDomain p := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align dfinsupp.subtype_domain_add DFinsupp.subtypeDomain_add @[simp] theorem subtypeDomain_smul [Monoid γ] [∀ i, AddMonoid (β i)] [∀ i, DistribMulAction γ (β i)] {p : ι → Prop} [DecidablePred p] (r : γ) (f : Π₀ i, β i) : (r • f).subtypeDomain p = r • f.subtypeDomain p := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align dfinsupp.subtype_domain_smul DFinsupp.subtypeDomain_smul variable (γ β) @@ -550,13 +550,13 @@ variable {γ β} @[simp] theorem subtypeDomain_neg [∀ i, AddGroup (β i)] {p : ι → Prop} [DecidablePred p] {v : Π₀ i, β i} : (-v).subtypeDomain p = -v.subtypeDomain p := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align dfinsupp.subtype_domain_neg DFinsupp.subtypeDomain_neg @[simp] theorem subtypeDomain_sub [∀ i, AddGroup (β i)] {p : ι → Prop} [DecidablePred p] {v v' : Π₀ i, β i} : (v - v').subtypeDomain p = v.subtypeDomain p - v'.subtypeDomain p := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align dfinsupp.subtype_domain_sub DFinsupp.subtypeDomain_sub end FilterAndSubtypeDomain @@ -606,11 +606,11 @@ theorem mk_injective (s : Finset ι) : Function.Injective (@mk ι β _ _ s) := b #align dfinsupp.mk_injective DFinsupp.mk_injective instance unique [∀ i, Subsingleton (β i)] : Unique (Π₀ i, β i) := - FunLike.coe_injective.unique + DFunLike.coe_injective.unique #align dfinsupp.unique DFinsupp.unique instance uniqueOfIsEmpty [IsEmpty ι] : Unique (Π₀ i, β i) := - FunLike.coe_injective.unique + DFunLike.coe_injective.unique #align dfinsupp.unique_of_is_empty DFinsupp.uniqueOfIsEmpty /-- Given `Fintype ι`, `equivFunOnFintype` is the `Equiv` between `Π₀ i, β i` and `Π i, β i`. @@ -620,7 +620,7 @@ def equivFunOnFintype [Fintype ι] : (Π₀ i, β i) ≃ ∀ i, β i where toFun := (⇑) invFun f := ⟨f, Trunc.mk ⟨Finset.univ.1, fun _ => Or.inl <| Finset.mem_univ_val _⟩⟩ - left_inv _ := FunLike.coe_injective rfl + left_inv _ := DFunLike.coe_injective rfl right_inv _ := rfl #align dfinsupp.equiv_fun_on_fintype DFinsupp.equivFunOnFintype #align dfinsupp.equiv_fun_on_fintype_apply DFinsupp.equivFunOnFintype_apply @@ -650,7 +650,7 @@ theorem single_apply {i i' b} : @[simp] theorem single_zero (i) : (single i 0 : Π₀ i, β i) = 0 := - FunLike.coe_injective <| Pi.single_zero _ + DFunLike.coe_injective <| Pi.single_zero _ #align dfinsupp.single_zero DFinsupp.single_zero -- @[simp] -- Porting note: simp can prove this @@ -663,7 +663,7 @@ theorem single_eq_of_ne {i i' b} (h : i ≠ i') : (single i b : Π₀ i, β i) i #align dfinsupp.single_eq_of_ne DFinsupp.single_eq_of_ne theorem single_injective {i} : Function.Injective (single i : β i → Π₀ i, β i) := fun _ _ H => - Pi.single_injective β i <| FunLike.coe_injective.eq_iff.mpr H + Pi.single_injective β i <| DFunLike.coe_injective.eq_iff.mpr H #align dfinsupp.single_injective DFinsupp.single_injective /-- Like `Finsupp.single_eq_single_iff`, but with a `HEq` due to dependent types -/ @@ -1040,7 +1040,7 @@ See note [partially-applied ext lemmas]. -/ @[ext] theorem addHom_ext' {γ : Type w} [AddZeroClass γ] ⦃f g : (Π₀ i, β i) →+ γ⦄ (H : ∀ x, f.comp (singleAddHom β x) = g.comp (singleAddHom β x)) : f = g := - addHom_ext fun x => FunLike.congr_fun (H x) + addHom_ext fun x => DFunLike.congr_fun (H x) #align dfinsupp.add_hom_ext' DFinsupp.addHom_ext' end AddMonoid @@ -1490,7 +1490,7 @@ def sigmaCurry [∀ i j, Zero (δ i j)] (f : Π₀ (i : Σ _, _), δ i.1 i.2) : toFun := fun i ↦ { toFun := fun j ↦ f ⟨i, j⟩, support' := f.support'.map (fun ⟨m, hm⟩ ↦ - ⟨m.filterMap (fun ⟨i', j'⟩ ↦ if h : i' = i then some $ h.rec j' else none), + ⟨m.filterMap (fun ⟨i', j'⟩ ↦ if h : i' = i then some <| h.rec j' else none), fun j ↦ (hm ⟨i, j⟩).imp_left (fun h ↦ (m.mem_filterMap _).mpr ⟨⟨i, j⟩, h, dif_pos rfl⟩)⟩) } support' := f.support'.map (fun ⟨m, hm⟩ ↦ ⟨m.map Sigma.fst, fun i ↦ Decidable.or_iff_not_imp_left.mpr (fun h ↦ DFinsupp.ext @@ -1584,7 +1584,7 @@ theorem sigmaUncurry_add [∀ i j, AddZeroClass (δ i j)] [∀ i, DecidableEq (α i)] [∀ i j (x : δ i j), Decidable (x ≠ 0)] (f g : Π₀ (i) (j), δ i j) : sigmaUncurry (f + g) = sigmaUncurry f + sigmaUncurry g := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align dfinsupp.sigma_uncurry_add DFinsupp.sigmaUncurry_add /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @@ -1593,7 +1593,7 @@ theorem sigmaUncurry_smul [Monoid γ] [∀ i j, AddMonoid (δ i j)] [∀ i, DecidableEq (α i)] [∀ i j (x : δ i j), Decidable (x ≠ 0)] [∀ i j, DistribMulAction γ (δ i j)] (r : γ) (f : Π₀ (i) (j), δ i j) : sigmaUncurry (r • f) = r • sigmaUncurry f := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align dfinsupp.sigma_uncurry_smul DFinsupp.sigmaUncurry_smul @[simp] @@ -2143,7 +2143,7 @@ theorem prod_sum_index {ι₁ : Type u₁} [DecidableEq ι₁] {β₁ : ι₁ @[simp] theorem sum_single [∀ i, AddCommMonoid (β i)] [∀ (i) (x : β i), Decidable (x ≠ 0)] {f : Π₀ i, β i} : f.sum single = f := by - have := FunLike.congr_fun (liftAddHom_singleAddHom (β := β)) f + have := DFunLike.congr_fun (liftAddHom_singleAddHom (β := β)) f rw [liftAddHom_apply, sumAddHom_apply] at this exact this #align dfinsupp.sum_single DFinsupp.sum_single @@ -2315,7 +2315,7 @@ open DFinsupp theorem map_dfinsupp_sumAddHom [AddCommMonoid R] [AddCommMonoid S] [∀ i, AddZeroClass (β i)] (h : R →+ S) (f : Π₀ i, β i) (g : ∀ i, β i →+ R) : h (sumAddHom g f) = sumAddHom (fun i => h.comp (g i)) f := - FunLike.congr_fun (comp_liftAddHom h g) f + DFunLike.congr_fun (comp_liftAddHom h g) f #align add_monoid_hom.map_dfinsupp_sum_add_hom AddMonoidHom.map_dfinsupp_sumAddHom theorem dfinsupp_sumAddHom_apply [AddZeroClass R] [AddCommMonoid S] [∀ i, AddZeroClass (β i)] @@ -2343,7 +2343,7 @@ open DFinsupp theorem map_dfinsupp_sumAddHom [NonAssocSemiring R] [NonAssocSemiring S] [∀ i, AddZeroClass (β i)] (h : R →+* S) (f : Π₀ i, β i) (g : ∀ i, β i →+ R) : h (sumAddHom g f) = sumAddHom (fun i => h.toAddMonoidHom.comp (g i)) f := - FunLike.congr_fun (comp_liftAddHom h.toAddMonoidHom g) f + DFunLike.congr_fun (comp_liftAddHom h.toAddMonoidHom g) f #align ring_hom.map_dfinsupp_sum_add_hom RingHom.map_dfinsupp_sumAddHom end RingHom @@ -2358,7 +2358,7 @@ open DFinsupp theorem map_dfinsupp_sumAddHom [AddCommMonoid R] [AddCommMonoid S] [∀ i, AddZeroClass (β i)] (h : R ≃+ S) (f : Π₀ i, β i) (g : ∀ i, β i →+ R) : h (sumAddHom g f) = sumAddHom (fun i => h.toAddMonoidHom.comp (g i)) f := - FunLike.congr_fun (comp_liftAddHom h.toAddMonoidHom g) f + DFunLike.congr_fun (comp_liftAddHom h.toAddMonoidHom g) f #align add_equiv.map_dfinsupp_sum_add_hom AddEquiv.map_dfinsupp_sumAddHom end AddEquiv diff --git a/Mathlib/Data/DFinsupp/Lex.lean b/Mathlib/Data/DFinsupp/Lex.lean index e1c9875ce1abc..279d15d99eac6 100644 --- a/Mathlib/Data/DFinsupp/Lex.lean +++ b/Mathlib/Data/DFinsupp/Lex.lean @@ -78,7 +78,7 @@ instance Lex.partialOrder [∀ i, PartialOrder (α i)] : PartialOrder (Lex (Π lt := (· < ·) le x y := ⇑(ofLex x) = ⇑(ofLex y) ∨ x < y __ := PartialOrder.lift (fun x : Lex (Π₀ i, α i) ↦ toLex (⇑(ofLex x))) - (FunLike.coe_injective (F := DFinsupp α)) + (DFunLike.coe_injective (F := DFinsupp α)) #align dfinsupp.lex.partial_order DFinsupp.Lex.partialOrder section LinearOrder diff --git a/Mathlib/Data/DFinsupp/Order.lean b/Mathlib/Data/DFinsupp/Order.lean index f0c4c51158c53..389015cbb6f63 100644 --- a/Mathlib/Data/DFinsupp/Order.lean +++ b/Mathlib/Data/DFinsupp/Order.lean @@ -47,13 +47,13 @@ lemma le_def : f ≤ g ↔ ∀ i, f i ≤ g i := Iff.rfl /-- The order on `DFinsupp`s over a partial order embeds into the order on functions -/ def orderEmbeddingToFun : (Π₀ i, α i) ↪o ∀ i, α i where - toFun := FunLike.coe - inj' := FunLike.coe_injective + toFun := DFunLike.coe + inj' := DFunLike.coe_injective map_rel_iff' := by rfl #align dfinsupp.order_embedding_to_fun DFinsupp.orderEmbeddingToFun @[simp, norm_cast] -lemma coe_orderEmbeddingToFun : ⇑(orderEmbeddingToFun (α := α)) = FunLike.coe := rfl +lemma coe_orderEmbeddingToFun : ⇑(orderEmbeddingToFun (α := α)) = DFunLike.coe := rfl -- Porting note: we added implicit arguments here in #3414. theorem orderEmbeddingToFun_apply {f : Π₀ i, α i} {i : ι} : @@ -124,11 +124,11 @@ instance lattice : Lattice (Π₀ i, α i) := variable [DecidableEq ι] [∀ (i) (x : α i), Decidable (x ≠ 0)] theorem support_inf_union_support_sup : (f ⊓ g).support ∪ (f ⊔ g).support = f.support ∪ g.support := - coe_injective $ compl_injective $ by ext; simp [inf_eq_and_sup_eq_iff] + coe_injective <| compl_injective <| by ext; simp [inf_eq_and_sup_eq_iff] #align dfinsupp.support_inf_union_support_sup DFinsupp.support_inf_union_support_sup theorem support_sup_union_support_inf : (f ⊔ g).support ∪ (f ⊓ g).support = f.support ∪ g.support := - (union_comm _ _).trans $ support_inf_union_support_sup _ _ + (union_comm _ _).trans <| support_inf_union_support_sup _ _ #align dfinsupp.support_sup_union_support_inf DFinsupp.support_sup_union_support_inf end Lattice @@ -205,7 +205,7 @@ protected theorem bot_eq_zero : (⊥ : Π₀ i, α i) = 0 := @[simp] theorem add_eq_zero_iff (f g : Π₀ i, α i) : f + g = 0 ↔ f = 0 ∧ g = 0 := by - simp [FunLike.ext_iff, forall_and] + simp [DFunLike.ext_iff, forall_and] #align dfinsupp.add_eq_zero_iff DFinsupp.add_eq_zero_iff section LE diff --git a/Mathlib/Data/DList/Basic.lean b/Mathlib/Data/DList/Basic.lean index 0ab79b30fb993..b300ca5bfd300 100644 --- a/Mathlib/Data/DList/Basic.lean +++ b/Mathlib/Data/DList/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ import Mathlib.Data.DList.Defs -import Mathlib.Tactic.Basic +import Mathlib.Tactic.TypeStar #align_import data.dlist.basic from "leanprover-community/mathlib"@"d6aae1bcbd04b8de2022b9b83a5b5b10e10c777d" diff --git a/Mathlib/Data/DList/Instances.lean b/Mathlib/Data/DList/Instances.lean index 86b72fb02ad55..7a20943829ec6 100644 --- a/Mathlib/Data/DList/Instances.lean +++ b/Mathlib/Data/DList/Instances.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ -import Mathlib.Data.DList.Basic +import Mathlib.Data.DList.Defs import Mathlib.Control.Traversable.Equiv import Mathlib.Control.Traversable.Instances diff --git a/Mathlib/Data/Real/ENNReal.lean b/Mathlib/Data/ENNReal/Basic.lean similarity index 99% rename from Mathlib/Data/Real/ENNReal.lean rename to Mathlib/Data/ENNReal/Basic.lean index c716ea8f42e42..10bf4079ad506 100644 --- a/Mathlib/Data/Real/ENNReal.lean +++ b/Mathlib/Data/ENNReal/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Real.NNReal import Mathlib.Algebra.Order.Sub.WithTop import Mathlib.Data.Set.Intervals.WithBotTop import Mathlib.Tactic.GCongr.Core +import Mathlib.Algebra.GroupPower.Order #align_import data.real.ennreal from "leanprover-community/mathlib"@"c14c8fcde993801fca8946b0d80131a1a81d1520" @@ -260,11 +261,13 @@ theorem forall_ne_top {p : ℝ≥0∞ → Prop} : (∀ a, a ≠ ∞ → p a) ↔ Option.ball_ne_none #align ennreal.forall_ne_top ENNReal.forall_ne_top +@[deprecated] theorem exists_ne_top' {p : ℝ≥0∞ → Prop} : (∃ (a : ℝ≥0∞) (_ : a ≠ ∞), p a) ↔ ∃ r : ℝ≥0, p r := Option.bex_ne_none #align ennreal.exists_ne_top ENNReal.exists_ne_top' -theorem exists_ne_top {p : ℝ≥0∞ → Prop} : (∃ a : ℝ≥0∞, a ≠ ∞ ∧ p a) ↔ ∃ r : ℝ≥0, p r := by +set_option linter.deprecated false in +theorem exists_ne_top {p : ℝ≥0∞ → Prop} : (∃ a ≠ ∞, p a) ↔ ∃ r : ℝ≥0, p r := by simp only [exists_ne_top', ← exists_prop] theorem toNNReal_eq_zero_iff (x : ℝ≥0∞) : x.toNNReal = 0 ↔ x = 0 ∨ x = ∞ := @@ -385,7 +388,7 @@ theorem coe_strictMono : StrictMono ofNNReal := fun _ _ => coe_lt_coe.2 theorem coe_ne_zero : (r : ℝ≥0∞) ≠ 0 ↔ r ≠ 0 := not_congr coe_eq_coe #align ennreal.coe_ne_zero ENNReal.coe_ne_zero -@[simp, norm_cast] theorem coe_add : ↑(r + p) = (r : ℝ≥0∞) + p := WithTop.coe_add +@[simp, norm_cast] theorem coe_add : ↑(r + p) = (r : ℝ≥0∞) + p := WithTop.coe_add _ _ #align ennreal.coe_add ENNReal.coe_add @[simp, norm_cast] diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index bcb95ce0da54e..241f10bf5ec97 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -88,8 +88,10 @@ theorem coe_mul (m n : ℕ) : ↑(m * n) = (m * n : ℕ∞) := WithTop.coe_mul #align enat.coe_mul ENat.coe_mul -instance canLift : CanLift ℕ∞ ℕ (↑) fun n => n ≠ ⊤ := - WithTop.canLift +@[simp] theorem mul_top (hm : m ≠ 0) : m * ⊤ = ⊤ := WithTop.mul_top hm +@[simp] theorem top_mul (hm : m ≠ 0) : ⊤ * m = ⊤ := WithTop.top_mul hm + +instance canLift : CanLift ℕ∞ ℕ (↑) (· ≠ ⊤) := WithTop.canLift #align enat.can_lift ENat.canLift instance : WellFoundedRelation ℕ∞ where @@ -97,8 +99,7 @@ instance : WellFoundedRelation ℕ∞ where wf := IsWellFounded.wf /-- Conversion of `ℕ∞` to `ℕ` sending `∞` to `0`. -/ -def toNat : MonoidWithZeroHom ℕ∞ ℕ - where +def toNat : MonoidWithZeroHom ℕ∞ ℕ where toFun := WithTop.untop' 0 map_one' := rfl map_zero' := rfl @@ -118,9 +119,9 @@ theorem toNat_top : toNat ⊤ = 0 := --Porting note: new definition copied from `WithTop` /-- Recursor for `ENat` using the preferred forms `⊤` and `↑a`. -/ @[elab_as_elim] -def recTopCoe {C : ℕ∞ → Sort*} (h₁ : C ⊤) (h₂ : ∀ a : ℕ, C a) : ∀ n : ℕ∞, C n - | none => h₁ - | Option.some a => h₂ a +def recTopCoe {C : ℕ∞ → Sort*} (top : C ⊤) (coe : ∀ a : ℕ, C a) : ∀ n : ℕ∞, C n + | none => top + | Option.some a => coe a --Porting note: new theorem copied from `WithTop` @[simp] diff --git a/Mathlib/Data/FP/Basic.lean b/Mathlib/Data/FP/Basic.lean index 8bec271be9db9..54eaa8c54201a 100644 --- a/Mathlib/Data/FP/Basic.lean +++ b/Mathlib/Data/FP/Basic.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.Semiquot -import Mathlib.Data.Rat.Floor +import Mathlib.Data.Nat.Size +import Mathlib.Tactic.Ring.RingNF #align_import data.fp.basic from "leanprover-community/mathlib"@"7b78d1776212a91ecc94cf601f83bdcc46b04213" @@ -97,7 +98,7 @@ theorem Float.Zero.valid : ValidFinite emin 0 := ring_nf rw [mul_comm] assumption - le_trans C.precMax (Nat.le_mul_of_pos_left (by decide)), + le_trans C.precMax (Nat.le_mul_of_pos_left _ two_pos), by (rw [max_eq_right]; simp [sub_eq_add_neg])⟩ #align fp.float.zero.valid FP.Float.Zero.valid diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index f69eb91d41f8c..ebc1b29f541ef 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -55,7 +55,7 @@ This file expands on the development in the core library. provided that `n = m`, see also `Equiv.finCongr`; * `Fin.castAddEmb m` : `Fin.castAdd` as an `OrderEmbedding`, embed `Fin n` into `Fin (n+m)`; * `Fin.castSuccEmb` : `Fin.castSucc` as an `OrderEmbedding`, embed `Fin n` into `Fin (n+1)`; -* `Fin.succAboveEmb p` : `Fin.auccAbove` as an `OrderEmbedding`, embed `Fin n` into `Fin (n + 1)` +* `Fin.succAboveEmb p` : `Fin.succAbove` as an `OrderEmbedding`, embed `Fin n` into `Fin (n + 1)` with a hole around `p`; * `Fin.addNatEmb m i` : `Fin.addNat` as an `OrderEmbedding`, add `m` on `i` on the right, generalizes `Fin.succ`; @@ -409,6 +409,11 @@ theorem cast_rev (i : Fin n) (h : n = m) : cast h i.rev = (i.cast h).rev := by subst h; simp +theorem rev_eq_iff {i j : Fin n} : rev i = j ↔ i = rev j := by + rw [← rev_inj, rev_rev] + +theorem rev_ne_iff {i j : Fin n} : rev i ≠ j ↔ i ≠ rev j := rev_eq_iff.not + #align fin.last Fin.last #align fin.coe_last Fin.val_last @@ -428,6 +433,10 @@ instance : Lattice (Fin (n + 1)) := #align fin.last_pos Fin.last_pos #align fin.eq_last_of_not_lt Fin.eq_last_of_not_lt +theorem last_pos' [NeZero n] : 0 < last n := NeZero.pos n + +theorem one_lt_last [NeZero n] : 1 < last (n + 1) := (lt_add_iff_pos_left 1).mpr (NeZero.pos n) + theorem top_eq_last (n : ℕ) : ⊤ = Fin.last n := rfl #align fin.top_eq_last Fin.top_eq_last @@ -738,6 +747,9 @@ theorem succ_zero_eq_one' [NeZero n] : Fin.succ (0 : Fin n) = 1 := by · rfl #align fin.succ_zero_eq_one Fin.succ_zero_eq_one' +theorem one_pos' [NeZero n] : (0 : Fin (n + 1)) < 1 := succ_zero_eq_one' (n := n) ▸ succ_pos _ +theorem zero_ne_one' [NeZero n] : (0 : Fin (n + 1)) ≠ 1 := Fin.ne_of_lt one_pos' + #align fin.succ_zero_eq_one' Fin.succ_zero_eq_one /-- @@ -769,7 +781,7 @@ This one instead uses a `NeZero n` typeclass hypothesis. -/ @[simp] theorem le_zero_iff' {n : ℕ} [NeZero n] {k : Fin n} : k ≤ 0 ↔ k = 0 := - ⟨fun h => Fin.eq_of_veq $ by rw [Nat.eq_zero_of_le_zero h]; rfl, by rintro rfl; exact le_refl _⟩ + ⟨fun h => Fin.eq_of_veq <| by rw [Nat.eq_zero_of_le_zero h]; rfl, by rintro rfl; exact le_refl _⟩ #align fin.le_zero_iff Fin.le_zero_iff' #align fin.succ_succ_ne_one Fin.succ_succ_ne_one @@ -934,6 +946,22 @@ def castSuccEmb : Fin n ↪o Fin (n + 1) := #align fin.cast_lt_cast_succ Fin.castLT_castSucc #align fin.cast_succ_lt_cast_succ_iff Fin.castSucc_lt_castSucc_iff +@[simp] +theorem castSucc_le_castSucc_iff : castSucc a ≤ castSucc b ↔ a ≤ b := Iff.rfl +@[simp] +theorem succ_le_castSucc_iff : succ a ≤ castSucc b ↔ a < b := + by rw [le_castSucc_iff, succ_lt_succ_iff] +@[simp] +theorem castSucc_lt_succ_iff : castSucc a < succ b ↔ a ≤ b := + by rw [castSucc_lt_iff_succ_le, succ_le_succ_iff] + +theorem le_of_castSucc_lt_of_succ_lt {a b : Fin (n + 1)} {i : Fin n} + (hl : castSucc i < a) (hu : b < succ i) : b < a := (castSucc_lt_iff_succ_le.mp hl).trans_lt' hu + +theorem castSucc_lt_or_lt_succ (p : Fin (n + 1)) (i : Fin n) : castSucc i < p ∨ p < i.succ := + (lt_or_le (castSucc i) p).imp id (fun h => le_castSucc_iff.mp h) +#align fin.succ_above_lt_gt Fin.castSucc_lt_or_lt_succ + theorem castSucc_injective (n : ℕ) : Injective (@Fin.castSucc n) := (castSuccEmb : Fin n ↪o _).injective #align fin.cast_succ_injective Fin.castSucc_injective @@ -976,6 +1004,9 @@ theorem castSucc_ne_zero_iff' [NeZero n] (a : Fin n) : castSucc a ≠ 0 ↔ a not_iff_not.mpr <| castSucc_eq_zero_iff' a #align fin.cast_succ_ne_zero_iff Fin.castSucc_ne_zero_iff +theorem succ_ne_last_iff (a : Fin (n + 1)) : succ a ≠ last (n + 1) ↔ a ≠ last n := + not_iff_not.mpr <| succ_eq_last_succ a + #align fin.cast_succ_fin_succ Fin.castSucc_fin_succ @[norm_cast, simp] @@ -1089,8 +1120,159 @@ section Pred #align fin.nat_add_sub_nat_cast Fin.natAdd_subNat_castₓ +theorem pred_one' [NeZero n] (h := (zero_ne_one' (n := n)).symm): + Fin.pred (1 : Fin (n + 1)) h = 0 := + by simp_rw [Fin.ext_iff, coe_pred, val_one', val_zero', + tsub_eq_zero_iff_le, Nat.mod_le] + +theorem pred_last (h := last_pos'.ne') : + pred (last (n + 1)) h = last n := by simp_rw [← succ_last, pred_succ] + +theorem pred_lt_iff {i : Fin (n + 1)} (hi : i ≠ 0) : pred i hi < j ↔ i < succ j := by + rw [← succ_lt_succ_iff, succ_pred] +theorem lt_pred_iff {i : Fin (n + 1)} (hi : i ≠ 0) : j < pred i hi ↔ succ j < i := by + rw [← succ_lt_succ_iff, succ_pred] +theorem pred_le_iff {i : Fin (n + 1)} (hi : i ≠ 0) : pred i hi ≤ j ↔ i ≤ succ j := by + rw [← succ_le_succ_iff, succ_pred] +theorem le_pred_iff {i : Fin (n + 1)} (hi : i ≠ 0) : j ≤ pred i hi ↔ succ j ≤ i := by + rw [← succ_le_succ_iff, succ_pred] + +theorem castSucc_pred_eq_pred_castSucc {a : Fin (n + 1)} (ha : a ≠ 0) + (ha' := a.castSucc_ne_zero_iff.mpr ha) : + castSucc (a.pred ha) = (castSucc a).pred ha' := rfl +#align fin.cast_succ_pred_eq_pred_cast_succ Fin.castSucc_pred_eq_pred_castSucc + +theorem le_pred_castSucc_iff {a b : Fin (n + 1)} (ha : castSucc a ≠ 0) : + b ≤ (castSucc a).pred ha ↔ b < a := by + rw [le_pred_iff, succ_le_castSucc_iff] + +theorem pred_castSucc_lt {a : Fin (n + 1)} (ha : castSucc a ≠ 0) : + (castSucc a).pred ha < a := by + rw [pred_lt_iff] + exact castSucc_lt_succ _ + +theorem le_castSucc_pred_iff {a b : Fin (n + 1)} (ha : a ≠ 0) : + b ≤ castSucc (a.pred ha) ↔ b < a := by + rw [castSucc_pred_eq_pred_castSucc, le_pred_castSucc_iff] + +theorem castSucc_pred_lt {a : Fin (n + 1)} (ha : a ≠ 0) : + castSucc (a.pred ha) < a := by + rw [lt_iff_not_le, le_castSucc_pred_iff] + exact lt_irrefl _ + end Pred +section CastPred + +/-- `castPred i` sends `i : Fin (n + 1)` to `Fin n` as long as i ≠ last n. -/ +@[inline] def castPred (i : Fin (n + 1)) (h : i ≠ last n) : Fin n := castLT i (val_lt_last h) +#align fin.cast_pred Fin.castPred + +@[simp] +lemma castLT_eq_castPred (i : Fin (n + 1)) (h : i < last _) (h' := h.ne) : + castLT i h = castPred i h' := rfl + +@[simp] +lemma coe_castPred (i : Fin (n + 1)) (h : i ≠ last _) : (castPred i h : ℕ) = i := rfl +#align fin.coe_cast_pred Fin.coe_castPred + +@[simp] +theorem castPred_castSucc {i : Fin n} (h' := (castSucc_lt_last i).ne) : + castPred (castSucc i) h' = i := rfl +#align fin.cast_pred_cast_succ Fin.castPred_castSucc + +@[simp] +theorem castSucc_castPred (i : Fin (n + 1)) (h : i ≠ last n) : + castSucc (i.castPred h) = i := by + rcases exists_castSucc_eq.mpr h with ⟨y, rfl⟩ + rw [castPred_castSucc] +#align fin.cast_succ_cast_pred Fin.castSucc_castPred + +theorem castPred_eq_iff_eq_castSucc (i : Fin (n + 1)) (hi : i ≠ last _) (j : Fin n) : + castPred i hi = j ↔ i = castSucc j := + ⟨fun h => by rw [← h, castSucc_castPred], fun h => by simp_rw [h, castPred_castSucc]⟩ + +@[simp] +theorem castPred_mk (i : ℕ) (h₁ : i < n) (h₂ := h₁.trans (Nat.lt_succ_self _)) + (h₃ : ⟨i, h₂⟩ ≠ last _ := (ne_iff_vne _ _).mpr (val_last _ ▸ h₁.ne)) : + castPred ⟨i, h₂⟩ h₃ = ⟨i, h₁⟩ := rfl +#align fin.cast_pred_mk Fin.castPred_mk + +theorem castPred_le_castPred_iff {i j : Fin (n + 1)} {hi : i ≠ last n} {hj : j ≠ last n} : + castPred i hi ≤ castPred j hj ↔ i ≤ j := Iff.rfl + +theorem castPred_lt_castPred_iff {i j : Fin (n + 1)} {hi : i ≠ last n} {hj : j ≠ last n} : + castPred i hi < castPred j hj ↔ i < j := Iff.rfl + +theorem castPred_lt_iff {i : Fin (n + 1)} (hi : i ≠ last n) : + castPred i hi < j ↔ i < castSucc j := by + rw [← castSucc_lt_castSucc_iff, castSucc_castPred] + +theorem lt_castPred_iff {i : Fin (n + 1)} (hi : i ≠ last n) : + j < castPred i hi ↔ castSucc j < i := by + rw [← castSucc_lt_castSucc_iff, castSucc_castPred] + +theorem castPred_le_iff {i : Fin (n + 1)} (hi : i ≠ last n) : + castPred i hi ≤ j ↔ i ≤ castSucc j := by + rw [← castSucc_le_castSucc_iff, castSucc_castPred] + +theorem le_castPred_iff {i : Fin (n + 1)} (hi : i ≠ last n) : + j ≤ castPred i hi ↔ castSucc j ≤ i := by + rw [← castSucc_le_castSucc_iff, castSucc_castPred] + +theorem castPred_inj {i j : Fin (n + 1)} {hi : i ≠ last n} {hj : j ≠ last n} : + castPred i hi = castPred j hj ↔ i = j := by + simp_rw [le_antisymm_iff, castPred_le_castPred_iff] + +theorem castPred_zero' [NeZero n] (h := last_pos'.ne) : + castPred (0 : Fin (n + 1)) h = 0 := rfl + +theorem castPred_zero (h := last_pos.ne) : + castPred (0 : Fin (n + 2)) h = 0 := rfl +#align fin.cast_pred_zero Fin.castPred_zero + +@[simp] +theorem castPred_one [NeZero n] (h := one_lt_last.ne) : castPred (1 : Fin (n + 2)) h = 1 := by + cases n + · exact subsingleton_one.elim _ 1 + · rfl +#align fin.cast_pred_one Fin.castPred_one + +theorem pred_lt_castPred (h₁ : i ≠ 0) (h₂ : i ≠ last n) : pred i h₁ < castPred i h₂ := by + rw [← castSucc_lt_castSucc_iff, castSucc_castPred, castSucc_lt_iff_succ_le, succ_pred] + +theorem rev_pred (h : i ≠ 0) (h' := rev_ne_iff.mpr ((rev_last _).symm ▸ h)) : + rev (pred i h) = castPred (rev i) h' := by + rw [← castSucc_inj, castSucc_castPred, ← rev_succ, succ_pred] + +theorem rev_castPred (h : i ≠ last n) (h' := rev_ne_iff.mpr ((rev_zero _).symm ▸ h)) : + rev (castPred i h) = pred (rev i) h' := by + rw [← succ_inj, succ_pred, ← rev_castSucc, castSucc_castPred] + +theorem succ_castPred_eq_castPred_succ {a : Fin (n + 1)} (ha : a ≠ last n) + (ha' := a.succ_ne_last_iff.mpr ha) : + succ (a.castPred ha) = (succ a).castPred ha' := rfl + +theorem le_castPred_succ_iff {a b : Fin (n + 1)} (ha : succ a ≠ last (n + 1)) : + (succ a).castPred ha ≤ b ↔ a < b := by + rw [castPred_le_iff, succ_le_castSucc_iff] + +theorem lt_castPred_succ {a : Fin (n + 1)} (ha : succ a ≠ last (n + 1)) : + a < (succ a).castPred ha := by + rw [lt_castPred_iff] + exact castSucc_lt_succ _ + +theorem succ_castPred_le_iff {a b : Fin (n + 1)} (ha : a ≠ last n) : + succ (a.castPred ha) ≤ b ↔ a < b := by + rw [succ_castPred_eq_castPred_succ ha, le_castPred_succ_iff] + +theorem lt_succ_castPred {a : Fin (n + 1)} (ha : a ≠ last n) : + a < succ (a.castPred ha) := by + rw [lt_iff_not_le, succ_castPred_le_iff] + exact lt_irrefl _ + +end CastPred + section DivMod /-- Compute `i / n`, where `n` is a `Nat` and inferred the type of `i`. -/ @@ -1377,7 +1559,7 @@ section SuccAbove /-- `succAbove p i` embeds `Fin n` into `Fin (n + 1)` with a hole around `p`. -/ def succAbove (p : Fin (n + 1)) (i : Fin n) : Fin (n + 1) := - if i.1 < p.1 then castSucc i else succ i + if castSucc i < p then i.castSucc else i.succ theorem strictMono_succAbove (p : Fin (n + 1)) : StrictMono (succAbove p) := (castSuccEmb : Fin n ↪o _).strictMono.ite (succEmbedding n).strictMono @@ -1385,7 +1567,7 @@ theorem strictMono_succAbove (p : Fin (n + 1)) : StrictMono (succAbove p) := (castSucc_lt_succ i).le #align fin.succ_above_aux Fin.strictMono_succAbove -/-- `Fin.auccAbove` as an `OrderEmbedding`, `succAboveEmb p i` embeds `Fin n` into `Fin (n + 1)` +/-- `Fin.succAbove` as an `OrderEmbedding`, `succAboveEmb p i` embeds `Fin n` into `Fin (n + 1)` with a hole around `p`. -/ @[simps! apply toEmbedding] def succAboveEmb (p : Fin (n + 1)) : Fin n ↪o Fin (n + 1) := @@ -1435,7 +1617,7 @@ theorem succAbove_last_apply (i : Fin n) : succAbove (Fin.last n) i = castSucc i /-- Embedding `i : Fin n` into `Fin (n + 1)` with a hole around `p : Fin (n + 1)` embeds `i` by `succ` when the resulting `p < i.succ`. -/ theorem succAbove_above (p : Fin (n + 1)) (i : Fin n) (h : p ≤ castSucc i) : - p.succAbove i = i.succ := by simp [le_iff_val_le_val] at h; simp [succAbove, h.not_lt] + p.succAbove i = i.succ := if_neg h.not_lt #align fin.succ_above_above Fin.succAbove_above /-- Embedding `i : Fin n` into `Fin (n + 1)` is always about some hole `p`. -/ @@ -1443,11 +1625,7 @@ theorem succAbove_lt_ge (p : Fin (n + 1)) (i : Fin n) : castSucc i < p ∨ p ≤ lt_or_ge (castSucc i) p #align fin.succ_above_lt_ge Fin.succAbove_lt_ge -/-- Embedding `i : Fin n` into `Fin (n + 1)` is always about some hole `p`. -/ -theorem succAbove_lt_gt (p : Fin (n + 1)) (i : Fin n) : castSucc i < p ∨ p < i.succ := - Or.casesOn (succAbove_lt_ge p i) (fun h => Or.inl h) fun h => - Or.inr (lt_of_le_of_lt h (castSucc_lt_succ i)) -#align fin.succ_above_lt_gt Fin.succAbove_lt_gt +@[deprecated castSucc_lt_or_lt_succ] alias succAbove_lt_gt := castSucc_lt_or_lt_succ /-- Embedding `i : Fin n` into `Fin (n + 1)` using a pivot `p` that is greater results in a value that is less than `p`. -/ @@ -1634,8 +1812,8 @@ section PredAbove /-- `predAbove p i` embeds `i : Fin (n+1)` into `Fin n` by subtracting one if `p < i`. -/ def predAbove (p : Fin n) (i : Fin (n + 1)) : Fin n := - if h : castSucc p < i then i.pred ((ne_iff_vne i 0).mpr (Nat.not_eq_zero_of_lt h)) - else i.castLT (Nat.lt_of_le_of_lt (Nat.ge_of_not_lt h) p.2) + if h : castSucc p < i then pred i ((zero_le _).trans_lt h).ne' + else castPred i ((le_of_not_lt h).trans_lt (castSucc_lt_last _)).ne #align fin.pred_above Fin.predAbove theorem predAbove_right_monotone (p : Fin n) : Monotone p.predAbove := fun a b H => by @@ -1662,23 +1840,6 @@ theorem predAbove_left_monotone (i : Fin (n + 1)) : · rfl #align fin.pred_above_left_monotone Fin.predAbove_left_monotone -/-- `castPred` embeds `i : Fin (n + 2)` into `Fin (n + 1)` -by lowering just `last (n + 1)` to `last n`. -/ -def castPred (i : Fin (n + 2)) : Fin (n + 1) := predAbove (last n) i -#align fin.cast_pred Fin.castPred - -@[simp] -theorem castPred_zero : castPred (0 : Fin (n + 2)) = 0 := - rfl -#align fin.cast_pred_zero Fin.castPred_zero - -@[simp] -theorem castPred_one : castPred (1 : Fin (n + 2)) = 1 := by - cases n - · rfl - · rfl -#align fin.cast_pred_one Fin.castPred_one - @[simp] theorem predAbove_zero {i : Fin (n + 2)} (hi : i ≠ 0) : predAbove 0 i = i.pred hi := by dsimp [predAbove] @@ -1686,54 +1847,36 @@ theorem predAbove_zero {i : Fin (n + 2)} (hi : i ≠ 0) : predAbove 0 i = i.pred exact pos_iff_ne_zero.mpr hi #align fin.pred_above_zero Fin.predAbove_zero -@[simp] -theorem castPred_last : castPred (last (n + 1)) = last n := - eq_of_veq (by simp [castPred, predAbove, castSucc_lt_last]) -#align fin.cast_pred_last Fin.castPred_last +theorem predAbove_below (p : Fin n) (i : Fin (n + 1)) (h : i ≤ castSucc p) + (hi := (h.trans_lt (castSucc_lt_last _)).ne) : + p.predAbove i = i.castPred hi := dif_neg h.not_lt +#align fin.pred_above_below Fin.predAbove_below ---Porting note: removing @[simp]. `castPred_mk'` has `simp` attribute instead -theorem castPred_mk (n i : ℕ) (h : i < n + 1) : castPred ⟨i, lt_succ_of_lt h⟩ = ⟨i, h⟩ := by - have : ¬castSucc (last n) < ⟨i, lt_succ_of_lt h⟩ := by - simpa [lt_iff_val_lt_val] using le_of_lt_succ h - simp [castPred, predAbove, this] -#align fin.cast_pred_mk Fin.castPred_mk +theorem predAbove_above (p : Fin n) (i : Fin (n + 1)) (h : castSucc p < i) + (hi := ((zero_le _).trans_lt h).ne') : + p.predAbove i = i.pred hi := dif_pos h +#align fin.pred_above_above Fin.predAbove_above ---Porting note: new lemma @[simp] -theorem castPred_mk' (n i : ℕ) (h₁ : i < n + 2) (h₂ : i < n + 1) : castPred ⟨i, h₁⟩ = ⟨i, h₂⟩ := - castPred_mk _ _ _ - -theorem coe_castPred {n : ℕ} (a : Fin (n + 2)) (hx : a < Fin.last _) : - (a.castPred : ℕ) = a := by - rcases a with ⟨a, ha⟩ - rw [castPred_mk] - exact hx -#align fin.coe_cast_pred Fin.coe_castPred - -theorem predAbove_below (p : Fin (n + 1)) (i : Fin (n + 2)) (h : i ≤ castSucc p) : - p.predAbove i = i.castPred := by - have : i ≤ castSucc (last n) := h.trans p.le_last - simp [predAbove, castPred, h.not_lt, this.not_lt] -#align fin.pred_above_below Fin.predAbove_below - +theorem predAbove_right_last : predAbove (i : Fin (n + 1)) (Fin.last (n + 1)) = last n := by + rw [predAbove_above _ _ (castSucc_lt_last _), pred_last] @[simp] -theorem predAbove_last : predAbove (Fin.last n) = castPred := - rfl -#align fin.pred_above_last Fin.predAbove_last - -theorem predAbove_last_apply (i : Fin n) : predAbove (Fin.last n) i = i.castPred := by - rw [predAbove_last] +theorem predAbove_last_castSucc {i : Fin (n + 1)} : + predAbove (Fin.last n) (i.castSucc) = i := by + rw [predAbove_below _ _ ((castSucc_le_castSucc_iff).mpr (le_last _)), castPred_castSucc] +@[simp] +theorem predAbove_last_of_ne_last {i : Fin (n + 2)} (hi : i ≠ last (n + 1)): + predAbove (Fin.last n) i = castPred i hi := by + rw [← exists_castSucc_eq] at hi + rcases hi with ⟨y, rfl⟩ + exact predAbove_last_castSucc +theorem predAbove_last_apply : + predAbove (last n) i = if hi : i = Fin.last _ then last _ else i.castPred hi := by + split_ifs with hi + · rw [hi, predAbove_right_last] + · rw [predAbove_last_of_ne_last hi] #align fin.pred_above_last_apply Fin.predAbove_last_apply -theorem predAbove_above (p : Fin n) (i : Fin (n + 1)) (h : castSucc p < i) : - p.predAbove i = i.pred ((zero_le <| castSucc p).trans_lt h).ne.symm := by - simp [predAbove, h] -#align fin.pred_above_above Fin.predAbove_above - -theorem castPred_monotone : Monotone (@castPred n) := - predAbove_right_monotone (last _) -#align fin.cast_pred_monotone Fin.castPred_monotone - /-- Sending `Fin (n+1)` to `Fin n` by subtracting one from anything above `p` then back to `Fin (n+1)` with a gap around `p` is the identity away from `p`. -/ @[simp] @@ -1775,19 +1918,11 @@ theorem predAbove_succAbove (p : Fin n) (i : Fin n) : contradiction #align fin.pred_above_succ_above Fin.predAbove_succAbove -theorem castSucc_pred_eq_pred_castSucc {a : Fin (n + 1)} (ha : a ≠ 0) - (ha' := a.castSucc_ne_zero_iff.mpr ha) : - castSucc (a.pred ha) = (castSucc a).pred ha' := by - cases a - rfl -#align fin.cast_succ_pred_eq_pred_cast_succ Fin.castSucc_pred_eq_pred_castSucc - /-- `pred` commutes with `succAbove`. -/ theorem pred_succAbove_pred {a : Fin (n + 2)} {b : Fin (n + 1)} (ha : a ≠ 0) (hb : b ≠ 0) (hk := succAbove_ne_zero ha hb) : (a.pred ha).succAbove (b.pred hb) = (a.succAbove b).pred hk := by obtain hbelow | habove := lt_or_le (castSucc b) a - -- `rwa` uses them · rw [Fin.succAbove_below] · rwa [castSucc_pred_eq_pred_castSucc, Fin.pred_inj, Fin.succAbove_below] · rwa [castSucc_pred_eq_pred_castSucc, pred_lt_pred_iff] @@ -1801,65 +1936,13 @@ theorem pred_succAbove_pred {a : Fin (n + 2)} {b : Fin (n + 1)} (ha : a ≠ 0) ( @[simp] theorem succ_predAbove_succ {n : ℕ} (a : Fin n) (b : Fin (n + 1)) : a.succ.predAbove b.succ = (a.predAbove b).succ := by - obtain h₁ | h₂ := lt_or_le (castSucc a) b - · rw [Fin.predAbove_above _ _ h₁, Fin.succ_pred, Fin.predAbove_above, Fin.pred_succ] - simpa only [lt_iff_val_lt_val, coe_castSucc, val_succ, add_lt_add_iff_right] using - h₁ - · cases' n with n - · exfalso - exact not_lt_zero' a.is_lt - · rw [Fin.predAbove_below a b h₂, - Fin.predAbove_below a.succ b.succ - (by - simpa only [le_iff_val_le_val, val_succ, coe_castSucc, add_le_add_iff_right] - using h₂)] - ext - have h₀ : (b : ℕ) < n + 1 := by - simp only [le_iff_val_le_val, coe_castSucc] at h₂ - simpa only [lt_succ_iff] using h₂.trans a.is_le - have h₁ : (b.succ : ℕ) < n + 2 := by - rw [← Nat.succ_lt_succ_iff] at h₀ - simpa only [val_succ] using h₀ - simp only [coe_castPred b h₀, coe_castPred b.succ h₁, val_succ] + obtain h | h := (lt_or_le (castSucc a) b) + · rw [Fin.predAbove_above _ _ h, succ_pred, Fin.predAbove_above, pred_succ] + rwa [castSucc_lt_succ_iff, ← castSucc_lt_iff_succ_le] + · rw [Fin.predAbove_below _ _ h, Fin.predAbove_below, succ_castPred_eq_castPred_succ] + rwa [succ_le_castSucc_iff, ← le_castSucc_iff] #align fin.succ_pred_above_succ Fin.succ_predAbove_succ -@[simp] -theorem castPred_castSucc (i : Fin (n + 1)) : castPred (castSucc i) = i := by - simp [castPred, predAbove, not_lt.mpr (le_last i)] -#align fin.cast_pred_cast_succ Fin.castPred_castSucc - -theorem castSucc_castPred {i : Fin (n + 2)} (h : i < last (n + 1)) : - castSucc i.castPred = i := by - rw [castPred, predAbove, dif_neg] - · simp [Fin.eq_iff_veq] - · exact h.not_le -#align fin.cast_succ_cast_pred Fin.castSucc_castPred - -theorem coe_castPred_le_self (i : Fin (n + 2)) : (i.castPred : ℕ) ≤ i := by - rcases i.le_last.eq_or_lt with (rfl | h) - · simp - · rw [castPred, predAbove, dif_neg] - · simp - · simpa [lt_iff_val_lt_val, le_iff_val_le_val, lt_succ_iff] using h -#align fin.coe_cast_pred_le_self Fin.coe_castPred_le_self - -theorem coe_castPred_lt_iff {i : Fin (n + 2)} : (i.castPred : ℕ) < i ↔ i = Fin.last _ := by - rcases i.le_last.eq_or_lt with (rfl | H) - · simp - · simp only [_root_.ne_of_lt H] - rw [← castSucc_castPred H] - simp -#align fin.coe_cast_pred_lt_iff Fin.coe_castPred_lt_iff - -theorem lt_last_iff_coe_castPred {i : Fin (n + 2)} : - i < Fin.last _ ↔ (i.castPred : ℕ) = i := by - rcases i.le_last.eq_or_lt with (rfl | H) - · simp - · simp only [H] - rw [← castSucc_castPred H] - simp -#align fin.lt_last_iff_coe_cast_pred Fin.lt_last_iff_coe_castPred - end PredAbove #align fin.coe_clamp Fin.coe_clamp diff --git a/Mathlib/Data/Fin/FlagRange.lean b/Mathlib/Data/Fin/FlagRange.lean index 6d2f96ee9c456..17082ff70e88a 100644 --- a/Mathlib/Data/Fin/FlagRange.lean +++ b/Mathlib/Data/Fin/FlagRange.lean @@ -28,10 +28,10 @@ variable {α : Type*} [PartialOrder α] [BoundedOrder α] {n : ℕ} {f : Fin (n - `fₖ₊₁` weakly covers `fₖ` for all `0 ≤ k < n`; this means that `fₖ ≤ fₖ₊₁` and there is no `c` such that `fₖ simpa [h0, bot_lt_iff_ne_bot] using (h 0).symm | succ k ihk => rw [range_subset_iff] at hbt - exact (htc.lt_of_le (hbt k.succ) hx (h _)).resolve_right ((hcovby k).2 ihk) + exact (htc.lt_of_le (hbt k.succ) hx (h _)).resolve_right ((hcovBy k).2 ihk) /-- Let `f : Fin (n + 1) → α` be an `(n + 1)`-tuple `(f₀, …, fₙ)` such that - `f₀ = ⊥` and `fₙ = ⊤`; @@ -49,11 +49,11 @@ theorem IsMaxChain.range_fin_of_covby (h0 : f 0 = ⊥) (hlast : f (.last n) = Then the range of `f` is a `Flag α`. -/ @[simps] def Flag.rangeFin (f : Fin (n + 1) → α) (h0 : f 0 = ⊥) (hlast : f (.last n) = ⊤) - (hcovby : ∀ k : Fin n, f k.castSucc ⩿ f k.succ) : Flag α where + (hcovBy : ∀ k : Fin n, f k.castSucc ⩿ f k.succ) : Flag α where carrier := range f - Chain' := (IsMaxChain.range_fin_of_covby h0 hlast hcovby).1 - max_chain' := (IsMaxChain.range_fin_of_covby h0 hlast hcovby).2 + Chain' := (IsMaxChain.range_fin_of_covBy h0 hlast hcovBy).1 + max_chain' := (IsMaxChain.range_fin_of_covBy h0 hlast hcovBy).2 -@[simp] theorem Flag.mem_rangeFin {x h0 hlast hcovby} : - x ∈ rangeFin f h0 hlast hcovby ↔ ∃ k, f k = x := +@[simp] theorem Flag.mem_rangeFin {x h0 hlast hcovBy} : + x ∈ rangeFin f h0 hlast hcovBy ↔ ∃ k, f k = x := Iff.rfl diff --git a/Mathlib/Data/Fin/Tuple/Basic.lean b/Mathlib/Data/Fin/Tuple/Basic.lean index fdf6c08e5b815..b41cfe9004d28 100644 --- a/Mathlib/Data/Fin/Tuple/Basic.lean +++ b/Mathlib/Data/Fin/Tuple/Basic.lean @@ -46,7 +46,7 @@ section Tuple /-- There is exactly one tuple of size zero. -/ example (α : Fin 0 → Sort u) : Unique (∀ i : Fin 0, α i) := by infer_instance -theorem tuple0_le {α : ∀ _ : Fin 0, Type*} [∀ i, Preorder (α i)] (f g : ∀ i, α i) : f ≤ g := +theorem tuple0_le {α : Fin 0 → Type*} [∀ i, Preorder (α i)] (f g : ∀ i, α i) : f ≤ g := finZeroElim #align fin.tuple0_le Fin.tuple0_le diff --git a/Mathlib/Data/Fin/Tuple/BubbleSortInduction.lean b/Mathlib/Data/Fin/Tuple/BubbleSortInduction.lean index 37dcb07a027fa..22ec0cc6c77dc 100644 --- a/Mathlib/Data/Fin/Tuple/BubbleSortInduction.lean +++ b/Mathlib/Data/Fin/Tuple/BubbleSortInduction.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Stoll -/ import Mathlib.Data.Fin.Tuple.Sort -import Mathlib.Data.Fintype.Perm import Mathlib.Order.WellFounded #align_import data.fin.tuple.bubble_sort_induction from "leanprover-community/mathlib"@"bf2428c9486c407ca38b5b3fb10b87dad0bc99fa" diff --git a/Mathlib/Data/Fin/Tuple/Finset.lean b/Mathlib/Data/Fin/Tuple/Finset.lean new file mode 100644 index 0000000000000..5a102d77f270b --- /dev/null +++ b/Mathlib/Data/Fin/Tuple/Finset.lean @@ -0,0 +1,36 @@ +/- +Copyright (c) 2023 Bolton Bailey. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bolton Bailey +-/ +import Mathlib.Data.Fin.Tuple.Basic +import Mathlib.Data.Fintype.Pi + +/-! +# Fin-indexed tuples of finsets +-/ + +open Fintype + +namespace Fin +variable {n : ℕ} {α : Fin (n + 1) → Type*} + +lemma mem_piFinset_succ {x : ∀ i, α i} {s : ∀ i, Finset (α i)} : + x ∈ piFinset s ↔ x 0 ∈ s 0 ∧ tail x ∈ piFinset (tail s) := by + simp only [mem_piFinset, forall_fin_succ, tail] + +lemma mem_piFinset_succ' {x : ∀ i, α i} {s : ∀ i, Finset (α i)} : + x ∈ piFinset s ↔ init x ∈ piFinset (init s) ∧ x (last n) ∈ s (last n) := by + simp only [mem_piFinset, forall_fin_succ', init] + +lemma cons_mem_piFinset_cons {x₀ : α 0} {x : ∀ i : Fin n, α i.succ} + {s₀ : Finset (α 0)} {s : ∀ i : Fin n, Finset (α i.succ)} : + cons x₀ x ∈ piFinset (cons s₀ s) ↔ x₀ ∈ s₀ ∧ x ∈ piFinset s := by + simp_rw [mem_piFinset_succ, cons_zero, tail_cons] + +lemma snoc_mem_piFinset_snoc {x : ∀ i : Fin n, α i.castSucc} {xₙ : α (.last n)} + {s : ∀ i : Fin n, Finset (α i.castSucc)} {sₙ : Finset (α $ .last n)} : + snoc x xₙ ∈ piFinset (snoc s sₙ) ↔ x ∈ piFinset s ∧ xₙ ∈ sₙ := by + simp_rw [mem_piFinset_succ', init_snoc, snoc_last] + +end Fin diff --git a/Mathlib/Data/Fin/Tuple/Sort.lean b/Mathlib/Data/Fin/Tuple/Sort.lean index 8ddb303d1017a..61cdb45831f6c 100644 --- a/Mathlib/Data/Fin/Tuple/Sort.lean +++ b/Mathlib/Data/Fin/Tuple/Sort.lean @@ -168,7 +168,7 @@ theorem eq_sort_iff' : σ = sort f ↔ StrictMono (σ.trans <| graphEquiv₁ f) exact (graphEquiv₂ f).strictMono · have := Subsingleton.elim (graphEquiv₂ f) (h.orderIsoOfSurjective _ <| Equiv.surjective _) ext1 x - exact (graphEquiv₁ f).apply_eq_iff_eq_symm_apply.1 (FunLike.congr_fun this x).symm + exact (graphEquiv₁ f).apply_eq_iff_eq_symm_apply.1 (DFunLike.congr_fun this x).symm #align tuple.eq_sort_iff' Tuple.eq_sort_iff' /-- A permutation `σ` equals `sort f` if and only if `f ∘ σ` is monotone and whenever `i < j` @@ -185,7 +185,7 @@ theorem eq_sort_iff : /-- The permutation that sorts `f` is the identity if and only if `f` is monotone. -/ theorem sort_eq_refl_iff_monotone : sort f = Equiv.refl _ ↔ Monotone f := by - rw [eq_comm, eq_sort_iff, Equiv.coe_refl, Function.comp.right_id] + rw [eq_comm, eq_sort_iff, Equiv.coe_refl, Function.comp_id] simp only [id.def, and_iff_left_iff_imp] exact fun _ _ _ hij _ => hij #align tuple.sort_eq_refl_iff_monotone Tuple.sort_eq_refl_iff_monotone diff --git a/Mathlib/Data/Fin/VecNotation.lean b/Mathlib/Data/Fin/VecNotation.lean index 7b8a98f5b6b5d..e2d51132d9bcd 100644 --- a/Mathlib/Data/Fin/VecNotation.lean +++ b/Mathlib/Data/Fin/VecNotation.lean @@ -5,7 +5,7 @@ Authors: Anne Baanen -/ import Mathlib.Data.Fin.Tuple.Basic import Mathlib.Data.List.Range -import Mathlib.GroupTheory.GroupAction.Pi +import Mathlib.Data.Set.Image #align_import data.fin.vec_notation from "leanprover-community/mathlib"@"2445c98ae4b87eabebdde552593519b9b6dc350c" diff --git a/Mathlib/Data/Finite/Basic.lean b/Mathlib/Data/Finite/Basic.lean index 5a075aab0fb45..72648bad8a9d0 100644 --- a/Mathlib/Data/Finite/Basic.lean +++ b/Mathlib/Data/Finite/Basic.lean @@ -140,12 +140,12 @@ instance Function.Embedding.finite {α β : Sort*} [Finite β] : Finite (α ↪ · refine' h.elim fun f => _ haveI : Finite α := Finite.of_injective _ f.injective - exact Finite.of_injective _ FunLike.coe_injective + exact Finite.of_injective _ DFunLike.coe_injective #align function.embedding.finite Function.Embedding.finite instance Equiv.finite_right {α β : Sort*} [Finite β] : Finite (α ≃ β) := Finite.of_injective Equiv.toEmbedding fun e₁ e₂ h => Equiv.ext <| by - convert FunLike.congr_fun h using 0 + convert DFunLike.congr_fun h using 0 #align equiv.finite_right Equiv.finite_right instance Equiv.finite_left {α β : Sort*} [Finite α] : Finite (α ≃ β) := diff --git a/Mathlib/Data/Finite/Defs.lean b/Mathlib/Data/Finite/Defs.lean index 91301838afba6..0a9f4a71be1eb 100644 --- a/Mathlib/Data/Finite/Defs.lean +++ b/Mathlib/Data/Finite/Defs.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Mathlib.Logic.Equiv.Basic +import Mathlib.Logic.Equiv.Defs +import Mathlib.Tactic.Cases #align_import data.finite.defs from "leanprover-community/mathlib"@"a148d797a1094ab554ad4183a4ad6f130358ef64" @@ -49,11 +50,34 @@ open Function variable {α β : Sort*} -/-- A type is `Finite` if it is in bijective correspondence to some -`Fin n`. - -While this could be defined as `Nonempty (Fintype α)`, it is defined -in this way to allow there to be `Finite` instances for propositions. +/-- A type is `Finite` if it is in bijective correspondence to some `Fin n`. + +This is similar to `Fintype`, but `Finite` is a proposition rather than data. +A particular benefit to this is that `Finite` instances are definitionally equal to one another +(due to proof irrelevance) rather than being merely propositionally equal, +and, furthermore, `Finite` instances generally avoid the need for `Decidable` instances. +One other notable difference is that `Finite` allows there to be `Finite p` instances +for all `p : Prop`, which is not allowed by `Fintype` due to universe constraints. +An application of this is that `Finite (x ∈ s → β x)` follows from the general instance for pi +types, assuming `[∀ x, Finite (β x)]`. +Implementation note: this is a reason `Finite α` is not defined as `Nonempty (Fintype α)`. + +Every `Fintype` instance provides a `Finite` instance via `Finite.of_fintype`. +Conversely, one can noncomputably create a `Fintype` instance from a `Finite` instance +via `Fintype.ofFinite`. In a proof one might write +```lean + have := Fintype.ofFinite α +``` +to obtain such an instance. + +Do not write noncomputable `Fintype` instances; instead write `Finite` instances +and use this `Fintype.ofFinite` interface. +The `Fintype` instances should be relied upon to be computable for evaluation purposes. + +Theorems should use `Finite` instead of `Fintype`, unless definitions in the theorem statement +require `Fintype`. +Definitions should prefer `Finite` as well, unless it is important that the definitions +are meant to be computable in the reduction or `#eval` sense. -/ class inductive Finite (α : Sort*) : Prop | intro {n : ℕ} : α ≃ Fin n → Finite _ diff --git a/Mathlib/Data/Finset/Antidiagonal.lean b/Mathlib/Data/Finset/Antidiagonal.lean index 86d9c25a68108..7b4a51ac6e8a7 100644 --- a/Mathlib/Data/Finset/Antidiagonal.lean +++ b/Mathlib/Data/Finset/Antidiagonal.lean @@ -5,9 +5,8 @@ Authors: Antoine Chambert-Loir, María Inés de Frutos-Fernández, Bhavik Mehta, -/ import Mathlib.Data.Finset.Basic -import Mathlib.Data.Finsupp.Defs -import Mathlib.Data.Finsupp.Interval import Mathlib.Algebra.Order.Sub.Defs +import Mathlib.Order.LocallyFinite /-! # Antidiagonal with values in general types diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index f1de472f9c74d..2cbed15f7771b 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -5,7 +5,6 @@ Authors: Leonardo de Moura, Jeremy Avigad, Minchao Wu, Mario Carneiro -/ import Mathlib.Data.Multiset.FinsetOps import Mathlib.Data.Set.Lattice -import Mathlib.Order.Cover #align_import data.finset.basic from "leanprover-community/mathlib"@"442a83d738cb208d3600056c489be16900ba701d" @@ -271,7 +270,7 @@ protected theorem exists_coe {α : Type*} (s : Finset α) (p : s → Prop) : Subtype.exists #align finset.exists_coe Finset.exists_coe -instance PiFinsetCoe.canLift (ι : Type*) (α : ∀ _i : ι, Type*) [_ne : ∀ i, Nonempty (α i)] +instance PiFinsetCoe.canLift (ι : Type*) (α : ι → Type*) [_ne : ∀ i, Nonempty (α i)] (s : Finset ι) : CanLift (∀ i : s, α i) (∀ i, α i) (fun f i => f i) fun _ => True := PiSubtype.canLift ι α (· ∈ s) #align finset.pi_finset_coe.can_lift Finset.PiFinsetCoe.canLift @@ -827,6 +826,8 @@ theorem Nontrivial.ne_singleton (hs : s.Nontrivial) : s ≠ {a} := by rintro rfl; exact not_nontrivial_singleton hs #align finset.nontrivial.ne_singleton Finset.Nontrivial.ne_singleton +nonrec lemma Nontrivial.exists_ne (hs : s.Nontrivial) (a : α) : ∃ b ∈ s, b ≠ a := hs.exists_ne _ + theorem eq_singleton_or_nontrivial (ha : a ∈ s) : s = {a} ∨ s.Nontrivial := by rw [← coe_eq_singleton]; exact Set.eq_singleton_or_nontrivial ha #align finset.eq_singleton_or_nontrivial Finset.eq_singleton_or_nontrivial @@ -1501,10 +1502,10 @@ theorem empty_union (s : Finset α) : ∅ ∪ s = s := #align finset.empty_union Finset.empty_union theorem Nonempty.inl {s t : Finset α} (h : s.Nonempty) : (s ∪ t).Nonempty := - h.mono $ subset_union_left s t + h.mono <| subset_union_left s t theorem Nonempty.inr {s t : Finset α} (h : t.Nonempty) : (s ∪ t).Nonempty := - h.mono $ subset_union_right s t + h.mono <| subset_union_right s t theorem insert_eq (a : α) (s : Finset α) : insert a s = {a} ∪ s := rfl @@ -1923,6 +1924,9 @@ theorem erase_empty (a : α) : erase ∅ a = ∅ := rfl #align finset.erase_empty Finset.erase_empty +protected lemma Nontrivial.erase_nonempty (hs : s.Nontrivial) : (s.erase a).Nonempty := + (hs.exists_ne a).imp $ by aesop + @[simp] lemma erase_nonempty (ha : a ∈ s) : (s.erase a).Nonempty ↔ s.Nontrivial := by simp only [Finset.Nonempty, mem_erase, and_comm (b := _ ∈ _)] refine ⟨?_, fun hs ↦ hs.exists_ne a⟩ @@ -2092,7 +2096,7 @@ lemma Nonempty.exists_cons_eq (hs : s.Nonempty) : ∃ t a ha, cons a t ha = s := exact ⟨s.erase a, a, not_mem_erase _ _, by simp [insert_erase ha]⟩ lemma Nontrivial.exists_cons_eq (hs : s.Nontrivial) : - ∃ t a ha b hb hab, (cons b t hb).cons a (mem_cons.not.2 $ not_or_intro hab ha) = s := by + ∃ t a ha b hb hab, (cons b t hb).cons a (mem_cons.not.2 <| not_or_intro hab ha) = s := by classical obtain ⟨a, ha, b, hb, hab⟩ := hs have : b ∈ s.erase a := mem_erase.2 ⟨hab.symm, hb⟩ @@ -2474,6 +2478,8 @@ end Sdiff section SymmDiff +open scoped symmDiff + variable [DecidableEq α] {s t : Finset α} {a b : α} theorem mem_symmDiff : a ∈ s ∆ t ↔ a ∈ s ∧ a ∉ t ∨ a ∈ t ∧ a ∉ s := by @@ -2917,6 +2923,13 @@ theorem filter_disj_union (s : Finset α) (t : Finset α) (h : Disjoint s t) : eq_of_veq <| Multiset.filter_add _ _ _ #align finset.filter_disj_union Finset.filter_disj_union +lemma _root_.Set.pairwiseDisjoint_filter [DecidableEq β] (f : α → β) (s : Set β) (t : Finset α) : + s.PairwiseDisjoint fun x ↦ t.filter (f · = x) := by + rintro i - j - h u hi hj x hx + obtain ⟨-, rfl⟩ : x ∈ t ∧ f x = i := by simpa using hi hx + obtain ⟨-, rfl⟩ : x ∈ t ∧ f x = j := by simpa using hj hx + contradiction + theorem filter_cons {a : α} (s : Finset α) (ha : a ∉ s) : filter p (cons a s ha) = (if p a then {a} else ∅ : Finset α).disjUnion (filter p s) @@ -3695,7 +3708,7 @@ theorem biUnion_insert [DecidableEq α] {a : α} : (insert a s).biUnion t = t a exists_eq_left] #align finset.bUnion_insert Finset.biUnion_insert --- ext $ λ x, by simp [or_and_distrib_right, exists_or_distrib] +-- ext <| λ x, by simp [or_and_distrib_right, exists_or_distrib] theorem biUnion_congr (hs : s₁ = s₂) (ht : ∀ a ∈ s₁, t₁ a = t₂ a) : s₁.biUnion t₁ = s₂.biUnion t₂ := ext fun x => by simp_rw [mem_biUnion] diff --git a/Mathlib/Data/Finset/Card.lean b/Mathlib/Data/Finset/Card.lean index aaea413bfd511..77a3bae747dd7 100644 --- a/Mathlib/Data/Finset/Card.lean +++ b/Mathlib/Data/Finset/Card.lean @@ -24,23 +24,20 @@ This defines the cardinality of a `Finset` and provides induction principles for * `Finset.strongDownwardInduction` * `Finset.strongDownwardInductionOn` * `Finset.case_strong_induction_on` - -## TODO - -Should we add a noncomputable version? +* `Finset.Nonempty.strong_induction` -/ open Function Multiset Nat -variable {α β : Type*} +variable {α β R : Type*} namespace Finset variable {s t : Finset α} {a b : α} /-- `s.card` is the number of elements of `s`, aka its cardinality. -/ -def card (s : Finset α) : ℕ := +@[pp_dot] def card (s : Finset α) : ℕ := Multiset.card s.1 #align finset.card Finset.card @@ -480,6 +477,9 @@ theorem card_sdiff (h : s ⊆ t) : card (t \ s) = t.card - s.card := by rw [card_disjoint_union sdiff_disjoint, add_tsub_cancel_right] #align finset.card_sdiff Finset.card_sdiff +lemma cast_card_sdiff [AddGroupWithOne R] (h : s ⊆ t) : ((t \ s).card : R) = t.card - s.card := by + rw [card_sdiff h, Nat.cast_sub (card_mono h)] + theorem card_sdiff_add_card_eq_card {s t : Finset α} (h : s ⊆ t) : card (t \ s) + card s = card t := ((Nat.sub_eq_iff_eq_add (card_le_card h)).mp (card_sdiff h).symm).symm #align finset.card_sdiff_add_card_eq_card Finset.card_sdiff_add_card_eq_card @@ -501,7 +501,8 @@ theorem card_sdiff_add_card : (s \ t).card + t.card = (s ∪ t).card := by #align finset.card_sdiff_add_card Finset.card_sdiff_add_card lemma card_sdiff_comm (h : s.card = t.card) : (s \ t).card = (t \ s).card := - add_left_injective t.card $ by simp_rw [card_sdiff_add_card, ← h, card_sdiff_add_card, union_comm] + add_left_injective t.card <| by + simp_rw [card_sdiff_add_card, ← h, card_sdiff_add_card, union_comm] @[simp] lemma card_sdiff_add_card_inter (s t : Finset α) : @@ -725,7 +726,7 @@ def strongInduction {p : Finset α → Sort*} (H : ∀ s, (∀ t ⊂ s, p t) → H s fun t h => have : t.card < s.card := card_lt_card h strongInduction H t - termination_by strongInduction s => Finset.card s + termination_by s => Finset.card s #align finset.strong_induction Finset.strongInduction @[nolint unusedHavesSuffices] --Porting note: false positive @@ -756,6 +757,26 @@ theorem case_strong_induction_on [DecidableEq α] {p : Finset α → Prop} (s : (h₁ a s n) fun t ss => ih _ (lt_of_le_of_lt ss (ssubset_insert n) : t < _) #align finset.case_strong_induction_on Finset.case_strong_induction_on +/-- Suppose that, given objects defined on all nonempty strict subsets of any nontrivial finset `s`, +one knows how to define an object on `s`. Then one can inductively define an object on all finsets, +starting from singletons and iterating. + +TODO: Currently this can only be used to prove properties. +Replace `Finset.Nonempty.exists_eq_singleton_or_nontrivial` with computational content +in order to let `p` be `Sort`-valued. -/ +@[elab_as_elim] +protected lemma Nonempty.strong_induction {p : ∀ s, s.Nonempty → Prop} + (h₀ : ∀ a, p {a} (singleton_nonempty _)) + (h₁ : ∀ ⦃s⦄ (hs : s.Nontrivial), (∀ t ht, t ⊂ s → p t ht) → p s hs.nonempty) : + ∀ ⦃s : Finset α⦄ (hs), p s hs + | s, hs => by + obtain ⟨a, rfl⟩ | hs := hs.exists_eq_singleton_or_nontrivial + · exact h₀ _ + · refine h₁ hs fun t ht hts ↦ ?_ + have := card_lt_card hts + exact ht.strong_induction h₀ h₁ +termination_by Finset.card ‹_› + /-- Suppose that, given that `p t` can be defined on all supersets of `s` of cardinality less than `n`, one knows how to define `p s`. Then one can inductively define `p s` for all finsets `s` of cardinality less than `n`, starting from finsets of card `n` and iterating. This @@ -767,7 +788,7 @@ def strongDownwardInduction {p : Finset α → Sort*} {n : ℕ} H s fun {t} ht h => have : n - t.card < n - s.card := (tsub_lt_tsub_iff_left_of_le ht).2 (Finset.card_lt_card h) strongDownwardInduction H t ht - termination_by strongDownwardInduction s => n - s.card + termination_by s => n - s.card #align finset.strong_downward_induction Finset.strongDownwardInduction @[nolint unusedHavesSuffices] --Porting note: false positive diff --git a/Mathlib/Data/Finset/Grade.lean b/Mathlib/Data/Finset/Grade.lean index 4241c7e79f0dc..4c5c5fc907f85 100644 --- a/Mathlib/Data/Finset/Grade.lean +++ b/Mathlib/Data/Finset/Grade.lean @@ -27,27 +27,27 @@ variable {α : Type*} namespace Multiset variable {s t : Multiset α} {a : α} -@[simp] lemma covby_cons (s : Multiset α) (a : α) : s ⋖ a ::ₘ s := - ⟨lt_cons_self _ _, fun t hst hts ↦ (covby_succ _).2 (card_lt_card hst) $ by +@[simp] lemma covBy_cons (s : Multiset α) (a : α) : s ⋖ a ::ₘ s := + ⟨lt_cons_self _ _, fun t hst hts ↦ (covBy_succ _).2 (card_lt_card hst) <| by simpa using card_lt_card hts⟩ -lemma _root_.Covby.exists_multiset_cons (h : s ⋖ t) : ∃ a, a ::ₘ s = t := - (lt_iff_cons_le.1 h.lt).imp fun _a ha ↦ ha.eq_of_not_lt $ h.2 $ lt_cons_self _ _ +lemma _root_.CovBy.exists_multiset_cons (h : s ⋖ t) : ∃ a, a ::ₘ s = t := + (lt_iff_cons_le.1 h.lt).imp fun _a ha ↦ ha.eq_of_not_lt <| h.2 <| lt_cons_self _ _ -lemma covby_iff : s ⋖ t ↔ ∃ a, a ::ₘ s = t := - ⟨Covby.exists_multiset_cons, by rintro ⟨a, rfl⟩; exact covby_cons _ _⟩ +lemma covBy_iff : s ⋖ t ↔ ∃ a, a ::ₘ s = t := + ⟨CovBy.exists_multiset_cons, by rintro ⟨a, rfl⟩; exact covBy_cons _ _⟩ -lemma _root_.Covby.card_multiset (h : s ⋖ t) : card s ⋖ card t := by - obtain ⟨a, rfl⟩ := h.exists_multiset_cons; rw [card_cons]; exact covby_succ _ +lemma _root_.CovBy.card_multiset (h : s ⋖ t) : card s ⋖ card t := by + obtain ⟨a, rfl⟩ := h.exists_multiset_cons; rw [card_cons]; exact covBy_succ _ -lemma isAtom_iff : IsAtom s ↔ ∃ a, s = {a} := by simp [← bot_covby_iff, covby_iff, eq_comm] +lemma isAtom_iff : IsAtom s ↔ ∃ a, s = {a} := by simp [← bot_covBy_iff, covBy_iff, eq_comm] @[simp] lemma isAtom_singleton (a : α) : IsAtom ({a} : Multiset α) := isAtom_iff.2 ⟨_, rfl⟩ instance instGradeMinOrder : GradeMinOrder ℕ (Multiset α) where grade := card grade_strictMono := card_strictMono - covby_grade s t := Covby.card_multiset + covBy_grade s t := CovBy.card_multiset isMin_grade s hs := by rw [isMin_iff_eq_bot.1 hs]; exact isMin_bot @[simp] lemma grade_eq (m : Multiset α) : grade ℕ m = card m := rfl @@ -58,73 +58,73 @@ namespace Finset variable {s t : Finset α} {a : α} /-- Finsets form an order-connected suborder of multisets. -/ -lemma ordConnected_range_val : Set.OrdConnected (Set.range val : Set $ Multiset α) := +lemma ordConnected_range_val : Set.OrdConnected (Set.range val : Set <| Multiset α) := ⟨by rintro _ _ _ ⟨s, rfl⟩ t ht; exact ⟨⟨t, Multiset.nodup_of_le ht.2 s.2⟩, rfl⟩⟩ /-- Finsets form an order-connected suborder of sets. -/ lemma ordConnected_range_coe : Set.OrdConnected (Set.range ((↑) : Finset α → Set α)) := ⟨by rintro _ _ _ ⟨s, rfl⟩ t ht; exact ⟨_, (s.finite_toSet.subset ht.2).coe_toFinset⟩⟩ -@[simp] lemma val_wcovby_val : s.1 ⩿ t.1 ↔ s ⩿ t := - ordConnected_range_val.apply_wcovby_apply_iff ⟨⟨_, val_injective⟩, val_le_iff⟩ +@[simp] lemma val_wcovBy_val : s.1 ⩿ t.1 ↔ s ⩿ t := + ordConnected_range_val.apply_wcovBy_apply_iff ⟨⟨_, val_injective⟩, val_le_iff⟩ -@[simp] lemma val_covby_val : s.1 ⋖ t.1 ↔ s ⋖ t := - ordConnected_range_val.apply_covby_apply_iff ⟨⟨_, val_injective⟩, val_le_iff⟩ +@[simp] lemma val_covBy_val : s.1 ⋖ t.1 ↔ s ⋖ t := + ordConnected_range_val.apply_covBy_apply_iff ⟨⟨_, val_injective⟩, val_le_iff⟩ -@[simp] lemma coe_wcovby_coe : (s : Set α) ⩿ t ↔ s ⩿ t := - ordConnected_range_coe.apply_wcovby_apply_iff ⟨⟨_, coe_injective⟩, coe_subset⟩ +@[simp] lemma coe_wcovBy_coe : (s : Set α) ⩿ t ↔ s ⩿ t := + ordConnected_range_coe.apply_wcovBy_apply_iff ⟨⟨_, coe_injective⟩, coe_subset⟩ -@[simp] lemma coe_covby_coe : (s : Set α) ⋖ t ↔ s ⋖ t := - ordConnected_range_coe.apply_covby_apply_iff ⟨⟨_, coe_injective⟩, coe_subset⟩ +@[simp] lemma coe_covBy_coe : (s : Set α) ⋖ t ↔ s ⋖ t := + ordConnected_range_coe.apply_covBy_apply_iff ⟨⟨_, coe_injective⟩, coe_subset⟩ -alias ⟨_, _root_.wcovby.finset_val⟩ := val_wcovby_val -alias ⟨_, _root_.Covby.finset_val⟩ := val_covby_val -alias ⟨_, _root_.wcovby.finset_coe⟩ := coe_wcovby_coe -alias ⟨_, _root_.Covby.finset_coe⟩ := coe_covby_coe +alias ⟨_, _root_.WCovBy.finset_val⟩ := val_wcovBy_val +alias ⟨_, _root_.CovBy.finset_val⟩ := val_covBy_val +alias ⟨_, _root_.WCovBy.finset_coe⟩ := coe_wcovBy_coe +alias ⟨_, _root_.CovBy.finset_coe⟩ := coe_covBy_coe -@[simp] lemma covby_cons (ha : a ∉ s) : s ⋖ s.cons a ha := by simp [← val_covby_val] +@[simp] lemma covBy_cons (ha : a ∉ s) : s ⋖ s.cons a ha := by simp [← val_covBy_val] -lemma _root_.Covby.exists_finset_cons (h : s ⋖ t) : ∃ a, ∃ ha : a ∉ s, s.cons a ha = t := +lemma _root_.CovBy.exists_finset_cons (h : s ⋖ t) : ∃ a, ∃ ha : a ∉ s, s.cons a ha = t := let ⟨a, ha, hst⟩ := ssubset_iff_exists_cons_subset.1 h.lt - ⟨a, ha, (hst.eq_of_not_ssuperset $ h.2 $ ssubset_cons _).symm⟩ + ⟨a, ha, (hst.eq_of_not_ssuperset <| h.2 <| ssubset_cons _).symm⟩ -lemma covby_iff_exists_cons : s ⋖ t ↔ ∃ a, ∃ ha : a ∉ s, s.cons a ha = t := - ⟨Covby.exists_finset_cons, by rintro ⟨a, ha, rfl⟩; exact covby_cons _⟩ +lemma covBy_iff_exists_cons : s ⋖ t ↔ ∃ a, ∃ ha : a ∉ s, s.cons a ha = t := + ⟨CovBy.exists_finset_cons, by rintro ⟨a, ha, rfl⟩; exact covBy_cons _⟩ -lemma _root_.Covby.card_finset (h : s ⋖ t) : s.card ⋖ t.card := (val_covby_val.2 h).card_multiset +lemma _root_.CovBy.card_finset (h : s ⋖ t) : s.card ⋖ t.card := (val_covBy_val.2 h).card_multiset section DecidableEq variable [DecidableEq α] -@[simp] lemma wcovby_insert (s : Finset α) (a : α) : s ⩿ insert a s := by simp [← coe_wcovby_coe] -@[simp] lemma erase_wcovby (s : Finset α) (a : α) : s.erase a ⩿ s := by simp [← coe_wcovby_coe] +@[simp] lemma wcovBy_insert (s : Finset α) (a : α) : s ⩿ insert a s := by simp [← coe_wcovBy_coe] +@[simp] lemma erase_wcovBy (s : Finset α) (a : α) : s.erase a ⩿ s := by simp [← coe_wcovBy_coe] -lemma covby_insert (ha : a ∉ s) : s ⋖ insert a s := - (wcovby_insert _ _).covby_of_lt $ ssubset_insert ha +lemma covBy_insert (ha : a ∉ s) : s ⋖ insert a s := + (wcovBy_insert _ _).covBy_of_lt <| ssubset_insert ha -@[simp] lemma erase_covby (ha : a ∈ s) : s.erase a ⋖ s := ⟨erase_ssubset ha, (erase_wcovby _ _).2⟩ +@[simp] lemma erase_covBy (ha : a ∈ s) : s.erase a ⋖ s := ⟨erase_ssubset ha, (erase_wcovBy _ _).2⟩ -lemma _root_.Covby.exists_finset_insert (h : s ⋖ t) : ∃ a ∉ s, insert a s = t := by +lemma _root_.CovBy.exists_finset_insert (h : s ⋖ t) : ∃ a ∉ s, insert a s = t := by simpa using h.exists_finset_cons -lemma _root_.Covby.exists_finset_erase (h : s ⋖ t) : ∃ a ∈ t, t.erase a = s := by +lemma _root_.CovBy.exists_finset_erase (h : s ⋖ t) : ∃ a ∈ t, t.erase a = s := by simpa only [← coe_inj, coe_erase] using h.finset_coe.exists_set_sdiff_singleton -lemma covby_iff_exists_insert : s ⋖ t ↔ ∃ a ∉ s, insert a s = t := by - simp only [← coe_covby_coe, Set.covby_iff_exists_insert, ← coe_inj, coe_insert, mem_coe] +lemma covBy_iff_exists_insert : s ⋖ t ↔ ∃ a ∉ s, insert a s = t := by + simp only [← coe_covBy_coe, Set.covBy_iff_exists_insert, ← coe_inj, coe_insert, mem_coe] -lemma covby_iff_card_sdiff_eq_one : t ⋖ s ↔ t ⊆ s ∧ (s \ t).card = 1 := by - rw [covby_iff_exists_insert] +lemma covBy_iff_card_sdiff_eq_one : t ⋖ s ↔ t ⊆ s ∧ (s \ t).card = 1 := by + rw [covBy_iff_exists_insert] constructor · rintro ⟨a, ha, rfl⟩ simp [*] · simp_rw [card_eq_one] rintro ⟨hts, a, ha⟩ - refine ⟨a, (mem_sdiff.1 $ superset_of_eq ha $ mem_singleton_self _).2, ?_⟩ + refine ⟨a, (mem_sdiff.1 <| superset_of_eq ha <| mem_singleton_self _).2, ?_⟩ rw [insert_eq, ← ha, sdiff_union_of_subset hts] -lemma covby_iff_exists_erase : s ⋖ t ↔ ∃ a ∈ t, t.erase a = s := by - simp only [← coe_covby_coe, Set.covby_iff_exists_sdiff_singleton, ← coe_inj, coe_erase, mem_coe] +lemma covBy_iff_exists_erase : s ⋖ t ↔ ∃ a ∈ t, t.erase a = s := by + simp only [← coe_covBy_coe, Set.covBy_iff_exists_sdiff_singleton, ← coe_inj, coe_erase, mem_coe] end DecidableEq @@ -132,7 +132,7 @@ end DecidableEq ⟨singleton_ne_empty a, fun _ ↦ eq_empty_of_ssubset_singleton⟩ protected lemma isAtom_iff : IsAtom s ↔ ∃ a, s = {a} := by - simp [← bot_covby_iff, covby_iff_exists_cons, eq_comm] + simp [← bot_covBy_iff, covBy_iff_exists_cons, eq_comm] section Fintype variable [Fintype α] [DecidableEq α] @@ -149,7 +149,7 @@ to record that the inclusion `Finset α ↪ Multiset α` preserves the covering instance instGradeMinOrder_multiset : GradeMinOrder (Multiset α) (Finset α) where grade := val grade_strictMono := val_strictMono - covby_grade _ _ := Covby.finset_val + covBy_grade _ _ := CovBy.finset_val isMin_grade s hs := by rw [isMin_iff_eq_bot.1 hs]; exact isMin_bot @[simp] lemma grade_multiset_eq (s : Finset α) : grade (Multiset α) s = s.1 := rfl @@ -157,7 +157,7 @@ instance instGradeMinOrder_multiset : GradeMinOrder (Multiset α) (Finset α) wh instance instGradeMinOrder_nat : GradeMinOrder ℕ (Finset α) where grade := card grade_strictMono := card_strictMono - covby_grade _ _ := Covby.card_finset + covBy_grade _ _ := CovBy.card_finset isMin_grade s hs := by rw [isMin_iff_eq_bot.1 hs]; exact isMin_bot @[simp] lemma grade_eq (s : Finset α) : grade ℕ s = s.card := rfl diff --git a/Mathlib/Data/Finset/Image.lean b/Mathlib/Data/Finset/Image.lean index 7dcd56092a49d..ed72378615a39 100644 --- a/Mathlib/Data/Finset/Image.lean +++ b/Mathlib/Data/Finset/Image.lean @@ -162,6 +162,18 @@ theorem map_subset_map {s₁ s₂ : Finset α} : s₁.map f ⊆ s₂.map f ↔ s fun h => by simp [subset_def, Multiset.map_subset_map h]⟩ #align finset.map_subset_map Finset.map_subset_map +/-- The `Finset` version of `Equiv.subset_symm_image`. -/ +theorem subset_map_symm {t : Finset β} {f : α ≃ β} : s ⊆ t.map f.symm ↔ s.map f ⊆ t := by + constructor <;> intro h x hx + · simp only [mem_map_equiv, Equiv.symm_symm] at hx + simpa using h hx + · simp only [mem_map_equiv] + exact h (by simp [hx]) + +/-- The `Finset` version of `Equiv.symm_image_subset`. -/ +theorem map_symm_subset {t : Finset β} {f : α ≃ β} : t.map f.symm ⊆ s ↔ t ⊆ s.map f := by + simp only [← subset_map_symm, Equiv.symm_symm] + /-- Associate to an embedding `f` from `α` to `β` the order embedding that maps a finset to its image under `f`. -/ def mapEmbedding (f : α ↪ β) : Finset α ↪o Finset β := @@ -408,22 +420,24 @@ theorem fiber_nonempty_iff_mem_image (f : α → β) (s : Finset α) (y : β) : #align finset.fiber_nonempty_iff_mem_image Finset.fiber_nonempty_iff_mem_image @[simp, norm_cast] -theorem coe_image {f : α → β} : ↑(s.image f) = f '' ↑s := +theorem coe_image : ↑(s.image f) = f '' ↑s := Set.ext <| by simp only [mem_coe, mem_image, Set.mem_image, implies_true] #align finset.coe_image Finset.coe_image +@[simp] +lemma image_nonempty : (s.image f).Nonempty ↔ s.Nonempty := by + exact_mod_cast Set.image_nonempty (f := f) (s := (s : Set α)) +#align finset.nonempty.image_iff Finset.image_nonempty + protected theorem Nonempty.image (h : s.Nonempty) (f : α → β) : (s.image f).Nonempty := - let ⟨a, ha⟩ := h - ⟨f a, mem_image_of_mem f ha⟩ + image_nonempty.2 h #align finset.nonempty.image Finset.Nonempty.image -@[simp] +alias ⟨Nonempty.of_image, _⟩ := image_nonempty + +@[deprecated image_nonempty] -- Since 29 December 2023 theorem Nonempty.image_iff (f : α → β) : (s.image f).Nonempty ↔ s.Nonempty := - ⟨fun ⟨_, hy⟩ => - let ⟨x, hx, _⟩ := mem_image.mp hy - ⟨x, hx⟩, - fun h => h.image f⟩ -#align finset.nonempty.image_iff Finset.Nonempty.image_iff + image_nonempty theorem image_toFinset [DecidableEq α] {s : Multiset α} : s.toFinset.image f = (s.map f).toFinset := @@ -571,6 +585,7 @@ theorem image_sdiff [DecidableEq α] {f : α → β} (s t : Finset α) (hf : Inj exact Set.image_diff hf _ _ #align finset.image_sdiff Finset.image_sdiff +open scoped symmDiff in theorem image_symmDiff [DecidableEq α] {f : α → β} (s t : Finset α) (hf : Injective f) : (s ∆ t).image f = s.image f ∆ t.image f := coe_injective <| by @@ -816,6 +831,8 @@ theorem fin_map {n} {s : Finset ℕ} : (s.fin n).map Fin.valEmbedding = s.filter simp [Finset.fin, Finset.map_map] #align finset.fin_map Finset.fin_map +/-- If a `Finset` is a subset of the image of a `Set` under `f`, +then it is equal to the `Finset.image` of a `Finset` subset of that `Set`. -/ theorem subset_image_iff [DecidableEq β] {s : Set α} {t : Finset β} {f : α → β} : ↑t ⊆ f '' s ↔ ∃ s' : Finset α, ↑s' ⊆ s ∧ s'.image f = t := by constructor; swap diff --git a/Mathlib/Data/Finset/Interval.lean b/Mathlib/Data/Finset/Interval.lean index dddeb3e61d7be..9c787cd92a468 100644 --- a/Mathlib/Data/Finset/Interval.lean +++ b/Mathlib/Data/Finset/Interval.lean @@ -140,7 +140,7 @@ section Cons /-- A function `f` from `Finset α` is monotone if and only if `f s ≤ f (cons a s ha)` for all `s` and `a ∉ s`. -/ lemma monotone_iff_forall_le_cons : Monotone f ↔ ∀ s, ∀ ⦃a⦄ (ha), f s ≤ f (cons a s ha) := by - classical simp [monotone_iff_forall_covby, covby_iff_exists_cons] + classical simp [monotone_iff_forall_covBy, covBy_iff_exists_cons] /-- A function `f` from `Finset α` is antitone if and only if `f (cons a s ha) ≤ f s` for all `s` and `a ∉ s`. -/ @@ -150,7 +150,7 @@ lemma antitone_iff_forall_cons_le : Antitone f ↔ ∀ s ⦃a⦄ ha, f (cons a s /-- A function `f` from `Finset α` is strictly monotone if and only if `f s < f (cons a s ha)` for all `s` and `a ∉ s`. -/ lemma strictMono_iff_forall_lt_cons : StrictMono f ↔ ∀ s ⦃a⦄ ha, f s < f (cons a s ha) := by - classical simp [strictMono_iff_forall_covby, covby_iff_exists_cons] + classical simp [strictMono_iff_forall_covBy, covBy_iff_exists_cons] /-- A function `f` from `Finset α` is strictly antitone if and only if `f (cons a s ha) < f s` for all `s` and `a ∉ s`. -/ diff --git a/Mathlib/Data/Finset/Lattice.lean b/Mathlib/Data/Finset/Lattice.lean index b4396a748263a..1499417cbcfca 100644 --- a/Mathlib/Data/Finset/Lattice.lean +++ b/Mathlib/Data/Finset/Lattice.lean @@ -60,6 +60,7 @@ theorem sup_insert [DecidableEq β] {b : β} : (insert b s : Finset β).sup f = fold_insert_idem #align finset.sup_insert Finset.sup_insert +@[simp] theorem sup_image [DecidableEq β] (s : Finset γ) (f : γ → β) (g : β → α) : (s.image f).sup g = s.sup (g ∘ f) := fold_image_idem @@ -249,7 +250,7 @@ theorem sup_induction {p : α → Prop} (hb : p ⊥) (hp : ∀ a₁, p a₁ → theorem sup_le_of_le_directed {α : Type*} [SemilatticeSup α] [OrderBot α] (s : Set α) (hs : s.Nonempty) (hdir : DirectedOn (· ≤ ·) s) (t : Finset α) : - (∀ x ∈ t, ∃ y ∈ s, x ≤ y) → ∃ x, x ∈ s ∧ t.sup id ≤ x := by + (∀ x ∈ t, ∃ y ∈ s, x ≤ y) → ∃ x ∈ s, t.sup id ≤ x := by classical induction' t using Finset.induction_on with a r _ ih h · simpa only [forall_prop_of_true, and_true_iff, forall_prop_of_false, bot_le, not_false_iff, @@ -304,7 +305,7 @@ theorem sup_set_eq_biUnion (s : Finset α) (f : α → Set β) : s.sup f = ⋃ x theorem sup_eq_sSup_image [CompleteLattice β] (s : Finset α) (f : α → β) : s.sup f = sSup (f '' s) := - by classical rw [← Finset.coe_image, ← sup_id_eq_sSup, sup_image, Function.comp.left_id] + by classical rw [← Finset.coe_image, ← sup_id_eq_sSup, sup_image, Function.id_comp] #align finset.sup_eq_Sup_image Finset.sup_eq_sSup_image /-! ### inf -/ @@ -341,6 +342,7 @@ theorem inf_insert [DecidableEq β] {b : β} : (insert b s : Finset β).inf f = fold_insert_idem #align finset.inf_insert Finset.inf_insert +@[simp] theorem inf_image [DecidableEq β] (s : Finset γ) (f : γ → β) (g : β → α) : (s.image f).inf g = s.inf (g ∘ f) := fold_image_idem @@ -794,32 +796,34 @@ theorem coe_sup' : ((s.sup' H f : α) : WithBot α) = s.sup ((↑) ∘ f) := by #align finset.coe_sup' Finset.coe_sup' @[simp] -theorem sup'_cons {b : β} {hb : b ∉ s} {h : (cons b s hb).Nonempty} : - (cons b s hb).sup' h f = f b ⊔ s.sup' H f := by +theorem sup'_cons {b : β} {hb : b ∉ s} : + (cons b s hb).sup' (nonempty_cons hb) f = f b ⊔ s.sup' H f := by rw [← WithBot.coe_eq_coe] simp [WithBot.coe_sup] #align finset.sup'_cons Finset.sup'_cons @[simp] -theorem sup'_insert [DecidableEq β] {b : β} {h : (insert b s).Nonempty} : - (insert b s).sup' h f = f b ⊔ s.sup' H f := by +theorem sup'_insert [DecidableEq β] {b : β} : + (insert b s).sup' (insert_nonempty _ _) f = f b ⊔ s.sup' H f := by rw [← WithBot.coe_eq_coe] simp [WithBot.coe_sup] #align finset.sup'_insert Finset.sup'_insert @[simp] -theorem sup'_singleton {b : β} {h : ({b} : Finset β).Nonempty} : ({b} : Finset β).sup' h f = f b := +theorem sup'_singleton {b : β} : ({b} : Finset β).sup' (singleton_nonempty _) f = f b := rfl #align finset.sup'_singleton Finset.sup'_singleton -theorem sup'_le {a : α} (hs : ∀ b ∈ s, f b ≤ a) : s.sup' H f ≤ a := by - rw [← WithBot.coe_le_coe, coe_sup'] - exact Finset.sup_le fun b h => WithBot.coe_le_coe.2 <| hs b h +@[simp] +theorem sup'_le_iff {a : α} : s.sup' H f ≤ a ↔ ∀ b ∈ s, f b ≤ a := by + simp_rw [← @WithBot.coe_le_coe α, coe_sup', Finset.sup_le_iff]; rfl +#align finset.sup'_le_iff Finset.sup'_le_iff + +alias ⟨_, sup'_le⟩ := sup'_le_iff #align finset.sup'_le Finset.sup'_le -theorem le_sup' {b : β} (h : b ∈ s) : f b ≤ s.sup' ⟨b, h⟩ f := by - rw [← WithBot.coe_le_coe, coe_sup'] - exact le_sup (f := fun c => WithBot.some (f c)) h +theorem le_sup' {b : β} (h : b ∈ s) : f b ≤ s.sup' ⟨b, h⟩ f := + (sup'_le_iff ⟨b, h⟩ f).1 le_rfl b h #align finset.le_sup' Finset.le_sup' theorem le_sup'_of_le {a : α} {b : β} (hb : b ∈ s) (h : a ≤ f b) : a ≤ s.sup' ⟨b, hb⟩ f := @@ -835,11 +839,6 @@ theorem sup'_const (a : α) : s.sup' H (fun _ => a) = a := by · apply le_sup' (fun _ => a) H.choose_spec #align finset.sup'_const Finset.sup'_const -@[simp] -theorem sup'_le_iff {a : α} : s.sup' H f ≤ a ↔ ∀ b ∈ s, f b ≤ a := - Iff.intro (fun h _ hb => le_trans (le_sup' f hb) h) (sup'_le H f) -#align finset.sup'_le_iff Finset.sup'_le_iff - theorem sup'_union [DecidableEq β] {s₁ s₂ : Finset β} (h₁ : s₁.Nonempty) (h₂ : s₂.Nonempty) (f : β → α) : (s₁ ∪ s₂).sup' (h₁.mono <| subset_union_left _ _) f = s₁.sup' h₁ f ⊔ s₂.sup' h₂ f := @@ -857,13 +856,13 @@ protected theorem sup'_comm {t : Finset γ} (hs : s.Nonempty) (ht : t.Nonempty) eq_of_forall_ge_iff fun a => by simpa using forall₂_swap #align finset.sup'_comm Finset.sup'_comm -theorem sup'_product_left {t : Finset γ} (hs : s.Nonempty) (ht : t.Nonempty) (f : β × γ → α) : - (s ×ˢ t).sup' (hs.product ht) f = s.sup' hs fun i => t.sup' ht fun i' => f ⟨i, i'⟩ := +theorem sup'_product_left {t : Finset γ} (h : (s ×ˢ t).Nonempty) (f : β × γ → α) : + (s ×ˢ t).sup' h f = s.sup' h.fst fun i => t.sup' h.snd fun i' => f ⟨i, i'⟩ := eq_of_forall_ge_iff fun a => by simp [@forall_swap _ γ] #align finset.sup'_product_left Finset.sup'_product_left -theorem sup'_product_right {t : Finset γ} (hs : s.Nonempty) (ht : t.Nonempty) (f : β × γ → α) : - (s ×ˢ t).sup' (hs.product ht) f = t.sup' ht fun i' => s.sup' hs fun i => f ⟨i, i'⟩ := by +theorem sup'_product_right {t : Finset γ} (h : (s ×ˢ t).Nonempty) (f : β × γ → α) : + (s ×ˢ t).sup' h f = t.sup' h.snd fun i' => s.sup' h.fst fun i => f ⟨i, i'⟩ := by rw [sup'_product_left, Finset.sup'_comm] #align finset.sup'_product_right Finset.sup'_product_right @@ -887,24 +886,6 @@ lemma sup'_prodMap (hst : (s ×ˢ t).Nonempty) (f : ι → α) (g : κ → β) : end Prod -theorem comp_sup'_eq_sup'_comp [SemilatticeSup γ] {s : Finset β} (H : s.Nonempty) {f : β → α} - (g : α → γ) (g_sup : ∀ x y, g (x ⊔ y) = g x ⊔ g y) : g (s.sup' H f) = s.sup' H (g ∘ f) := by - rw [← WithBot.coe_eq_coe, coe_sup'] - let g' := WithBot.map g - show g' ↑(s.sup' H f) = s.sup fun a => g' ↑(f a) - rw [coe_sup'] - refine' comp_sup_eq_sup_comp g' _ rfl - intro f₁ f₂ - cases f₁ using WithBot.recBotCoe with - | bot => - rw [bot_sup_eq] - exact bot_sup_eq.symm - | coe f₁ => - cases f₂ using WithBot.recBotCoe with - | bot => rfl - | coe f₂ => exact congr_arg _ (g_sup f₁ f₂) -#align finset.comp_sup'_eq_sup'_comp Finset.comp_sup'_eq_sup'_comp - theorem sup'_induction {p : α → Prop} (hp : ∀ a₁, p a₁ → ∀ a₂, p a₂ → p (a₁ ⊔ a₂)) (hs : ∀ b ∈ s, p (f b)) : p (s.sup' H f) := by show @WithBot.recBotCoe α (fun _ => Prop) True p ↑(s.sup' H f) @@ -931,26 +912,45 @@ theorem sup'_congr {t : Finset β} {f g : β → α} (h₁ : s = t) (h₂ : ∀ simp (config := { contextual := true }) only [sup'_le_iff, h₂] #align finset.sup'_congr Finset.sup'_congr +theorem comp_sup'_eq_sup'_comp [SemilatticeSup γ] {s : Finset β} (H : s.Nonempty) {f : β → α} + (g : α → γ) (g_sup : ∀ x y, g (x ⊔ y) = g x ⊔ g y) : g (s.sup' H f) = s.sup' H (g ∘ f) := by + refine' H.cons_induction _ _ <;> intros <;> simp [*] +#align finset.comp_sup'_eq_sup'_comp Finset.comp_sup'_eq_sup'_comp + @[simp] theorem _root_.map_finset_sup' [SemilatticeSup β] [SupHomClass F α β] (f : F) {s : Finset ι} (hs) - (g : ι → α) : f (s.sup' hs g) = s.sup' hs (f ∘ g) := by - refine' hs.cons_induction _ _ <;> intros <;> simp [*] + (g : ι → α) : f (s.sup' hs g) = s.sup' hs (f ∘ g) := + comp_sup'_eq_sup'_comp hs _ (map_sup f) #align map_finset_sup' map_finset_sup' +/-- To rewrite from right to left, use `Finset.sup'_comp_eq_image`. -/ @[simp] theorem sup'_image [DecidableEq β] {s : Finset γ} {f : γ → β} (hs : (s.image f).Nonempty) - (g : β → α) (hs' : s.Nonempty := (Nonempty.image_iff _).1 hs) : - (s.image f).sup' hs g = s.sup' hs' (g ∘ f) := by + (g : β → α) : + (s.image f).sup' hs g = s.sup' hs.of_image (g ∘ f) := by rw [← WithBot.coe_eq_coe]; simp only [coe_sup', sup_image, WithBot.coe_sup]; rfl #align finset.sup'_image Finset.sup'_image +/-- A version of `Finset.sup'_image` with LHS and RHS reversed. +Also, this lemma assumes that `s` is nonempty instead of assuming that its image is nonempty. -/ +lemma sup'_comp_eq_image [DecidableEq β] {s : Finset γ} {f : γ → β} (hs : s.Nonempty) (g : β → α) : + s.sup' hs (g ∘ f) = (s.image f).sup' (hs.image f) g := + .symm <| sup'_image _ _ + +/-- To rewrite from right to left, use `Finset.sup'_comp_eq_map`. -/ @[simp] -theorem sup'_map {s : Finset γ} {f : γ ↪ β} (g : β → α) (hs : (s.map f).Nonempty) - (hs' : s.Nonempty := Finset.map_nonempty.mp hs) : (s.map f).sup' hs g = s.sup' hs' (g ∘ f) := by +theorem sup'_map {s : Finset γ} {f : γ ↪ β} (g : β → α) (hs : (s.map f).Nonempty) : + (s.map f).sup' hs g = s.sup' (map_nonempty.1 hs) (g ∘ f) := by rw [← WithBot.coe_eq_coe, coe_sup', sup_map, coe_sup'] rfl #align finset.sup'_map Finset.sup'_map +/-- A version of `Finset.sup'_map` with LHS and RHS reversed. +Also, this lemma assumes that `s` is nonempty instead of assuming that its image is nonempty. -/ +lemma sup'_comp_eq_map {s : Finset γ} {f : γ ↪ β} (g : β → α) (hs : s.Nonempty) : + s.sup' hs (g ∘ f) = (s.map f).sup' (map_nonempty.2 hs) g := + .symm <| sup'_map _ _ + theorem sup'_mono {s₁ s₂ : Finset β} (h : s₁ ⊆ s₂) (h₁ : s₁.Nonempty): s₁.sup' h₁ f ≤ s₂.sup' (h₁.mono h) f := Finset.sup'_le h₁ _ (fun _ hb => le_sup' _ (h hb)) @@ -981,22 +981,27 @@ theorem coe_inf' : ((s.inf' H f : α) : WithTop α) = s.inf ((↑) ∘ f) := #align finset.coe_inf' Finset.coe_inf' @[simp] -theorem inf'_cons {b : β} {hb : b ∉ s} {h : (cons b s hb).Nonempty} : - (cons b s hb).inf' h f = f b ⊓ s.inf' H f := - @sup'_cons αᵒᵈ _ _ _ H f _ _ h +theorem inf'_cons {b : β} {hb : b ∉ s} : + (cons b s hb).inf' (nonempty_cons hb) f = f b ⊓ s.inf' H f := + @sup'_cons αᵒᵈ _ _ _ H f _ _ #align finset.inf'_cons Finset.inf'_cons @[simp] -theorem inf'_insert [DecidableEq β] {b : β} {h : (insert b s).Nonempty} : - (insert b s).inf' h f = f b ⊓ s.inf' H f := - @sup'_insert αᵒᵈ _ _ _ H f _ _ h +theorem inf'_insert [DecidableEq β] {b : β} : + (insert b s).inf' (insert_nonempty _ _) f = f b ⊓ s.inf' H f := + @sup'_insert αᵒᵈ _ _ _ H f _ _ #align finset.inf'_insert Finset.inf'_insert @[simp] -theorem inf'_singleton {b : β} {h : ({b} : Finset β).Nonempty} : ({b} : Finset β).inf' h f = f b := +theorem inf'_singleton {b : β} : ({b} : Finset β).inf' (singleton_nonempty _) f = f b := rfl #align finset.inf'_singleton Finset.inf'_singleton +@[simp] +theorem le_inf'_iff {a : α} : a ≤ s.inf' H f ↔ ∀ b ∈ s, a ≤ f b := + sup'_le_iff (α := αᵒᵈ) H f +#align finset.le_inf'_iff Finset.le_inf'_iff + theorem le_inf' {a : α} (hs : ∀ b ∈ s, a ≤ f b) : a ≤ s.inf' H f := sup'_le (α := αᵒᵈ) H f hs #align finset.le_inf' Finset.le_inf' @@ -1013,11 +1018,6 @@ theorem inf'_const (a : α) : (s.inf' H fun _ => a) = a := sup'_const (α := αᵒᵈ) H a #align finset.inf'_const Finset.inf'_const -@[simp] -theorem le_inf'_iff {a : α} : a ≤ s.inf' H f ↔ ∀ b ∈ s, a ≤ f b := - sup'_le_iff (α := αᵒᵈ) H f -#align finset.le_inf'_iff Finset.le_inf'_iff - theorem inf'_union [DecidableEq β] {s₁ s₂ : Finset β} (h₁ : s₁.Nonempty) (h₂ : s₂.Nonempty) (f : β → α) : (s₁ ∪ s₂).inf' (h₁.mono <| subset_union_left _ _) f = s₁.inf' h₁ f ⊓ s₂.inf' h₂ f := @@ -1035,14 +1035,14 @@ protected theorem inf'_comm {t : Finset γ} (hs : s.Nonempty) (ht : t.Nonempty) @Finset.sup'_comm αᵒᵈ _ _ _ _ _ hs ht _ #align finset.inf'_comm Finset.inf'_comm -theorem inf'_product_left {t : Finset γ} (hs : s.Nonempty) (ht : t.Nonempty) (f : β × γ → α) : - (s ×ˢ t).inf' (hs.product ht) f = s.inf' hs fun i => t.inf' ht fun i' => f ⟨i, i'⟩ := - @sup'_product_left αᵒᵈ _ _ _ _ _ hs ht _ +theorem inf'_product_left {t : Finset γ} (h : (s ×ˢ t).Nonempty) (f : β × γ → α) : + (s ×ˢ t).inf' h f = s.inf' h.fst fun i => t.inf' h.snd fun i' => f ⟨i, i'⟩ := + sup'_product_left (α := αᵒᵈ) h f #align finset.inf'_product_left Finset.inf'_product_left -theorem inf'_product_right {t : Finset γ} (hs : s.Nonempty) (ht : t.Nonempty) (f : β × γ → α) : - (s ×ˢ t).inf' (hs.product ht) f = t.inf' ht fun i' => s.inf' hs fun i => f ⟨i, i'⟩ := - @sup'_product_right αᵒᵈ _ _ _ _ _ hs ht _ +theorem inf'_product_right {t : Finset γ} (h : (s ×ˢ t).Nonempty) (f : β × γ → α) : + (s ×ˢ t).inf' h f = t.inf' h.snd fun i' => s.inf' h.fst fun i => f ⟨i, i'⟩ := + sup'_product_right (α := αᵒᵈ) h f #align finset.inf'_product_right Finset.inf'_product_right section Prod @@ -1088,19 +1088,33 @@ theorem _root_.map_finset_inf' [SemilatticeInf β] [InfHomClass F α β] (f : F) refine' hs.cons_induction _ _ <;> intros <;> simp [*] #align map_finset_inf' map_finset_inf' +/-- To rewrite from right to left, use `Finset.inf'_comp_eq_image`. -/ @[simp] theorem inf'_image [DecidableEq β] {s : Finset γ} {f : γ → β} (hs : (s.image f).Nonempty) - (g : β → α) (hs' : s.Nonempty := (Nonempty.image_iff _).1 hs) : - (s.image f).inf' hs g = s.inf' hs' (g ∘ f) := - @sup'_image αᵒᵈ _ _ _ _ _ _ hs _ hs' + (g : β → α) : + (s.image f).inf' hs g = s.inf' hs.of_image (g ∘ f) := + @sup'_image αᵒᵈ _ _ _ _ _ _ hs _ #align finset.inf'_image Finset.inf'_image +/-- A version of `Finset.inf'_image` with LHS and RHS reversed. +Also, this lemma assumes that `s` is nonempty instead of assuming that its image is nonempty. -/ +lemma inf'_comp_eq_image [DecidableEq β] {s : Finset γ} {f : γ → β} (hs : s.Nonempty) (g : β → α) : + s.inf' hs (g ∘ f) = (s.image f).inf' (hs.image f) g := + sup'_comp_eq_image (α := αᵒᵈ) hs g + +/-- To rewrite from right to left, use `Finset.inf'_comp_eq_map`. -/ @[simp] -theorem inf'_map {s : Finset γ} {f : γ ↪ β} (g : β → α) (hs : (s.map f).Nonempty) - (hs' : s.Nonempty := Finset.map_nonempty.mp hs) : (s.map f).inf' hs g = s.inf' hs' (g ∘ f) := - sup'_map (α := αᵒᵈ) _ hs hs' +theorem inf'_map {s : Finset γ} {f : γ ↪ β} (g : β → α) (hs : (s.map f).Nonempty) : + (s.map f).inf' hs g = s.inf' (map_nonempty.1 hs) (g ∘ f) := + sup'_map (α := αᵒᵈ) _ hs #align finset.inf'_map Finset.inf'_map +/-- A version of `Finset.inf'_map` with LHS and RHS reversed. +Also, this lemma assumes that `s` is nonempty instead of assuming that its image is nonempty. -/ +lemma inf'_comp_eq_map {s : Finset γ} {f : γ ↪ β} (g : β → α) (hs : s.Nonempty) : + s.inf' hs (g ∘ f) = (s.map f).inf' (map_nonempty.2 hs) g := + sup'_comp_eq_map (α := αᵒᵈ) g hs + theorem inf'_mono {s₁ s₂ : Finset β} (h : s₁ ⊆ s₂) (h₁ : s₁.Nonempty) : s₂.inf' (h₁.mono h) f ≤ s₁.inf' h₁ f := Finset.le_inf' h₁ _ (fun _ hb => inf'_le _ (h hb)) @@ -1205,7 +1219,7 @@ theorem sup'_inf_distrib_right (f : ι → α) (a : α) : s.sup' hs f ⊓ a = s. theorem sup'_inf_sup' (f : ι → α) (g : κ → α) : s.sup' hs f ⊓ t.sup' ht g = (s ×ˢ t).sup' (hs.product ht) fun i => f i.1 ⊓ g i.2 := by - simp_rw [Finset.sup'_inf_distrib_right, Finset.sup'_inf_distrib_left, sup'_product_left hs ht] + simp_rw [Finset.sup'_inf_distrib_right, Finset.sup'_inf_distrib_left, sup'_product_left] #align finset.sup'_inf_sup' Finset.sup'_inf_sup' theorem inf'_sup_distrib_left (f : ι → α) (a : α) : a ⊔ s.inf' hs f = s.inf' hs fun i => a ⊔ f i := @@ -1641,24 +1655,34 @@ theorem min'_lt_of_mem_erase_min' [DecidableEq α] {a : α} (ha : a ∈ s.erase @lt_max'_of_mem_erase_max' αᵒᵈ _ s H _ a ha #align finset.min'_lt_of_mem_erase_min' Finset.min'_lt_of_mem_erase_min' +/-- To rewrite from right to left, use `Monotone.map_finset_max'`. -/ @[simp] theorem max'_image [LinearOrder β] {f : α → β} (hf : Monotone f) (s : Finset α) - (h : (s.image f).Nonempty) : (s.image f).max' h = f (s.max' ((Nonempty.image_iff f).mp h)) := by - refine' - le_antisymm (max'_le _ _ _ fun y hy => _) (le_max' _ _ (mem_image.mpr ⟨_, max'_mem _ _, rfl⟩)) - obtain ⟨x, hx, rfl⟩ := mem_image.mp hy - exact hf (le_max' _ _ hx) + (h : (s.image f).Nonempty) : (s.image f).max' h = f (s.max' h.of_image) := by + simp only [max', sup'_image] + exact .symm <| comp_sup'_eq_sup'_comp _ _ fun _ _ ↦ hf.map_max #align finset.max'_image Finset.max'_image +/-- A version of `Finset.max'_image` with LHS and RHS reversed. +Also, this version assumes that `s` is nonempty, not its image. -/ +lemma _root_.Monotone.map_finset_max' [LinearOrder β] {f : α → β} (hf : Monotone f) {s : Finset α} + (h : s.Nonempty) : f (s.max' h) = (s.image f).max' (h.image f) := + .symm <| max'_image hf .. + +/-- To rewrite from right to left, use `Monotone.map_finset_min'`. -/ @[simp] theorem min'_image [LinearOrder β] {f : α → β} (hf : Monotone f) (s : Finset α) - (h : (s.image f).Nonempty) : (s.image f).min' h = f (s.min' ((Nonempty.image_iff f).mp h)) := by - refine' - le_antisymm (min'_le _ _ (mem_image.mpr ⟨_, min'_mem _ _, rfl⟩)) (le_min' _ _ _ fun y hy => _) - obtain ⟨x, hx, rfl⟩ := mem_image.mp hy - exact hf (min'_le _ _ hx) + (h : (s.image f).Nonempty) : (s.image f).min' h = f (s.min' h.of_image) := by + simp only [min', inf'_image] + exact .symm <| comp_inf'_eq_inf'_comp _ _ fun _ _ ↦ hf.map_min #align finset.min'_image Finset.min'_image +/-- A version of `Finset.min'_image` with LHS and RHS reversed. +Also, this version assumes that `s` is nonempty, not its image. -/ +lemma _root_.Monotone.map_finset_min' [LinearOrder β] {f : α → β} (hf : Monotone f) {s : Finset α} + (h : s.Nonempty) : f (s.min' h) = (s.image f).min' (h.image f) := + .symm <| min'_image hf .. + theorem coe_max' {s : Finset α} (hs : s.Nonempty) : ↑(s.max' hs) = s.max := coe_sup' hs id #align finset.coe_max' Finset.coe_max' @@ -1899,23 +1923,7 @@ theorem count_finset_sup [DecidableEq β] (s : Finset α) (f : α → Multiset theorem mem_sup {α β} [DecidableEq β] {s : Finset α} {f : α → Multiset β} {x : β} : x ∈ s.sup f ↔ ∃ v ∈ s, x ∈ f v := by - classical - induction' s using Finset.induction_on with a s has hxs - · simp - · rw [Finset.sup_insert, Multiset.sup_eq_union, Multiset.mem_union] - constructor - · intro hxi - cases' hxi with hf hf - · refine' ⟨a, _, hf⟩ - simp only [true_or_iff, eq_self_iff_true, Finset.mem_insert] - · rcases hxs.mp hf with ⟨v, hv, hfv⟩ - refine' ⟨v, _, hfv⟩ - simp only [hv, or_true_iff, Finset.mem_insert] - · rintro ⟨v, hv, hfv⟩ - rw [Finset.mem_insert] at hv - rcases hv with (rfl | hv) - · exact Or.inl hfv - · refine' Or.inr (hxs.mpr ⟨v, hv, hfv⟩) + induction s using Finset.cons_induction <;> simp [*] #align multiset.mem_sup Multiset.mem_sup end Multiset diff --git a/Mathlib/Data/Finset/LocallyFinite.lean b/Mathlib/Data/Finset/LocallyFinite.lean index f0293ee9a027f..72d72cc237776 100644 --- a/Mathlib/Data/Finset/LocallyFinite.lean +++ b/Mathlib/Data/Finset/LocallyFinite.lean @@ -19,10 +19,10 @@ In addition, it shows that in a locally finite order `≤` and `<` are the trans respectively, `⩿` and `⋖`, which then leads to a characterization of monotone and strictly functions whose domain is a locally finite order. In particular, this file proves: -* `le_iff_transGen_wcovby`: `≤` is the transitive closure of `⩿` -* `lt_iff_transGen_covby`: `≤` is the transitive closure of `⩿` -* `monotone_iff_forall_wcovby`: Characterization of monotone functions -* `strictMono_iff_forall_covby`: Characterization of strictly monotone functions +* `le_iff_transGen_wcovBy`: `≤` is the transitive closure of `⩿` +* `lt_iff_transGen_covBy`: `≤` is the transitive closure of `⩿` +* `monotone_iff_forall_wcovBy`: Characterization of monotone functions +* `strictMono_iff_forall_covBy`: Characterization of strictly monotone functions ## TODO @@ -1192,7 +1192,7 @@ section Cover open Finset Relation set_option linter.unusedVariables false in -- `have` for wf induction triggers linter -lemma transGen_wcovby_of_le [Preorder α] [LocallyFiniteOrder α] {x y : α} (hxy : x ≤ y) : +lemma transGen_wcovBy_of_le [Preorder α] [LocallyFiniteOrder α] {x y : α} (hxy : x ≤ y) : TransGen (· ⩿ ·) x y := by -- We proceed by well-founded induction on the cardinality of `Icc x y`. -- It's impossible for the cardinality to be zero since `x ≤ y` @@ -1200,7 +1200,7 @@ lemma transGen_wcovby_of_le [Preorder α] [LocallyFiniteOrder α] {x y : α} (hx ⟨Ico_subset_Icc_self, not_subset.mpr ⟨y, ⟨right_mem_Icc.mpr hxy, right_not_mem_Ico⟩⟩⟩ by_cases hxy' : y ≤ x -- If `y ≤ x`, then `x ⩿ y` - · exact .single <| wcovby_of_le_of_le hxy hxy' + · exact .single <| wcovBy_of_le_of_le hxy hxy' /- and if `¬ y ≤ x`, then `x < y`, not because it is a linear order, but because `x ≤ y` already. In that case, since `z` is maximal in `Ico x y`, then `z ⩿ y` and we can use the induction hypothesis to show that `Relation.TransGen (· ⩿ ·) x z`. -/ @@ -1210,28 +1210,28 @@ lemma transGen_wcovby_of_le [Preorder α] [LocallyFiniteOrder α] {x y : α} (hx (Icc x z).card ≤ (Ico x y).card := card_le_card <| Icc_subset_Ico_right (mem_Ico.mp z_mem).2 _ < (Icc x y).card := this - have h₁ := transGen_wcovby_of_le (mem_Ico.mp z_mem).1 + have h₁ := transGen_wcovBy_of_le (mem_Ico.mp z_mem).1 have h₂ : z ⩿ y := by refine ⟨(mem_Ico.mp z_mem).2.le, fun c hzc hcy ↦ hz c ?_ hzc⟩ exact mem_Ico.mpr <| ⟨(mem_Ico.mp z_mem).1.trans hzc.le, hcy⟩ exact .tail h₁ h₂ -termination_by _ => (Icc x y).card +termination_by (Icc x y).card /-- In a locally finite preorder, `≤` is the transitive closure of `⩿`. -/ -lemma le_iff_transGen_wcovby [Preorder α] [LocallyFiniteOrder α] {x y : α} : +lemma le_iff_transGen_wcovBy [Preorder α] [LocallyFiniteOrder α] {x y : α} : x ≤ y ↔ TransGen (· ⩿ ·) x y := by - refine ⟨transGen_wcovby_of_le, fun h ↦ ?_⟩ + refine ⟨transGen_wcovBy_of_le, fun h ↦ ?_⟩ induction h with | single h => exact h.le | tail _ h₁ h₂ => exact h₂.trans h₁.le /-- In a locally finite partial order, `≤` is the reflexive transitive closure of `⋖`. -/ -lemma le_iff_reflTransGen_covby [PartialOrder α] [LocallyFiniteOrder α] {x y : α} : +lemma le_iff_reflTransGen_covBy [PartialOrder α] [LocallyFiniteOrder α] {x y : α} : x ≤ y ↔ ReflTransGen (· ⋖ ·) x y := by - rw [le_iff_transGen_wcovby, wcovby_eq_reflGen_covby, transGen_reflGen] + rw [le_iff_transGen_wcovBy, wcovBy_eq_reflGen_covBy, transGen_reflGen] set_option linter.unusedVariables false in -- `have` for wf induction triggers linter -lemma transGen_covby_of_lt [Preorder α] [LocallyFiniteOrder α] {x y : α} (hxy : x < y) : +lemma transGen_covBy_of_lt [Preorder α] [LocallyFiniteOrder α] {x y : α} (hxy : x < y) : TransGen (· ⋖ ·) x y := by -- We proceed by well-founded induction on the cardinality of `Ico x y`. -- It's impossible for the cardinality to be zero since `x < y` @@ -1248,17 +1248,17 @@ lemma transGen_covby_of_lt [Preorder α] [LocallyFiniteOrder α] {x y : α} (hxy by_cases hxz : x < z /- when `x < z`, then we may use the induction hypothesis to get a chain `Relation.TransGen (· ⋖ ·) x z`, which we can extend with `Relation.TransGen.tail`. -/ - · exact .tail (transGen_covby_of_lt hxz) hzy + · exact .tail (transGen_covBy_of_lt hxz) hzy /- when `¬ x < z`, then actually `z ≤ x` (not because it's a linear order, but because `x ≤ z`), and since `z ⋖ y` we conclude that `x ⋖ y` , then `Relation.TransGen.single`. -/ · simp only [lt_iff_le_not_le, not_and, not_not] at hxz exact .single (hzy.of_le_of_lt (hxz (mem_Ico.mp z_mem).1) hxy) -termination_by _ => (Ico x y).card +termination_by (Ico x y).card /-- In a locally finite preorder, `<` is the transitive closure of `⋖`. -/ -lemma lt_iff_transGen_covby [Preorder α] [LocallyFiniteOrder α] {x y : α} : +lemma lt_iff_transGen_covBy [Preorder α] [LocallyFiniteOrder α] {x y : α} : x < y ↔ TransGen (· ⋖ ·) x y := by - refine ⟨transGen_covby_of_lt, fun h ↦ ?_⟩ + refine ⟨transGen_covBy_of_lt, fun h ↦ ?_⟩ induction h with | single hx => exact hx.1 | tail _ hb ih => exact ih.trans hb.1 @@ -1267,45 +1267,45 @@ variable {β : Type*} /-- A function from a locally finite preorder is monotone if and only if it is monotone when restricted to pairs satisfying `a ⩿ b`. -/ -lemma monotone_iff_forall_wcovby [Preorder α] [LocallyFiniteOrder α] [Preorder β] +lemma monotone_iff_forall_wcovBy [Preorder α] [LocallyFiniteOrder α] [Preorder β] (f : α → β) : Monotone f ↔ ∀ a b : α, a ⩿ b → f a ≤ f b := by refine ⟨fun hf _ _ h ↦ hf h.le, fun h a b hab ↦ ?_⟩ simpa [transGen_eq_self (r := ((· : β) ≤ ·)) transitive_le] - using TransGen.lift f h <| le_iff_transGen_wcovby.mp hab + using TransGen.lift f h <| le_iff_transGen_wcovBy.mp hab /-- A function from a locally finite partial order is monotone if and only if it is monotone when restricted to pairs satisfying `a ⋖ b`. -/ -lemma monotone_iff_forall_covby [PartialOrder α] [LocallyFiniteOrder α] [Preorder β] +lemma monotone_iff_forall_covBy [PartialOrder α] [LocallyFiniteOrder α] [Preorder β] (f : α → β) : Monotone f ↔ ∀ a b : α, a ⋖ b → f a ≤ f b := by refine ⟨fun hf _ _ h ↦ hf h.le, fun h a b hab ↦ ?_⟩ simpa [reflTransGen_eq_self (r := ((· : β) ≤ ·)) IsRefl.reflexive transitive_le] - using ReflTransGen.lift f h <| le_iff_reflTransGen_covby.mp hab + using ReflTransGen.lift f h <| le_iff_reflTransGen_covBy.mp hab /-- A function from a locally finite preorder is strictly monotone if and only if it is strictly monotone when restricted to pairs satisfying `a ⋖ b`. -/ -lemma strictMono_iff_forall_covby [Preorder α] [LocallyFiniteOrder α] [Preorder β] +lemma strictMono_iff_forall_covBy [Preorder α] [LocallyFiniteOrder α] [Preorder β] (f : α → β) : StrictMono f ↔ ∀ a b : α, a ⋖ b → f a < f b := by refine ⟨fun hf _ _ h ↦ hf h.lt, fun h a b hab ↦ ?_⟩ have := Relation.TransGen.lift f h (a := a) (b := b) - rw [← lt_iff_transGen_covby, transGen_eq_self (@lt_trans β _)] at this + rw [← lt_iff_transGen_covBy, transGen_eq_self (@lt_trans β _)] at this · exact this hab /-- A function from a locally finite preorder is antitone if and only if it is antitone when restricted to pairs satisfying `a ⩿ b`. -/ -lemma antitone_iff_forall_wcovby [Preorder α] [LocallyFiniteOrder α] [Preorder β] +lemma antitone_iff_forall_wcovBy [Preorder α] [LocallyFiniteOrder α] [Preorder β] (f : α → β) : Antitone f ↔ ∀ a b : α, a ⩿ b → f b ≤ f a := - monotone_iff_forall_wcovby (β := βᵒᵈ) f + monotone_iff_forall_wcovBy (β := βᵒᵈ) f /-- A function from a locally finite partial order is antitone if and only if it is antitone when restricted to pairs satisfying `a ⋖ b`. -/ -lemma antitone_iff_forall_covby [PartialOrder α] [LocallyFiniteOrder α] [Preorder β] +lemma antitone_iff_forall_covBy [PartialOrder α] [LocallyFiniteOrder α] [Preorder β] (f : α → β) : Antitone f ↔ ∀ a b : α, a ⋖ b → f b ≤ f a := - monotone_iff_forall_covby (β := βᵒᵈ) f + monotone_iff_forall_covBy (β := βᵒᵈ) f /-- A function from a locally finite preorder is strictly antitone if and only if it is strictly antitone when restricted to pairs satisfying `a ⋖ b`. -/ -lemma strictAnti_iff_forall_covby [Preorder α] [LocallyFiniteOrder α] [Preorder β] +lemma strictAnti_iff_forall_covBy [Preorder α] [LocallyFiniteOrder α] [Preorder β] (f : α → β) : StrictAnti f ↔ ∀ a b : α, a ⋖ b → f b < f a := - strictMono_iff_forall_covby (β := βᵒᵈ) f + strictMono_iff_forall_covBy (β := βᵒᵈ) f end Cover diff --git a/Mathlib/Data/Finset/MulAntidiagonal.lean b/Mathlib/Data/Finset/MulAntidiagonal.lean index 1abc6eea244d8..8101970182230 100644 --- a/Mathlib/Data/Finset/MulAntidiagonal.lean +++ b/Mathlib/Data/Finset/MulAntidiagonal.lean @@ -22,29 +22,29 @@ open Pointwise variable {α : Type*} {s t : Set α} @[to_additive] -theorem IsPwo.mul [OrderedCancelCommMonoid α] (hs : s.IsPwo) (ht : t.IsPwo) : IsPwo (s * t) := by +theorem IsPWO.mul [OrderedCancelCommMonoid α] (hs : s.IsPWO) (ht : t.IsPWO) : IsPWO (s * t) := by rw [← image_mul_prod] exact (hs.prod ht).image_of_monotone (monotone_fst.mul' monotone_snd) -#align set.is_pwo.mul Set.IsPwo.mul -#align set.is_pwo.add Set.IsPwo.add +#align set.is_pwo.mul Set.IsPWO.mul +#align set.is_pwo.add Set.IsPWO.add variable [LinearOrderedCancelCommMonoid α] @[to_additive] -theorem IsWf.mul (hs : s.IsWf) (ht : t.IsWf) : IsWf (s * t) := - (hs.isPwo.mul ht.isPwo).isWf -#align set.is_wf.mul Set.IsWf.mul -#align set.is_wf.add Set.IsWf.add +theorem IsWF.mul (hs : s.IsWF) (ht : t.IsWF) : IsWF (s * t) := + (hs.isPWO.mul ht.isPWO).isWF +#align set.is_wf.mul Set.IsWF.mul +#align set.is_wf.add Set.IsWF.add @[to_additive] -theorem IsWf.min_mul (hs : s.IsWf) (ht : t.IsWf) (hsn : s.Nonempty) (htn : t.Nonempty) : +theorem IsWF.min_mul (hs : s.IsWF) (ht : t.IsWF) (hsn : s.Nonempty) (htn : t.Nonempty) : (hs.mul ht).min (hsn.mul htn) = hs.min hsn * ht.min htn := by - refine' le_antisymm (IsWf.min_le _ _ (mem_mul.2 ⟨_, hs.min_mem _, _, ht.min_mem _, rfl⟩)) _ - rw [IsWf.le_min_iff] + refine' le_antisymm (IsWF.min_le _ _ (mem_mul.2 ⟨_, hs.min_mem _, _, ht.min_mem _, rfl⟩)) _ + rw [IsWF.le_min_iff] rintro _ ⟨x, hx, y, hy, rfl⟩ exact mul_le_mul' (hs.min_le _ hx) (ht.min_le _ hy) -#align set.is_wf.min_mul Set.IsWf.min_mul -#align set.is_wf.min_add Set.IsWf.min_add +#align set.is_wf.min_mul Set.IsWF.min_mul +#align set.is_wf.min_add Set.IsWF.min_add end Set @@ -54,7 +54,7 @@ open Pointwise variable {α : Type*} -variable [OrderedCancelCommMonoid α] {s t : Set α} (hs : s.IsPwo) (ht : t.IsPwo) (a : α) +variable [OrderedCancelCommMonoid α] {s t : Set α} (hs : s.IsPWO) (ht : t.IsPWO) (a : α) /-- `Finset.mulAntidiagonal hs ht a` is the set of all pairs of an element in `s` and an element in `t` that multiply to `a`, but its construction requires proofs that `s` and `t` are @@ -63,11 +63,11 @@ well-ordered. -/ `s` and an element in `t` that add to `a`, but its construction requires proofs that `s` and `t` are well-ordered."] noncomputable def mulAntidiagonal : Finset (α × α) := - (Set.MulAntidiagonal.finite_of_isPwo hs ht a).toFinset + (Set.MulAntidiagonal.finite_of_isPWO hs ht a).toFinset #align finset.mul_antidiagonal Finset.mulAntidiagonal #align finset.add_antidiagonal Finset.addAntidiagonal -variable {hs ht a} {u : Set α} {hu : u.IsPwo} {x : α × α} +variable {hs ht a} {u : Set α} {hu : u.IsPWO} {x : α × α} @[to_additive (attr := simp)] theorem mem_mulAntidiagonal : x ∈ mulAntidiagonal hs ht a ↔ x.1 ∈ s ∧ x.2 ∈ t ∧ x.1 * x.2 = a := by @@ -106,15 +106,15 @@ theorem support_mulAntidiagonal_subset_mul : { a | (mulAntidiagonal hs ht a).Non #align finset.support_add_antidiagonal_subset_add Finset.support_addAntidiagonal_subset_add @[to_additive] -theorem isPwo_support_mulAntidiagonal : { a | (mulAntidiagonal hs ht a).Nonempty }.IsPwo := +theorem isPWO_support_mulAntidiagonal : { a | (mulAntidiagonal hs ht a).Nonempty }.IsPWO := (hs.mul ht).mono support_mulAntidiagonal_subset_mul -#align finset.is_pwo_support_mul_antidiagonal Finset.isPwo_support_mulAntidiagonal -#align finset.is_pwo_support_add_antidiagonal Finset.isPwo_support_addAntidiagonal +#align finset.is_pwo_support_mul_antidiagonal Finset.isPWO_support_mulAntidiagonal +#align finset.is_pwo_support_add_antidiagonal Finset.isPWO_support_addAntidiagonal @[to_additive] theorem mulAntidiagonal_min_mul_min {α} [LinearOrderedCancelCommMonoid α] {s t : Set α} - (hs : s.IsWf) (ht : t.IsWf) (hns : s.Nonempty) (hnt : t.Nonempty) : - mulAntidiagonal hs.isPwo ht.isPwo (hs.min hns * ht.min hnt) = {(hs.min hns, ht.min hnt)} := by + (hs : s.IsWF) (ht : t.IsWF) (hns : s.Nonempty) (hnt : t.Nonempty) : + mulAntidiagonal hs.isPWO ht.isPWO (hs.min hns * ht.min hnt) = {(hs.min hns, ht.min hnt)} := by ext ⟨a, b⟩ simp only [mem_mulAntidiagonal, mem_singleton, Prod.ext_iff] constructor diff --git a/Mathlib/Data/Finset/NAry.lean b/Mathlib/Data/Finset/NAry.lean index 9637e38b97341..1c9c4edae80ea 100644 --- a/Mathlib/Data/Finset/NAry.lean +++ b/Mathlib/Data/Finset/NAry.lean @@ -317,15 +317,12 @@ theorem image₂_mk_eq_product [DecidableEq α] [DecidableEq β] (s : Finset α) @[simp] theorem image₂_curry (f : α × β → γ) (s : Finset α) (t : Finset β) : - image₂ (curry f) s t = (s ×ˢ t).image f := by - classical - rw [← image₂_mk_eq_product, image_image₂] - dsimp (config := { unfoldPartialApp := true }) [curry] + image₂ (curry f) s t = (s ×ˢ t).image f := rfl #align finset.image₂_curry Finset.image₂_curry @[simp] theorem image_uncurry_product (f : α → β → γ) (s : Finset α) (t : Finset β) : - (s ×ˢ t).image (uncurry f) = image₂ f s t := by rw [← image₂_curry, curry_uncurry] + (s ×ˢ t).image (uncurry f) = image₂ f s t := rfl #align finset.image_uncurry_product Finset.image_uncurry_product theorem image₂_swap (f : α → β → γ) (s : Finset α) (t : Finset β) : @@ -529,6 +526,8 @@ theorem card_dvd_card_image₂_left (hf : ∀ b ∈ t, Injective fun a => f a b) s.card ∣ (image₂ f s t).card := by rw [← image₂_swap]; exact card_dvd_card_image₂_right hf ht #align finset.card_dvd_card_image₂_left Finset.card_dvd_card_image₂_left +/-- If a `Finset` is a subset of the image of two `Set`s under a binary operation, +then it is a subset of the `Finset.image₂` of two `Finset` subsets of these `Set`s. -/ theorem subset_image₂ {s : Set α} {t : Set β} (hu : ↑u ⊆ image2 f s t) : ∃ (s' : Finset α) (t' : Finset β), ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ image₂ f s' t' := by rw [← Set.image_prod, subset_image_iff] at hu @@ -540,6 +539,8 @@ theorem subset_image₂ {s : Set α} {t : Set β} (hu : ↑u ⊆ image2 f s t) : exact ⟨fun _ h ↦ (hu h).1, fun _ h ↦ (hu h).2, fun x hx ↦ mem_image₂_of_mem hx hx⟩ #align finset.subset_image₂ Finset.subset_image₂ +section UnionInter + variable [DecidableEq α] [DecidableEq β] theorem image₂_inter_union_subset_union : @@ -570,6 +571,80 @@ theorem image₂_union_inter_subset {f : α → α → β} {s t : Finset α} (hf exact image2_union_inter_subset hf #align finset.image₂_union_inter_subset Finset.image₂_union_inter_subset +end UnionInter + +section SemilatticeSup + +variable [SemilatticeSup δ] + +@[simp (default + 1)] -- otherwise `simp` doesn't use `forall_image₂_iff` +lemma sup'_image₂_le {g : γ → δ} {a : δ} (h : (image₂ f s t).Nonempty) : + sup' (image₂ f s t) h g ≤ a ↔ ∀ x ∈ s, ∀ y ∈ t, g (f x y) ≤ a := by + rw [sup'_le_iff, forall_image₂_iff] + +lemma sup'_image₂_left (g : γ → δ) (h : (image₂ f s t).Nonempty) : + sup' (image₂ f s t) h g = + sup' s h.of_image₂_left fun x ↦ sup' t h.of_image₂_right (g <| f x ·) := by + simp only [image₂, sup'_image, sup'_product_left]; rfl + +lemma sup'_image₂_right (g : γ → δ) (h : (image₂ f s t).Nonempty) : + sup' (image₂ f s t) h g = + sup' t h.of_image₂_right fun y ↦ sup' s h.of_image₂_left (g <| f · y) := by + simp only [image₂, sup'_image, sup'_product_right]; rfl + +variable [OrderBot δ] + +@[simp (default + 1)] -- otherwise `simp` doesn't use `forall_image₂_iff` +lemma sup_image₂_le {g : γ → δ} {a : δ} : + sup (image₂ f s t) g ≤ a ↔ ∀ x ∈ s, ∀ y ∈ t, g (f x y) ≤ a := by + rw [Finset.sup_le_iff, forall_image₂_iff] + +variable (s t) + +lemma sup_image₂_left (g : γ → δ) : sup (image₂ f s t) g = sup s fun x ↦ sup t (g <| f x ·) := by + simp only [image₂, sup_image, sup_product_left]; rfl + +lemma sup_image₂_right (g : γ → δ) : sup (image₂ f s t) g = sup t fun y ↦ sup s (g <| f · y) := by + simp only [image₂, sup_image, sup_product_right]; rfl + +end SemilatticeSup + +section SemilatticeInf + +variable [SemilatticeInf δ] + +@[simp (default + 1)] -- otherwise `simp` doesn't use `forall_image₂_iff` +lemma le_inf'_image₂ {g : γ → δ} {a : δ} (h : (image₂ f s t).Nonempty) : + a ≤ inf' (image₂ f s t) h g ↔ ∀ x ∈ s, ∀ y ∈ t, a ≤ g (f x y) := by + rw [le_inf'_iff, forall_image₂_iff] + +lemma inf'_image₂_left (g : γ → δ) (h : (image₂ f s t).Nonempty) : + inf' (image₂ f s t) h g = + inf' s h.of_image₂_left fun x ↦ inf' t h.of_image₂_right (g <| f x ·) := + sup'_image₂_left (δ := δᵒᵈ) g h + +lemma inf'_image₂_right (g : γ → δ) (h : (image₂ f s t).Nonempty) : + inf' (image₂ f s t) h g = + inf' t h.of_image₂_right fun y ↦ inf' s h.of_image₂_left (g <| f · y) := + sup'_image₂_right (δ := δᵒᵈ) g h + +variable [OrderTop δ] + +@[simp (default + 1)] -- otherwise `simp` doesn't use `forall_image₂_iff` +lemma le_inf_image₂ {g : γ → δ} {a : δ} : + a ≤ inf (image₂ f s t) g ↔ ∀ x ∈ s, ∀ y ∈ t, a ≤ g (f x y) := + sup_image₂_le (δ := δᵒᵈ) + +variable (s t) + +lemma inf_image₂_left (g : γ → δ) : inf (image₂ f s t) g = inf s fun x ↦ inf t (g ∘ f x) := + sup_image₂_left (δ := δᵒᵈ) .. + +lemma inf_image₂_right (g : γ → δ) : inf (image₂ f s t) g = inf t fun y ↦ inf s (g <| f · y) := + sup_image₂_right (δ := δᵒᵈ) .. + +end SemilatticeInf + end Finset open Finset diff --git a/Mathlib/Data/Finset/NatAntidiagonal.lean b/Mathlib/Data/Finset/NatAntidiagonal.lean index 7a0c66b041439..05d54a73f6e2a 100644 --- a/Mathlib/Data/Finset/NatAntidiagonal.lean +++ b/Mathlib/Data/Finset/NatAntidiagonal.lean @@ -99,10 +99,10 @@ theorem antidiagonal_succ_succ' {n : ℕ} : #align finset.nat.antidiagonal_succ_succ' Finset.Nat.antidiagonal_succ_succ' theorem antidiagonal.fst_lt {n : ℕ} {kl : ℕ × ℕ} (hlk : kl ∈ antidiagonal n) : kl.1 < n + 1 := - Nat.lt_succ_of_le $ antidiagonal.fst_le hlk + Nat.lt_succ_of_le <| antidiagonal.fst_le hlk theorem antidiagonal.snd_lt {n : ℕ} {kl : ℕ × ℕ} (hlk : kl ∈ antidiagonal n) : kl.2 < n + 1 := - Nat.lt_succ_of_le $ antidiagonal.snd_le hlk + Nat.lt_succ_of_le <| antidiagonal.snd_le hlk @[simp] lemma antidiagonal_filter_snd_le_of_le {n k : ℕ} (h : k ≤ n) : (antidiagonal n).filter (fun a ↦ a.snd ≤ k) = (antidiagonal k).map diff --git a/Mathlib/Data/Finset/NatDivisors.lean b/Mathlib/Data/Finset/NatDivisors.lean index fbd3060800350..a62b6b340ad98 100644 --- a/Mathlib/Data/Finset/NatDivisors.lean +++ b/Mathlib/Data/Finset/NatDivisors.lean @@ -3,9 +3,9 @@ Copyright (c) 2023 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa, Yury Kudryashov -/ -import Mathlib.RingTheory.Int.Basic import Mathlib.NumberTheory.Divisors import Mathlib.Data.Nat.Order.Lemmas +import Mathlib.Data.Finset.Pointwise /-! # `Nat.divisors` as a multiplicative homomorpism diff --git a/Mathlib/Data/Finset/PiAntidiagonal.lean b/Mathlib/Data/Finset/PiAntidiagonal.lean new file mode 100644 index 0000000000000..94b77b5611dcb --- /dev/null +++ b/Mathlib/Data/Finset/PiAntidiagonal.lean @@ -0,0 +1,276 @@ +/- +Copyright (c) 2023 Antoine Chambert-Loir and María Inés de Frutos-Fernández. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Antoine Chambert-Loir, María Inés de Frutos-Fernández, Eric Wieser, Bhavik Mehta +-/ +import Mathlib.Data.Finset.Antidiagonal +import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Basic + +/-! +# Partial HasAntidiagonal for functions with finite support + +For an `AddCommMonoid` `μ`, +`Finset.HasAntidiagonal μ` provides a function `antidiagonal : μ → Finset (μ × μ)` +which maps `n : μ` to a `Finset` of pairs `(a, b)` such that `a + b = n`. + +In this file, we provide an analogous definition for `ι →₀ μ`, +with an explicit finiteness condition on the support, +assuming `AddCommMonoid μ`, `HasAntidiagonal μ`, +For computability reasons, we also need `DecidableEq ι` and `DecidableEq μ`. + +This Finset could be viewed inside `ι → μ`, +but the `Finsupp` condition provides a natural `DecidableEq` instance. + +## Main definitions + +* `Finset.piAntidiagonal s n` is the finite set of all functions + with finite support contained in `s` and sum `n : μ` + That condition is expressed by `Finset.mem_piAntidiagonal` +* `Finset.mem_piAntidiagonal'` rewrites the `Finsupp.sum` condition as a `Finset.sum`. +* `Finset.finAntidiagonal`, a more general case of `Finset.Nat.antidiagonalTuple` + (TODO: deduplicate). + +-/ + +namespace Finset + +variable {ι μ μ' : Type*} + +open scoped BigOperators + +open Function Finsupp + +section Fin + +variable [AddCommMonoid μ] [DecidableEq μ] [HasAntidiagonal μ] + +/-- `finAntidiagonal d n` is the type of `d`-tuples with sum `n`. + +TODO: deduplicate with the less general `Finset.Nat.antidiagonalTuple`. -/ +def finAntidiagonal (d : ℕ) (n : μ) : Finset (Fin d → μ) := + aux d n +where + /-- Auxiliary construction for `finAntidiagonal` that bundles a proof of lawfulness + (`mem_finAntidiagonal`), as this is needed to invoke `disjiUnion`. Using `Finset.disjiUnion` makes + this computationally much more efficient than using `Finset.biUnion`. -/ + aux (d : ℕ) (n : μ) : {s : Finset (Fin d → μ) // ∀ f, f ∈ s ↔ ∑ i, f i = n} := + match d with + | 0 => + if h : n = 0 then + ⟨{0}, by simp [h, Subsingleton.elim finZeroElim ![]]⟩ + else + ⟨∅, by simp [Ne.symm h]⟩ + | d + 1 => + { val := (antidiagonal n).disjiUnion + (fun ab => (aux d ab.2).1.map { + toFun := Fin.cons (ab.1) + inj' := Fin.cons_right_injective _ }) + (fun i _hi j _hj hij => Finset.disjoint_left.2 fun t hti htj => hij <| by + simp_rw [Finset.mem_map, Embedding.coeFn_mk] at hti htj + obtain ⟨ai, hai, hij'⟩ := hti + obtain ⟨aj, haj, rfl⟩ := htj + rw [Fin.cons_eq_cons] at hij' + ext + · exact hij'.1 + · obtain ⟨-, rfl⟩ := hij' + rw [← (aux d i.2).prop ai |>.mp hai, ← (aux d j.2).prop ai |>.mp haj]) + property := fun f => by + simp_rw [mem_disjiUnion, mem_antidiagonal, mem_map, Embedding.coeFn_mk, Prod.exists, + (aux d _).prop, Fin.sum_univ_succ] + constructor + · rintro ⟨a, b, rfl, g, rfl, rfl⟩ + simp only [Fin.cons_zero, Fin.cons_succ] + · intro hf + exact ⟨_, _, hf, _, rfl, Fin.cons_self_tail f⟩ } + +lemma mem_finAntidiagonal (d : ℕ) (n : μ) (f : Fin d → μ) : + f ∈ finAntidiagonal d n ↔ ∑ i, f i = n := + (finAntidiagonal.aux d n).prop f + +/-- `finAntidiagonal₀ d n` is the type of d-tuples with sum `n` -/ +def finAntidiagonal₀ (d : ℕ) (n : μ) : Finset (Fin d →₀ μ) := + (finAntidiagonal d n).map + { toFun := fun f => + -- this is `Finsupp.onFinset`, but computable + { toFun := f, support := univ.filter (f · ≠ 0), mem_support_toFun := fun x => by simp } + inj' := fun _ _ h => DFunLike.coe_fn_eq.mpr h } + +lemma mem_finAntidiagonal₀' (d : ℕ) (n : μ) (f : Fin d →₀ μ) : + f ∈ finAntidiagonal₀ d n ↔ ∑ i, f i = n := by + simp only [finAntidiagonal₀, mem_map, Embedding.coeFn_mk, ← mem_finAntidiagonal, + ← DFunLike.coe_injective.eq_iff, Finsupp.coe_mk, exists_eq_right] + +lemma mem_finAntidiagonal₀ (d : ℕ) (n : μ) (f : Fin d →₀ μ) : + f ∈ finAntidiagonal₀ d n ↔ sum f (fun _ x => x) = n := by + rw [mem_finAntidiagonal₀', sum_of_support_subset f (subset_univ _) _ (fun _ _ => rfl)] + +end Fin + +section piAntidiagonal + +variable [DecidableEq ι] +variable [AddCommMonoid μ] [HasAntidiagonal μ] [DecidableEq μ] + +/-- The Finset of functions `ι →₀ μ` with support contained in `s` and sum `n`. -/ +def piAntidiagonal (s : Finset ι) (n : μ) : Finset (ι →₀ μ) := + let x : Finset (s →₀ μ) := + -- any ordering of elements of `s` will do, the result is the same + (Fintype.truncEquivFinOfCardEq <| Fintype.card_coe s).lift + (fun e => (finAntidiagonal₀ s.card n).map (equivCongrLeft e.symm).toEmbedding) + (fun e1 e2 => Finset.ext fun x => by + simp only [mem_map_equiv, equivCongrLeft_symm, Equiv.symm_symm, equivCongrLeft_apply, + mem_finAntidiagonal₀, sum_equivMapDomain]) + x.map + ⟨Finsupp.extendDomain, Function.LeftInverse.injective subtypeDomain_extendDomain⟩ + +/-- A function belongs to `piAntidiagonal s n` + iff its support is contained in `s` and the sum of its components is equal to `n` -/ +lemma mem_piAntidiagonal {s : Finset ι} {n : μ} {f : ι →₀ μ} : + f ∈ piAntidiagonal s n ↔ f.support ⊆ s ∧ Finsupp.sum f (fun _ x => x) = n := by + simp only [piAntidiagonal, mem_map, Embedding.coeFn_mk, mem_finAntidiagonal₀] + induction' (Fintype.truncEquivFinOfCardEq <| Fintype.card_coe s) using Trunc.ind with e' + simp_rw [Trunc.lift_mk, mem_map_equiv, equivCongrLeft_symm, Equiv.symm_symm, equivCongrLeft_apply, + mem_finAntidiagonal₀, sum_equivMapDomain] + constructor + · rintro ⟨f, rfl, rfl⟩ + dsimp [sum] + constructor + · exact Finset.coe_subset.mpr (support_extendDomain_subset _) + · simp + · rintro ⟨hsupp, rfl⟩ + refine (Function.RightInverse.surjective subtypeDomain_extendDomain).exists.mpr ⟨f, ?_⟩ + constructor + · simp_rw [sum, support_subtypeDomain, subtypeDomain_apply, sum_subtype_of_mem _ hsupp] + · rw [extendDomain_subtypeDomain _ hsupp] + +end piAntidiagonal + +section + +variable [DecidableEq ι] +variable [AddCommMonoid μ] [HasAntidiagonal μ] [DecidableEq μ] +variable [AddCommMonoid μ'] [HasAntidiagonal μ'] [DecidableEq μ'] + +lemma mem_piAntidiagonal' (s : Finset ι) (n : μ) (f) : + f ∈ piAntidiagonal s n ↔ f.support ⊆ s ∧ s.sum f = n := by + rw [mem_piAntidiagonal, and_congr_right_iff] + intro hs + rw [sum_of_support_subset _ hs] + exact fun _ _ => rfl + +@[simp] +theorem piAntidiagonal_empty_of_zero : + piAntidiagonal (∅ : Finset ι) (0 : μ) = {0} := by + ext f + rw [mem_piAntidiagonal] + simp only [mem_singleton, subset_empty] + rw [support_eq_empty, and_iff_left_iff_imp] + intro hf + rw [hf, sum_zero_index] + +theorem piAntidiagonal_empty_of_ne_zero {n : μ} (hn : n ≠ 0) : + piAntidiagonal (∅ : Finset ι) n = ∅ := by + ext f + rw [mem_piAntidiagonal] + simp only [subset_empty, support_eq_empty, sum_empty, + not_mem_empty, iff_false, not_and] + intro hf + rw [hf, sum_zero_index] + exact Ne.symm hn + +theorem piAntidiagonal_empty [DecidableEq μ] (n : μ) : + piAntidiagonal (∅ : Finset ι) n = if n = 0 then {0} else ∅ := by + split_ifs with hn + · rw [hn] + apply piAntidiagonal_empty_of_zero + · apply piAntidiagonal_empty_of_ne_zero hn + +theorem mem_piAntidiagonal_insert [DecidableEq ι] {a : ι} {s : Finset ι} + (h : a ∉ s) (n : μ) {f : ι →₀ μ} : + f ∈ piAntidiagonal (insert a s) n ↔ + ∃ m ∈ antidiagonal n, ∃ (g : ι →₀ μ), + f = Finsupp.update g a m.1 ∧ g ∈ piAntidiagonal s m.2 := by + simp only [mem_piAntidiagonal', mem_antidiagonal, Prod.exists, sum_insert h] + constructor + · rintro ⟨hsupp, rfl⟩ + refine ⟨_, _, rfl, Finsupp.erase a f, ?_, ?_, ?_⟩ + · rw [update_erase_eq_update, update_self] + · rwa [support_erase, ← subset_insert_iff] + · apply sum_congr rfl + intro x hx + rw [Finsupp.erase_ne (ne_of_mem_of_not_mem hx h)] + · rintro ⟨n1, n2, rfl, g, rfl, hgsupp, rfl⟩ + constructor + · exact (support_update_subset _ _).trans (insert_subset_insert a hgsupp) + · simp only [coe_update] + apply congr_arg₂ + · rw [update_same] + · apply sum_congr rfl + intro x hx + rw [update_noteq (ne_of_mem_of_not_mem hx h) n1 ⇑g] + +theorem piAntidiagonal_insert [DecidableEq ι] [DecidableEq μ] {a : ι} {s : Finset ι} + (h : a ∉ s) (n : μ) : + piAntidiagonal (insert a s) n = (antidiagonal n).biUnion + (fun p : μ × μ => + (piAntidiagonal s p.snd).attach.map + ⟨fun f => Finsupp.update f.val a p.fst, + (fun ⟨f, hf⟩ ⟨g, hg⟩ hfg => Subtype.ext <| by + simp only [mem_val, mem_piAntidiagonal] at hf hg + simp only [DFunLike.ext_iff] at hfg ⊢ + intro x + obtain rfl | hx := eq_or_ne x a + · replace hf := mt (hf.1 ·) h + replace hg := mt (hg.1 ·) h + rw [not_mem_support_iff.mp hf, not_mem_support_iff.mp hg] + · simpa only [coe_update, Function.update, dif_neg hx] using hfg x)⟩) := by + ext f + rw [mem_piAntidiagonal_insert h, mem_biUnion] + simp_rw [mem_map, mem_attach, true_and, Subtype.exists, Embedding.coeFn_mk, exists_prop, and_comm, + eq_comm] + +-- This should work under the assumption that e is an embedding and an AddHom +lemma mapRange_piAntidiagonal_subset {e : μ ≃+ μ'} {s : Finset ι} {n : μ} : + (piAntidiagonal s n).map (mapRange.addEquiv e).toEmbedding ⊆ piAntidiagonal s (e n) := by + intro f + simp only [mem_map, mem_piAntidiagonal] + rintro ⟨g, ⟨hsupp, hsum⟩, rfl⟩ + simp only [AddEquiv.toEquiv_eq_coe, mapRange.addEquiv_toEquiv, Equiv.coe_toEmbedding, + mapRange.equiv_apply, EquivLike.coe_coe] + constructor + · exact subset_trans (support_mapRange) hsupp + · rw [sum_mapRange_index (fun _ => rfl), ← hsum, _root_.map_finsupp_sum] + +lemma mapRange_piAntidiagonal_eq {e : μ ≃+ μ'} {s : Finset ι} {n : μ} : + (piAntidiagonal s n).map (mapRange.addEquiv e).toEmbedding = piAntidiagonal s (e n) := by + ext f + constructor + · apply mapRange_piAntidiagonal_subset + · set h := (mapRange.addEquiv e).toEquiv with hh + intro hf + have : n = e.symm (e n) := (AddEquiv.eq_symm_apply e).mpr rfl + rw [mem_map_equiv, this] + apply mapRange_piAntidiagonal_subset + rw [← mem_map_equiv] + convert hf + rw [map_map, hh] + convert map_refl + apply Function.Embedding.equiv_symm_toEmbedding_trans_toEmbedding + +end + +section CanonicallyOrderedAddCommMonoid +variable [DecidableEq ι] +variable [CanonicallyOrderedAddCommMonoid μ] [HasAntidiagonal μ] [DecidableEq μ] + +theorem piAntidiagonal_zero (s : Finset ι) : + piAntidiagonal s (0 : μ) = {(0 : ι →₀ μ)} := by + ext f + simp_rw [mem_piAntidiagonal', mem_singleton, sum_eq_zero_iff, Finset.subset_iff, + mem_support_iff, not_imp_comm, ← forall_and, ← or_imp, DFunLike.ext_iff, zero_apply, or_comm, + or_not, true_imp_iff] + +end CanonicallyOrderedAddCommMonoid + +end Finset diff --git a/Mathlib/Data/Finset/PiInduction.lean b/Mathlib/Data/Finset/PiInduction.lean index 89d485a353e17..c6cc3d33ffdaf 100644 --- a/Mathlib/Data/Finset/PiInduction.lean +++ b/Mathlib/Data/Finset/PiInduction.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Data.Fintype.Lattice import Mathlib.Data.Finset.Sigma +import Mathlib.Data.Fintype.Card #align_import data.finset.pi_induction from "leanprover-community/mathlib"@"f93c11933efbc3c2f0299e47b8ff83e9b539cbf6" diff --git a/Mathlib/Data/Finset/Pointwise.lean b/Mathlib/Data/Finset/Pointwise.lean index dd61ba78f05a5..0b2655e1646a0 100644 --- a/Mathlib/Data/Finset/Pointwise.lean +++ b/Mathlib/Data/Finset/Pointwise.lean @@ -65,7 +65,6 @@ namespace Finset /-! ### `0`/`1` as finsets -/ - section One variable [One α] {s : Finset α} {a : α} @@ -169,18 +168,41 @@ theorem singletonOneHom_apply (a : α) : singletonOneHom a = {a} := /-- Lift a `OneHom` to `Finset` via `image`. -/ @[to_additive (attr := simps) "Lift a `ZeroHom` to `Finset` via `image`"] -def imageOneHom [DecidableEq β] [One β] [OneHomClass F α β] (f : F) : OneHom (Finset α) (Finset β) - where +def imageOneHom [DecidableEq β] [One β] [OneHomClass F α β] (f : F) : + OneHom (Finset α) (Finset β) where toFun := Finset.image f map_one' := by rw [image_one, map_one, singleton_one] #align finset.image_one_hom Finset.imageOneHom #align finset.image_zero_hom Finset.imageZeroHom +@[to_additive (attr := simp)] +lemma sup_one [SemilatticeSup β] [OrderBot β] (f : α → β) : sup 1 f = f 1 := sup_singleton + +@[to_additive (attr := simp)] +lemma sup'_one [SemilatticeSup β] (f : α → β) : sup' 1 one_nonempty f = f 1 := rfl + +@[to_additive (attr := simp)] +lemma inf_one [SemilatticeInf β] [OrderTop β] (f : α → β) : inf 1 f = f 1 := inf_singleton + +@[to_additive (attr := simp)] +lemma inf'_one [SemilatticeInf β] (f : α → β) : inf' 1 one_nonempty f = f 1 := rfl + +@[to_additive (attr := simp)] +lemma max_one [LinearOrder α] : (1 : Finset α).max = 1 := rfl + +@[to_additive (attr := simp)] +lemma min_one [LinearOrder α] : (1 : Finset α).min = 1 := rfl + +@[to_additive (attr := simp)] +lemma max'_one [LinearOrder α] : (1 : Finset α).max' one_nonempty = 1 := rfl + +@[to_additive (attr := simp)] +lemma min'_one [LinearOrder α] : (1 : Finset α).min' one_nonempty = 1 := rfl + end One /-! ### Finset negation/inversion -/ - section Inv variable [DecidableEq α] [Inv α] {s s₁ s₂ t t₁ t₂ u : Finset α} {a b : α} @@ -232,8 +254,7 @@ theorem inv_empty : (∅ : Finset α)⁻¹ = ∅ := #align finset.neg_empty Finset.neg_empty @[to_additive (attr := simp)] -theorem inv_nonempty_iff : s⁻¹.Nonempty ↔ s.Nonempty := - Nonempty.image_iff _ +theorem inv_nonempty_iff : s⁻¹.Nonempty ↔ s.Nonempty := image_nonempty #align finset.inv_nonempty_iff Finset.inv_nonempty_iff #align finset.neg_nonempty_iff Finset.neg_nonempty_iff @@ -261,6 +282,26 @@ theorem inv_insert (a : α) (s : Finset α) : (insert a s)⁻¹ = insert a⁻¹ #align finset.inv_insert Finset.inv_insert #align finset.neg_insert Finset.neg_insert +@[to_additive (attr := simp)] +lemma sup_inv [SemilatticeSup β] [OrderBot β] (s : Finset α) (f : α → β) : + sup s⁻¹ f = sup s (f ·⁻¹) := + sup_image .. + +@[to_additive (attr := simp)] +lemma sup'_inv [SemilatticeSup β] {s : Finset α} (hs : s⁻¹.Nonempty) (f : α → β) : + sup' s⁻¹ hs f = sup' s hs.of_inv (f ·⁻¹) := + sup'_image .. + +@[to_additive (attr := simp)] +lemma inf_inv [SemilatticeInf β] [OrderTop β] (s : Finset α) (f : α → β) : + inf s⁻¹ f = inf s (f ·⁻¹) := + inf_image .. + +@[to_additive (attr := simp)] +lemma inf'_inv [SemilatticeInf β] {s : Finset α} (hs : s⁻¹.Nonempty) (f : α → β) : + inf' s⁻¹ hs f = inf' s hs.of_inv (f ·⁻¹) := + inf'_image .. + @[to_additive] lemma image_op_inv (s : Finset α) : s⁻¹.image op = (s.image op)⁻¹ := image_comm op_inv @@ -521,11 +562,40 @@ def imageMulHom : Finset α →ₙ* Finset β where #align finset.image_mul_hom Finset.imageMulHom #align finset.image_add_hom Finset.imageAddHom +@[to_additive (attr := simp (default + 1))] +lemma sup_mul_le [SemilatticeSup β] [OrderBot β] {s t : Finset α} {f : α → β} {a : β} : + sup (s * t) f ≤ a ↔ ∀ x ∈ s, ∀ y ∈ t, f (x * y) ≤ a := + sup_image₂_le + +@[to_additive] +lemma sup_mul_left [SemilatticeSup β] [OrderBot β] (s t : Finset α) (f : α → β) : + sup (s * t) f = sup s fun x ↦ sup t (f <| x * ·) := + sup_image₂_left .. + +@[to_additive] +lemma sup_mul_right [SemilatticeSup β] [OrderBot β] (s t : Finset α) (f : α → β) : + sup (s * t) f = sup t fun y ↦ sup s (f <| · * y) := + sup_image₂_right .. + +@[to_additive (attr := simp (default + 1))] +lemma le_inf_mul [SemilatticeInf β] [OrderTop β] {s t : Finset α} {f : α → β} {a : β} : + a ≤ inf (s * t) f ↔ ∀ x ∈ s, ∀ y ∈ t, a ≤ f (x * y) := + le_inf_image₂ + +@[to_additive] +lemma inf_mul_left [SemilatticeInf β] [OrderTop β] (s t : Finset α) (f : α → β) : + inf (s * t) f = inf s fun x ↦ inf t (f <| x * ·) := + inf_image₂_left .. + +@[to_additive] +lemma inf_mul_right [SemilatticeInf β] [OrderTop β] (s t : Finset α) (f : α → β) : + inf (s * t) f = inf t fun y ↦ inf s (f <| · * y) := + inf_image₂_right .. + end Mul /-! ### Finset subtraction/division -/ - section Div variable [DecidableEq α] [Div α] {s s₁ s₂ t t₁ t₂ u : Finset α} {a b : α} @@ -710,6 +780,36 @@ theorem subset_div {s t : Set α} : #align finset.subset_div Finset.subset_div #align finset.subset_sub Finset.subset_sub +@[to_additive (attr := simp (default + 1))] +lemma sup_div_le [SemilatticeSup β] [OrderBot β] {s t : Finset α} {f : α → β} {a : β} : + sup (s / t) f ≤ a ↔ ∀ x ∈ s, ∀ y ∈ t, f (x / y) ≤ a := + sup_image₂_le + +@[to_additive] +lemma sup_div_left [SemilatticeSup β] [OrderBot β] (s t : Finset α) (f : α → β) : + sup (s / t) f = sup s fun x ↦ sup t (f <| x / ·) := + sup_image₂_left .. + +@[to_additive] +lemma sup_div_right [SemilatticeSup β] [OrderBot β] (s t : Finset α) (f : α → β) : + sup (s / t) f = sup t fun y ↦ sup s (f <| · / y) := + sup_image₂_right .. + +@[to_additive (attr := simp (default + 1))] +lemma le_inf_div [SemilatticeInf β] [OrderTop β] {s t : Finset α} {f : α → β} {a : β} : + a ≤ inf (s / t) f ↔ ∀ x ∈ s, ∀ y ∈ t, a ≤ f (x / y) := + le_inf_image₂ + +@[to_additive] +lemma inf_div_left [SemilatticeInf β] [OrderTop β] (s t : Finset α) (f : α → β) : + inf (s / t) f = inf s fun x ↦ inf t (f <| x / ·) := + inf_image₂_left .. + +@[to_additive] +lemma inf_div_right [SemilatticeInf β] [OrderTop β] (s t : Finset α) (f : α → β) : + inf (s / t) f = inf t fun y ↦ inf s (f <| · / y) := + inf_image₂_right .. + end Div /-! ### Instances -/ @@ -1639,7 +1739,7 @@ theorem smul_finset_eq_empty : a • s = ∅ ↔ s = ∅ := @[to_additive (attr := simp)] theorem smul_finset_nonempty : (a • s).Nonempty ↔ s.Nonempty := - Nonempty.image_iff _ + image_nonempty #align finset.smul_finset_nonempty Finset.smul_finset_nonempty #align finset.vadd_finset_nonempty Finset.vadd_finset_nonempty @@ -2016,6 +2116,7 @@ theorem smul_finset_sdiff : a • (s \ t) = a • s \ a • t := #align finset.smul_finset_sdiff Finset.smul_finset_sdiff #align finset.vadd_finset_sdiff Finset.vadd_finset_sdiff +open scoped symmDiff in @[to_additive] theorem smul_finset_symmDiff : a • s ∆ t = (a • s) ∆ (a • t) := image_symmDiff _ _ <| MulAction.injective a @@ -2119,16 +2220,16 @@ lemma zero_smul_subset (t : Finset β) : (0 : Finset α) • t ⊆ 0 := by simp #align finset.zero_smul_subset Finset.zero_smul_subset lemma Nonempty.zero_smul (ht : t.Nonempty) : (0 : Finset α) • t = 0 := - t.zero_smul_subset.antisymm $ by simpa [mem_smul] using ht + t.zero_smul_subset.antisymm <| by simpa [mem_smul] using ht #align finset.nonempty.zero_smul Finset.Nonempty.zero_smul /-- A nonempty set is scaled by zero to the singleton set containing zero. -/ @[simp] lemma zero_smul_finset {s : Finset β} (h : s.Nonempty) : (0 : α) • s = (0 : Finset β) := - coe_injective $ by simpa using @Set.zero_smul_set α _ _ _ _ _ h + coe_injective <| by simpa using @Set.zero_smul_set α _ _ _ _ _ h #align finset.zero_smul_finset Finset.zero_smul_finset lemma zero_smul_finset_subset (s : Finset β) : (0 : α) • s ⊆ 0 := - image_subset_iff.2 fun x _ ↦ mem_zero.2 $ zero_smul α x + image_subset_iff.2 fun x _ ↦ mem_zero.2 <| zero_smul α x #align finset.zero_smul_finset_subset Finset.zero_smul_finset_subset variable [NoZeroSMulDivisors α β] {a : α} @@ -2178,12 +2279,13 @@ theorem smul_finset_sdiff₀ (ha : a ≠ 0) : a • (s \ t) = a • s \ a • t image_sdiff _ _ <| MulAction.injective₀ ha #align finset.smul_finset_sdiff₀ Finset.smul_finset_sdiff₀ +open scoped symmDiff in theorem smul_finset_symmDiff₀ (ha : a ≠ 0) : a • s ∆ t = (a • s) ∆ (a • t) := image_symmDiff _ _ <| MulAction.injective₀ ha #align finset.smul_finset_symm_diff₀ Finset.smul_finset_symmDiff₀ lemma smul_finset_univ₀ [Fintype β] (ha : a ≠ 0) : a • (univ : Finset β) = univ := - coe_injective $ by push_cast; exact Set.smul_set_univ₀ ha + coe_injective <| by push_cast; exact Set.smul_set_univ₀ ha #align finset.smul_finset_univ₀ Finset.smul_finset_univ₀ theorem smul_univ₀ [Fintype β] {s : Finset α} (hs : ¬s ⊆ 0) : s • (univ : Finset β) = univ := @@ -2194,7 +2296,7 @@ theorem smul_univ₀ [Fintype β] {s : Finset α} (hs : ¬s ⊆ 0) : s • (univ #align finset.smul_univ₀ Finset.smul_univ₀ lemma smul_univ₀' [Fintype β] {s : Finset α} (hs : s.Nontrivial) : s • (univ : Finset β) = univ := - coe_injective $ by push_cast; exact Set.smul_univ₀' hs + coe_injective <| by push_cast; exact Set.smul_univ₀' hs variable [DecidableEq α] @@ -2253,10 +2355,10 @@ section CommMonoid variable [CommMonoid α] {ι : Type*} [DecidableEq ι] @[to_additive (attr := simp)] lemma prod_inv_index [InvolutiveInv ι] (s : Finset ι) (f : ι → α) : - ∏ i in s⁻¹, f i = ∏ i in s, f i⁻¹ := prod_image $ inv_injective.injOn _ + ∏ i in s⁻¹, f i = ∏ i in s, f i⁻¹ := prod_image <| inv_injective.injOn _ @[to_additive existing, simp] lemma prod_neg_index [InvolutiveNeg ι] (s : Finset ι) (f : ι → α) : - ∏ i in -s, f i = ∏ i in s, f (-i) := prod_image $ neg_injective.injOn _ + ∏ i in -s, f i = ∏ i in s, f (-i) := prod_image <| neg_injective.injOn _ end CommMonoid @@ -2264,7 +2366,7 @@ section AddCommMonoid variable [AddCommMonoid α] {ι : Type*} [DecidableEq ι] @[to_additive existing, simp] lemma sum_inv_index [InvolutiveInv ι] (s : Finset ι) (f : ι → α) : - ∑ i in s⁻¹, f i = ∑ i in s, f i⁻¹ := sum_image $ inv_injective.injOn _ + ∑ i in s⁻¹, f i = ∑ i in s, f i⁻¹ := sum_image <| inv_injective.injOn _ end AddCommMonoid end BigOps @@ -2446,5 +2548,5 @@ end Set instance Nat.decidablePred_mem_vadd_set {s : Set ℕ} [DecidablePred (· ∈ s)] (a : ℕ) : DecidablePred (· ∈ a +ᵥ s) := - fun n ↦ decidable_of_iff' (a ≤ n ∧ n - a ∈ s) $ by + fun n ↦ decidable_of_iff' (a ≤ n ∧ n - a ∈ s) <| by simp only [Set.mem_vadd_set, vadd_eq_add]; aesop diff --git a/Mathlib/Data/Finset/Pointwise/Interval.lean b/Mathlib/Data/Finset/Pointwise/Interval.lean index d7870a6744107..916e1b6c56618 100644 --- a/Mathlib/Data/Finset/Pointwise/Interval.lean +++ b/Mathlib/Data/Finset/Pointwise/Interval.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.Data.Finset.Pointwise -import Mathlib.Data.Finset.Interval import Mathlib.Data.Set.Pointwise.Interval diff --git a/Mathlib/Data/Finset/Powerset.lean b/Mathlib/Data/Finset/Powerset.lean index e3e890c9f61bf..92c6c0a7b3831 100644 --- a/Mathlib/Data/Finset/Powerset.lean +++ b/Mathlib/Data/Finset/Powerset.lean @@ -191,6 +191,7 @@ def decidableForallOfDecidableSSubsets' {s : Finset α} {p : Finset α → Prop} end SSubsets section powersetCard +variable {n} {s t : Finset α} /-- Given an integer `n` and a finset `s`, then `powersetCard n s` is the finset of subsets of `s` of cardinality `n`. -/ @@ -199,8 +200,7 @@ def powersetCard (n : ℕ) (s : Finset α) : Finset (Finset α) := s.2.powersetCard.pmap fun _a _ha _b _hb => congr_arg Finset.val⟩ #align finset.powerset_len Finset.powersetCard -/-- **Formula for the Number of Combinations** -/ -theorem mem_powersetCard {n} {s t : Finset α} : s ∈ powersetCard n t ↔ s ⊆ t ∧ card s = n := by +@[simp] lemma mem_powersetCard : s ∈ powersetCard n t ↔ s ⊆ t ∧ card s = n := by cases s; simp [powersetCard, val_le_iff.symm] #align finset.mem_powerset_len Finset.mem_powersetCard @@ -226,6 +226,10 @@ theorem powersetCard_zero (s : Finset α) : s.powersetCard 0 = {∅} := by exact ⟨empty_subset s, rfl⟩⟩ #align finset.powerset_len_zero Finset.powersetCard_zero +lemma powersetCard_empty_subsingleton (n : ℕ) : + (powersetCard n (∅ : Finset α) : Set $ Finset α).Subsingleton := by + simp [Set.Subsingleton, subset_empty] + @[simp] theorem map_val_val_powersetCard (s : Finset α) (i : ℕ) : (s.powersetCard i).val.map Finset.val = s.1.powersetCard i := by @@ -237,9 +241,15 @@ theorem powersetCard_one (s : Finset α) : eq_of_veq <| Multiset.map_injective val_injective <| by simp [Multiset.powersetCard_one] @[simp] -theorem powersetCard_empty (n : ℕ) {s : Finset α} (h : s.card < n) : powersetCard n s = ∅ := - Finset.card_eq_zero.mp (by rw [card_powersetCard, Nat.choose_eq_zero_of_lt h]) -#align finset.powerset_len_empty Finset.powersetCard_empty +lemma powersetCard_eq_empty : powersetCard n s = ∅ ↔ s.card < n := by + refine ⟨?_, fun h ↦ card_eq_zero.1 $ by rw [card_powersetCard, Nat.choose_eq_zero_of_lt h]⟩ + contrapose! + exact fun h ↦ nonempty_iff_ne_empty.1 $ (exists_smaller_set _ _ h).imp $ by simp +#align finset.powerset_len_empty Finset.powersetCard_eq_empty + +@[simp] lemma powersetCard_card_add (s : Finset α) (hn : 0 < n) : + s.powersetCard (s.card + n) = ∅ := by simpa +#align finset.powerset_len_card_add Finset.powersetCard_card_add theorem powersetCard_eq_filter {n} {s : Finset α} : powersetCard n s = (powerset s).filter fun x => x.card = n := by @@ -326,12 +336,6 @@ theorem powersetCard_sup [DecidableEq α] (u : Finset α) (n : ℕ) (hn : n < u. exact mem_union_right _ (mem_image_of_mem _ ht) #align finset.powerset_len_sup Finset.powersetCard_sup -@[simp] -theorem powersetCard_card_add (s : Finset α) {i : ℕ} (hi : 0 < i) : - s.powersetCard (s.card + i) = ∅ := - Finset.powersetCard_empty _ (lt_add_of_pos_right (Finset.card s) hi) -#align finset.powerset_len_card_add Finset.powersetCard_card_add - theorem powersetCard_map {β : Type*} (f : α ↪ β) (n : ℕ) (s : Finset α) : powersetCard n (s.map f) = (powersetCard n s).map (mapEmbedding f).toEmbedding := ext fun t => by diff --git a/Mathlib/Data/Finset/Sort.lean b/Mathlib/Data/Finset/Sort.lean index 3665e174537b0..5630aedf19407 100644 --- a/Mathlib/Data/Finset/Sort.lean +++ b/Mathlib/Data/Finset/Sort.lean @@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Order.RelIso.Set -import Mathlib.Data.Fintype.Lattice import Mathlib.Data.Multiset.Sort import Mathlib.Data.List.NodupEquivFin +import Mathlib.Data.Finset.Lattice +import Mathlib.Data.Fintype.Card #align_import data.finset.sort from "leanprover-community/mathlib"@"509de852e1de55e1efa8eacfa11df0823f26f226" diff --git a/Mathlib/Data/Finset/Sups.lean b/Mathlib/Data/Finset/Sups.lean index 65234580b325c..9169ee5753fb9 100644 --- a/Mathlib/Data/Finset/Sups.lean +++ b/Mathlib/Data/Finset/Sups.lean @@ -179,7 +179,7 @@ theorem subset_sups {s t : Set α} : #align finset.subset_sups Finset.subset_sups lemma image_sups (f : F) (s t : Finset α) : image f (s ⊻ t) = image f s ⊻ image f t := - image_image₂_distrib $ map_sup f + image_image₂_distrib <| map_sup f lemma map_sups (f : F) (hf) (s t : Finset α) : map ⟨f, hf⟩ (s ⊻ t) = map ⟨f, hf⟩ s ⊻ map ⟨f, hf⟩ t := by @@ -363,7 +363,7 @@ theorem subset_infs {s t : Set α} : #align finset.subset_infs Finset.subset_infs lemma image_infs (f : F) (s t : Finset α) : image f (s ⊼ t) = image f s ⊼ image f t := - image_image₂_distrib $ map_inf f + image_image₂_distrib <| map_inf f lemma map_infs (f : F) (hf) (s t : Finset α) : map ⟨f, hf⟩ (s ⊼ t) = map ⟨f, hf⟩ s ⊼ map ⟨f, hf⟩ t := by @@ -757,7 +757,7 @@ variable [Fintype α] {𝒜 : Finset (Finset α)} {n : ℕ} protected lemma _root_.Set.Sized.compls (h𝒜 : (𝒜 : Set (Finset α)).Sized n) : (𝒜ᶜˢ : Set (Finset α)).Sized (Fintype.card α - n) := - Finset.forall_mem_compls.2 $ λ s hs ↦ by rw [Finset.card_compl, h𝒜 hs] + Finset.forall_mem_compls.2 <| λ s hs ↦ by rw [Finset.card_compl, h𝒜 hs] lemma sized_compls (hn : n ≤ Fintype.card α) : (𝒜ᶜˢ : Set (Finset α)).Sized n ↔ (𝒜 : Set (Finset α)).Sized (Fintype.card α - n) where diff --git a/Mathlib/Data/Finset/Sym.lean b/Mathlib/Data/Finset/Sym.lean index b9c5f52c9eecc..9de49e739e2ac 100644 --- a/Mathlib/Data/Finset/Sym.lean +++ b/Mathlib/Data/Finset/Sym.lean @@ -6,7 +6,6 @@ Authors: Yaël Dillies [`data.finset.sym`@`98e83c3d541c77cdb7da20d79611a780ff8e7d90`..`02ba8949f486ebecf93fe7460f1ed0564b5e442c`](https://leanprover-community.github.io/mathlib-port-status/file/data/finset/sym?range=98e83c3d541c77cdb7da20d79611a780ff8e7d90..02ba8949f486ebecf93fe7460f1ed0564b5e442c) -/ import Mathlib.Data.Finset.Lattice -import Mathlib.Data.Fintype.Prod import Mathlib.Data.Fintype.Vector import Mathlib.Data.Multiset.Sym diff --git a/Mathlib/Data/Finsupp/Antidiagonal.lean b/Mathlib/Data/Finsupp/Antidiagonal.lean index 36fcb225a2f10..023a3891419d2 100644 --- a/Mathlib/Data/Finsupp/Antidiagonal.lean +++ b/Mathlib/Data/Finsupp/Antidiagonal.lean @@ -6,7 +6,6 @@ Authors: Johannes Hölzl, Yury Kudryashov import Mathlib.Data.Finset.NatAntidiagonal import Mathlib.Data.Finsupp.Multiset import Mathlib.Data.Multiset.Antidiagonal -import Mathlib.Init.IteSimp #align_import data.finsupp.antidiagonal from "leanprover-community/mathlib"@"0a0ec35061ed9960bf0e7ffb0335f44447b58977" @@ -69,10 +68,10 @@ theorem antidiagonal_single (a : α) (n : ℕ) : Function.Embedding.coeFn_mk, Prod_map, Prod.mk.injEq, Prod.exists] constructor · intro h - refine ⟨x a, y a, FunLike.congr_fun h a |>.trans single_eq_same, ?_⟩ - simp_rw [FunLike.ext_iff, ← forall_and] + refine ⟨x a, y a, DFunLike.congr_fun h a |>.trans single_eq_same, ?_⟩ + simp_rw [DFunLike.ext_iff, ← forall_and] intro i - replace h := FunLike.congr_fun h i + replace h := DFunLike.congr_fun h i simp_rw [single_apply, Finsupp.add_apply] at h ⊢ obtain rfl | hai := Decidable.eq_or_ne a i · exact ⟨if_pos rfl, if_pos rfl⟩ diff --git a/Mathlib/Data/Finsupp/Basic.lean b/Mathlib/Data/Finsupp/Basic.lean index 1032755daf26f..94c1ea871f3cc 100644 --- a/Mathlib/Data/Finsupp/Basic.lean +++ b/Mathlib/Data/Finsupp/Basic.lean @@ -6,9 +6,7 @@ Authors: Johannes Hölzl, Scott Morrison import Mathlib.Algebra.BigOperators.Finsupp import Mathlib.Algebra.Regular.SMul import Mathlib.Data.Finset.Preimage -import Mathlib.Data.Finsupp.Notation import Mathlib.Data.Rat.BigOperators -import Mathlib.Data.Set.Countable import Mathlib.GroupTheory.GroupAction.Hom #align_import data.finsupp.basic from "leanprover-community/mathlib"@"f69db8cecc668e2d5894d7e9bfc491da60db3b9f" @@ -354,6 +352,11 @@ theorem equivMapDomain_zero {f : α ≃ β} : equivMapDomain f (0 : α →₀ M) ext; simp only [equivMapDomain_apply, coe_zero, Pi.zero_apply] #align finsupp.equiv_map_domain_zero Finsupp.equivMapDomain_zero +@[to_additive (attr := simp)] +theorem prod_equivMapDomain [CommMonoid N] (f : α ≃ β) (l : α →₀ M) (g : β → M → N): + prod (equivMapDomain f l) g = prod l (fun a m => g (f a) m) := by + simp [prod, equivMapDomain] + /-- Given `f : α ≃ β`, the finitely supported function spaces are also in bijection: `(α →₀ M) ≃ (β →₀ M)`. @@ -642,7 +645,7 @@ theorem mapDomain_mapRange [AddCommMonoid N] (f : α → β) (v : α →₀ M) ( { toFun := g map_zero' := h0 map_add' := hadd } - FunLike.congr_fun (mapDomain.addMonoidHom_comp_mapRange f g') v + DFunLike.congr_fun (mapDomain.addMonoidHom_comp_mapRange f g') v #align finsupp.map_domain_map_range Finsupp.mapDomain_mapRange theorem sum_update_add [AddCommMonoid α] [AddCommMonoid β] (f : ι →₀ α) (i : ι) (a : α) @@ -722,6 +725,15 @@ section Zero variable [Zero M] +lemma embDomain_comapDomain {f : α ↪ β} {g : β →₀ M} (hg : ↑g.support ⊆ Set.range f) : + embDomain f (comapDomain f g (f.injective.injOn _)) = g := by + ext b + by_cases hb : b ∈ Set.range f + · obtain ⟨a, rfl⟩ := hb + rw [embDomain_apply, comapDomain_apply] + · replace hg : g b = 0 := not_mem_support_iff.mp <| mt (hg ·) hb + rw [embDomain_notin_range _ _ _ hb, hg] + /-- Note the `hif` argument is needed for this to work in `rw`. -/ @[simp] theorem comapDomain_zero (f : α → β) @@ -777,14 +789,9 @@ end AddZeroClass variable [AddCommMonoid M] (f : α → β) theorem mapDomain_comapDomain (hf : Function.Injective f) (l : β →₀ M) - (hl : ↑l.support ⊆ Set.range f) : mapDomain f (comapDomain f l (hf.injOn _)) = l := by - ext a - by_cases h_cases : a ∈ Set.range f - · rcases Set.mem_range.1 h_cases with ⟨b, hb⟩ - rw [hb.symm, mapDomain_apply hf, comapDomain_apply] - · rw [mapDomain_notin_range _ _ h_cases] - by_contra h_contr - apply h_cases (hl <| Finset.mem_coe.2 <| mem_support_iff.2 fun h => h_contr h.symm) + (hl : ↑l.support ⊆ Set.range f) : + mapDomain f (comapDomain f l (hf.injOn _)) = l := by + conv_rhs => rw [← embDomain_comapDomain (f := ⟨f, hf⟩) hl (M := M), embDomain_eq_mapDomain] #align finsupp.map_domain_comap_domain Finsupp.mapDomain_comapDomain end FInjective @@ -894,12 +901,12 @@ theorem filter_eq_indicator : ⇑(f.filter p) = Set.indicator { x | p x } f := #align finsupp.filter_eq_indicator Finsupp.filter_eq_indicator theorem filter_eq_zero_iff : f.filter p = 0 ↔ ∀ x, p x → f x = 0 := by - simp only [FunLike.ext_iff, filter_eq_indicator, zero_apply, Set.indicator_apply_eq_zero, + simp only [DFunLike.ext_iff, filter_eq_indicator, zero_apply, Set.indicator_apply_eq_zero, Set.mem_setOf_eq] #align finsupp.filter_eq_zero_iff Finsupp.filter_eq_zero_iff theorem filter_eq_self_iff : f.filter p = f ↔ ∀ x, f x ≠ 0 → p x := by - simp only [FunLike.ext_iff, filter_eq_indicator, Set.indicator_apply_eq_self, Set.mem_setOf_eq, + simp only [DFunLike.ext_iff, filter_eq_indicator, Set.indicator_apply_eq_self, Set.mem_setOf_eq, not_imp_comm] #align finsupp.filter_eq_self_iff Finsupp.filter_eq_self_iff @@ -960,7 +967,7 @@ end Zero theorem filter_pos_add_filter_neg [AddZeroClass M] (f : α →₀ M) (p : α → Prop) : (f.filter p + f.filter fun a => ¬p a) = f := - FunLike.coe_injective <| Set.indicator_self_add_compl { x | p x } f + DFunLike.coe_injective <| Set.indicator_self_add_compl { x | p x } f #align finsupp.filter_pos_add_filter_neg Finsupp.filter_pos_add_filter_neg end Filter @@ -1082,7 +1089,7 @@ def filterAddHom (p : α → Prop) : (α →₀ M) →+ α →₀ M where toFun := filter p map_zero' := filter_zero p - map_add' f g := FunLike.coe_injective <| Set.indicator_add { x | p x } f g + map_add' f g := DFunLike.coe_injective <| Set.indicator_add { x | p x } f g #align finsupp.filter_add_hom Finsupp.filterAddHom @[simp] @@ -1495,14 +1502,14 @@ theorem smul_apply [Zero M] [SMulZeroClass R M] (b : R) (v : α →₀ M) (a : theorem _root_.IsSMulRegular.finsupp [Zero M] [SMulZeroClass R M] {k : R} (hk : IsSMulRegular M k) : IsSMulRegular (α →₀ M) k := - fun _ _ h => ext fun i => hk (FunLike.congr_fun h i) + fun _ _ h => ext fun i => hk (DFunLike.congr_fun h i) #align is_smul_regular.finsupp IsSMulRegular.finsupp instance faithfulSMul [Nonempty α] [Zero M] [SMulZeroClass R M] [FaithfulSMul R M] : FaithfulSMul R (α →₀ M) where eq_of_smul_eq_smul h := let ⟨a⟩ := ‹Nonempty α› - eq_of_smul_eq_smul fun m : M => by simpa using FunLike.congr_fun (h (single a m)) a + eq_of_smul_eq_smul fun m : M => by simpa using DFunLike.congr_fun (h (single a m)) a #align finsupp.faithful_smul Finsupp.faithfulSMul instance instSMulWithZero [Zero R] [Zero M] [SMulWithZero R M] : SMulWithZero R (α →₀ M) where @@ -1564,7 +1571,7 @@ variable {p : α → Prop} @[simp] theorem filter_smul {_ : Monoid R} [AddMonoid M] [DistribMulAction R M] {b : R} {v : α →₀ M} : (b • v).filter p = b • v.filter p := - FunLike.coe_injective <| Set.indicator_const_smul { x | p x } b v + DFunLike.coe_injective <| Set.indicator_const_smul { x | p x } b v #align finsupp.filter_smul Finsupp.filter_smul end @@ -1638,7 +1645,7 @@ instance noZeroSMulDivisors [Semiring R] [AddCommMonoid M] [Module R M] {ι : Ty [NoZeroSMulDivisors R M] : NoZeroSMulDivisors R (ι →₀ M) := ⟨fun h => or_iff_not_imp_left.mpr fun hc => - Finsupp.ext fun i => (smul_eq_zero.mp (FunLike.ext_iff.mp h i)).resolve_left hc⟩ + Finsupp.ext fun i => (smul_eq_zero.mp (DFunLike.ext_iff.mp h i)).resolve_left hc⟩ #align finsupp.no_zero_smul_divisors Finsupp.noZeroSMulDivisors section DistribMulActionHom @@ -1681,36 +1688,101 @@ variable [Zero R] /-- The `Finsupp` version of `Pi.unique`. -/ instance uniqueOfRight [Subsingleton R] : Unique (α →₀ R) := - FunLike.coe_injective.unique + DFunLike.coe_injective.unique #align finsupp.unique_of_right Finsupp.uniqueOfRight /-- The `Finsupp` version of `Pi.uniqueOfIsEmpty`. -/ instance uniqueOfLeft [IsEmpty α] : Unique (α →₀ R) := - FunLike.coe_injective.unique + DFunLike.coe_injective.unique #align finsupp.unique_of_left Finsupp.uniqueOfLeft end +section +variable {M : Type*} [Zero M] {P : α → Prop} [DecidablePred P] + +/-- Combine finitely supported functions over `{a // P a}` and `{a // ¬P a}`, by case-splitting on +`P a`. -/ +@[simps] +def piecewise (f : Subtype P →₀ M) (g : {a // ¬ P a} →₀ M) : α →₀ M where + toFun a := if h : P a then f ⟨a, h⟩ else g ⟨a, h⟩ + support := (f.support.map (.subtype _)).disjUnion (g.support.map (.subtype _)) <| by + simp_rw [Finset.disjoint_left, mem_map, forall_exists_index, Embedding.coe_subtype, + Subtype.forall, Subtype.exists] + rintro _ a ha ⟨-, rfl⟩ ⟨b, hb, -, rfl⟩ + exact hb ha + mem_support_toFun a := by + by_cases ha : P a <;> simp [ha] + +@[simp] +theorem subtypeDomain_piecewise (f : Subtype P →₀ M) (g : {a // ¬ P a} →₀ M) : + subtypeDomain P (f.piecewise g) = f := + Finsupp.ext fun a => dif_pos a.prop + +@[simp] +theorem subtypeDomain_not_piecewise (f : Subtype P →₀ M) (g : {a // ¬ P a} →₀ M) : + subtypeDomain (¬P ·) (f.piecewise g) = g := + Finsupp.ext fun a => dif_neg a.prop + +/-- Extend the domain of a `Finsupp` by using `0` where `P x` does not hold. -/ +@[simps! support toFun] +def extendDomain (f : Subtype P →₀ M) : α →₀ M := piecewise f 0 + +theorem extendDomain_eq_embDomain_subtype (f : Subtype P →₀ M) : + extendDomain f = embDomain (.subtype _) f := by + ext a + by_cases h : P a + · refine Eq.trans ?_ (embDomain_apply (.subtype P) f (Subtype.mk a h)).symm + simp [h] + · rw [embDomain_notin_range, extendDomain_toFun, dif_neg h] + simp [h] + +theorem support_extendDomain_subset (f : Subtype P →₀ M) : + ↑(f.extendDomain).support ⊆ {x | P x} := by + intro x + rw [extendDomain_support, mem_coe, mem_map, Embedding.coe_subtype] + rintro ⟨x, -, rfl⟩ + exact x.prop + +@[simp] +theorem subtypeDomain_extendDomain (f : Subtype P →₀ M) : + subtypeDomain P f.extendDomain = f := + subtypeDomain_piecewise _ _ + +theorem extendDomain_subtypeDomain (f : α →₀ M) (hf : ∀ a ∈ f.support, P a) : + (subtypeDomain P f).extendDomain = f := by + ext a + by_cases h : P a + · exact dif_pos h + · dsimp + rw [if_neg h, eq_comm, ← not_mem_support_iff] + refine mt ?_ h + exact @hf _ + +@[simp] +theorem extendDomain_single (a : Subtype P) (m : M) : + (single a m).extendDomain = single a.val m := by + ext a' + dsimp only [extendDomain_toFun] + obtain rfl | ha := eq_or_ne a.val a' + · simp_rw [single_eq_same, dif_pos a.prop] + · simp_rw [single_eq_of_ne ha, dite_eq_right_iff] + intro h + rw [single_eq_of_ne] + simp [Subtype.ext_iff, ha] + +end + /-- Given an `AddCommMonoid M` and `s : Set α`, `restrictSupportEquiv s M` is the `Equiv` between the subtype of finitely supported functions with support contained in `s` and the type of finitely supported functions from `s`. -/ def restrictSupportEquiv (s : Set α) (M : Type*) [AddCommMonoid M] : { f : α →₀ M // ↑f.support ⊆ s } ≃ (s →₀ M) where - toFun f := subtypeDomain (fun x => x ∈ s) f.1 - invFun f := - ⟨f.embDomain <| Embedding.subtype _, by - rw [support_embDomain, Finset.coe_map, Set.image_subset_iff] - exact fun x _ => x.2⟩ - left_inv := by - rintro ⟨f, hf⟩ - ext a - by_cases h : a ∈ s - · lift a to s using h - exact embDomain_apply _ _ _ - rw [embDomain_notin_range, eq_comm, ← Finsupp.not_mem_support_iff] - · exact fun hs => h <| hf hs - · simp [h] - right_inv f := ext <| embDomain_apply _ f + toFun f := subtypeDomain (· ∈ s) f.1 + invFun f := letI := Classical.decPred (· ∈ s); ⟨f.extendDomain, support_extendDomain_subset _⟩ + left_inv f := + letI := Classical.decPred (· ∈ s); Subtype.ext <| extendDomain_subtypeDomain f.1 f.prop + right_inv _ := letI := Classical.decPred (· ∈ s); subtypeDomain_extendDomain _ #align finsupp.restrict_support_equiv Finsupp.restrictSupportEquiv /-- Given `AddCommMonoid M` and `e : α ≃ β`, `domCongr e` is the corresponding `Equiv` between diff --git a/Mathlib/Data/Finsupp/BigOperators.lean b/Mathlib/Data/Finsupp/BigOperators.lean index 71e10eb0d3dba..dfea1c9ec5979 100644 --- a/Mathlib/Data/Finsupp/BigOperators.lean +++ b/Mathlib/Data/Finsupp/BigOperators.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ +import Mathlib.Algebra.BigOperators.Basic import Mathlib.Data.Finsupp.Defs import Mathlib.Data.Finset.Pairwise diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index e5ccb62273dd2..46b0ede43e835 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Scott Morrison -/ -import Mathlib.Algebra.BigOperators.Basic +import Mathlib.Algebra.Function.Indicator import Mathlib.Data.Set.Finite import Mathlib.GroupTheory.Submonoid.Basic @@ -86,8 +86,6 @@ noncomputable section open Finset Function -open BigOperators - variable {α β γ ι M M' N P G H R S : Type*} /-- `Finsupp α M`, denoted `α →₀ M`, is the type of functions `f : α → M` such that @@ -117,15 +115,15 @@ section Basic variable [Zero M] -instance funLike : FunLike (α →₀ M) α fun _ => M := +instance instFunLike : FunLike (α →₀ M) α M := ⟨toFun, by rintro ⟨s, f, hf⟩ ⟨t, g, hg⟩ (rfl : f = g) congr ext a exact (hf _).trans (hg _).symm⟩ -#align finsupp.fun_like Finsupp.funLike +#align finsupp.fun_like Finsupp.instFunLike -/-- Helper instance for when there are too many metavariables to apply the `FunLike` instance +/-- Helper instance for when there are too many metavariables to apply the `DFunLike` instance directly. -/ instance coeFun : CoeFun (α →₀ M) fun _ => α → M := inferInstance @@ -133,29 +131,29 @@ instance coeFun : CoeFun (α →₀ M) fun _ => α → M := @[ext] theorem ext {f g : α →₀ M} (h : ∀ a, f a = g a) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align finsupp.ext Finsupp.ext -@[deprecated FunLike.ext_iff] +@[deprecated DFunLike.ext_iff] theorem ext_iff {f g : α →₀ M} : f = g ↔ ∀ a, f a = g a := - FunLike.ext_iff + DFunLike.ext_iff #align finsupp.ext_iff Finsupp.ext_iff -lemma ne_iff {f g : α →₀ M} : f ≠ g ↔ ∃ a, f a ≠ g a := FunLike.ne_iff +lemma ne_iff {f g : α →₀ M} : f ≠ g ↔ ∃ a, f a ≠ g a := DFunLike.ne_iff -@[deprecated FunLike.coe_fn_eq] +@[deprecated DFunLike.coe_fn_eq] theorem coeFn_inj {f g : α →₀ M} : (f : α → M) = g ↔ f = g := - FunLike.coe_fn_eq + DFunLike.coe_fn_eq #align finsupp.coe_fn_inj Finsupp.coeFn_inj -@[deprecated FunLike.coe_injective] +@[deprecated DFunLike.coe_injective] theorem coeFn_injective : @Function.Injective (α →₀ M) (α → M) (⇑) := - FunLike.coe_injective + DFunLike.coe_injective #align finsupp.coe_fn_injective Finsupp.coeFn_injective -@[deprecated FunLike.congr_fun] +@[deprecated DFunLike.congr_fun] theorem congr_fun {f g : α →₀ M} (h : f = g) (a : α) : f a = g a := - FunLike.congr_fun h _ + DFunLike.congr_fun h _ #align finsupp.congr_fun Finsupp.congr_fun @[simp, norm_cast] @@ -198,7 +196,7 @@ theorem not_mem_support_iff {f : α →₀ M} {a} : a ∉ f.support ↔ f a = 0 #align finsupp.not_mem_support_iff Finsupp.not_mem_support_iff @[simp, norm_cast] -theorem coe_eq_zero {f : α →₀ M} : (f : α → M) = 0 ↔ f = 0 := by rw [← coe_zero, FunLike.coe_fn_eq] +theorem coe_eq_zero {f : α →₀ M} : (f : α → M) = 0 ↔ f = 0 := by rw [← coe_zero, DFunLike.coe_fn_eq] #align finsupp.coe_eq_zero Finsupp.coe_eq_zero theorem ext_iff' {f g : α →₀ M} : f = g ↔ f.support = g.support ∧ ∀ x ∈ f.support, f x = g x := @@ -340,7 +338,7 @@ theorem single_eq_pi_single [DecidableEq α] (a : α) (b : M) : ⇑(single a b) @[simp] theorem single_zero (a : α) : (single a 0 : α →₀ M) = 0 := - FunLike.coe_injective <| by + DFunLike.coe_injective <| by classical simpa only [single_eq_update, coe_zero] using Function.update_eq_self a (0 : α → M) #align finsupp.single_zero Finsupp.single_zero @@ -404,7 +402,7 @@ theorem single_eq_single_iff (a₁ a₂ : α) (b₁ b₂ : M) : by_cases h : a₁ = a₂ · refine' Or.inl ⟨h, _⟩ rwa [h, (single_injective a₂).eq_iff] at eq - · rw [FunLike.ext_iff] at eq + · rw [DFunLike.ext_iff] at eq have h₁ := eq a₁ have h₂ := eq a₂ simp only [single_eq_same, single_eq_of_ne h, single_eq_of_ne (Ne.symm h)] at h₁ h₂ @@ -435,7 +433,7 @@ theorem support_single_disjoint {b' : M} (hb : b ≠ 0) (hb' : b' ≠ 0) {i j : @[simp] theorem single_eq_zero : single a b = 0 ↔ b = 0 := by - simp [FunLike.ext_iff, single_eq_set_indicator] + simp [DFunLike.ext_iff, single_eq_set_indicator] #align finsupp.single_eq_zero Finsupp.single_eq_zero theorem single_swap (a₁ a₂ : α) (b : M) : single a₁ b a₂ = single a₂ b a₁ := by @@ -610,12 +608,12 @@ theorem support_update_subset [DecidableEq α] [DecidableEq M] : theorem update_comm (f : α →₀ M) {a₁ a₂ : α} (h : a₁ ≠ a₂) (m₁ m₂ : M) : update (update f a₁ m₁) a₂ m₂ = update (update f a₂ m₂) a₁ m₁ := letI := Classical.decEq α - FunLike.coe_injective <| Function.update_comm h _ _ _ + DFunLike.coe_injective <| Function.update_comm h _ _ _ @[simp] theorem update_idem (f : α →₀ M) (a : α) (b c : M) : update (update f a b) a c = update f a c := letI := Classical.decEq α - FunLike.coe_injective <| Function.update_idem _ _ _ + DFunLike.coe_injective <| Function.update_idem _ _ _ end Update @@ -905,7 +903,7 @@ theorem embDomain_notin_range (f : α ↪ β) (v : α →₀ M) (a : β) (h : a #align finsupp.emb_domain_notin_range Finsupp.embDomain_notin_range theorem embDomain_injective (f : α ↪ β) : Function.Injective (embDomain f : (α →₀ M) → β →₀ M) := - fun l₁ l₂ h => ext fun a => by simpa only [embDomain_apply] using FunLike.ext_iff.1 h (f a) + fun l₁ l₂ h => ext fun a => by simpa only [embDomain_apply] using DFunLike.ext_iff.1 h (f a) #align finsupp.emb_domain_injective Finsupp.embDomain_injective @[simp] @@ -1045,14 +1043,27 @@ theorem single_add (a : α) (b₁ b₂ : M) : single a (b₁ + b₂) = single a #align finsupp.single_add Finsupp.single_add instance addZeroClass : AddZeroClass (α →₀ M) := - FunLike.coe_injective.addZeroClass _ coe_zero coe_add + DFunLike.coe_injective.addZeroClass _ coe_zero coe_add #align finsupp.add_zero_class Finsupp.addZeroClass instance instIsLeftCancelAdd [IsLeftCancelAdd M] : IsLeftCancelAdd (α →₀ M) where - add_left_cancel _ _ _ h := ext fun x => add_left_cancel <| FunLike.congr_fun h x + add_left_cancel _ _ _ h := ext fun x => add_left_cancel <| DFunLike.congr_fun h x + +/-- When ι is finite and M is an AddMonoid, + then Finsupp.equivFunOnFinite gives an AddEquiv -/ +noncomputable def addEquivFunOnFinite {ι : Type*} [Finite ι] : + (ι →₀ M) ≃+ (ι → M) where + __ := Finsupp.equivFunOnFinite + map_add' _ _ := rfl + +/-- AddEquiv between (ι →₀ M) and M, when ι has a unique element -/ +noncomputable def _root_.AddEquiv.finsuppUnique {ι : Type*} [Unique ι] : + (ι →₀ M) ≃+ M where + __ := Equiv.finsuppUnique + map_add' _ _ := rfl instance instIsRightCancelAdd [IsRightCancelAdd M] : IsRightCancelAdd (α →₀ M) where - add_right_cancel _ _ _ h := ext fun x => add_right_cancel <| FunLike.congr_fun h x + add_right_cancel _ _ _ h := ext fun x => add_right_cancel <| DFunLike.congr_fun h x instance instIsCancelAdd [IsCancelAdd M] : IsCancelAdd (α →₀ M) where @@ -1191,18 +1202,18 @@ verify `f (single a 1) = g (single a 1)`. -/ @[ext high] theorem addHom_ext' [AddZeroClass N] ⦃f g : (α →₀ M) →+ N⦄ (H : ∀ x, f.comp (singleAddHom x) = g.comp (singleAddHom x)) : f = g := - addHom_ext fun x => FunLike.congr_fun (H x) + addHom_ext fun x => DFunLike.congr_fun (H x) #align finsupp.add_hom_ext' Finsupp.addHom_ext' theorem mulHom_ext [MulOneClass N] ⦃f g : Multiplicative (α →₀ M) →* N⦄ (H : ∀ x y, f (Multiplicative.ofAdd <| single x y) = g (Multiplicative.ofAdd <| single x y)) : f = g := MonoidHom.ext <| - FunLike.congr_fun <| by + DFunLike.congr_fun <| by have := @addHom_ext α M (Additive N) _ _ (MonoidHom.toAdditive'' f) (MonoidHom.toAdditive'' g) H ext - rw [FunLike.ext_iff] at this + rw [DFunLike.ext_iff] at this apply this #align finsupp.mul_hom_ext Finsupp.mulHom_ext @@ -1211,7 +1222,7 @@ theorem mulHom_ext' [MulOneClass N] {f g : Multiplicative (α →₀ M) →* N} (H : ∀ x, f.comp (AddMonoidHom.toMultiplicative (singleAddHom x)) = g.comp (AddMonoidHom.toMultiplicative (singleAddHom x))) : f = g := - mulHom_ext fun x => FunLike.congr_fun (H x) + mulHom_ext fun x => DFunLike.congr_fun (H x) #align finsupp.mul_hom_ext' Finsupp.mulHom_ext' theorem mapRange_add [AddZeroClass N] {f : M → N} {hf : f 0 = 0} @@ -1258,14 +1269,14 @@ instance hasNatScalar : SMul ℕ (α →₀ M) := #align finsupp.has_nat_scalar Finsupp.hasNatScalar instance addMonoid : AddMonoid (α →₀ M) := - FunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => rfl + DFunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => rfl #align finsupp.add_monoid Finsupp.addMonoid end AddMonoid instance addCommMonoid [AddCommMonoid M] : AddCommMonoid (α →₀ M) := --TODO: add reference to library note in PR #7432 - { FunLike.coe_injective.addCommMonoid (↑) coe_zero coe_add (fun _ _ => rfl) with + { DFunLike.coe_injective.addCommMonoid (↑) coe_zero coe_add (fun _ _ => rfl) with toAddMonoid := Finsupp.addMonoid } #align finsupp.add_comm_monoid Finsupp.addCommMonoid @@ -1321,14 +1332,14 @@ instance hasIntScalar [AddGroup G] : SMul ℤ (α →₀ G) := instance addGroup [AddGroup G] : AddGroup (α →₀ G) := --TODO: add reference to library note in PR #7432 - { FunLike.coe_injective.addGroup (↑) coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) + { DFunLike.coe_injective.addGroup (↑) coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) fun _ _ => rfl with toAddMonoid := Finsupp.addMonoid } #align finsupp.add_group Finsupp.addGroup instance addCommGroup [AddCommGroup G] : AddCommGroup (α →₀ G) := --TODO: add reference to library note in PR #7432 - { FunLike.coe_injective.addCommGroup (↑) coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) + { DFunLike.coe_injective.addCommGroup (↑) coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) fun _ _ => rfl with toAddGroup := Finsupp.addGroup } #align finsupp.add_comm_group Finsupp.addCommGroup @@ -1338,7 +1349,7 @@ theorem single_add_single_eq_single_add_single [AddCommMonoid M] {k l m n : α} single k u + single l v = single m u + single n v ↔ (k = m ∧ l = n) ∨ (u = v ∧ k = n ∧ l = m) ∨ (u + v = 0 ∧ k = l ∧ m = n) := by classical - simp_rw [FunLike.ext_iff, coe_add, single_eq_pi_single, ← funext_iff] + simp_rw [DFunLike.ext_iff, coe_add, single_eq_pi_single, ← funext_iff] exact Pi.single_add_single_eq_single_add_single hu hv #align finsupp.single_add_single_eq_single_add_single Finsupp.single_add_single_eq_single_add_single diff --git a/Mathlib/Data/Finsupp/Indicator.lean b/Mathlib/Data/Finsupp/Indicator.lean index 6b028fdf993ea..e3c7774e5f996 100644 --- a/Mathlib/Data/Finsupp/Indicator.lean +++ b/Mathlib/Data/Finsupp/Indicator.lean @@ -61,7 +61,7 @@ theorem indicator_injective : Injective fun f : ∀ i ∈ s, α => indicator s f intro a b h ext i hi rw [← indicator_of_mem hi a, ← indicator_of_mem hi b] - exact FunLike.congr_fun h i + exact DFunLike.congr_fun h i #align finsupp.indicator_injective Finsupp.indicator_injective theorem support_indicator_subset : ((indicator s f).support : Set ι) ⊆ s := by diff --git a/Mathlib/Data/Finsupp/Lex.lean b/Mathlib/Data/Finsupp/Lex.lean index 69b40e4754657..3d84301c23b36 100644 --- a/Mathlib/Data/Finsupp/Lex.lean +++ b/Mathlib/Data/Finsupp/Lex.lean @@ -77,7 +77,7 @@ instance Lex.partialOrder [PartialOrder N] : PartialOrder (Lex (α →₀ N)) wh lt := (· < ·) le x y := ⇑(ofLex x) = ⇑(ofLex y) ∨ x < y __ := PartialOrder.lift (fun x : Lex (α →₀ N) ↦ toLex (⇑(ofLex x))) - (FunLike.coe_injective (F := Finsupp α N)) + (DFunLike.coe_injective (F := Finsupp α N)) #align finsupp.lex.partial_order Finsupp.Lex.partialOrder /-- The linear order on `Finsupp`s obtained by the lexicographic ordering. -/ diff --git a/Mathlib/Data/Finsupp/Notation.lean b/Mathlib/Data/Finsupp/Notation.lean index d5358e1cd2baa..e0a8cf9e63a94 100644 --- a/Mathlib/Data/Finsupp/Notation.lean +++ b/Mathlib/Data/Finsupp/Notation.lean @@ -22,7 +22,7 @@ open Lean.Parser.Term -- A variant of `Lean.Parser.Term.matchAlts` with less line wrapping. @[nolint docBlame] -- we do not want any doc hover on this notation. def fun₀.matchAlts : Parser := - leading_parser withPosition $ ppRealGroup <| many1Indent (ppSpace >> ppGroup matchAlt) + leading_parser withPosition <| ppRealGroup <| many1Indent (ppSpace >> ppGroup matchAlt) /-- `fun₀ | i => a` is notation for `Finsupp.single i a`, and with multiple match arms, `fun₀ ... | i => a` is notation for `Finsupp.update (fun₀ ...) i a`. diff --git a/Mathlib/Data/Finsupp/Order.lean b/Mathlib/Data/Finsupp/Order.lean index baa09ec25ec16..c2bf7c7f3586e 100644 --- a/Mathlib/Data/Finsupp/Order.lean +++ b/Mathlib/Data/Finsupp/Order.lean @@ -197,7 +197,7 @@ protected theorem bot_eq_zero : (⊥ : ι →₀ α) = 0 := @[simp] theorem add_eq_zero_iff (f g : ι →₀ α) : f + g = 0 ↔ f = 0 ∧ g = 0 := by - simp [FunLike.ext_iff, forall_and] + simp [DFunLike.ext_iff, forall_and] #align finsupp.add_eq_zero_iff Finsupp.add_eq_zero_iff theorem le_iff' (f g : ι →₀ α) {s : Finset ι} (hf : f.support ⊆ s) : f ≤ g ↔ ∀ i ∈ s, f i ≤ g i := diff --git a/Mathlib/Data/Finsupp/Pwo.lean b/Mathlib/Data/Finsupp/PWO.lean similarity index 81% rename from Mathlib/Data/Finsupp/Pwo.lean rename to Mathlib/Data/Finsupp/PWO.lean index a329cd7f6c6dd..7193a1767bd8e 100644 --- a/Mathlib/Data/Finsupp/Pwo.lean +++ b/Mathlib/Data/Finsupp/PWO.lean @@ -17,7 +17,7 @@ It is in a separate file for now so as to not add imports to the file `Order.Wel ## Main statements -* `Finsupp.isPwo` - finitely supported functions from a fintype are partially well ordered when +* `Finsupp.isPWO` - finitely supported functions from a fintype are partially well ordered when the codomain is a linear order that is well ordered ## Tags @@ -30,8 +30,8 @@ Dickson, order, partial well order ordered, when `σ` is `Finite` and `α` is a linear well order. This version uses finsupps on a finite type as it is intended for use with `MVPowerSeries`. -/ -theorem Finsupp.isPwo {α σ : Type*} [Zero α] [LinearOrder α] [IsWellOrder α (· < ·)] [Finite σ] - (S : Set (σ →₀ α)) : S.IsPwo := +theorem Finsupp.isPWO {α σ : Type*} [Zero α] [LinearOrder α] [IsWellOrder α (· < ·)] [Finite σ] + (S : Set (σ →₀ α)) : S.IsPWO := Finsupp.equivFunOnFinite.symm_image_image S ▸ - Set.PartiallyWellOrderedOn.image_of_monotone_on (Pi.isPwo _) fun _a _b _ha _hb => id -#align finsupp.is_pwo Finsupp.isPwo + Set.PartiallyWellOrderedOn.image_of_monotone_on (Pi.isPWO _) fun _a _b _ha _hb => id +#align finsupp.is_pwo Finsupp.isPWO diff --git a/Mathlib/Data/Finsupp/Pointwise.lean b/Mathlib/Data/Finsupp/Pointwise.lean index ca9d3b4b08ab0..aff78166b469c 100644 --- a/Mathlib/Data/Finsupp/Pointwise.lean +++ b/Mathlib/Data/Finsupp/Pointwise.lean @@ -66,32 +66,32 @@ theorem support_mul [DecidableEq α] {g₁ g₂ : α →₀ β} : #align finsupp.support_mul Finsupp.support_mul instance : MulZeroClass (α →₀ β) := - FunLike.coe_injective.mulZeroClass _ coe_zero coe_mul + DFunLike.coe_injective.mulZeroClass _ coe_zero coe_mul end instance [SemigroupWithZero β] : SemigroupWithZero (α →₀ β) := - FunLike.coe_injective.semigroupWithZero _ coe_zero coe_mul + DFunLike.coe_injective.semigroupWithZero _ coe_zero coe_mul instance [NonUnitalNonAssocSemiring β] : NonUnitalNonAssocSemiring (α →₀ β) := - FunLike.coe_injective.nonUnitalNonAssocSemiring _ coe_zero coe_add coe_mul fun _ _ ↦ rfl + DFunLike.coe_injective.nonUnitalNonAssocSemiring _ coe_zero coe_add coe_mul fun _ _ ↦ rfl instance [NonUnitalSemiring β] : NonUnitalSemiring (α →₀ β) := - FunLike.coe_injective.nonUnitalSemiring _ coe_zero coe_add coe_mul fun _ _ ↦ rfl + DFunLike.coe_injective.nonUnitalSemiring _ coe_zero coe_add coe_mul fun _ _ ↦ rfl instance [NonUnitalCommSemiring β] : NonUnitalCommSemiring (α →₀ β) := - FunLike.coe_injective.nonUnitalCommSemiring _ coe_zero coe_add coe_mul fun _ _ ↦ rfl + DFunLike.coe_injective.nonUnitalCommSemiring _ coe_zero coe_add coe_mul fun _ _ ↦ rfl instance [NonUnitalNonAssocRing β] : NonUnitalNonAssocRing (α →₀ β) := - FunLike.coe_injective.nonUnitalNonAssocRing _ coe_zero coe_add coe_mul coe_neg coe_sub + DFunLike.coe_injective.nonUnitalNonAssocRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ ↦ rfl) fun _ _ ↦ rfl instance [NonUnitalRing β] : NonUnitalRing (α →₀ β) := - FunLike.coe_injective.nonUnitalRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ ↦ rfl) + DFunLike.coe_injective.nonUnitalRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ ↦ rfl) fun _ _ ↦ rfl instance [NonUnitalCommRing β] : NonUnitalCommRing (α →₀ β) := - FunLike.coe_injective.nonUnitalCommRing _ coe_zero coe_add coe_mul coe_neg coe_sub + DFunLike.coe_injective.nonUnitalCommRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ ↦ rfl) fun _ _ ↦ rfl -- TODO can this be generalized in the direction of `Pi.smul'` @@ -115,7 +115,7 @@ theorem coe_pointwise_smul [Semiring β] (f : α → β) (g : α →₀ β) : /-- The pointwise multiplicative action of functions on finitely supported functions -/ instance pointwiseModule [Semiring β] : Module (α → β) (α →₀ β) := - Function.Injective.module _ coeFnAddHom FunLike.coe_injective coe_pointwise_smul + Function.Injective.module _ coeFnAddHom DFunLike.coe_injective coe_pointwise_smul #align finsupp.pointwise_module Finsupp.pointwiseModule end Finsupp diff --git a/Mathlib/Data/Finsupp/ToDFinsupp.lean b/Mathlib/Data/Finsupp/ToDFinsupp.lean index 5c120e2423c2c..ab488db8d69dc 100644 --- a/Mathlib/Data/Finsupp/ToDFinsupp.lean +++ b/Mathlib/Data/Finsupp/ToDFinsupp.lean @@ -128,12 +128,12 @@ theorem DFinsupp.toFinsupp_single (i : ι) (m : M) : @[simp] theorem Finsupp.toDFinsupp_toFinsupp (f : ι →₀ M) : f.toDFinsupp.toFinsupp = f := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align finsupp.to_dfinsupp_to_finsupp Finsupp.toDFinsupp_toFinsupp @[simp] theorem DFinsupp.toFinsupp_toDFinsupp (f : Π₀ _ : ι, M) : f.toFinsupp.toDFinsupp = f := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align dfinsupp.to_finsupp_to_dfinsupp DFinsupp.toFinsupp_toDFinsupp end @@ -149,30 +149,30 @@ namespace Finsupp @[simp] theorem toDFinsupp_zero [Zero M] : (0 : ι →₀ M).toDFinsupp = 0 := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align finsupp.to_dfinsupp_zero Finsupp.toDFinsupp_zero @[simp] theorem toDFinsupp_add [AddZeroClass M] (f g : ι →₀ M) : (f + g).toDFinsupp = f.toDFinsupp + g.toDFinsupp := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align finsupp.to_dfinsupp_add Finsupp.toDFinsupp_add @[simp] theorem toDFinsupp_neg [AddGroup M] (f : ι →₀ M) : (-f).toDFinsupp = -f.toDFinsupp := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align finsupp.to_dfinsupp_neg Finsupp.toDFinsupp_neg @[simp] theorem toDFinsupp_sub [AddGroup M] (f g : ι →₀ M) : (f - g).toDFinsupp = f.toDFinsupp - g.toDFinsupp := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align finsupp.to_dfinsupp_sub Finsupp.toDFinsupp_sub @[simp] theorem toDFinsupp_smul [Monoid R] [AddMonoid M] [DistribMulAction R M] (r : R) (f : ι →₀ M) : (r • f).toDFinsupp = r • f.toDFinsupp := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align finsupp.to_dfinsupp_smul Finsupp.toDFinsupp_smul end Finsupp @@ -183,31 +183,31 @@ variable [DecidableEq ι] @[simp] theorem toFinsupp_zero [Zero M] [∀ m : M, Decidable (m ≠ 0)] : toFinsupp 0 = (0 : ι →₀ M) := - FunLike.coe_injective rfl + DFunLike.coe_injective rfl #align dfinsupp.to_finsupp_zero DFinsupp.toFinsupp_zero @[simp] theorem toFinsupp_add [AddZeroClass M] [∀ m : M, Decidable (m ≠ 0)] (f g : Π₀ _ : ι, M) : (toFinsupp (f + g) : ι →₀ M) = toFinsupp f + toFinsupp g := - FunLike.coe_injective <| DFinsupp.coe_add _ _ + DFunLike.coe_injective <| DFinsupp.coe_add _ _ #align dfinsupp.to_finsupp_add DFinsupp.toFinsupp_add @[simp] theorem toFinsupp_neg [AddGroup M] [∀ m : M, Decidable (m ≠ 0)] (f : Π₀ _ : ι, M) : (toFinsupp (-f) : ι →₀ M) = -toFinsupp f := - FunLike.coe_injective <| DFinsupp.coe_neg _ + DFunLike.coe_injective <| DFinsupp.coe_neg _ #align dfinsupp.to_finsupp_neg DFinsupp.toFinsupp_neg @[simp] theorem toFinsupp_sub [AddGroup M] [∀ m : M, Decidable (m ≠ 0)] (f g : Π₀ _ : ι, M) : (toFinsupp (f - g) : ι →₀ M) = toFinsupp f - toFinsupp g := - FunLike.coe_injective <| DFinsupp.coe_sub _ _ + DFunLike.coe_injective <| DFinsupp.coe_sub _ _ #align dfinsupp.to_finsupp_sub DFinsupp.toFinsupp_sub @[simp] theorem toFinsupp_smul [Monoid R] [AddMonoid M] [DistribMulAction R M] [∀ m : M, Decidable (m ≠ 0)] (r : R) (f : Π₀ _ : ι, M) : (toFinsupp (r • f) : ι →₀ M) = r • toFinsupp f := - FunLike.coe_injective <| DFinsupp.coe_smul _ _ + DFunLike.coe_injective <| DFinsupp.coe_smul _ _ #align dfinsupp.to_finsupp_smul DFinsupp.toFinsupp_smul end DFinsupp diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index 1ed5dfa4db982..cdfac4911074d 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -386,27 +386,27 @@ instance decidableEqEmbeddingFintype [DecidableEq β] [Fintype α] : DecidableEq @[to_additive] instance decidableEqOneHomFintype [DecidableEq β] [Fintype α] [One α] [One β] : DecidableEq (OneHom α β) := fun a b => - decidable_of_iff ((a : α → β) = b) (Injective.eq_iff FunLike.coe_injective) + decidable_of_iff ((a : α → β) = b) (Injective.eq_iff DFunLike.coe_injective) #align fintype.decidable_eq_one_hom_fintype Fintype.decidableEqOneHomFintype #align fintype.decidable_eq_zero_hom_fintype Fintype.decidableEqZeroHomFintype @[to_additive] instance decidableEqMulHomFintype [DecidableEq β] [Fintype α] [Mul α] [Mul β] : DecidableEq (α →ₙ* β) := fun a b => - decidable_of_iff ((a : α → β) = b) (Injective.eq_iff FunLike.coe_injective) + decidable_of_iff ((a : α → β) = b) (Injective.eq_iff DFunLike.coe_injective) #align fintype.decidable_eq_mul_hom_fintype Fintype.decidableEqMulHomFintype #align fintype.decidable_eq_add_hom_fintype Fintype.decidableEqAddHomFintype @[to_additive] instance decidableEqMonoidHomFintype [DecidableEq β] [Fintype α] [MulOneClass α] [MulOneClass β] : DecidableEq (α →* β) := fun a b => - decidable_of_iff ((a : α → β) = b) (Injective.eq_iff FunLike.coe_injective) + decidable_of_iff ((a : α → β) = b) (Injective.eq_iff DFunLike.coe_injective) #align fintype.decidable_eq_monoid_hom_fintype Fintype.decidableEqMonoidHomFintype #align fintype.decidable_eq_add_monoid_hom_fintype Fintype.decidableEqAddMonoidHomFintype instance decidableEqMonoidWithZeroHomFintype [DecidableEq β] [Fintype α] [MulZeroOneClass α] [MulZeroOneClass β] : DecidableEq (α →*₀ β) := fun a b => - decidable_of_iff ((a : α → β) = b) (Injective.eq_iff FunLike.coe_injective) + decidable_of_iff ((a : α → β) = b) (Injective.eq_iff DFunLike.coe_injective) #align fintype.decidable_eq_monoid_with_zero_hom_fintype Fintype.decidableEqMonoidWithZeroHomFintype instance decidableEqRingHomFintype [DecidableEq β] [Fintype α] [Semiring α] [Semiring β] : @@ -742,6 +742,7 @@ theorem toFinset_diff [Fintype (s \ t : Set _)] : (s \ t).toFinset = s.toFinset simp #align set.to_finset_diff Set.toFinset_diff +open scoped symmDiff in @[simp] theorem toFinset_symmDiff [Fintype (s ∆ t : Set _)] : (s ∆ t).toFinset = s.toFinset ∆ t.toFinset := by @@ -1268,7 +1269,7 @@ noncomputable def seqOfForallFinsetExistsAux {α : Type*} [DecidableEq α] (P : (h (Finset.image (fun i : Fin n => seqOfForallFinsetExistsAux P r h i) (Finset.univ : Finset (Fin n)))) - decreasing_by exact i.2 + decreasing_by all_goals exact i.2 #align seq_of_forall_finset_exists_aux seqOfForallFinsetExistsAux /-- Induction principle to build a sequence, by adding one point at a time satisfying a given diff --git a/Mathlib/Data/Fintype/BigOperators.lean b/Mathlib/Data/Fintype/BigOperators.lean index 94cc552427eb2..10bb80f39daae 100644 --- a/Mathlib/Data/Fintype/BigOperators.lean +++ b/Mathlib/Data/Fintype/BigOperators.lean @@ -4,12 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.Fintype.Option -import Mathlib.Data.Fintype.Powerset import Mathlib.Data.Fintype.Sigma import Mathlib.Data.Fintype.Sum import Mathlib.Data.Fintype.Prod import Mathlib.Data.Fintype.Vector -import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.BigOperators.Option #align_import data.fintype.big_operators from "leanprover-community/mathlib"@"2445c98ae4b87eabebdde552593519b9b6dc350c" @@ -155,47 +153,6 @@ theorem card_vector [Fintype α] (n : ℕ) : Fintype.card (Vector α n) = Fintyp rw [Fintype.ofEquiv_card]; simp #align card_vector card_vector -@[to_additive (attr := simp)] -theorem Finset.prod_attach_univ [Fintype α] [CommMonoid β] (f : { a : α // a ∈ @univ α _ } → β) : - ∏ x in univ.attach, f x = ∏ x, f ⟨x, mem_univ _⟩ := - Fintype.prod_equiv (Equiv.subtypeUnivEquiv fun x => mem_univ _) _ _ fun x => by simp -#align finset.prod_attach_univ Finset.prod_attach_univ -#align finset.sum_attach_univ Finset.sum_attach_univ - -/-- Taking a product over `univ.pi t` is the same as taking the product over `Fintype.piFinset t`. - `univ.pi t` and `Fintype.piFinset t` are essentially the same `Finset`, but differ - in the type of their element, `univ.pi t` is a `Finset (Π a ∈ univ, t a)` and - `Fintype.piFinset t` is a `Finset (Π a, t a)`. -/ -@[to_additive "Taking a sum over `univ.pi t` is the same as taking the sum over - `Fintype.piFinset t`. `univ.pi t` and `Fintype.piFinset t` are essentially the same `Finset`, - but differ in the type of their element, `univ.pi t` is a `Finset (Π a ∈ univ, t a)` and - `Fintype.piFinset t` is a `Finset (Π a, t a)`."] -theorem Finset.prod_univ_pi [DecidableEq α] [Fintype α] [CommMonoid β] {δ : α → Type*} - {t : ∀ a : α, Finset (δ a)} (f : (∀ a : α, a ∈ (univ : Finset α) → δ a) → β) : - ∏ x in univ.pi t, f x = ∏ x in Fintype.piFinset t, f fun a _ => x a := by - apply prod_nbij' (fun x i ↦ x i $ mem_univ _) (fun x i _ ↦ x i) <;> simp -#align finset.prod_univ_pi Finset.prod_univ_pi -#align finset.sum_univ_pi Finset.sum_univ_pi - -/-- The product over `univ` of a sum can be written as a sum over the product of sets, - `Fintype.piFinset`. `Finset.prod_sum` is an alternative statement when the product is not - over `univ` -/ -theorem Finset.prod_univ_sum [DecidableEq α] [Fintype α] [CommSemiring β] {δ : α → Type u_1} - [∀ a : α, DecidableEq (δ a)] {t : ∀ a : α, Finset (δ a)} {f : ∀ a : α, δ a → β} : - (∏ a, ∑ b in t a, f a b) = ∑ p in Fintype.piFinset t, ∏ x, f x (p x) := by - simp only [Finset.prod_attach_univ, prod_sum, Finset.sum_univ_pi] -#align finset.prod_univ_sum Finset.prod_univ_sum - -/-- Summing `a^s.card * b^(n-s.card)` over all finite subsets `s` of a fintype of cardinality `n` -gives `(a + b)^n`. The "good" proof involves expanding along all coordinates using the fact that -`x^n` is multilinear, but multilinear maps are only available now over rings, so we give instead -a proof reducing to the usual binomial theorem to have a result over semirings. -/ -theorem Fintype.sum_pow_mul_eq_add_pow (α : Type*) [Fintype α] {R : Type*} [CommSemiring R] - (a b : R) : - (∑ s : Finset α, a ^ s.card * b ^ (Fintype.card α - s.card)) = (a + b) ^ Fintype.card α := - Finset.sum_pow_mul_eq_add_pow _ _ _ -#align fintype.sum_pow_mul_eq_add_pow Fintype.sum_pow_mul_eq_add_pow - /-- It is equivalent to compute the product of a function over `Fin n` or `Finset.range n`. -/ @[to_additive "It is equivalent to sum a function over `fin n` or `finset.range n`."] theorem Fin.prod_univ_eq_prod_range [CommMonoid α] (f : ℕ → α) (n : ℕ) : @@ -230,8 +187,8 @@ nonrec theorem Fintype.prod_dite [Fintype α] {p : α → Prop} [DecidablePred p (∏ a : { a // p a }, f a a.2) * ∏ a : { a // ¬p a }, g a a.2 := by simp only [prod_dite, attach_eq_univ] congr 1 - · exact (Equiv.subtypeEquivRight $ by simp).prod_comp fun x : { x // p x } => f x x.2 - · exact (Equiv.subtypeEquivRight $ by simp).prod_comp fun x : { x // ¬p x } => g x x.2 + · exact (Equiv.subtypeEquivRight <| by simp).prod_comp fun x : { x // p x } => f x x.2 + · exact (Equiv.subtypeEquivRight <| by simp).prod_comp fun x : { x // ¬p x } => g x x.2 #align fintype.prod_dite Fintype.prod_dite section diff --git a/Mathlib/Data/Fintype/Card.lean b/Mathlib/Data/Fintype/Card.lean index 7f1b2f374ef14..eec3e5e80c75e 100644 --- a/Mathlib/Data/Fintype/Card.lean +++ b/Mathlib/Data/Fintype/Card.lean @@ -6,7 +6,7 @@ Authors: Mario Carneiro import Mathlib.Data.Fintype.Basic import Mathlib.Data.Finset.Card import Mathlib.Data.List.NodupEquivFin -import Mathlib.Tactic.Positivity +import Mathlib.Data.Set.Image #align_import data.fintype.card from "leanprover-community/mathlib"@"bf2428c9486c407ca38b5b3fb10b87dad0bc99fa" @@ -581,7 +581,7 @@ theorem card_le_one_iff : card α ≤ 1 ↔ ∀ a b : α, a = b := let ⟨x, hx⟩ := card_eq_one_iff.1 ha.symm rw [hx a, hx b], fun _ => ha ▸ le_rfl⟩ | n + 2, ha => - ⟨fun h => False.elim $ by rw [← ha] at h; cases h with | step h => cases h; done, fun h => + ⟨fun h => False.elim <| by rw [← ha] at h; cases h with | step h => cases h; done, fun h => card_unit ▸ card_le_of_injective (fun _ => ()) fun _ _ _ => h _ _⟩ #align fintype.card_le_one_iff Fintype.card_le_one_iff @@ -1118,7 +1118,7 @@ private theorem natEmbeddingAux_injective (α : Type*) [Infinite α] : rintro m n h letI := Classical.decEq α wlog hmlen : m ≤ n generalizing m n - · exact (this h.symm $ le_of_not_le hmlen).symm + · exact (this h.symm <| le_of_not_le hmlen).symm by_contra hmn have hmn : m < n := lt_of_le_of_ne hmlen hmn refine (Classical.choose_spec (exists_not_mem_finset @@ -1280,9 +1280,8 @@ to that instance and use that name. @[elab_as_elim] theorem Fintype.induction_subsingleton_or_nontrivial {P : ∀ (α) [Fintype α], Prop} (α : Type*) [Fintype α] (hbase : ∀ (α) [Fintype α] [Subsingleton α], P α) - (hstep : - ∀ (α) [Fintype α] [Nontrivial α], - ∀ _ih : ∀ (β) [Fintype β], ∀ _h : Fintype.card β < Fintype.card α, P β, P α) : + (hstep : ∀ (α) [Fintype α] [Nontrivial α], + (∀ (β) [Fintype β], Fintype.card β < Fintype.card α → P β) → P α) : P α := by obtain ⟨n, hn⟩ : ∃ n, Fintype.card α = n := ⟨Fintype.card α, rfl⟩ induction' n using Nat.strong_induction_on with n ih generalizing α diff --git a/Mathlib/Data/Fintype/CardEmbedding.lean b/Mathlib/Data/Fintype/CardEmbedding.lean index 5ddebd9f5afae..80a71c5f1523f 100644 --- a/Mathlib/Data/Fintype/CardEmbedding.lean +++ b/Mathlib/Data/Fintype/CardEmbedding.lean @@ -42,7 +42,7 @@ theorem card_embedding_eq {α β : Type*} [Fintype α] [Fintype β] [emb : Finty · letI := Fintype.ofEquiv _ e.symm rw [← card_congr (Equiv.embeddingCongr e (Equiv.refl β)), ih, card_congr e] · rw [card_pempty, Nat.descFactorial_zero, card_eq_one_iff] - exact ⟨Embedding.ofIsEmpty, fun x ↦ FunLike.ext _ _ isEmptyElim⟩ + exact ⟨Embedding.ofIsEmpty, fun x ↦ DFunLike.ext _ _ isEmptyElim⟩ · classical dsimp only at ih rw [card_option, Nat.descFactorial_succ, card_congr (Embedding.optionEmbeddingEquiv γ β), diff --git a/Mathlib/Data/Fintype/Lattice.lean b/Mathlib/Data/Fintype/Lattice.lean index 853387c7ca755..a328954aa08bd 100644 --- a/Mathlib/Data/Fintype/Lattice.lean +++ b/Mathlib/Data/Fintype/Lattice.lean @@ -19,7 +19,7 @@ open Nat universe u v -variable {α β : Type*} +variable {ι α β : Type*} namespace Finset @@ -52,6 +52,9 @@ theorem fold_sup_univ [SemilatticeSup α] [OrderTop α] (a : α) : @fold_inf_univ αᵒᵈ _ _ _ _ #align finset.fold_sup_univ Finset.fold_sup_univ +lemma mem_inf [DecidableEq α] {s : Finset ι} {f : ι → Finset α} {a : α} : + a ∈ s.inf f ↔ ∀ i ∈ s, a ∈ f i := by induction' s using Finset.cons_induction <;> simp [*] + end Finset open Finset Function diff --git a/Mathlib/Data/Fintype/Order.lean b/Mathlib/Data/Fintype/Order.lean index 6e9b0113b497c..a91da9267059a 100644 --- a/Mathlib/Data/Fintype/Order.lean +++ b/Mathlib/Data/Fintype/Order.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Peter Nelson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Peter Nelson, Yaël Dillies -/ -import Mathlib.Data.Fintype.Lattice import Mathlib.Data.Finset.Order import Mathlib.Order.Atoms.Finite @@ -198,35 +197,50 @@ noncomputable instance Bool.completeAtomicBooleanAlgebra : CompleteAtomicBoolean /-! ### Directed Orders -/ -variable {α : Type*} +variable {α : Type*} {r : α → α → Prop} [IsTrans α r] {β γ : Type*} [Nonempty γ] {f : γ → α} + [Finite β] (D : Directed r f) -theorem Directed.fintype_le {r : α → α → Prop} [IsTrans α r] {β γ : Type*} [Nonempty γ] {f : γ → α} - [Fintype β] (D : Directed r f) (g : β → γ) : ∃ z, ∀ i, r (f (g i)) (f z) := by +theorem Directed.finite_set_le {s : Set γ} (hs : s.Finite) : ∃ z, ∀ i ∈ s, r (f i) (f z) := by + convert D.finset_le hs.toFinset; rw [Set.Finite.mem_toFinset] + +theorem Directed.finite_le (g : β → γ) : ∃ z, ∀ i, r (f (g i)) (f z) := by classical - obtain ⟨z, hz⟩ := D.finset_le (Finset.image g Finset.univ) - exact ⟨z, fun i => hz (g i) (Finset.mem_image_of_mem g (Finset.mem_univ i))⟩ -#align directed.fintype_le Directed.fintype_le - -theorem Fintype.exists_le [Nonempty α] [Preorder α] [IsDirected α (· ≤ ·)] {β : Type*} [Fintype β] - (f : β → α) : ∃ M, ∀ i, f i ≤ M := - directed_id.fintype_le _ -#align fintype.exists_le Fintype.exists_le - -theorem Fintype.exists_ge [Nonempty α] [Preorder α] [IsDirected α (· ≥ ·)] {β : Type*} [Fintype β] - (f : β → α) : ∃ M, ∀ i, M ≤ f i := - directed_id.fintype_le (r := (· ≥ ·)) _ - -theorem Fintype.bddAbove_range [Nonempty α] [Preorder α] [IsDirected α (· ≤ ·)] {β : Type*} - [Fintype β] (f : β → α) : BddAbove (Set.range f) := by - obtain ⟨M, hM⟩ := Fintype.exists_le f + obtain ⟨z, hz⟩ := D.finite_set_le (Set.finite_range g) + exact ⟨z, fun i => hz (g i) ⟨i, rfl⟩⟩ +#align directed.fintype_le Directed.finite_le + +variable [Nonempty α] [Preorder α] + +theorem Finite.exists_le [IsDirected α (· ≤ ·)] (f : β → α) : ∃ M, ∀ i, f i ≤ M := + directed_id.finite_le _ +#align fintype.exists_le Finite.exists_le + +theorem Finite.exists_ge [IsDirected α (· ≥ ·)] (f : β → α) : ∃ M, ∀ i, M ≤ f i := + directed_id.finite_le (r := (· ≥ ·)) _ + +theorem Set.Finite.exists_le [IsDirected α (· ≤ ·)] {s : Set α} (hs : s.Finite) : + ∃ M, ∀ i ∈ s, i ≤ M := + directed_id.finite_set_le hs + +theorem Set.Finite.exists_ge [IsDirected α (· ≥ ·)] {s : Set α} (hs : s.Finite) : + ∃ M, ∀ i ∈ s, M ≤ i := + directed_id.finite_set_le (r := (· ≥ ·)) hs + +theorem Finite.bddAbove_range [IsDirected α (· ≤ ·)] (f : β → α) : BddAbove (Set.range f) := by + obtain ⟨M, hM⟩ := Finite.exists_le f refine' ⟨M, fun a ha => _⟩ obtain ⟨b, rfl⟩ := ha exact hM b -#align fintype.bdd_above_range Fintype.bddAbove_range +#align fintype.bdd_above_range Finite.bddAbove_range -theorem Fintype.bddBelow_range [Nonempty α] [Preorder α] [IsDirected α (· ≥ ·)] {β : Type*} - [Fintype β] (f : β → α) : BddBelow (Set.range f) := by - obtain ⟨M, hM⟩ := Fintype.exists_ge f +theorem Finite.bddBelow_range [IsDirected α (· ≥ ·)] (f : β → α) : BddBelow (Set.range f) := by + obtain ⟨M, hM⟩ := Finite.exists_ge f refine' ⟨M, fun a ha => _⟩ obtain ⟨b, rfl⟩ := ha exact hM b + +@[deprecated] alias Directed.fintype_le := Directed.finite_le +@[deprecated] alias Fintype.exists_le := Finite.exists_le +@[deprecated] alias Fintype.exists_ge := Finite.exists_ge +@[deprecated] alias Fintype.bddAbove_range := Finite.bddAbove_range +@[deprecated] alias Fintype.bddBelow_range := Finite.bddBelow_range diff --git a/Mathlib/Data/Fintype/Pi.lean b/Mathlib/Data/Fintype/Pi.lean index 2d43eaaf8030d..a672ba966b864 100644 --- a/Mathlib/Data/Fintype/Pi.lean +++ b/Mathlib/Data/Fintype/Pi.lean @@ -3,9 +3,8 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Fintype.Basic -import Mathlib.Data.Fin.Tuple.Basic import Mathlib.Data.Finset.Pi +import Mathlib.Data.Fintype.Basic #align_import data.fintype.pi from "leanprover-community/mathlib"@"9003f28797c0664a49e4179487267c494477d853" @@ -134,26 +133,3 @@ theorem Finset.univ_pi_univ {α : Type*} {β : α → Type*} [DecidableEq α] [F (Finset.univ.pi fun a : α => (Finset.univ : Finset (β a))) = Finset.univ := by ext; simp #align finset.univ_pi_univ Finset.univ_pi_univ - -lemma Fin.mem_piFinset_succ_iff {n : ℕ} {α : Fin (n + 1) → Type*} (p : (i : Fin (n + 1)) → α i) - (S : (i : Fin (n + 1)) → Finset (α i)) : - p ∈ Fintype.piFinset S ↔ p 0 ∈ S 0 ∧ Fin.tail p ∈ Fintype.piFinset (Fin.tail S) := by - simp only [Fintype.mem_piFinset, forall_fin_succ, Fin.tail] - -lemma Fin.cons_mem_piFinset_cons_iff {n : ℕ} {α : Fin (n + 1) → Type*} - (x : α 0) (xs : (i : Fin n) → α i.succ) - (S₀ : Finset (α 0)) (Sᵢ : (i : Fin n) → Finset (α i.succ)) : - Fin.cons x xs ∈ Fintype.piFinset (Fin.cons S₀ Sᵢ) ↔ x ∈ S₀ ∧ xs ∈ Fintype.piFinset Sᵢ := by - simp_rw [Fin.mem_piFinset_succ_iff, cons_zero, tail_cons] - -lemma Fin.mem_piFinset_succ_iff' {n : ℕ} {α : Fin (n + 1) → Type*} (p : (i : Fin (n + 1)) → α i) - (S : (i : Fin (n + 1)) → Finset (α i)) : - p ∈ Fintype.piFinset S ↔ - Fin.init p ∈ Fintype.piFinset (Fin.init S) ∧ p (Fin.last n) ∈ S (Fin.last n) := by - simp only [Fintype.mem_piFinset, forall_fin_succ', Fin.init] - -lemma Fin.snoc_mem_piFinset_snoc_iff {n : ℕ} {α : Fin (n + 1) → Type*} - (xs : (i : Fin n) → α i.castSucc) (x : α (.last n)) - (Sᵢ : (i : Fin n) → Finset (α i.castSucc)) (Sₙ : Finset (α <| .last n)) : - Fin.snoc xs x ∈ Fintype.piFinset (Fin.snoc Sᵢ Sₙ) ↔ xs ∈ Fintype.piFinset Sᵢ ∧ x ∈ Sₙ := by - simp_rw [Fin.mem_piFinset_succ_iff', init_snoc, snoc_last] diff --git a/Mathlib/Data/Fintype/Powerset.lean b/Mathlib/Data/Fintype/Powerset.lean index 2b3d43c5a5e50..63d6e40da8857 100644 --- a/Mathlib/Data/Fintype/Powerset.lean +++ b/Mathlib/Data/Fintype/Powerset.lean @@ -40,7 +40,7 @@ lemma filter_subset_univ [DecidableEq α] (s : Finset α) : rw [← Finset.powerset_univ, powerset_inj] #align finset.powerset_eq_univ Finset.powerset_eq_univ -@[simp] lemma mem_powersetCard_univ : s ∈ powersetCard k (univ : Finset α) ↔ card s = k := +lemma mem_powersetCard_univ : s ∈ powersetCard k (univ : Finset α) ↔ card s = k := mem_powersetCard.trans <| and_iff_right <| subset_univ _ #align finset.mem_powerset_len_univ_iff Finset.mem_powersetCard_univ diff --git a/Mathlib/Data/Fintype/Prod.lean b/Mathlib/Data/Fintype/Prod.lean index a4db59e985088..fe74b2cc10b55 100644 --- a/Mathlib/Data/Fintype/Prod.lean +++ b/Mathlib/Data/Fintype/Prod.lean @@ -87,7 +87,7 @@ instance Pi.infinite_of_left {ι : Sort*} {π : ι → Sort _} [∀ i, Nontrivia /-- If at least one `π i` is infinite and the rest nonempty, the pi type of all `π` is infinite. -/ theorem Pi.infinite_of_exists_right {ι : Type*} {π : ι → Type*} (i : ι) [Infinite <| π i] [∀ i, Nonempty <| π i] : Infinite (∀ i : ι, π i) := - let ⟨m⟩ := @Pi.Nonempty ι π _ + let ⟨m⟩ := @Pi.instNonempty ι π _ Infinite.of_injective _ (update_injective m i) #align pi.infinite_of_exists_right Pi.infinite_of_exists_right diff --git a/Mathlib/Data/Fintype/Small.lean b/Mathlib/Data/Fintype/Small.lean index 472bbd590b365..9b40e0b4b9511 100644 --- a/Mathlib/Data/Fintype/Small.lean +++ b/Mathlib/Data/Fintype/Small.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Mathlib.Data.Fintype.Card -import Mathlib.Logic.Small.Basic +import Mathlib.Logic.Small.Defs #align_import data.fintype.small from "leanprover-community/mathlib"@"1126441d6bccf98c81214a0780c73d499f6721fe" diff --git a/Mathlib/Data/FunLike/Basic.lean b/Mathlib/Data/FunLike/Basic.lean index 1b518f9aa6905..6eb8b96995dc2 100644 --- a/Mathlib/Data/FunLike/Basic.lean +++ b/Mathlib/Data/FunLike/Basic.lean @@ -13,7 +13,7 @@ import Mathlib.Util.CompileInductive This typeclass is primarily for use by homomorphisms like `MonoidHom` and `LinearMap`. -## Basic usage of `FunLike` +## Basic usage of `DFunLike` A typical type of morphisms should be declared as: ``` @@ -26,14 +26,14 @@ namespace MyHom variables (A B : Type*) [MyClass A] [MyClass B] -- This instance is optional if you follow the "morphism class" design below: -instance : FunLike (MyHom A B) A (λ _, B) := +instance : DFunLike (MyHom A B) A (λ _, B) := { coe := MyHom.toFun, coe_injective' := λ f g h, by cases f; cases g; congr' } /-- Helper instance for when there's too many metavariables to apply -`FunLike.coe` directly. -/ +`DFunLike.coe` directly. -/ instance : CoeFun (MyHom A B) (λ _, A → B) := ⟨MyHom.toFun⟩ -@[ext] theorem ext {f g : MyHom A B} (h : ∀ x, f x = g x) : f = g := FunLike.ext f g h +@[ext] theorem ext {f g : MyHom A B} (h : ∀ x, f x = g x) : f = g := DFunLike.ext f g h /-- Copy of a `MyHom` with a new `toFun` equal to the old one. Useful to fix definitional equalities. -/ @@ -47,10 +47,10 @@ end MyHom This file will then provide a `CoeFun` instance and various extensionality and simp lemmas. -## Morphism classes extending `FunLike` +## Morphism classes extending `DFunLike` -The `FunLike` design provides further benefits if you put in a bit more work. -The first step is to extend `FunLike` to create a class of those types satisfying +The `DFunLike` design provides further benefits if you put in a bit more work. +The first step is to extend `DFunLike` to create a class of those types satisfying the axioms of your new type of morphisms. Continuing the example above: @@ -58,14 +58,14 @@ Continuing the example above: /-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms. You should extend this class when you extend `MyHom`. -/ class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B] - extends FunLike F A (λ _, B) := + extends DFunLike F A (λ _, B) := (map_op : ∀ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y)) @[simp] lemma map_op {F A B : Type*} [MyClass A] [MyClass B] [MyHomClass F A B] (f : F) (x y : A) : f (MyClass.op x y) = MyClass.op (f x) (f y) := MyHomClass.map_op --- You can replace `MyHom.FunLike` with the below instance: +-- You can replace `MyHom.DFunLike` with the below instance: instance : MyHomClass (MyHom A B) A B := { coe := MyHom.toFun, coe_injective' := λ f g h, by cases f; cases g; congr', @@ -90,7 +90,7 @@ class CoolerHomClass (F : Type*) (A B : outParam <| Type*) [CoolClass A] [CoolCl (f : F) : f CoolClass.cool = CoolClass.cool := MyHomClass.map_op --- You can also replace `MyHom.FunLike` with the below instance: +-- You can also replace `MyHom.DFunLike` with the below instance: instance : CoolerHomClass (CoolHom A B) A B := { coe := CoolHom.toFun, coe_injective' := λ f g h, by cases f; cases g; congr', @@ -114,111 +114,121 @@ instead of linearly increasing the work per `MyHom`-related declaration. -/ -- This instance should have low priority, to ensure we follow the chain --- `FunLike → CoeFun` +-- `DFunLike → CoeFun` -- Porting note: this is an elaboration detail from Lean 3, we are going to disable it -- until it is clearer what the Lean 4 elaborator needs. -- attribute [instance, priority 10] coe_fn_trans -/-- The class `FunLike F α β` expresses that terms of type `F` have an -injective coercion to functions from `α` to `β`. +/-- The class `DFunLike F α β` expresses that terms of type `F` have an +injective coercion to (dependent) functions from `α` to `β`. + +For non-dependent functions you can also use the abbreviation `FunLike`. This typeclass is used in the definition of the homomorphism typeclasses, such as `ZeroHomClass`, `MulHomClass`, `MonoidHomClass`, .... -/ @[notation_class * toFun Simps.findCoercionArgs] -class FunLike (F : Sort*) (α : outParam (Sort*)) (β : outParam <| α → Sort*) where +class DFunLike (F : Sort*) (α : outParam (Sort*)) (β : outParam <| α → Sort*) where /-- The coercion from `F` to a function. -/ coe : F → ∀ a : α, β a /-- The coercion to functions must be injective. -/ coe_injective' : Function.Injective coe -#align fun_like FunLike +#align fun_like DFunLike -- https://github.com/leanprover/lean4/issues/2096 -compile_def% FunLike.coe +compile_def% DFunLike.coe + +/-- The class `FunLike F α β` (`Fun`ction-`Like`) expresses that terms of type `F` +have an injective coercion to functions from `α` to `β`. +`FunLike` is the non-dependent version of `DFunLike`. +This typeclass is used in the definition of the homomorphism typeclasses, +such as `ZeroHomClass`, `MulHomClass`, `MonoidHomClass`, .... +-/ +abbrev FunLike F α β := DFunLike F α fun _ => β section Dependent -/-! ### `FunLike F α β` where `β` depends on `a : α` -/ +/-! ### `DFunLike F α β` where `β` depends on `a : α` -/ variable (F α : Sort*) (β : α → Sort*) -namespace FunLike +namespace DFunLike -variable {F α β} [i : FunLike F α β] +variable {F α β} [i : DFunLike F α β] instance (priority := 100) hasCoeToFun : CoeFun F (fun _ ↦ ∀ a : α, β a) where - coe := @FunLike.coe _ _ β _ -- need to make explicit to beta reduce for non-dependent functions + coe := @DFunLike.coe _ _ β _ -- need to make explicit to beta reduce for non-dependent functions #eval Lean.Elab.Command.liftTermElabM do - Std.Tactic.Coe.registerCoercion ``FunLike.coe + Std.Tactic.Coe.registerCoercion ``DFunLike.coe (some { numArgs := 5, coercee := 4, type := .coeFun }) -- @[simp] -- porting note: this loops in lean 4 -theorem coe_eq_coe_fn : (FunLike.coe (F := F)) = (fun f => ↑f) := rfl -#align fun_like.coe_eq_coe_fn FunLike.coe_eq_coe_fn +theorem coe_eq_coe_fn : (DFunLike.coe (F := F)) = (fun f => ↑f) := rfl +#align fun_like.coe_eq_coe_fn DFunLike.coe_eq_coe_fn theorem coe_injective : Function.Injective (fun f : F ↦ (f : ∀ a : α, β a)) := - FunLike.coe_injective' -#align fun_like.coe_injective FunLike.coe_injective + DFunLike.coe_injective' +#align fun_like.coe_injective DFunLike.coe_injective @[simp] theorem coe_fn_eq {f g : F} : (f : ∀ a : α, β a) = (g : ∀ a : α, β a) ↔ f = g := - ⟨fun h ↦ FunLike.coe_injective' h, fun h ↦ by cases h; rfl⟩ -#align fun_like.coe_fn_eq FunLike.coe_fn_eq + ⟨fun h ↦ DFunLike.coe_injective' h, fun h ↦ by cases h; rfl⟩ +#align fun_like.coe_fn_eq DFunLike.coe_fn_eq theorem ext' {f g : F} (h : (f : ∀ a : α, β a) = (g : ∀ a : α, β a)) : f = g := - FunLike.coe_injective' h -#align fun_like.ext' FunLike.ext' + DFunLike.coe_injective' h +#align fun_like.ext' DFunLike.ext' theorem ext'_iff {f g : F} : f = g ↔ (f : ∀ a : α, β a) = (g : ∀ a : α, β a) := coe_fn_eq.symm -#align fun_like.ext'_iff FunLike.ext'_iff +#align fun_like.ext'_iff DFunLike.ext'_iff theorem ext (f g : F) (h : ∀ x : α, f x = g x) : f = g := - FunLike.coe_injective' (funext h) -#align fun_like.ext FunLike.ext + DFunLike.coe_injective' (funext h) +#align fun_like.ext DFunLike.ext theorem ext_iff {f g : F} : f = g ↔ ∀ x, f x = g x := coe_fn_eq.symm.trans Function.funext_iff -#align fun_like.ext_iff FunLike.ext_iff +#align fun_like.ext_iff DFunLike.ext_iff protected theorem congr_fun {f g : F} (h₁ : f = g) (x : α) : f x = g x := congr_fun (congr_arg _ h₁) x -#align fun_like.congr_fun FunLike.congr_fun +#align fun_like.congr_fun DFunLike.congr_fun theorem ne_iff {f g : F} : f ≠ g ↔ ∃ a, f a ≠ g a := ext_iff.not.trans not_forall -#align fun_like.ne_iff FunLike.ne_iff +#align fun_like.ne_iff DFunLike.ne_iff theorem exists_ne {f g : F} (h : f ≠ g) : ∃ x, f x ≠ g x := ne_iff.mp h -#align fun_like.exists_ne FunLike.exists_ne +#align fun_like.exists_ne DFunLike.exists_ne /-- This is not an instance to avoid slowing down every single `Subsingleton` typeclass search.-/ lemma subsingleton_cod [∀ a, Subsingleton (β a)] : Subsingleton F := - ⟨fun _ _ ↦ coe_injective $ Subsingleton.elim _ _⟩ -#align fun_like.subsingleton_cod FunLike.subsingleton_cod + ⟨fun _ _ ↦ coe_injective <| Subsingleton.elim _ _⟩ +#align fun_like.subsingleton_cod DFunLike.subsingleton_cod -end FunLike +end DFunLike end Dependent section NonDependent -/-! ### `FunLike F α (λ _, β)` where `β` does not depend on `a : α` -/ +/-! ### `FunLike F α β` where `β` does not depend on `a : α` -/ -variable {F α β : Sort*} [i : FunLike F α fun _ ↦ β] +variable {F α β : Sort*} [i : FunLike F α β] -namespace FunLike +namespace DFunLike protected theorem congr {f g : F} {x y : α} (h₁ : f = g) (h₂ : x = y) : f x = g y := congr (congr_arg _ h₁) h₂ -#align fun_like.congr FunLike.congr +#align fun_like.congr DFunLike.congr protected theorem congr_arg (f : F) {x y : α} (h₂ : x = y) : f x = f y := congr_arg _ h₂ -#align fun_like.congr_arg FunLike.congr_arg +#align fun_like.congr_arg DFunLike.congr_arg -end FunLike +end DFunLike end NonDependent diff --git a/Mathlib/Data/FunLike/Embedding.lean b/Mathlib/Data/FunLike/Embedding.lean index b559aeaf167c2..d78f281170d78 100644 --- a/Mathlib/Data/FunLike/Embedding.lean +++ b/Mathlib/Data/FunLike/Embedding.lean @@ -34,7 +34,7 @@ instance : EmbeddingLike (MyEmbedding A B) A B := /-- Helper instance for when there's too many metavariables to `EmbeddingLike.coe` directly. -/ instance : CoeFun (MyEmbedding A B) (λ _, A → B) := ⟨MyEmbedding.toFun⟩ -@[ext] theorem ext {f g : MyEmbedding A B} (h : ∀ x, f x = g x) : f = g := FunLike.ext f g h +@[ext] theorem ext {f g : MyEmbedding A B} (h : ∀ x, f x = g x) : f = g := DFunLike.ext f g h /-- Copy of a `MyEmbedding` with a new `toFun` equal to the old one. Useful to fix definitional equalities. -/ @@ -131,7 +131,7 @@ instead of linearly increasing the work per `MyEmbedding`-related declaration. /-- The class `EmbeddingLike F α β` expresses that terms of type `F` have an injective coercion to injective functions `α ↪ β`. -/ -class EmbeddingLike (F : Sort*) (α β : outParam (Sort*)) extends FunLike F α fun _ ↦ β where +class EmbeddingLike (F : Sort*) (α β : outParam (Sort*)) extends DFunLike F α fun _ ↦ β where /-- The coercion to functions must produce injective functions. -/ injective' : ∀ f : F, Function.Injective (coe f) #align embedding_like EmbeddingLike diff --git a/Mathlib/Data/FunLike/Equiv.lean b/Mathlib/Data/FunLike/Equiv.lean index cb8e16fc8c21f..a29cf214645b0 100644 --- a/Mathlib/Data/FunLike/Equiv.lean +++ b/Mathlib/Data/FunLike/Equiv.lean @@ -33,9 +33,9 @@ instance : EquivLike (MyIso A B) A (λ _, B) := coe_injective' := λ f g h, by cases f; cases g; congr' } /-- Helper instance for when there's too many metavariables to apply `EquivLike.coe` directly. -/ -instance : CoeFun (MyIso A B) := FunLike.instCoeFunForAll +instance : CoeFun (MyIso A B) := DFunLike.instCoeFunForAll -@[ext] theorem ext {f g : MyIso A B} (h : ∀ x, f x = g x) : f = g := FunLike.ext f g h +@[ext] theorem ext {f g : MyIso A B} (h : ∀ x, f x = g x) : f = g := DFunLike.ext f g h /-- Copy of a `MyIso` with a new `toFun` equal to the old one. Useful to fix definitional equalities. -/ @@ -228,7 +228,7 @@ theorem comp_bijective (f : α → β) (e : F) : Function.Bijective (e ∘ f) /-- This is not an instance to avoid slowing down every single `Subsingleton` typeclass search.-/ lemma subsingleton_dom [Subsingleton β] : Subsingleton F := - ⟨fun f g ↦ FunLike.ext f g fun _ ↦ (right_inv f).injective $ Subsingleton.elim _ _⟩ + ⟨fun f g ↦ DFunLike.ext f g fun _ ↦ (right_inv f).injective <| Subsingleton.elim _ _⟩ #align equiv_like.subsingleton_dom EquivLike.subsingleton_dom end EquivLike diff --git a/Mathlib/Data/FunLike/Fintype.lean b/Mathlib/Data/FunLike/Fintype.lean index a0c8284e635a1..bfa2bca283ade 100644 --- a/Mathlib/Data/FunLike/Fintype.lean +++ b/Mathlib/Data/FunLike/Fintype.lean @@ -10,20 +10,20 @@ import Mathlib.Data.FunLike.Basic #align_import data.fun_like.fintype from "leanprover-community/mathlib"@"f7fc89d5d5ff1db2d1242c7bb0e9062ce47ef47c" /-! -# Finiteness of `FunLike` types +# Finiteness of `DFunLike` types -We show a type `F` with a `FunLike F α β` is finite if both `α` and `β` are finite. +We show a type `F` with a `DFunLike F α β` is finite if both `α` and `β` are finite. This corresponds to the following two pairs of declarations: - * `FunLike.fintype` is a definition stating all `FunLike`s are finite if their domain and + * `DFunLike.fintype` is a definition stating all `DFunLike`s are finite if their domain and codomain are. - * `FunLike.finite` is a lemma stating all `FunLike`s are finite if their domain and + * `DFunLike.finite` is a lemma stating all `DFunLike`s are finite if their domain and codomain are. - * `FunLike.fintype'` is a non-dependent version of `FunLike.fintype` and - * `FunLike.finite` is a non-dependent version of `FunLike.finite`, because dependent instances + * `DFunLike.fintype'` is a non-dependent version of `DFunLike.fintype` and + * `DFunLike.finite` is a non-dependent version of `DFunLike.finite`, because dependent instances are harder to infer. -You can use these to produce instances for specific `FunLike` types. +You can use these to produce instances for specific `DFunLike` types. (Although there might be options for `Fintype` instances with better definitional behaviour.) They can't be instances themselves since they can cause loops. -/ @@ -31,49 +31,49 @@ They can't be instances themselves since they can cause loops. -- porting notes: `Type` is a reserved word, switched to `Type'` section Type' -variable (F G : Type*) {α γ : Type*} {β : α → Type*} [FunLike F α β] [FunLike G α fun _ => γ] +variable (F G : Type*) {α γ : Type*} {β : α → Type*} [DFunLike F α β] [FunLike G α γ] -/-- All `FunLike`s are finite if their domain and codomain are. +/-- All `DFunLike`s are finite if their domain and codomain are. -This is not an instance because specific `FunLike` types might have a better-suited definition. +This is not an instance because specific `DFunLike` types might have a better-suited definition. -See also `FunLike.finite`. +See also `DFunLike.finite`. -/ -noncomputable def FunLike.fintype [DecidableEq α] [Fintype α] [∀ i, Fintype (β i)] : Fintype F := - Fintype.ofInjective _ FunLike.coe_injective -#align fun_like.fintype FunLike.fintype +noncomputable def DFunLike.fintype [DecidableEq α] [Fintype α] [∀ i, Fintype (β i)] : Fintype F := + Fintype.ofInjective _ DFunLike.coe_injective +#align fun_like.fintype DFunLike.fintype /-- All `FunLike`s are finite if their domain and codomain are. -Non-dependent version of `FunLike.fintype` that might be easier to infer. +Non-dependent version of `DFunLike.fintype` that might be easier to infer. This is not an instance because specific `FunLike` types might have a better-suited definition. -/ -noncomputable def FunLike.fintype' [DecidableEq α] [Fintype α] [Fintype γ] : Fintype G := - FunLike.fintype G -#align fun_like.fintype' FunLike.fintype' +noncomputable def FunLike.fintype [DecidableEq α] [Fintype α] [Fintype γ] : Fintype G := + DFunLike.fintype G +#align fun_like.fintype' FunLike.fintype end Type' -- porting notes: `Sort` is a reserved word, switched to `Sort'` section Sort' -variable (F G : Sort*) {α γ : Sort*} {β : α → Sort*} [FunLike F α β] [FunLike G α fun _ => γ] +variable (F G : Sort*) {α γ : Sort*} {β : α → Sort*} [DFunLike F α β] [FunLike G α γ] -/-- All `FunLike`s are finite if their domain and codomain are. +/-- All `DFunLike`s are finite if their domain and codomain are. Can't be an instance because it can cause infinite loops. -/ -theorem FunLike.finite [Finite α] [∀ i, Finite (β i)] : Finite F := - Finite.of_injective _ FunLike.coe_injective -#align fun_like.finite FunLike.finite +theorem DFunLike.finite [Finite α] [∀ i, Finite (β i)] : Finite F := + Finite.of_injective _ DFunLike.coe_injective +#align fun_like.finite DFunLike.finite /-- All `FunLike`s are finite if their domain and codomain are. -Non-dependent version of `FunLike.finite` that might be easier to infer. +Non-dependent version of `DFunLike.finite` that might be easier to infer. Can't be an instance because it can cause infinite loops. -/ -theorem FunLike.finite' [Finite α] [Finite γ] : Finite G := - FunLike.finite G -#align fun_like.finite' FunLike.finite' +theorem FunLike.finite [Finite α] [Finite γ] : Finite G := + DFunLike.finite G +#align fun_like.finite' FunLike.finite end Sort' diff --git a/Mathlib/Data/HashMap.lean b/Mathlib/Data/HashMap.lean index eb84a05f27aa9..71f51c5c30249 100644 --- a/Mathlib/Data/HashMap.lean +++ b/Mathlib/Data/HashMap.lean @@ -7,9 +7,9 @@ As `HashMap` has been completely reimplemented in `Std`, nothing from the mathlib3 file `data.hash_map` is reflected here. The porting header is just here to mark that no further work on `data.hash_map` is desired. -/ -import Mathlib.Init.Align import Std.Data.HashMap.Basic import Std.Data.RBMap.Basic +import Mathlib.Mathport.Rename #align_import data.hash_map from "leanprover-community/mathlib"@"f0c8bf9245297a541f468be517f1bde6195105e9" diff --git a/Mathlib/Data/Int/Basic.lean b/Mathlib/Data/Int/Basic.lean index d608336210a56..f6ab4b5aff4e3 100644 --- a/Mathlib/Data/Int/Basic.lean +++ b/Mathlib/Data/Int/Basic.lean @@ -3,19 +3,17 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Init.Data.Int.Order +import Mathlib.Algebra.Group.TypeTags +import Mathlib.Algebra.Ring.Defs import Mathlib.Data.Int.Cast.Basic -import Mathlib.Algebra.Ring.Basic import Mathlib.Order.Monotone.Basic #align_import data.int.basic from "leanprover-community/mathlib"@"00d163e35035c3577c1c79fa53b68de17781ffc1" /-! -# Basic operations on the integers +# Basic algebraic instances on the integers -This file contains: -* instances on `ℤ`. The stronger one is `Int.linearOrderedCommRing`. -* some basic lemmas about integers +This file contains instances on `ℤ`. The stronger one is `Int.linearOrderedCommRing`. -/ set_option autoImplicit true @@ -24,8 +22,6 @@ open Nat namespace Int -instance instNontrivialInt : Nontrivial ℤ := ⟨⟨0, 1, Int.zero_ne_one⟩⟩ - instance instCommRingInt : CommRing ℤ where zero_mul := Int.zero_mul mul_zero := Int.mul_zero @@ -74,19 +70,12 @@ theorem cast_mul [NonAssocRing α] : ∀ m n, ((m * n : ℤ) : α) = m * n := fu | succ m ih => simp_all [add_mul] #align int.cast_mul Int.cast_mulₓ -- dubious translation, type involves HasLiftT -@[simp] lemma ofNat_eq_cast : Int.ofNat n = n := rfl - lemma cast_Nat_cast [AddGroupWithOne R] : (Int.cast (Nat.cast n) : R) = Nat.cast n := Int.cast_ofNat _ -@[norm_cast] -lemma cast_eq_cast_iff_Nat (m n : ℕ) : (m : ℤ) = (n : ℤ) ↔ m = n := ofNat_inj - -@[simp, norm_cast] -lemma natAbs_cast (n : ℕ) : natAbs ↑n = n := rfl - -@[norm_cast] -protected lemma coe_nat_sub {n m : ℕ} : n ≤ m → (↑(m - n) : ℤ) = ↑m - ↑n := ofNat_sub +@[simp, norm_cast] lemma cast_pow [Ring R] (n : ℤ) (m : ℕ) : ↑(n ^ m) = (n ^ m : R) := by + induction' m with m ih <;> simp [_root_.pow_succ, *] +#align int.cast_pow Int.cast_pow /-! ### Extra instances to short-circuit type class resolution @@ -108,203 +97,37 @@ instance : Semiring ℤ := by infer_instance instance instRingInt : Ring ℤ := by infer_instance instance : Distrib ℤ := by infer_instance -#align int.neg_succ_not_nonneg Int.negSucc_not_nonneg -#align int.neg_succ_not_pos Int.negSucc_not_pos -#align int.neg_succ_sub_one Int.negSucc_sub_one -#align int.coe_nat_mul_neg_succ Int.ofNat_mul_negSucc -#align int.neg_succ_mul_coe_nat Int.negSucc_mul_ofNat -#align int.neg_succ_mul_neg_succ Int.negSucc_mul_negSucc - -#align int.coe_nat_le Int.ofNat_le -#align int.coe_nat_lt Int.ofNat_lt - -theorem coe_nat_inj' {m n : ℕ} : (↑m : ℤ) = ↑n ↔ m = n := Int.ofNat_inj -#align int.coe_nat_inj' Int.coe_nat_inj' +lemma natAbs_pow (n : ℤ) (k : ℕ) : Int.natAbs (n ^ k) = Int.natAbs n ^ k := by + induction' k with k ih + · rfl + · rw [_root_.pow_succ, natAbs_mul, Nat.pow_succ, ih, Nat.mul_comm] +#align int.nat_abs_pow Int.natAbs_pow theorem coe_nat_strictMono : StrictMono (· : ℕ → ℤ) := fun _ _ ↦ Int.ofNat_lt.2 #align int.coe_nat_strict_mono Int.coe_nat_strictMono -theorem coe_nat_nonneg (n : ℕ) : 0 ≤ (n : ℤ) := ofNat_le.2 (Nat.zero_le _) -#align int.coe_nat_nonneg Int.coe_nat_nonneg - -#align int.neg_of_nat_ne_zero Int.negSucc_ne_zero -#align int.zero_ne_neg_of_nat Int.zero_ne_negSucc - -@[simp] -theorem sign_coe_add_one (n : ℕ) : Int.sign (n + 1) = 1 := - rfl -#align int.sign_coe_add_one Int.sign_coe_add_one - -#align int.sign_neg_succ_of_nat Int.sign_negSucc - -/-! ### succ and pred -/ - -/-- Immediate successor of an integer: `succ n = n + 1` -/ -def succ (a : ℤ) := a + 1 -#align int.succ Int.succ - -/-- Immediate predecessor of an integer: `pred n = n - 1` -/ -def pred (a : ℤ) := a - 1 -#align int.pred Int.pred - -theorem nat_succ_eq_int_succ (n : ℕ) : (Nat.succ n : ℤ) = Int.succ n := rfl -#align int.nat_succ_eq_int_succ Int.nat_succ_eq_int_succ - -theorem pred_succ (a : ℤ) : pred (succ a) = a := add_sub_cancel _ _ -#align int.pred_succ Int.pred_succ - -theorem succ_pred (a : ℤ) : succ (pred a) = a := sub_add_cancel _ _ -#align int.succ_pred Int.succ_pred - -theorem neg_succ (a : ℤ) : -succ a = pred (-a) := neg_add _ _ -#align int.neg_succ Int.neg_succ - -theorem succ_neg_succ (a : ℤ) : succ (-succ a) = -a := by rw [neg_succ, succ_pred] -#align int.succ_neg_succ Int.succ_neg_succ - -theorem neg_pred (a : ℤ) : -pred a = succ (-a) := by - rw [neg_eq_iff_eq_neg.mp (neg_succ (-a)), neg_neg] -#align int.neg_pred Int.neg_pred - -theorem pred_neg_pred (a : ℤ) : pred (-pred a) = -a := by rw [neg_pred, pred_succ] -#align int.pred_neg_pred Int.pred_neg_pred - -theorem pred_nat_succ (n : ℕ) : pred (Nat.succ n) = n := pred_succ n -#align int.pred_nat_succ Int.pred_nat_succ - -theorem neg_nat_succ (n : ℕ) : -(Nat.succ n : ℤ) = pred (-n) := neg_succ n -#align int.neg_nat_succ Int.neg_nat_succ - -theorem succ_neg_nat_succ (n : ℕ) : succ (-Nat.succ n) = -n := succ_neg_succ n -#align int.succ_neg_nat_succ Int.succ_neg_nat_succ - -@[norm_cast] theorem coe_pred_of_pos {n : ℕ} (h : 0 < n) : ((n - 1 : ℕ) : ℤ) = (n : ℤ) - 1 := by - cases n; cases h; simp -#align int.coe_pred_of_pos Int.coe_pred_of_pos - -@[elab_as_elim] protected theorem induction_on {p : ℤ → Prop} (i : ℤ) - (hz : p 0) (hp : ∀ i : ℕ, p i → p (i + 1)) (hn : ∀ i : ℕ, p (-i) → p (-i - 1)) : p i := by - induction i with - | ofNat i => - induction i with - | zero => exact hz - | succ i ih => exact hp _ ih - | negSucc i => - suffices ∀ n : ℕ, p (-n) from this (i + 1) - intro n; induction n with - | zero => simp [hz, Nat.cast_zero] - | succ n ih => convert hn _ ih using 1; simp [sub_eq_neg_add] -#align int.induction_on Int.induction_on - -/-! ### nat abs -/ - -theorem natAbs_surjective : natAbs.Surjective := fun n => ⟨n, natAbs_ofNat n⟩ -#align int.nat_abs_surjective Int.natAbs_surjective - -#align int.nat_abs_add_le Int.natAbs_add_le -#align int.nat_abs_sub_le Int.natAbs_sub_le -#align int.nat_abs_neg_of_nat Int.natAbs_negOfNat -#align int.nat_abs_mul Int.natAbs_mul -#align int.nat_abs_mul_nat_abs_eq Int.natAbs_mul_natAbs_eq -#align int.nat_abs_mul_self' Int.natAbs_mul_self' -#align int.neg_succ_of_nat_eq' Int.negSucc_eq' - -@[deprecated natAbs_ne_zero] -theorem natAbs_ne_zero_of_ne_zero : ∀ {a : ℤ}, a ≠ 0 → natAbs a ≠ 0 := natAbs_ne_zero.2 -#align int.nat_abs_ne_zero_of_ne_zero Int.natAbs_ne_zero_of_ne_zero - -#align int.nat_abs_eq_zero Int.natAbs_eq_zero -#align int.nat_abs_ne_zero Int.natAbs_ne_zero -#align int.nat_abs_lt_nat_abs_of_nonneg_of_lt Int.natAbs_lt_natAbs_of_nonneg_of_lt -#align int.nat_abs_eq_nat_abs_iff Int.natAbs_eq_natAbs_iff -#align int.nat_abs_eq_iff Int.natAbs_eq_iff - -/-! ### `/` -/ - --- Porting note: Many of the theorems in this section are dubious alignments because the default --- division on `Int` has changed from the E-rounding convention to the T-rounding convention --- (see `Int.ediv`). We have attempted to align the theorems to continue to use the `/` symbol --- where possible, but some theorems fail to hold on T-rounding division and have been aligned to --- `Int.ediv` instead. - -#align int.of_nat_div Int.ofNat_div - -@[simp, norm_cast] theorem coe_nat_div (m n : ℕ) : ((m / n : ℕ) : ℤ) = m / n := rfl -#align int.coe_nat_div Int.coe_nat_div - -theorem coe_nat_ediv (m n : ℕ) : ((m / n : ℕ) : ℤ) = ediv m n := rfl - -#align int.neg_succ_of_nat_div Int.negSucc_ediv - -#align int.div_neg Int.div_negₓ -- int div alignment - -theorem ediv_of_neg_of_pos {a b : ℤ} (Ha : a < 0) (Hb : 0 < b) : ediv a b = -((-a - 1) / b + 1) := - match a, b, eq_negSucc_of_lt_zero Ha, eq_succ_of_zero_lt Hb with - | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by - rw [show (- -[m+1] : ℤ) = (m + 1 : ℤ) by rfl]; rw [add_sub_cancel]; rfl -#align int.div_of_neg_of_pos Int.ediv_of_neg_of_pos - -#align int.div_nonneg Int.div_nonnegₓ -- int div alignment -#align int.div_neg' Int.ediv_neg' -#align int.div_one Int.div_oneₓ -- int div alignment -#align int.div_eq_zero_of_lt Int.div_eq_zero_of_ltₓ -- int div alignment - -/-! ### mod -/ - -#align int.of_nat_mod Int.ofNat_mod_ofNat - -@[simp, norm_cast] theorem coe_nat_mod (m n : ℕ) : (↑(m % n) : ℤ) = ↑m % ↑n := rfl -#align int.coe_nat_mod Int.coe_nat_mod - -#align int.neg_succ_of_nat_mod Int.negSucc_emod -#align int.mod_neg Int.mod_negₓ -- int div alignment -#align int.zero_mod Int.zero_modₓ -- int div alignment -#align int.mod_zero Int.mod_zeroₓ -- int div alignment -#align int.mod_one Int.mod_oneₓ -- int div alignment -#align int.mod_eq_of_lt Int.emod_eq_of_lt -- int div alignment -#align int.mod_add_div Int.emod_add_ediv -- int div alignment -#align int.div_add_mod Int.div_add_modₓ -- int div alignment -#align int.mod_add_div' Int.mod_add_div'ₓ -- int div alignment -#align int.div_add_mod' Int.div_add_mod'ₓ -- int div alignment -#align int.mod_def Int.mod_defₓ -- int div alignment - -/-! ### properties of `/` and `%` -/ +section Multiplicative -#align int.mul_div_mul_of_pos Int.mul_ediv_mul_of_pos -#align int.mul_div_mul_of_pos_left Int.mul_ediv_mul_of_pos_left -#align int.mul_mod_mul_of_pos Int.mul_emod_mul_of_pos -#align int.mul_div_cancel_of_mod_eq_zero Int.mul_div_cancel_of_mod_eq_zeroₓ -- int div alignment -#align int.div_mul_cancel_of_mod_eq_zero Int.div_mul_cancel_of_mod_eq_zeroₓ -- int div alignment +open Multiplicative -#align int.nat_abs_sign Int.natAbs_sign -#align int.nat_abs_sign_of_nonzero Int.natAbs_sign_of_nonzero +lemma toAdd_pow (a : Multiplicative ℤ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b := mul_comm _ _ +#align int.to_add_pow Int.toAdd_pow -theorem sign_coe_nat_of_nonzero {n : ℕ} (hn : n ≠ 0) : Int.sign n = 1 := sign_ofNat_of_nonzero hn -#align int.sign_coe_nat_of_nonzero Int.sign_coe_nat_of_nonzero +lemma toAdd_zpow (a : Multiplicative ℤ) (b : ℤ) : toAdd (a ^ b) = toAdd a * b := mul_comm _ _ +#align int.to_add_zpow Int.toAdd_zpow -#align int.div_sign Int.div_sign -- int div alignment -#align int.of_nat_add_neg_succ_of_nat_of_lt Int.ofNat_add_negSucc_of_lt -#align int.neg_add_neg Int.negSucc_add_negSucc +@[simp] lemma ofAdd_mul (a b : ℤ) : ofAdd (a * b) = ofAdd a ^ b := (toAdd_zpow ..).symm +#align int.of_add_mul Int.ofAdd_mul -/-! ### toNat -/ +end Multiplicative -#align int.to_nat_eq_max Int.toNat_eq_max -#align int.to_nat_zero Int.toNat_zero -#align int.to_nat_one Int.toNat_one -#align int.to_nat_of_nonneg Int.toNat_of_nonneg +end Int -@[simp] theorem toNat_coe_nat (n : ℕ) : toNat ↑n = n := rfl -#align int.to_nat_coe_nat Int.toNat_coe_nat +-- TODO: Do we really need this lemma? This is just `smul_eq_mul` +lemma zsmul_int_int (a b : ℤ) : a • b = a * b := rfl +#align zsmul_int_int zsmul_int_int -@[simp] theorem toNat_coe_nat_add_one {n : ℕ} : ((n : ℤ) + 1).toNat = n + 1 := rfl -#align int.to_nat_coe_nat_add_one Int.toNat_coe_nat_add_one +lemma zsmul_int_one (n : ℤ) : n • (1 : ℤ) = n := mul_one _ +#align zsmul_int_one zsmul_int_one -#align int.le_to_nat Int.self_le_toNat -#align int.le_to_nat_iff Int.le_toNat -#align int.to_nat_add Int.toNat_add -#align int.to_nat_add_nat Int.toNat_add_nat -#align int.pred_to_nat Int.pred_toNat -#align int.to_nat_sub_to_nat_neg Int.toNat_sub_toNat_neg -#align int.to_nat_add_to_nat_neg_eq_nat_abs Int.toNat_add_toNat_neg_eq_natAbs -#align int.mem_to_nat' Int.mem_toNat' -#align int.to_nat_neg_nat Int.toNat_neg_nat +assert_not_exists Set.range diff --git a/Mathlib/Data/Int/Cast/Basic.lean b/Mathlib/Data/Int/Cast/Basic.lean index 49d39feab2002..191a8aa7b66ca 100644 --- a/Mathlib/Data/Int/Cast/Basic.lean +++ b/Mathlib/Data/Int/Cast/Basic.lean @@ -128,16 +128,6 @@ theorem cast_sub (m n) : ((m - n : ℤ) : R) = m - n := by section deprecated set_option linter.deprecated false -@[norm_cast, deprecated] -theorem ofNat_bit0 (n : ℕ) : (↑(bit0 n) : ℤ) = bit0 ↑n := - rfl -#align int.coe_nat_bit0 Int.ofNat_bit0 - -@[norm_cast, deprecated] -theorem ofNat_bit1 (n : ℕ) : (↑(bit1 n) : ℤ) = bit1 ↑n := - rfl -#align int.coe_nat_bit1 Int.ofNat_bit1 - @[norm_cast, deprecated] theorem cast_bit0 (n : ℤ) : ((bit0 n : ℤ) : R) = bit0 (n : R) := Int.cast_add _ _ diff --git a/Mathlib/Data/Int/Cast/Field.lean b/Mathlib/Data/Int/Cast/Field.lean index 152150f0ace0e..0023250828ef1 100644 --- a/Mathlib/Data/Int/Cast/Field.lean +++ b/Mathlib/Data/Int/Cast/Field.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bhavik Mehta -/ -import Mathlib.Data.Int.Cast.Lemmas +import Mathlib.Data.Int.Basic import Mathlib.Algebra.Field.Defs import Mathlib.Algebra.GroupWithZero.Units.Lemmas diff --git a/Mathlib/Data/Int/Cast/Lemmas.lean b/Mathlib/Data/Int/Cast/Lemmas.lean index 462fcc0d89724..64c0d8b03b53d 100644 --- a/Mathlib/Data/Int/Cast/Lemmas.lean +++ b/Mathlib/Data/Int/Cast/Lemmas.lean @@ -3,7 +3,6 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Group.TypeTags import Mathlib.Algebra.Ring.Hom.Basic import Mathlib.Data.Int.Order.Basic import Mathlib.Data.Nat.Cast.Commute @@ -25,8 +24,7 @@ which were not available in the import dependencies of `Data.Int.Cast.Basic`. * `castRingHom`: `cast` bundled as a `RingHom`. -/ - -open Nat +open Additive Multiplicative Nat variable {F ι α β : Type*} @@ -52,7 +50,7 @@ lemma toNat_lt' {a : ℤ} {b : ℕ} (hb : b ≠ 0) : a.toNat < b ↔ a < b := by #align int.to_nat_lt Int.toNat_lt' lemma natMod_lt {a : ℤ} {b : ℕ} (hb : b ≠ 0) : a.natMod b < b := - (toNat_lt' hb).2 $ emod_lt_of_pos _ $ coe_nat_pos.2 hb.bot_lt + (toNat_lt' hb).2 <| emod_lt_of_pos _ <| coe_nat_pos.2 hb.bot_lt #align int.nat_mod_lt Int.natMod_lt section cast @@ -75,8 +73,12 @@ theorem coe_castAddHom [AddGroupWithOne α] : ⇑(castAddHom α) = fun x : ℤ = rfl #align int.coe_cast_add_hom Int.coe_castAddHom +section NonAssocRing +variable [NonAssocRing α] {a b : α} {n : ℤ} + +variable (α) in /-- `coe : ℤ → α` as a `RingHom`. -/ -def castRingHom (α : Type*) [NonAssocRing α] : ℤ →+* α where +def castRingHom : ℤ →+* α where toFun := Int.cast map_zero' := cast_zero map_add' := cast_add @@ -84,26 +86,38 @@ def castRingHom (α : Type*) [NonAssocRing α] : ℤ →+* α where map_mul' := cast_mul #align int.cast_ring_hom Int.castRingHom -@[simp] -theorem coe_castRingHom [NonAssocRing α] : ⇑(castRingHom α) = fun x : ℤ => (x : α) := - rfl +@[simp] lemma coe_castRingHom : ⇑(castRingHom α) = fun x : ℤ ↦ (x : α) := rfl #align int.coe_cast_ring_hom Int.coe_castRingHom -theorem cast_commute [NonAssocRing α] : ∀ (m : ℤ) (x : α), Commute (↑m) x +lemma cast_commute : ∀ (n : ℤ) (a : α), Commute ↑n a | (n : ℕ), x => by simpa using n.cast_commute x | -[n+1], x => by simpa only [cast_negSucc, Commute.neg_left_iff, Commute.neg_right_iff] using (n + 1).cast_commute (-x) #align int.cast_commute Int.cast_commute -theorem cast_comm [NonAssocRing α] (m : ℤ) (x : α) : (m : α) * x = x * m := - (cast_commute m x).eq +lemma cast_comm (n : ℤ) (x : α) : n * x = x * n := (cast_commute ..).eq #align int.cast_comm Int.cast_comm -theorem commute_cast [NonAssocRing α] (x : α) (m : ℤ) : Commute x m := - (m.cast_commute x).symm +lemma commute_cast (a : α) (n : ℤ) : Commute a n := (cast_commute ..).symm #align int.commute_cast Int.commute_cast +end NonAssocRing + +section Ring +variable [Ring α] + +@[simp] lemma _root_.zsmul_eq_mul (a : α) : ∀ n : ℤ, n • a = n * a + | (n : ℕ) => by rw [coe_nat_zsmul, nsmul_eq_mul, Int.cast_ofNat] + | -[n+1] => by simp [Nat.cast_succ, neg_add_rev, Int.cast_negSucc, add_mul] +#align zsmul_eq_mul zsmul_eq_mul + +lemma _root_.zsmul_eq_mul' (a : α) (n : ℤ) : n • a = a * n := by + rw [zsmul_eq_mul, (n.cast_commute a).eq] +#align zsmul_eq_mul' zsmul_eq_mul' + +end Ring + theorem cast_mono [OrderedRing α] : Monotone (fun x : ℤ => (x : α)) := by intro m n h rw [← sub_nonneg] at h @@ -209,12 +223,85 @@ theorem coe_int_dvd [CommRing α] (m n : ℤ) (h : m ∣ n) : (m : α) ∣ (n : RingHom.map_dvd (Int.castRingHom α) h #align int.coe_int_dvd Int.coe_int_dvd +-- Porting note: `simp` and `norm_cast` attribute removed. This is a special case of `Nat.cast_pow` +lemma coe_nat_pow (m n : ℕ) : ↑(m ^ n : ℕ) = (m ^ n : ℤ) := by + induction' m with m _ <;> simp +#align int.coe_nat_pow Int.coe_nat_pow + end cast end Int open Int +namespace SemiconjBy +variable [Ring α] {a x y : α} + +@[simp] lemma cast_int_mul_right (h : SemiconjBy a x y) (n : ℤ) : SemiconjBy a (n * x) (n * y) := + SemiconjBy.mul_right (Int.commute_cast _ _) h +#align semiconj_by.cast_int_mul_right SemiconjBy.cast_int_mul_right + +@[simp] lemma cast_int_mul_left (h : SemiconjBy a x y) (n : ℤ) : SemiconjBy (n * a) x y := + SemiconjBy.mul_left (Int.cast_commute _ _) h +#align semiconj_by.cast_int_mul_left SemiconjBy.cast_int_mul_left + +@[simp] lemma cast_int_mul_cast_int_mul (h : SemiconjBy a x y) (m n : ℤ) : + SemiconjBy (m * a) (n * x) (n * y) := (h.cast_int_mul_left m).cast_int_mul_right n +#align semiconj_by.cast_int_mul_cast_int_mul SemiconjBy.cast_int_mul_cast_int_mul + +end SemiconjBy + +namespace Commute +section NonAssocRing +variable [NonAssocRing α] {a b : α} {n : ℤ} + +@[simp] lemma cast_int_left : Commute (n : α) a := Int.cast_commute _ _ +#align commute.cast_int_left Commute.cast_int_left + +@[simp] lemma cast_int_right : Commute a n := Int.commute_cast _ _ +#align commute.cast_int_right Commute.cast_int_right +end NonAssocRing + +section Ring +variable [Ring α] {a b : α} {n : ℤ} + +@[simp] lemma cast_int_mul_right (h : Commute a b) (m : ℤ) : Commute a (m * b) := + SemiconjBy.cast_int_mul_right h m +#align commute.cast_int_mul_right Commute.cast_int_mul_right + +@[simp] lemma cast_int_mul_left (h : Commute a b) (m : ℤ) : Commute (m * a) b := + SemiconjBy.cast_int_mul_left h m +#align commute.cast_int_mul_left Commute.cast_int_mul_left + +lemma cast_int_mul_cast_int_mul (h : Commute a b) (m n : ℤ) : Commute (m * a) (n * b) := + SemiconjBy.cast_int_mul_cast_int_mul h m n +#align commute.cast_int_mul_cast_int_mul Commute.cast_int_mul_cast_int_mul + +variable (a) (m n : ℤ) + +/- Porting note: `simp` attribute removed as linter reports: +simp can prove this: + by simp only [Commute.cast_int_right, Commute.refl, Commute.mul_right] +-/ +-- @[simp] +lemma self_cast_int_mul : Commute a (n * a : α) := (Commute.refl a).cast_int_mul_right n +#align commute.self_cast_int_mul Commute.self_cast_int_mul + +/- Porting note: `simp` attribute removed as linter reports: +simp can prove this: + by simp only [Commute.cast_int_left, Commute.refl, Commute.mul_left] +-/ +-- @[simp] +lemma cast_int_mul_self : Commute ((n : α) * a) a := (Commute.refl a).cast_int_mul_left n +#align commute.cast_int_mul_self Commute.cast_int_mul_self + +lemma self_cast_int_mul_cast_int_mul : Commute (m * a : α) (n * a : α) := + (Commute.refl a).cast_int_mul_cast_int_mul m n +#align commute.self_cast_int_mul_cast_int_mul Commute.self_cast_int_mul_cast_int_mul + +end Ring +end Commute + namespace AddMonoidHom variable {A : Type*} @@ -224,7 +311,7 @@ if `f 1 = g 1`. -/ @[ext high] theorem ext_int [AddMonoid A] {f g : ℤ →+ A} (h1 : f 1 = g 1) : f = g := have : f.comp (Int.ofNatHom : ℕ →+ ℤ) = g.comp (Int.ofNatHom : ℕ →+ ℤ) := ext_nat' _ _ h1 - have this' : ∀ n : ℕ, f n = g n := FunLike.ext_iff.1 this + have this' : ∀ n : ℕ, f n = g n := DFunLike.ext_iff.1 this ext fun n => match n with | (n : ℕ) => this' n | .negSucc n => eq_on_neg _ _ (this' <| n + 1) @@ -240,9 +327,12 @@ end AddMonoidHom theorem eq_intCast' [AddGroupWithOne α] [AddMonoidHomClass F ℤ α] (f : F) (h₁ : f 1 = 1) : ∀ n : ℤ, f n = n := - FunLike.ext_iff.1 <| (f : ℤ →+ α).eq_int_castAddHom h₁ + DFunLike.ext_iff.1 <| (f : ℤ →+ α).eq_int_castAddHom h₁ #align eq_int_cast' eq_intCast' +@[simp] lemma zsmul_one [AddGroupWithOne α] (n : ℤ) : n • (1 : α) = n := by cases n <;> simp +#align zsmul_one zsmul_one + @[simp] theorem Int.castAddHom_int : Int.castAddHom ℤ = AddMonoidHom.id ℤ := ((AddMonoidHom.id ℤ).eq_int_castAddHom rfl).symm @@ -264,10 +354,10 @@ theorem ext_mint {f g : Multiplicative ℤ →* M} (h1 : f (ofAdd 1) = g (ofAdd theorem ext_int {f g : ℤ →* M} (h_neg_one : f (-1) = g (-1)) (h_nat : f.comp Int.ofNatHom.toMonoidHom = g.comp Int.ofNatHom.toMonoidHom) : f = g := by ext (x | x) - · exact (FunLike.congr_fun h_nat x : _) + · exact (DFunLike.congr_fun h_nat x : _) · rw [Int.negSucc_eq, ← neg_one_mul, f.map_mul, g.map_mul] congr 1 - exact mod_cast (FunLike.congr_fun h_nat (x + 1) : _) + exact mod_cast (DFunLike.congr_fun h_nat (x + 1) : _) #align monoid_hom.ext_int MonoidHom.ext_int end MonoidHom @@ -282,7 +372,7 @@ theorem ext_int {f g : ℤ →*₀ M} (h_neg_one : f (-1) = g (-1)) (h_nat : f.comp Int.ofNatHom.toMonoidWithZeroHom = g.comp Int.ofNatHom.toMonoidWithZeroHom) : f = g := toMonoidHom_injective <| MonoidHom.ext_int h_neg_one <| - MonoidHom.ext (FunLike.congr_fun h_nat : _) + MonoidHom.ext (DFunLike.congr_fun h_nat : _) #align monoid_with_zero_hom.ext_int MonoidWithZeroHom.ext_int end MonoidWithZeroHom @@ -290,15 +380,95 @@ end MonoidWithZeroHom /-- If two `MonoidWithZeroHom`s agree on `-1` and the _positive_ naturals then they are equal. -/ theorem ext_int' [MonoidWithZero α] [MonoidWithZeroHomClass F ℤ α] {f g : F} (h_neg_one : f (-1) = g (-1)) (h_pos : ∀ n : ℕ, 0 < n → f n = g n) : f = g := - (FunLike.ext _ _) fun n => + (DFunLike.ext _ _) fun n => haveI := - FunLike.congr_fun + DFunLike.congr_fun (@MonoidWithZeroHom.ext_int _ _ (f : ℤ →*₀ α) (g : ℤ →*₀ α) h_neg_one <| MonoidWithZeroHom.ext_nat (h_pos _)) n this #align ext_int' ext_int' +section Group +variable (α) [Group α] [AddGroup α] + +/-- Additive homomorphisms from `ℤ` are defined by the image of `1`. -/ +def zmultiplesHom : α ≃ (ℤ →+ α) where + toFun x := + { toFun := fun n => n • x + map_zero' := zero_zsmul x + map_add' := fun _ _ => add_zsmul _ _ _ } + invFun f := f 1 + left_inv := one_zsmul + right_inv f := AddMonoidHom.ext_int <| one_zsmul (f 1) +#align zmultiples_hom zmultiplesHom +#align powers_hom powersHom + +/-- Monoid homomorphisms from `Multiplicative ℤ` are defined by the image +of `Multiplicative.ofAdd 1`. -/ +@[to_additive existing zmultiplesHom] +def zpowersHom : α ≃ (Multiplicative ℤ →* α) := + ofMul.trans <| (zmultiplesHom _).trans <| AddMonoidHom.toMultiplicative'' +#align zpowers_hom zpowersHom + +lemma zmultiplesHom_apply (x : α) (n : ℤ) : zmultiplesHom α x n = n • x := rfl +#align zmultiples_hom_apply zmultiplesHom_apply + +lemma zmultiplesHom_symm_apply (f : ℤ →+ α) : (zmultiplesHom α).symm f = f 1 := rfl +#align zmultiples_hom_symm_apply zmultiplesHom_symm_apply + +@[to_additive existing (attr := simp) zmultiplesHom_apply] +lemma zpowersHom_apply (x : α) (n : Multiplicative ℤ) :zpowersHom α x n = x ^ toAdd n := rfl +#align zpowers_hom_apply zpowersHom_apply + +@[to_additive existing (attr := simp) zmultiplesHom_symm_apply] +lemma zpowersHom_symm_apply (f : Multiplicative ℤ →* α) : + (zpowersHom α).symm f = f (ofAdd 1) := rfl +#align zpowers_hom_symm_apply zpowersHom_symm_apply + +lemma MonoidHom.apply_mint (f : Multiplicative ℤ →* α) (n : Multiplicative ℤ) : + f n = f (ofAdd 1) ^ (toAdd n) := by + rw [← zpowersHom_symm_apply, ← zpowersHom_apply, Equiv.apply_symm_apply] +#align monoid_hom.apply_mint MonoidHom.apply_mint + +lemma AddMonoidHom.apply_int (f : ℤ →+ α) (n : ℤ) : f n = n • f 1 := by + rw [← zmultiplesHom_symm_apply, ← zmultiplesHom_apply, Equiv.apply_symm_apply] +#align add_monoid_hom.apply_int AddMonoidHom.apply_int + +end Group + +section CommGroup +variable (α) [CommGroup α] [AddCommGroup α] + +/-- If `α` is commutative, `zmultiplesHom` is an additive equivalence. -/ +def zmultiplesAddHom : α ≃+ (ℤ →+ α) := + { zmultiplesHom α with map_add' := fun a b => AddMonoidHom.ext fun n => by simp [zsmul_add] } +#align zmultiples_add_hom zmultiplesAddHom + +/-- If `α` is commutative, `zpowersHom` is a multiplicative equivalence. -/ +def zpowersMulHom : α ≃* (Multiplicative ℤ →* α) := + { zpowersHom α with map_mul' := fun a b => MonoidHom.ext fun n => by simp [mul_zpow] } +#align zpowers_mul_hom zpowersMulHom + +variable {α} + +@[simp] +lemma zpowersMulHom_apply (x : α) (n : Multiplicative ℤ) : zpowersMulHom α x n = x ^ toAdd n := rfl +#align zpowers_mul_hom_apply zpowersMulHom_apply + +@[simp] +lemma zpowersMulHom_symm_apply (f : Multiplicative ℤ →* α) : + (zpowersMulHom α).symm f = f (ofAdd 1) := rfl +#align zpowers_mul_hom_symm_apply zpowersMulHom_symm_apply + +@[simp] lemma zmultiplesAddHom_apply (x : α) (n : ℤ) : zmultiplesAddHom α x n = n • x := rfl +#align zmultiples_add_hom_apply zmultiplesAddHom_apply + +@[simp] lemma zmultiplesAddHom_symm_apply (f : ℤ →+ α) : (zmultiplesAddHom α).symm f = f 1 := rfl +#align zmultiples_add_hom_symm_apply zmultiplesAddHom_symm_apply + +end CommGroup + section NonAssocRing variable [NonAssocRing α] [NonAssocRing β] @@ -361,6 +531,7 @@ theorem Sum.elim_intCast_intCast {α β γ : Type*} [IntCast γ] (n : ℤ) : Sum.elim_lam_const_lam_const (γ := γ) n #align sum.elim_int_cast_int_cast Sum.elim_intCast_intCast + /-! ### Order dual -/ diff --git a/Mathlib/Data/Int/Cast/Prod.lean b/Mathlib/Data/Int/Cast/Prod.lean index aa7301d65b164..54325719fc13f 100644 --- a/Mathlib/Data/Int/Cast/Prod.lean +++ b/Mathlib/Data/Int/Cast/Prod.lean @@ -3,7 +3,6 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Int.Cast.Lemmas import Mathlib.Data.Nat.Cast.Prod #align_import data.int.cast.prod from "leanprover-community/mathlib"@"ee0c179cd3c8a45aa5bffbf1b41d8dbede452865" diff --git a/Mathlib/Data/Int/CharZero.lean b/Mathlib/Data/Int/CharZero.lean index b4c716548800c..ebd2c95330558 100644 --- a/Mathlib/Data/Int/CharZero.lean +++ b/Mathlib/Data/Int/CharZero.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Algebra.Function.Support import Mathlib.Data.Int.Cast.Field +import Mathlib.Data.Int.Cast.Lemmas #align_import data.int.char_zero from "leanprover-community/mathlib"@"29cb56a7b35f72758b05a30490e1f10bd62c35c1" @@ -77,11 +78,11 @@ namespace Function variable [AddGroupWithOne β] [CharZero β] {n : ℤ} lemma support_int_cast (hn : n ≠ 0) : support (n : α → β) = univ := - support_const $ Int.cast_ne_zero.2 hn + support_const <| Int.cast_ne_zero.2 hn #align function.support_int_cast Function.support_int_cast lemma mulSupport_int_cast (hn : n ≠ 1) : mulSupport (n : α → β) = univ := - mulSupport_const $ Int.cast_ne_one.2 hn + mulSupport_const <| Int.cast_ne_one.2 hn #align function.mul_support_int_cast Function.mulSupport_int_cast end Function diff --git a/Mathlib/Data/Int/Defs.lean b/Mathlib/Data/Int/Defs.lean new file mode 100644 index 0000000000000..ea4348d51a820 --- /dev/null +++ b/Mathlib/Data/Int/Defs.lean @@ -0,0 +1,248 @@ +/- +Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad +-/ +import Mathlib.Init.Data.Int.Basic +import Mathlib.Init.ZeroOne +import Mathlib.Logic.Nontrivial.Defs +import Mathlib.Tactic.Convert + +/-! +# Basic operations on the integers + +This file contains some basic lemmas about integers. +-/ + +open Nat + +namespace Int +variable {m n : ℕ} + +instance instNontrivialInt : Nontrivial ℤ := ⟨⟨0, 1, Int.zero_ne_one⟩⟩ + +@[simp] lemma ofNat_eq_cast : Int.ofNat n = n := rfl + +@[norm_cast] lemma cast_eq_cast_iff_Nat (m n : ℕ) : (m : ℤ) = (n : ℤ) ↔ m = n := ofNat_inj + +@[simp, norm_cast] lemma natAbs_cast (n : ℕ) : natAbs ↑n = n := rfl + +@[norm_cast] +protected lemma coe_nat_sub {n m : ℕ} : n ≤ m → (↑(m - n) : ℤ) = ↑m - ↑n := ofNat_sub + +#align int.neg_succ_not_nonneg Int.negSucc_not_nonneg +#align int.neg_succ_not_pos Int.negSucc_not_pos +#align int.neg_succ_sub_one Int.negSucc_sub_one +#align int.coe_nat_mul_neg_succ Int.ofNat_mul_negSucc +#align int.neg_succ_mul_coe_nat Int.negSucc_mul_ofNat +#align int.neg_succ_mul_neg_succ Int.negSucc_mul_negSucc + +#align int.coe_nat_le Int.ofNat_le +#align int.coe_nat_lt Int.ofNat_lt + +lemma coe_nat_inj' : (↑m : ℤ) = ↑n ↔ m = n := Int.ofNat_inj +#align int.coe_nat_inj' Int.coe_nat_inj' + +lemma coe_nat_nonneg (n : ℕ) : 0 ≤ (n : ℤ) := ofNat_le.2 (Nat.zero_le _) +#align int.coe_nat_nonneg Int.coe_nat_nonneg + +#align int.neg_of_nat_ne_zero Int.negSucc_ne_zero +#align int.zero_ne_neg_of_nat Int.zero_ne_negSucc + +@[simp] lemma sign_coe_add_one (n : ℕ) : sign (n + 1) = 1 := rfl +#align int.sign_coe_add_one Int.sign_coe_add_one + +#align int.sign_neg_succ_of_nat Int.sign_negSucc + +protected lemma two_mul : ∀ n : ℤ, 2 * n = n + n + | (n : ℕ) => by norm_cast; exact n.two_mul + | -[n+1] => by + change (2 : ℕ) * (_ : ℤ) = _ + rw [Int.ofNat_mul_negSucc, Nat.two_mul, ofNat_add, Int.neg_add] + rfl + +section deprecated +set_option linter.deprecated false + +@[norm_cast, deprecated] lemma ofNat_bit0 (n : ℕ) : (↑(bit0 n) : ℤ) = bit0 ↑n := rfl +#align int.coe_nat_bit0 Int.ofNat_bit0 + +@[norm_cast, deprecated] lemma ofNat_bit1 (n : ℕ) : (↑(bit1 n) : ℤ) = bit1 ↑n := rfl +#align int.coe_nat_bit1 Int.ofNat_bit1 + +end deprecated + +/-! ### succ and pred -/ + +/-- Immediate successor of an integer: `succ n = n + 1` -/ +def succ (a : ℤ) := a + 1 +#align int.succ Int.succ + +/-- Immediate predecessor of an integer: `pred n = n - 1` -/ +def pred (a : ℤ) := a - 1 +#align int.pred Int.pred + +lemma nat_succ_eq_int_succ (n : ℕ) : (Nat.succ n : ℤ) = Int.succ n := rfl +#align int.nat_succ_eq_int_succ Int.nat_succ_eq_int_succ + +lemma pred_succ (a : ℤ) : pred (succ a) = a := Int.add_sub_cancel _ _ +#align int.pred_succ Int.pred_succ + +lemma succ_pred (a : ℤ) : succ (pred a) = a := Int.sub_add_cancel _ _ +#align int.succ_pred Int.succ_pred + +lemma neg_succ (a : ℤ) : -succ a = pred (-a) := Int.neg_add +#align int.neg_succ Int.neg_succ + +lemma succ_neg_succ (a : ℤ) : succ (-succ a) = -a := by rw [neg_succ, succ_pred] +#align int.succ_neg_succ Int.succ_neg_succ + +lemma neg_pred (a : ℤ) : -pred a = succ (-a) := by + rw [← Int.neg_eq_comm.mp (neg_succ (-a)), Int.neg_neg] +#align int.neg_pred Int.neg_pred + +lemma pred_neg_pred (a : ℤ) : pred (-pred a) = -a := by rw [neg_pred, pred_succ] +#align int.pred_neg_pred Int.pred_neg_pred + +lemma pred_nat_succ (n : ℕ) : pred (Nat.succ n) = n := pred_succ n +#align int.pred_nat_succ Int.pred_nat_succ + +lemma neg_nat_succ (n : ℕ) : -(Nat.succ n : ℤ) = pred (-n) := neg_succ n +#align int.neg_nat_succ Int.neg_nat_succ + +lemma succ_neg_nat_succ (n : ℕ) : succ (-Nat.succ n) = -n := succ_neg_succ n +#align int.succ_neg_nat_succ Int.succ_neg_nat_succ + +@[norm_cast] lemma coe_pred_of_pos {n : ℕ} (h : 0 < n) : ((n - 1 : ℕ) : ℤ) = (n : ℤ) - 1 := by + cases n; cases h; simp [ofNat_succ] +#align int.coe_pred_of_pos Int.coe_pred_of_pos + +@[elab_as_elim] protected lemma induction_on {p : ℤ → Prop} (i : ℤ) + (hz : p 0) (hp : ∀ i : ℕ, p i → p (i + 1)) (hn : ∀ i : ℕ, p (-i) → p (-i - 1)) : p i := by + induction i with + | ofNat i => + induction i with + | zero => exact hz + | succ i ih => exact hp _ ih + | negSucc i => + suffices ∀ n : ℕ, p (-n) from this (i + 1) + intro n; induction n with + | zero => simp [hz] + | succ n ih => convert hn _ ih using 1; simp [ofNat_succ, Int.neg_add, Int.sub_eq_add_neg] +#align int.induction_on Int.induction_on + +/-! ### nat abs -/ + +lemma natAbs_surjective : natAbs.Surjective := fun n => ⟨n, natAbs_ofNat n⟩ +#align int.nat_abs_surjective Int.natAbs_surjective + +#align int.nat_abs_add_le Int.natAbs_add_le +#align int.nat_abs_sub_le Int.natAbs_sub_le +#align int.nat_abs_neg_of_nat Int.natAbs_negOfNat +#align int.nat_abs_mul Int.natAbs_mul +#align int.nat_abs_mul_nat_abs_eq Int.natAbs_mul_natAbs_eq +#align int.nat_abs_mul_self' Int.natAbs_mul_self' +#align int.neg_succ_of_nat_eq' Int.negSucc_eq' + +@[deprecated natAbs_ne_zero] +lemma natAbs_ne_zero_of_ne_zero : ∀ {a : ℤ}, a ≠ 0 → natAbs a ≠ 0 := natAbs_ne_zero.2 +#align int.nat_abs_ne_zero_of_ne_zero Int.natAbs_ne_zero_of_ne_zero + +#align int.nat_abs_eq_zero Int.natAbs_eq_zero +#align int.nat_abs_ne_zero Int.natAbs_ne_zero +#align int.nat_abs_lt_nat_abs_of_nonneg_of_lt Int.natAbs_lt_natAbs_of_nonneg_of_lt +#align int.nat_abs_eq_nat_abs_iff Int.natAbs_eq_natAbs_iff +#align int.nat_abs_eq_iff Int.natAbs_eq_iff + +/-! ### `/` -/ + +-- Porting note: Many of the lemmas in this section are dubious alignments because the default +-- division on `Int` has changed from the E-rounding convention to the T-rounding convention +-- (see `Int.ediv`). We have attempted to align the lemmas to continue to use the `/` symbol +-- where possible, but some lemmas fail to hold on T-rounding division and have been aligned to +-- `Int.ediv` instead. + +#align int.of_nat_div Int.ofNat_div + +@[simp, norm_cast] lemma coe_nat_div (m n : ℕ) : ((m / n : ℕ) : ℤ) = m / n := rfl +#align int.coe_nat_div Int.coe_nat_div + +lemma coe_nat_ediv (m n : ℕ) : ((m / n : ℕ) : ℤ) = ediv m n := rfl + +#align int.neg_succ_of_nat_div Int.negSucc_ediv + +#align int.div_neg Int.div_negₓ -- int div alignment + +lemma ediv_of_neg_of_pos {a b : ℤ} (Ha : a < 0) (Hb : 0 < b) : ediv a b = -((-a - 1) / b + 1) := + match a, b, eq_negSucc_of_lt_zero Ha, eq_succ_of_zero_lt Hb with + | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by + rw [show (- -[m+1] : ℤ) = (m + 1 : ℤ) by rfl]; rw [Int.add_sub_cancel]; rfl +#align int.div_of_neg_of_pos Int.ediv_of_neg_of_pos + +#align int.div_nonneg Int.div_nonnegₓ -- int div alignment +#align int.div_neg' Int.ediv_neg' +#align int.div_one Int.div_oneₓ -- int div alignment +#align int.div_eq_zero_of_lt Int.div_eq_zero_of_ltₓ -- int div alignment + +/-! ### mod -/ + +#align int.of_nat_mod Int.ofNat_mod_ofNat + +@[simp, norm_cast] lemma coe_nat_mod (m n : ℕ) : (↑(m % n) : ℤ) = ↑m % ↑n := rfl +#align int.coe_nat_mod Int.coe_nat_mod + +#align int.neg_succ_of_nat_mod Int.negSucc_emod +#align int.mod_neg Int.mod_negₓ -- int div alignment +#align int.zero_mod Int.zero_modₓ -- int div alignment +#align int.mod_zero Int.mod_zeroₓ -- int div alignment +#align int.mod_one Int.mod_oneₓ -- int div alignment +#align int.mod_eq_of_lt Int.emod_eq_of_lt -- int div alignment +#align int.mod_add_div Int.emod_add_ediv -- int div alignment +#align int.div_add_mod Int.div_add_modₓ -- int div alignment +#align int.mod_add_div' Int.mod_add_div'ₓ -- int div alignment +#align int.div_add_mod' Int.div_add_mod'ₓ -- int div alignment +#align int.mod_def Int.mod_defₓ -- int div alignment + +/-! ### properties of `/` and `%` -/ + +#align int.mul_div_mul_of_pos Int.mul_ediv_mul_of_pos +#align int.mul_div_mul_of_pos_left Int.mul_ediv_mul_of_pos_left +#align int.mul_mod_mul_of_pos Int.mul_emod_mul_of_pos +#align int.mul_div_cancel_of_mod_eq_zero Int.mul_div_cancel_of_mod_eq_zeroₓ -- int div alignment +#align int.div_mul_cancel_of_mod_eq_zero Int.div_mul_cancel_of_mod_eq_zeroₓ -- int div alignment + +#align int.nat_abs_sign Int.natAbs_sign +#align int.nat_abs_sign_of_nonzero Int.natAbs_sign_of_nonzero + +lemma sign_coe_nat_of_nonzero {n : ℕ} (hn : n ≠ 0) : Int.sign n = 1 := sign_ofNat_of_nonzero hn +#align int.sign_coe_nat_of_nonzero Int.sign_coe_nat_of_nonzero + +#align int.div_sign Int.div_sign -- int div alignment +#align int.of_nat_add_neg_succ_of_nat_of_lt Int.ofNat_add_negSucc_of_lt +#align int.neg_add_neg Int.negSucc_add_negSucc + +/-! ### toNat -/ + +#align int.to_nat_eq_max Int.toNat_eq_max +#align int.to_nat_zero Int.toNat_zero +#align int.to_nat_one Int.toNat_one +#align int.to_nat_of_nonneg Int.toNat_of_nonneg + +@[simp] lemma toNat_coe_nat (n : ℕ) : toNat ↑n = n := rfl +#align int.to_nat_coe_nat Int.toNat_coe_nat + +@[simp] lemma toNat_coe_nat_add_one {n : ℕ} : ((n : ℤ) + 1).toNat = n + 1 := rfl +#align int.to_nat_coe_nat_add_one Int.toNat_coe_nat_add_one + +#align int.le_to_nat Int.self_le_toNat +#align int.le_to_nat_iff Int.le_toNat +#align int.to_nat_add Int.toNat_add +#align int.to_nat_add_nat Int.toNat_add_nat +#align int.pred_to_nat Int.pred_toNat +#align int.to_nat_sub_to_nat_neg Int.toNat_sub_toNat_neg +#align int.to_nat_add_to_nat_neg_eq_nat_abs Int.toNat_add_toNat_neg_eq_natAbs +#align int.mem_to_nat' Int.mem_toNat' +#align int.to_nat_neg_nat Int.toNat_neg_nat + +-- Porting note: this was added in an ad hoc port for use in `Tactic/NormNum/Basic` +@[simp] lemma pow_eq (m : ℤ) (n : ℕ) : m.pow n = m ^ n := rfl diff --git a/Mathlib/Data/Int/Dvd/Basic.lean b/Mathlib/Data/Int/Dvd/Basic.lean index 9f905edfecbc9..5e43bcd8b71d8 100644 --- a/Mathlib/Data/Int/Dvd/Basic.lean +++ b/Mathlib/Data/Int/Dvd/Basic.lean @@ -5,6 +5,7 @@ Authors: Jeremy Avigad -/ import Mathlib.Data.Int.Order.Basic import Mathlib.Data.Nat.Cast.Order +import Mathlib.Algebra.Ring.Divisibility.Basic #align_import data.int.dvd.basic from "leanprover-community/mathlib"@"e8638a0fcaf73e4500469f368ef9494e495099b3" @@ -31,11 +32,11 @@ theorem coe_nat_dvd {m n : ℕ} : (↑m : ℤ) ∣ ↑n ↔ m ∣ n := #align int.coe_nat_dvd Int.coe_nat_dvd theorem coe_nat_dvd_left {n : ℕ} {z : ℤ} : (↑n : ℤ) ∣ z ↔ n ∣ z.natAbs := by - rcases natAbs_eq z with (eq | eq) <;> rw [eq] <;> simp [← coe_nat_dvd] + rcases natAbs_eq z with (eq | eq) <;> rw [eq] <;> simp [← coe_nat_dvd, Int.dvd_neg] #align int.coe_nat_dvd_left Int.coe_nat_dvd_left theorem coe_nat_dvd_right {n : ℕ} {z : ℤ} : z ∣ (↑n : ℤ) ↔ z.natAbs ∣ n := by - rcases natAbs_eq z with (eq | eq) <;> rw [eq] <;> simp [← coe_nat_dvd] + rcases natAbs_eq z with (eq | eq) <;> rw [eq] <;> simp [← coe_nat_dvd, Int.neg_dvd] #align int.coe_nat_dvd_right Int.coe_nat_dvd_right #align int.le_of_dvd Int.le_of_dvd diff --git a/Mathlib/Data/Int/Dvd/Pow.lean b/Mathlib/Data/Int/Dvd/Pow.lean index d853d9caac280..f9e921bae03bf 100644 --- a/Mathlib/Data/Int/Dvd/Pow.lean +++ b/Mathlib/Data/Int/Dvd/Pow.lean @@ -3,8 +3,9 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Data.Int.Dvd.Basic -import Mathlib.Data.Nat.Pow +import Mathlib.Algebra.GroupPower.Ring +import Mathlib.Data.Int.Basic +import Mathlib.Data.Nat.Cast.Basic #align_import data.int.dvd.pow from "leanprover-community/mathlib"@"e8638a0fcaf73e4500469f368ef9494e495099b3" diff --git a/Mathlib/Data/Int/GCD.lean b/Mathlib/Data/Int/GCD.lean index 7e6959244c3ab..01f1267947098 100644 --- a/Mathlib/Data/Int/GCD.lean +++ b/Mathlib/Data/Int/GCD.lean @@ -3,10 +3,10 @@ Copyright (c) 2018 Guy Leroy. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sangwoo Jo (aka Jason), Guy Leroy, Johannes Hölzl, Mario Carneiro -/ -import Mathlib.Data.Nat.GCD.Basic -import Mathlib.Algebra.GroupPower.Lemmas +import Mathlib.Algebra.GroupWithZero.Power import Mathlib.Algebra.Ring.Regular import Mathlib.Data.Int.Dvd.Basic +import Mathlib.Data.Nat.GCD.Basic import Mathlib.Order.Bounds.Basic #align_import data.int.gcd from "leanprover-community/mathlib"@"47a1a73351de8dd6c8d3d32b569c8e434b03ca47" @@ -231,9 +231,6 @@ theorem dvd_of_mul_dvd_mul_right {i j k : ℤ} (k_non_zero : k ≠ 0) (H : i * k rw [mul_comm i k, mul_comm j k] at H; exact dvd_of_mul_dvd_mul_left k_non_zero H #align int.dvd_of_mul_dvd_mul_right Int.dvd_of_mul_dvd_mul_right -/-- ℤ specific version of least common multiple. -/ -def lcm (i j : ℤ) : ℕ := - Nat.lcm (natAbs i) (natAbs j) #align int.lcm Int.lcm theorem lcm_def (i j : ℤ) : lcm i j = Nat.lcm (natAbs i) (natAbs j) := @@ -244,12 +241,7 @@ protected theorem coe_nat_lcm (m n : ℕ) : Int.lcm ↑m ↑n = Nat.lcm m n := rfl #align int.coe_nat_lcm Int.coe_nat_lcm -theorem gcd_dvd_left (i j : ℤ) : (gcd i j : ℤ) ∣ i := - dvd_natAbs.mp <| coe_nat_dvd.mpr <| Nat.gcd_dvd_left _ _ #align int.gcd_dvd_left Int.gcd_dvd_left - -theorem gcd_dvd_right (i j : ℤ) : (gcd i j : ℤ) ∣ j := - dvd_natAbs.mp <| coe_nat_dvd.mpr <| Nat.gcd_dvd_right _ _ #align int.gcd_dvd_right Int.gcd_dvd_right theorem dvd_gcd {i j k : ℤ} (h1 : k ∣ i) (h2 : k ∣ j) : k ∣ gcd i j := @@ -281,23 +273,10 @@ theorem gcd_zero_left (i : ℤ) : gcd 0 i = natAbs i := by simp [gcd] theorem gcd_zero_right (i : ℤ) : gcd i 0 = natAbs i := by simp [gcd] #align int.gcd_zero_right Int.gcd_zero_right -@[simp] -theorem gcd_one_left (i : ℤ) : gcd 1 i = 1 := - Nat.gcd_one_left _ -#align int.gcd_one_left Int.gcd_one_left - -@[simp] -theorem gcd_one_right (i : ℤ) : gcd i 1 = 1 := - Nat.gcd_one_right _ -#align int.gcd_one_right Int.gcd_one_right - -@[simp] -theorem gcd_neg_right {x y : ℤ} : gcd x (-y) = gcd x y := by rw [Int.gcd, Int.gcd, natAbs_neg] -#align int.gcd_neg_right Int.gcd_neg_right - -@[simp] -theorem gcd_neg_left {x y : ℤ} : gcd (-x) y = gcd x y := by rw [Int.gcd, Int.gcd, natAbs_neg] -#align int.gcd_neg_left Int.gcd_neg_left +#align int.gcd_one_left Int.one_gcd +#align int.gcd_one_right Int.gcd_one +#align int.gcd_neg_right Int.gcd_neg +#align int.gcd_neg_left Int.neg_gcd theorem gcd_mul_left (i j k : ℤ) : gcd (i * j) (i * k) = natAbs i * gcd j k := by rw [Int.gcd, Int.gcd, natAbs_mul, natAbs_mul] @@ -310,11 +289,11 @@ theorem gcd_mul_right (i j k : ℤ) : gcd (i * j) (k * j) = gcd i k * natAbs j : #align int.gcd_mul_right Int.gcd_mul_right theorem gcd_pos_of_ne_zero_left {i : ℤ} (j : ℤ) (hi : i ≠ 0) : 0 < gcd i j := - Nat.gcd_pos_of_pos_left _ $ natAbs_pos.2 hi + Nat.gcd_pos_of_pos_left _ <| natAbs_pos.2 hi #align int.gcd_pos_of_ne_zero_left Int.gcd_pos_of_ne_zero_left theorem gcd_pos_of_ne_zero_right (i : ℤ) {j : ℤ} (hj : j ≠ 0) : 0 < gcd i j := - Nat.gcd_pos_of_pos_right _ $ natAbs_pos.2 hj + Nat.gcd_pos_of_pos_right _ <| natAbs_pos.2 hj #align int.gcd_pos_of_ne_zero_right Int.gcd_pos_of_ne_zero_right theorem gcd_eq_zero_iff {i j : ℤ} : gcd i j = 0 ↔ i = 0 ∧ j = 0 := by @@ -332,15 +311,15 @@ theorem gcd_div {i j k : ℤ} (H1 : k ∣ i) (H2 : k ∣ j) : #align int.gcd_div Int.gcd_div theorem gcd_div_gcd_div_gcd {i j : ℤ} (H : 0 < gcd i j) : gcd (i / gcd i j) (j / gcd i j) = 1 := by - rw [gcd_div (gcd_dvd_left i j) (gcd_dvd_right i j), natAbs_ofNat, Nat.div_self H] + rw [gcd_div gcd_dvd_left gcd_dvd_right, natAbs_ofNat, Nat.div_self H] #align int.gcd_div_gcd_div_gcd Int.gcd_div_gcd_div_gcd theorem gcd_dvd_gcd_of_dvd_left {i k : ℤ} (j : ℤ) (H : i ∣ k) : gcd i j ∣ gcd k j := - Int.coe_nat_dvd.1 <| dvd_gcd ((gcd_dvd_left i j).trans H) (gcd_dvd_right i j) + Int.coe_nat_dvd.1 <| dvd_gcd (gcd_dvd_left.trans H) gcd_dvd_right #align int.gcd_dvd_gcd_of_dvd_left Int.gcd_dvd_gcd_of_dvd_left theorem gcd_dvd_gcd_of_dvd_right {i k : ℤ} (j : ℤ) (H : i ∣ k) : gcd j i ∣ gcd j k := - Int.coe_nat_dvd.1 <| dvd_gcd (gcd_dvd_left j i) ((gcd_dvd_right j i).trans H) + Int.coe_nat_dvd.1 <| dvd_gcd gcd_dvd_left (gcd_dvd_right.trans H) #align int.gcd_dvd_gcd_of_dvd_right Int.gcd_dvd_gcd_of_dvd_right theorem gcd_dvd_gcd_mul_left (i j k : ℤ) : gcd i j ∣ gcd (k * i) j := @@ -373,8 +352,8 @@ theorem ne_zero_of_gcd {x y : ℤ} (hc : gcd x y ≠ 0) : x ≠ 0 ∨ y ≠ 0 := theorem exists_gcd_one {m n : ℤ} (H : 0 < gcd m n) : ∃ m' n' : ℤ, gcd m' n' = 1 ∧ m = m' * gcd m n ∧ n = n' * gcd m n := - ⟨_, _, gcd_div_gcd_div_gcd H, (Int.ediv_mul_cancel (gcd_dvd_left m n)).symm, - (Int.ediv_mul_cancel (gcd_dvd_right m n)).symm⟩ + ⟨_, _, gcd_div_gcd_div_gcd H, (Int.ediv_mul_cancel gcd_dvd_left).symm, + (Int.ediv_mul_cancel gcd_dvd_right).symm⟩ #align int.exists_gcd_one Int.exists_gcd_one theorem exists_gcd_one' {m n : ℤ} (H : 0 < gcd m n) : @@ -397,13 +376,13 @@ theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑ · rintro ⟨x, y, h⟩ rw [← Int.coe_nat_dvd, h] exact - dvd_add (dvd_mul_of_dvd_left (gcd_dvd_left a b) _) (dvd_mul_of_dvd_left (gcd_dvd_right a b) y) + dvd_add (dvd_mul_of_dvd_left gcd_dvd_left _) (dvd_mul_of_dvd_left gcd_dvd_right y) #align int.gcd_dvd_iff Int.gcd_dvd_iff theorem gcd_greatest {a b d : ℤ} (hd_pos : 0 ≤ d) (hda : d ∣ a) (hdb : d ∣ b) (hd : ∀ e : ℤ, e ∣ a → e ∣ b → e ∣ d) : d = gcd a b := dvd_antisymm hd_pos (ofNat_zero_le (gcd a b)) (dvd_gcd hda hdb) - (hd _ (gcd_dvd_left a b) (gcd_dvd_right a b)) + (hd _ gcd_dvd_left gcd_dvd_right) #align int.gcd_greatest Int.gcd_greatest /-- Euclid's lemma: if `a ∣ b * c` and `gcd a c = 1` then `a ∣ b`. @@ -475,22 +454,8 @@ theorem lcm_one_right (i : ℤ) : lcm i 1 = natAbs i := by apply Nat.lcm_one_right #align int.lcm_one_right Int.lcm_one_right -@[simp] -theorem lcm_self (i : ℤ) : lcm i i = natAbs i := by - rw [Int.lcm] - apply Nat.lcm_self #align int.lcm_self Int.lcm_self - -theorem dvd_lcm_left (i j : ℤ) : i ∣ lcm i j := by - rw [Int.lcm] - apply coe_nat_dvd_right.mpr - apply Nat.dvd_lcm_left #align int.dvd_lcm_left Int.dvd_lcm_left - -theorem dvd_lcm_right (i j : ℤ) : j ∣ lcm i j := by - rw [Int.lcm] - apply coe_nat_dvd_right.mpr - apply Nat.dvd_lcm_right #align int.dvd_lcm_right Int.dvd_lcm_right theorem lcm_dvd {i j k : ℤ} : i ∣ k → j ∣ k → (lcm i j : ℤ) ∣ k := by @@ -517,3 +482,37 @@ theorem pow_gcd_eq_one {M : Type*} [Monoid M] (x : M) {m n : ℕ} (hm : x ^ m = simp only [Nat.gcd_eq_gcd_ab, zpow_add, zpow_mul, hm, hn, one_zpow, one_mul] #align pow_gcd_eq_one pow_gcd_eq_one #align gcd_nsmul_eq_zero gcd_nsmul_eq_zero + +variable {α : Type*} + +section GroupWithZero +variable [GroupWithZero α] {a b : α} {m n : ℕ} + +protected lemma Commute.pow_eq_pow_iff_of_coprime (hab : Commute a b) (hmn : m.Coprime n) : + a ^ m = b ^ n ↔ ∃ c, a = c ^ n ∧ b = c ^ m := by + refine ⟨fun h ↦ ?_, by rintro ⟨c, rfl, rfl⟩; rw [← pow_mul, ← pow_mul']⟩ + by_cases m = 0; · aesop + by_cases n = 0; · aesop + by_cases hb : b = 0; · exact ⟨0, by aesop⟩ + by_cases ha : a = 0; · exact ⟨0, by have := h.symm; aesop⟩ + refine ⟨a ^ Nat.gcdB m n * b ^ Nat.gcdA m n, ?_, ?_⟩ <;> + · refine (pow_one _).symm.trans ?_ + conv_lhs => rw [← zpow_ofNat, ← hmn, Nat.gcd_eq_gcd_ab] + simp only [zpow_add₀ ha, zpow_add₀ hb, ← zpow_ofNat, (hab.zpow_zpow₀ _ _).mul_zpow, ← zpow_mul, + mul_comm (Nat.gcdB m n), mul_comm (Nat.gcdA m n)] + simp only [zpow_mul, zpow_ofNat, h] + exact ((Commute.pow_pow (by aesop) _ _).zpow_zpow₀ _ _).symm + +end GroupWithZero + +section CommGroupWithZero +variable [CommGroupWithZero α] {a b : α} {m n : ℕ} + +lemma pow_eq_pow_iff_of_coprime (hmn : m.Coprime n) : a ^ m = b ^ n ↔ ∃ c, a = c ^ n ∧ b = c ^ m := + (Commute.all _ _).pow_eq_pow_iff_of_coprime hmn + +lemma pow_mem_range_pow_of_coprime (hmn : m.Coprime n) (a : α) : + a ^ m ∈ Set.range (· ^ n : α → α) ↔ a ∈ Set.range (· ^ n : α → α) := by + simp [pow_eq_pow_iff_of_coprime hmn.symm]; aesop + +end CommGroupWithZero diff --git a/Mathlib/Data/Int/Interval.lean b/Mathlib/Data/Int/Interval.lean index 703abb4c9049a..e0f08d5e2b71d 100644 --- a/Mathlib/Data/Int/Interval.lean +++ b/Mathlib/Data/Int/Interval.lean @@ -102,23 +102,23 @@ theorem Ioo_eq_finset_map : theorem uIcc_eq_finset_map : uIcc a b = (range (max a b + 1 - min a b).toNat).map - (Nat.castEmbedding.trans <| addLeftEmbedding $ min a b) := rfl + (Nat.castEmbedding.trans <| addLeftEmbedding <| min a b) := rfl #align int.uIcc_eq_finset_map Int.uIcc_eq_finset_map @[simp] -theorem card_Icc : (Icc a b).card = (b + 1 - a).toNat := (card_map _).trans $ card_range _ +theorem card_Icc : (Icc a b).card = (b + 1 - a).toNat := (card_map _).trans <| card_range _ #align int.card_Icc Int.card_Icc @[simp] -theorem card_Ico : (Ico a b).card = (b - a).toNat := (card_map _).trans $ card_range _ +theorem card_Ico : (Ico a b).card = (b - a).toNat := (card_map _).trans <| card_range _ #align int.card_Ico Int.card_Ico @[simp] -theorem card_Ioc : (Ioc a b).card = (b - a).toNat := (card_map _).trans $ card_range _ +theorem card_Ioc : (Ioc a b).card = (b - a).toNat := (card_map _).trans <| card_range _ #align int.card_Ioc Int.card_Ioc @[simp] -theorem card_Ioo : (Ioo a b).card = (b - a - 1).toNat := (card_map _).trans $ card_range _ +theorem card_Ioo : (Ioo a b).card = (b - a - 1).toNat := (card_map _).trans <| card_range _ #align int.card_Ioo Int.card_Ioo @[simp] diff --git a/Mathlib/Data/Int/Lemmas.lean b/Mathlib/Data/Int/Lemmas.lean index 5fa5f5943d0b9..4c1dbb7baf18b 100644 --- a/Mathlib/Data/Int/Lemmas.lean +++ b/Mathlib/Data/Int/Lemmas.lean @@ -3,11 +3,10 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Data.Set.Function -import Mathlib.Data.Int.Order.Lemmas import Mathlib.Data.Int.Bitwise -import Mathlib.Data.Nat.Cast.Order -import Mathlib.Data.Nat.Order.Lemmas +import Mathlib.Data.Int.Order.Lemmas +import Mathlib.Data.Set.Function +import Mathlib.Data.Set.Intervals.Basic #align_import data.int.lemmas from "leanprover-community/mathlib"@"09597669f02422ed388036273d8848119699c22f" diff --git a/Mathlib/Data/Int/ModEq.lean b/Mathlib/Data/Int/ModEq.lean index fcdf45a50b175..0b3352a262b09 100644 --- a/Mathlib/Data/Int/ModEq.lean +++ b/Mathlib/Data/Int/ModEq.lean @@ -223,14 +223,13 @@ lemma of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] := theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] := by letI d := gcd m c - have hmd := gcd_dvd_left m c - have hcd := gcd_dvd_right m c rw [modEq_iff_dvd] at h ⊢ -- porting note: removed `show` due to leanprover-community/mathlib4#3305 refine Int.dvd_of_dvd_mul_right_of_gcd_one (?_ : m / d ∣ c / d * (b - a)) ?_ - · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) hcd, sub_mul] - exact Int.ediv_dvd_ediv hmd h - · rw [gcd_div hmd hcd, natAbs_ofNat, Nat.div_self (gcd_pos_of_ne_zero_left c hm.ne')] + · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) gcd_dvd_right, sub_mul] + exact Int.ediv_dvd_ediv gcd_dvd_left h + · rw [gcd_div gcd_dvd_left gcd_dvd_right, natAbs_ofNat, + Nat.div_self (gcd_pos_of_ne_zero_left c hm.ne')] #align int.modeq.cancel_right_div_gcd Int.ModEq.cancel_right_div_gcd /-- To cancel a common factor `c` from a `ModEq` we must divide the modulus `m` by `gcd m c`. -/ diff --git a/Mathlib/Data/Int/NatPrime.lean b/Mathlib/Data/Int/NatPrime.lean index 80a57a0b16024..56b3defbd7341 100644 --- a/Mathlib/Data/Int/NatPrime.lean +++ b/Mathlib/Data/Int/NatPrime.lean @@ -16,7 +16,7 @@ open Nat namespace Int -theorem not_prime_of_int_mul {a b : ℤ} {c : ℕ} (ha : 1 < a.natAbs) (hb : 1 < b.natAbs) +theorem not_prime_of_int_mul {a b : ℤ} {c : ℕ} (ha : a.natAbs ≠ 1) (hb : b.natAbs ≠ 1) (hc : a * b = (c : ℤ)) : ¬Nat.Prime c := not_prime_mul' (natAbs_mul_natAbs_eq hc) ha hb #align int.not_prime_of_int_mul Int.not_prime_of_int_mul diff --git a/Mathlib/Data/Int/Order/Basic.lean b/Mathlib/Data/Int/Order/Basic.lean index 1af07234505af..177971f7c3c2c 100644 --- a/Mathlib/Data/Int/Order/Basic.lean +++ b/Mathlib/Data/Int/Order/Basic.lean @@ -3,11 +3,11 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ - +import Mathlib.Data.Nat.Order.Basic import Mathlib.Data.Int.Basic -import Mathlib.Algebra.Ring.Divisibility.Basic import Mathlib.Algebra.Order.Group.Abs import Mathlib.Algebra.Order.Ring.CharZero +import Mathlib.Algebra.Divisibility.Basic #align_import data.int.order.basic from "leanprover-community/mathlib"@"e8638a0fcaf73e4500469f368ef9494e495099b3" @@ -28,7 +28,7 @@ This file contains: induction on numbers less than `b`. -/ -open Nat +open Function Nat namespace Int @@ -72,6 +72,26 @@ theorem sign_mul_abs (a : ℤ) : sign a * |a| = a := by rw [abs_eq_natAbs, sign_mul_natAbs a] #align int.sign_mul_abs Int.sign_mul_abs +lemma natAbs_sq (x : ℤ) : (x.natAbs : ℤ) ^ 2 = x ^ 2 := by rw [sq, Int.natAbs_mul_self', sq] +#align int.nat_abs_sq Int.natAbs_sq + +alias natAbs_pow_two := natAbs_sq +#align int.nat_abs_pow_two Int.natAbs_pow_two + +lemma natAbs_le_self_sq (a : ℤ) : (Int.natAbs a : ℤ) ≤ a ^ 2 := by + rw [← Int.natAbs_sq a, sq] + norm_cast + apply Nat.le_mul_self +#align int.abs_le_self_sq Int.natAbs_le_self_sq + +alias natAbs_le_self_pow_two := natAbs_le_self_sq + +lemma le_self_sq (b : ℤ) : b ≤ b ^ 2 := le_trans le_natAbs (natAbs_le_self_sq _) +#align int.le_self_sq Int.le_self_sq + +alias le_self_pow_two := le_self_sq +#align int.le_self_pow_two Int.le_self_pow_two + theorem coe_nat_eq_zero {n : ℕ} : (n : ℤ) = 0 ↔ n = 0 := Nat.cast_eq_zero #align int.coe_nat_eq_zero Int.coe_nat_eq_zero @@ -94,6 +114,14 @@ theorem sign_add_eq_of_sign_eq : ∀ {m n : ℤ}, m.sign = n.sign → (m + n).si apply Int.add_pos <;> · exact zero_lt_one.trans_le (le_add_of_nonneg_left <| coe_nat_nonneg _) #align int.sign_add_eq_of_sign_eq Int.sign_add_eq_of_sign_eq +/-- Note this holds in marginally more generality than `Int.cast_mul` -/ +lemma cast_mul_eq_zsmul_cast {α : Type*} [AddCommGroupWithOne α] : + ∀ m n : ℤ, ↑(m * n) = m • (n : α) := + fun m ↦ Int.induction_on m (by simp) (fun _ ih ↦ by simp [add_mul, add_zsmul, ih]) fun _ ih ↦ by + simp only [sub_mul, one_mul, cast_sub, ih, sub_zsmul, one_zsmul, ← sub_eq_add_neg, forall_const] +#align int.cast_mul_eq_zsmul_cast Int.cast_mul_eq_zsmul_cast + + /-! ### succ and pred -/ @@ -550,5 +578,37 @@ theorem toNat_sub_of_le {a b : ℤ} (h : b ≤ a) : (toNat (a - b) : ℤ) = a - end Int +section bit0_bit1 +variable {R} +set_option linter.deprecated false + +-- The next four lemmas allow us to replace multiplication by a numeral with a `zsmul` expression. + +section NonUnitalNonAssocRing +variable [NonUnitalNonAssocRing R] (n r : R) + +lemma bit0_mul : bit0 n * r = (2 : ℤ) • (n * r) := by + rw [bit0, add_mul, ← one_add_one_eq_two, add_zsmul, one_zsmul] +#align bit0_mul bit0_mul + +lemma mul_bit0 : r * bit0 n = (2 : ℤ) • (r * n) := by + rw [bit0, mul_add, ← one_add_one_eq_two, add_zsmul, one_zsmul] +#align mul_bit0 mul_bit0 + +end NonUnitalNonAssocRing + +section NonAssocRing +variable [NonAssocRing R] (n r : R) + +lemma bit1_mul : bit1 n * r = (2 : ℤ) • (n * r) + r := by rw [bit1, add_mul, bit0_mul, one_mul] +#align bit1_mul bit1_mul + +lemma mul_bit1 [NonAssocRing R] {n r : R} : r * bit1 n = (2 : ℤ) • (r * n) + r := by + rw [bit1, mul_add, mul_bit0, mul_one] +#align mul_bit1 mul_bit1 + +end NonAssocRing +end bit0_bit1 + -- We should need only a minimal development of sets in order to get here. assert_not_exists Set.range diff --git a/Mathlib/Data/Int/Order/Lemmas.lean b/Mathlib/Data/Int/Order/Lemmas.lean index a59129f08d9da..567f58a174b28 100644 --- a/Mathlib/Data/Int/Order/Lemmas.lean +++ b/Mathlib/Data/Int/Order/Lemmas.lean @@ -3,21 +3,20 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Data.Int.Order.Basic -import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.Order.Ring.Abs +import Mathlib.Data.Nat.Pow #align_import data.int.order.lemmas from "leanprover-community/mathlib"@"fc2ed6f838ce7c9b7c7171e58d78eaf7b438fb0e" /-! # Further lemmas about the integers + The distinction between this file and `Data.Int.Order.Basic` is not particularly clear. They are separated by now to minimize the porting requirements for tactics during the transition to -mathlib4. After `data.rat.order` has been ported, please feel free to reorganize these two files. +mathlib4. Now that `Data.Rat.Order` has been ported, please feel free to reorganize these two files. -/ - -open Nat +open Function Nat namespace Int @@ -51,6 +50,12 @@ theorem dvd_div_of_mul_dvd {a b c : ℤ} (h : a * b ∣ c) : b ∣ c / a := by rw [mul_assoc, Int.mul_ediv_cancel_left _ ha] #align int.dvd_div_of_mul_dvd Int.dvd_div_of_mul_dvd +lemma pow_right_injective (h : 1 < a.natAbs) : Injective ((a ^ ·) : ℕ → ℤ) := by + refine (?_ : Injective (natAbs ∘ (a ^ · : ℕ → ℤ))).of_comp + convert Nat.pow_right_injective h using 2 + rw [Function.comp_apply, natAbs_pow] +#align int.pow_right_injective Int.pow_right_injective + /-! ### units -/ diff --git a/Mathlib/Data/Int/Order/Units.lean b/Mathlib/Data/Int/Order/Units.lean index e52bd2471a8c4..b1a2fedcfd2ea 100644 --- a/Mathlib/Data/Int/Order/Units.lean +++ b/Mathlib/Data/Int/Order/Units.lean @@ -3,9 +3,8 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Data.Int.Order.Basic +import Mathlib.Algebra.Order.Ring.Abs import Mathlib.Data.Int.Units -import Mathlib.Algebra.GroupPower.Order #align_import data.int.order.units from "leanprover-community/mathlib"@"d012cd09a9b256d870751284dd6a29882b0be105" diff --git a/Mathlib/Data/Int/Range.lean b/Mathlib/Data/Int/Range.lean index cc7e2b9ac47e1..a059baa98ce10 100644 --- a/Mathlib/Data/Int/Range.lean +++ b/Mathlib/Data/Int/Range.lean @@ -3,8 +3,8 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kenny Lau -/ -import Mathlib.Data.List.Range import Mathlib.Data.Int.Order.Basic +import Mathlib.Init.Data.List.Instances #align_import data.int.range from "leanprover-community/mathlib"@"7b78d1776212a91ecc94cf601f83bdcc46b04213" diff --git a/Mathlib/Data/Int/SuccPred.lean b/Mathlib/Data/Int/SuccPred.lean index a54db0d57a2d6..0b39e3cbe3b87 100644 --- a/Mathlib/Data/Int/SuccPred.lean +++ b/Mathlib/Data/Int/SuccPred.lean @@ -73,26 +73,26 @@ instance : IsPredArchimedean ℤ := /-! ### Covering relation -/ -protected theorem covby_iff_succ_eq {m n : ℤ} : m ⋖ n ↔ m + 1 = n := - succ_eq_iff_covby.symm -#align int.covby_iff_succ_eq Int.covby_iff_succ_eq +protected theorem covBy_iff_succ_eq {m n : ℤ} : m ⋖ n ↔ m + 1 = n := + succ_eq_iff_covBy.symm +#align int.covby_iff_succ_eq Int.covBy_iff_succ_eq @[simp] -theorem sub_one_covby (z : ℤ) : z - 1 ⋖ z := by rw [Int.covby_iff_succ_eq, sub_add_cancel] -#align int.sub_one_covby Int.sub_one_covby +theorem sub_one_covBy (z : ℤ) : z - 1 ⋖ z := by rw [Int.covBy_iff_succ_eq, sub_add_cancel] +#align int.sub_one_covby Int.sub_one_covBy @[simp] -theorem covby_add_one (z : ℤ) : z ⋖ z + 1 := - Int.covby_iff_succ_eq.mpr rfl -#align int.covby_add_one Int.covby_add_one +theorem covBy_add_one (z : ℤ) : z ⋖ z + 1 := + Int.covBy_iff_succ_eq.mpr rfl +#align int.covby_add_one Int.covBy_add_one end Int @[simp, norm_cast] -theorem Nat.cast_int_covby_iff {a b : ℕ} : (a : ℤ) ⋖ b ↔ a ⋖ b := by - rw [Nat.covby_iff_succ_eq, Int.covby_iff_succ_eq] +theorem Nat.cast_int_covBy_iff {a b : ℕ} : (a : ℤ) ⋖ b ↔ a ⋖ b := by + rw [Nat.covBy_iff_succ_eq, Int.covBy_iff_succ_eq] exact Int.coe_nat_inj' -#align nat.cast_int_covby_iff Nat.cast_int_covby_iff +#align nat.cast_int_covby_iff Nat.cast_int_covBy_iff -alias ⟨_, Covby.cast_int⟩ := Nat.cast_int_covby_iff -#align covby.cast_int Covby.cast_int +alias ⟨_, CovBy.cast_int⟩ := Nat.cast_int_covBy_iff +#align covby.cast_int CovBy.cast_int diff --git a/Mathlib/Data/IsROrC/Basic.lean b/Mathlib/Data/IsROrC/Basic.lean index 1a1c188d8cd9d..d962f92ea4f3b 100644 --- a/Mathlib/Data/IsROrC/Basic.lean +++ b/Mathlib/Data/IsROrC/Basic.lean @@ -277,23 +277,23 @@ theorem real_smul_ofReal (r x : ℝ) : r • (x : K) = (r : K) * (x : K) := #align is_R_or_C.real_smul_of_real IsROrC.real_smul_ofReal @[isROrC_simps] -theorem ofReal_mul_re (r : ℝ) (z : K) : re (↑r * z) = r * re z := by +theorem re_ofReal_mul (r : ℝ) (z : K) : re (↑r * z) = r * re z := by simp only [mul_re, ofReal_im, zero_mul, ofReal_re, sub_zero] -#align is_R_or_C.of_real_mul_re IsROrC.ofReal_mul_re +#align is_R_or_C.of_real_mul_re IsROrC.re_ofReal_mul @[isROrC_simps] -theorem ofReal_mul_im (r : ℝ) (z : K) : im (↑r * z) = r * im z := by +theorem im_ofReal_mul (r : ℝ) (z : K) : im (↑r * z) = r * im z := by simp only [add_zero, ofReal_im, zero_mul, ofReal_re, mul_im] -#align is_R_or_C.of_real_mul_im IsROrC.ofReal_mul_im +#align is_R_or_C.of_real_mul_im IsROrC.im_ofReal_mul @[isROrC_simps] theorem smul_re (r : ℝ) (z : K) : re (r • z) = r * re z := by - rw [real_smul_eq_coe_mul, ofReal_mul_re] + rw [real_smul_eq_coe_mul, re_ofReal_mul] #align is_R_or_C.smul_re IsROrC.smul_re @[isROrC_simps] theorem smul_im (r : ℝ) (z : K) : im (r • z) = r * im z := by - rw [real_smul_eq_coe_mul, ofReal_mul_im] + rw [real_smul_eq_coe_mul, im_ofReal_mul] #align is_R_or_C.smul_im IsROrC.smul_im @[simp, norm_cast, isROrC_simps] @@ -341,6 +341,10 @@ theorem I_mul_I : (I : K) = 0 ∨ (I : K) * I = -1 := set_option linter.uppercaseLean3 false in #align is_R_or_C.I_mul_I IsROrC.I_mul_I +variable (𝕜) in +lemma I_eq_zero_or_im_I_eq_one : (I : K) = 0 ∨ im (I : K) = 1 := + I_mul_I (K := K) |>.imp_right fun h ↦ by simpa [h] using (I_mul_re (I : K)).symm + @[simp, isROrC_simps] theorem conj_re (z : K) : re (conj z) = re z := IsROrC.conj_re_ax z @@ -452,7 +456,7 @@ abbrev conjToRingEquiv : K ≃+* Kᵐᵒᵖ := starRingEquiv #align is_R_or_C.conj_to_ring_equiv IsROrC.conjToRingEquiv -variable {K} +variable {K} {z : K} /-- The norm squared function. -/ def normSq : K →*₀ ℝ where @@ -527,13 +531,17 @@ theorem im_sq_le_normSq (z : K) : im z * im z ≤ normSq z := le_add_of_nonneg_left (mul_self_nonneg _) #align is_R_or_C.im_sq_le_norm_sq IsROrC.im_sq_le_normSq -theorem mul_conj (z : K) : z * conj z = (normSq z : K) := by - apply ext <;> simp only [normSq_apply, isROrC_simps, map_add, mul_zero] <;> ring +theorem mul_conj (z : K) : z * conj z = ‖z‖ ^ 2 := by + apply ext <;> simp [← ofReal_pow, norm_sq_eq_def, mul_comm] + #align is_R_or_C.mul_conj IsROrC.mul_conj -theorem conj_mul (x : K) : conj x * x = (normSq x : K) := by rw [mul_comm, mul_conj] +theorem conj_mul (z : K) : conj z * z = ‖z‖ ^ 2 := by rw [mul_comm, mul_conj] #align is_R_or_C.conj_mul IsROrC.conj_mul +lemma inv_eq_conj (hz : ‖z‖ = 1) : z⁻¹ = conj z := + inv_eq_of_mul_eq_one_left $ by simp_rw [conj_mul, hz, algebraMap.coe_one, one_pow] + theorem normSq_sub (z w : K) : normSq (z - w) = normSq z + normSq w - 2 * re (z * conj w) := by simp only [normSq_add, sub_eq_add_neg, map_neg, mul_neg, normSq_neg, map_neg] #align is_R_or_C.norm_sq_sub IsROrC.normSq_sub @@ -553,18 +561,18 @@ theorem inv_def (z : K) : z⁻¹ = conj z * ((‖z‖ ^ 2)⁻¹ : ℝ) := by rcases eq_or_ne z 0 with (rfl | h₀) · simp · apply inv_eq_of_mul_eq_one_right - rw [← mul_assoc, mul_conj, ofReal_inv, ← normSq_eq_def', mul_inv_cancel] - rwa [ofReal_ne_zero, Ne.def, normSq_eq_zero] + rw [← mul_assoc, mul_conj, ofReal_inv, ofReal_pow, mul_inv_cancel] + simpa #align is_R_or_C.inv_def IsROrC.inv_def @[simp, isROrC_simps] theorem inv_re (z : K) : re z⁻¹ = re z / normSq z := by - rw [inv_def, normSq_eq_def', mul_comm, ofReal_mul_re, conj_re, div_eq_inv_mul] + rw [inv_def, normSq_eq_def', mul_comm, re_ofReal_mul, conj_re, div_eq_inv_mul] #align is_R_or_C.inv_re IsROrC.inv_re @[simp, isROrC_simps] theorem inv_im (z : K) : im z⁻¹ = -im z / normSq z := by - rw [inv_def, normSq_eq_def', mul_comm, ofReal_mul_im, conj_im, div_eq_inv_mul] + rw [inv_def, normSq_eq_def', mul_comm, im_ofReal_mul, conj_im, div_eq_inv_mul] #align is_R_or_C.inv_im IsROrC.inv_im theorem div_re (z w : K) : re (z / w) = re z * re w / normSq w + im z * im w / normSq w := by @@ -582,13 +590,26 @@ theorem conj_inv (x : K) : conj x⁻¹ = (conj x)⁻¹ := star_inv' _ #align is_R_or_C.conj_inv IsROrC.conj_inv +lemma conj_div (x y : K) : conj (x / y) = conj x / conj y := map_div' conj conj_inv _ _ + +--TODO: Do we rather want the map as an explicit definition? +lemma exists_norm_eq_mul_self (x : K) : ∃ c, ‖c‖ = 1 ∧ ↑‖x‖ = c * x := by + obtain rfl | hx := eq_or_ne x 0 + · exact ⟨1, by simp⟩ + · exact ⟨‖x‖ / x, by simp [norm_ne_zero_iff.2, hx]⟩ + +lemma exists_norm_mul_eq_self (x : K) : ∃ c, ‖c‖ = 1 ∧ c * ‖x‖ = x := by + obtain rfl | hx := eq_or_ne x 0 + · exact ⟨1, by simp⟩ + · exact ⟨x / ‖x‖, by simp [norm_ne_zero_iff.2, hx]⟩ + @[simp, norm_cast, isROrC_simps] theorem ofReal_div (r s : ℝ) : ((r / s : ℝ) : K) = r / s := map_div₀ (algebraMap ℝ K) r s #align is_R_or_C.of_real_div IsROrC.ofReal_div theorem div_re_ofReal {z : K} {r : ℝ} : re (z / r) = re z / r := by - rw [div_eq_inv_mul, div_eq_inv_mul, ← ofReal_inv, ofReal_mul_re] + rw [div_eq_inv_mul, div_eq_inv_mul, ← ofReal_inv, re_ofReal_mul] #align is_R_or_C.div_re_of_real IsROrC.div_re_ofReal @[simp, norm_cast, isROrC_simps] @@ -664,11 +685,11 @@ theorem ofReal_ofNat (n : ℕ) [n.AtLeastTwo] : theorem ofNat_mul_re (n : ℕ) [n.AtLeastTwo] (z : K) : re (OfNat.ofNat n * z) = OfNat.ofNat n * re z := by - rw [← ofReal_ofNat, ofReal_mul_re] + rw [← ofReal_ofNat, re_ofReal_mul] theorem ofNat_mul_im (n : ℕ) [n.AtLeastTwo] (z : K) : im (OfNat.ofNat n * z) = OfNat.ofNat n * im z := by - rw [← ofReal_ofNat, ofReal_mul_im] + rw [← ofReal_ofNat, im_ofReal_mul] @[simp, isROrC_simps, norm_cast] theorem ofReal_intCast (n : ℤ) : ((n : ℝ) : K) = n := @@ -712,6 +733,10 @@ theorem norm_natCast (n : ℕ) : ‖(n : K)‖ = n := by theorem norm_ofNat (n : ℕ) [n.AtLeastTwo] : ‖(no_index (OfNat.ofNat n) : K)‖ = OfNat.ofNat n := norm_natCast n +variable (K) in +lemma norm_nsmul [NormedAddCommGroup E] [NormedSpace K E] (n : ℕ) (x : E) : ‖n • x‖ = n • ‖x‖ := by + rw [nsmul_eq_smul_cast K, norm_smul, IsROrC.norm_natCast, nsmul_eq_mul] + theorem mul_self_norm (z : K) : ‖z‖ * ‖z‖ = normSq z := by rw [normSq_eq_def', sq] #align is_R_or_C.mul_self_norm IsROrC.mul_self_norm @@ -775,7 +800,7 @@ set_option linter.uppercaseLean3 false in #align is_R_or_C.norm_I_of_ne_zero IsROrC.norm_I_of_ne_zero theorem re_eq_norm_of_mul_conj (x : K) : re (x * conj x) = ‖x * conj x‖ := by - rw [mul_conj, ofReal_re, norm_ofReal, abs_of_nonneg (normSq_nonneg _)] + rw [mul_conj, ← ofReal_pow]; simp [-ofReal_pow] #align is_R_or_C.re_eq_norm_of_mul_conj IsROrC.re_eq_norm_of_mul_conj theorem norm_sq_re_add_conj (x : K) : ‖x + conj x‖ ^ 2 = re (x + conj x) ^ 2 := by @@ -845,8 +870,9 @@ namespace IsROrC section Order open scoped ComplexOrder +variable {z w : K} -theorem lt_iff_re_im {z w : K} : z < w ↔ re z < re w ∧ im z = im w := by +theorem lt_iff_re_im : z < w ↔ re z < re w ∧ im z = im w := by simp_rw [lt_iff_le_and_ne, @IsROrC.le_iff_re_im K] constructor · rintro ⟨⟨hr, hi⟩, heq⟩ @@ -854,18 +880,30 @@ theorem lt_iff_re_im {z w : K} : z < w ↔ re z < re w ∧ im z = im w := by · rintro ⟨⟨hr, hrn⟩, hi⟩ exact ⟨⟨hr, hi⟩, ne_of_apply_ne _ hrn⟩ -theorem nonneg_iff {z : K} : 0 ≤ z ↔ 0 ≤ re z ∧ im z = 0 := by +theorem nonneg_iff : 0 ≤ z ↔ 0 ≤ re z ∧ im z = 0 := by simpa only [map_zero, eq_comm] using le_iff_re_im (z := 0) (w := z) -theorem pos_iff {z : K} : 0 < z ↔ 0 < re z ∧ im z = 0 := by +theorem pos_iff : 0 < z ↔ 0 < re z ∧ im z = 0 := by simpa only [map_zero, eq_comm] using lt_iff_re_im (z := 0) (w := z) -theorem nonpos_iff {z : K} : z ≤ 0 ↔ re z ≤ 0 ∧ im z = 0 := by +theorem nonpos_iff : z ≤ 0 ↔ re z ≤ 0 ∧ im z = 0 := by simpa only [map_zero] using le_iff_re_im (z := z) (w := 0) -theorem neg_iff {z : K} : z < 0 ↔ re z < 0 ∧ im z = 0 := by +theorem neg_iff : z < 0 ↔ re z < 0 ∧ im z = 0 := by simpa only [map_zero] using lt_iff_re_im (z := z) (w := 0) +lemma nonneg_iff_exists_ofReal : 0 ≤ z ↔ ∃ x ≥ (0 : ℝ), x = z := by + simp_rw [nonneg_iff (K := K), ext_iff (K := K)]; aesop + +lemma pos_iff_exists_ofReal : 0 < z ↔ ∃ x > (0 : ℝ), x = z := by + simp_rw [pos_iff (K := K), ext_iff (K := K)]; aesop + +lemma nonpos_iff_exists_ofReal : z ≤ 0 ↔ ∃ x ≤ (0 : ℝ), x = z := by + simp_rw [nonpos_iff (K := K), ext_iff (K := K)]; aesop + +lemma neg_iff_exists_ofReal : z < 0 ↔ ∃ x < (0 : ℝ), x = z := by + simp_rw [neg_iff (K := K), ext_iff (K := K)]; aesop + /-- With `z ≤ w` iff `w - z` is real and nonnegative, `ℝ` and `ℂ` are star ordered rings. (That is, a star ring in which the nonnegative elements are those of the form `star z * z`.) @@ -876,16 +914,10 @@ def toStarOrderedRing : StarOrderedRing K := rw [IsROrC.le_iff_re_im] at * simpa [map_add, add_le_add_iff_left, add_right_inj] using hxy) (h_nonneg_iff := fun x => by - rw [IsROrC.le_iff_re_im, map_zero, map_zero, IsROrC.star_def, eq_comm] - constructor - · rintro ⟨hr, hi⟩ - refine ⟨Real.sqrt (IsROrC.re x), ?_⟩ - have := (IsROrC.is_real_TFAE x).out 2 3 - rw [IsROrC.conj_ofReal, ← IsROrC.ofReal_mul, Real.mul_self_sqrt hr, eq_comm, this, hi] - · rintro ⟨s, rfl⟩ - simp only [IsROrC.star_def, IsROrC.conj_mul] - rw [IsROrC.ofReal_re, IsROrC.ofReal_im, eq_self, and_true] - apply IsROrC.normSq_nonneg) + rw [nonneg_iff] + refine ⟨fun h ↦ ⟨(re x).sqrt, by simp [ext_iff (K := K), h.1, h.2]⟩, ?_⟩ + rintro ⟨s, rfl⟩ + simp [mul_comm, mul_self_nonneg, add_nonneg]) scoped[ComplexOrder] attribute [instance] IsROrC.toStarOrderedRing @@ -932,7 +964,7 @@ theorem im_to_real {x : ℝ} : imR x = 0 := rfl #align is_R_or_C.im_to_real IsROrC.im_to_real -@[simp, isROrC_simps] +@[isROrC_simps] theorem conj_to_real {x : ℝ} : conj x = x := rfl #align is_R_or_C.conj_to_real IsROrC.conj_to_real @@ -1115,4 +1147,35 @@ theorem continuous_normSq : Continuous (normSq : K → ℝ) := end LinearMaps +/-! +### ℝ-dependent results + +Here we gather results that depend on whether `K` is `ℝ`. +-/ +section CaseSpecific + +lemma im_eq_zero (h : I = (0 : K)) (z : K) : im z = 0 := by + rw [← re_add_im z, h] + simp + +/-- The natural isomorphism between `𝕜` satisfying `IsROrC 𝕜` and `ℝ` when `IsROrC.I = 0`. -/ +@[simps] +def realRingEquiv (h : I = (0 : K)) : K ≃+* ℝ where + toFun := re + invFun := (↑) + left_inv x := by nth_rw 2 [← re_add_im x]; simp [h] + right_inv := ofReal_re + map_add' := map_add re + map_mul' := by simp [im_eq_zero h] + +/-- The natural `ℝ`-linear isometry equivalence between `𝕜` satisfying `IsROrC 𝕜` and `ℝ` when +`IsROrC.I = 0`. -/ +@[simps] +noncomputable def realLinearIsometryEquiv (h : I = (0 : K)) : K ≃ₗᵢ[ℝ] ℝ where + map_smul' := smul_re + norm_map' z := by rw [← re_add_im z]; simp [- re_add_im, h] + __ := realRingEquiv h + +end CaseSpecific + end IsROrC diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index aff660eff8f4f..58fa0bead9274 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -6,9 +6,10 @@ Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, M import Mathlib.Init.Data.List.Instances import Mathlib.Data.Nat.Order.Basic import Mathlib.Data.List.Defs -import Mathlib.Init.Core import Std.Data.List.Lemmas import Mathlib.Tactic.Common +import Mathlib.Init.Data.Bool.Lemmas +import Mathlib.Init.Data.List.Lemmas #align_import data.list.basic from "leanprover-community/mathlib"@"65a1391a0106c9204fe45bc73a039f056558cb83" @@ -392,22 +393,20 @@ theorem cons_eq_append_iff {a b c : List α} {x : α} : #align list.append_inj_left' List.append_inj_left'ₓ -- implicits order -theorem append_left_cancel {s t₁ t₂ : List α} (h : s ++ t₁ = s ++ t₂) : t₁ = t₂ := - (append_right_inj _).1 h -#align list.append_left_cancel List.append_left_cancel +@[deprecated] alias append_left_cancel := append_cancel_left -- deprecated since 2024-01-18 +#align list.append_left_cancel List.append_cancel_left -theorem append_right_cancel {s₁ s₂ t : List α} (h : s₁ ++ t = s₂ ++ t) : s₁ = s₂ := - (append_left_inj _).1 h -#align list.append_right_cancel List.append_right_cancel +@[deprecated] alias append_right_cancel := append_cancel_right -- deprecated since 2024-01-18 +#align list.append_right_cancel List.append_cancel_right theorem append_right_injective (s : List α) : Injective fun t ↦ s ++ t := - fun _ _ ↦ append_left_cancel + fun _ _ ↦ append_cancel_left #align list.append_right_injective List.append_right_injective #align list.append_right_inj List.append_right_inj theorem append_left_injective (t : List α) : Injective fun s ↦ s ++ t := - fun _ _ ↦ append_right_cancel + fun _ _ ↦ append_cancel_right #align list.append_left_injective List.append_left_injective #align list.append_left_inj List.append_left_inj @@ -524,13 +523,13 @@ theorem concat_eq_append' (a : α) (l : List α) : concat l a = l ++ [a] := theorem init_eq_of_concat_eq {a : α} {l₁ l₂ : List α} : concat l₁ a = concat l₂ a → l₁ = l₂ := by intro h rw [concat_eq_append, concat_eq_append] at h - exact append_right_cancel h + exact append_cancel_right h #align list.init_eq_of_concat_eq List.init_eq_of_concat_eq theorem last_eq_of_concat_eq {a b : α} {l : List α} : concat l a = concat l b → a = b := by intro h rw [concat_eq_append, concat_eq_append] at h - exact head_eq_of_cons_eq (append_left_cancel h) + exact head_eq_of_cons_eq (append_cancel_left h) #align list.last_eq_of_concat_eq List.last_eq_of_concat_eq theorem concat_ne_nil (a : α) (l : List α) : concat l a ≠ [] := by simp @@ -695,13 +694,6 @@ theorem getLast_congr {l₁ l₂ : List α} (h₁ : l₁ ≠ []) (h₂ : l₂ getLast l₁ h₁ = getLast l₂ h₂ := by subst l₁; rfl #align list.last_congr List.getLast_congr -theorem getLast_mem : ∀ {l : List α} (h : l ≠ []), getLast l h ∈ l - | [], h => absurd rfl h - | [a], _ => by simp only [getLast, mem_singleton] - | a :: b :: l, h => - List.mem_cons.2 <| Or.inr <| by - rw [getLast_cons_cons] - exact getLast_mem (cons_ne_nil b l) #align list.last_mem List.getLast_mem theorem getLast_replicate_succ (m : ℕ) (a : α) : @@ -712,11 +704,6 @@ theorem getLast_replicate_succ (m : ℕ) (a : α) : /-! ### getLast? -/ --- Porting note: New lemma, since definition of getLast? is slightly different. -@[simp] -theorem getLast?_singleton (a : α) : - getLast? [a] = a := rfl - -- Porting note: Moved earlier in file, for use in subsequent lemmas. @[simp] theorem getLast?_cons_cons (a b : α) (l : List α) : @@ -954,7 +941,7 @@ def reverseRecOn {C : List α → Sort*} (l : List α) (H0 : C []) let ih := reverseRecOn (reverse tail) H0 H1 rw [reverse_cons] exact H1 _ _ ih -termination_by _ _ l _ _ => l.length +termination_by l.length #align list.reverse_rec_on List.reverseRecOn /-- Bidirectional induction principle for lists: if a property holds for the empty list, the @@ -971,7 +958,7 @@ def bidirectionalRec {C : List α → Sort*} (H0 : C []) (H1 : ∀ a : α, C [a] rw [← dropLast_append_getLast (cons_ne_nil b l)] have : C l' := bidirectionalRec H0 H1 Hn l' exact Hn a l' b' this -termination_by _ l => l.length +termination_by l => l.length #align list.bidirectional_rec List.bidirectionalRecₓ -- universe order /-- Like `bidirectionalRec`, but with the list parameter placed first. -/ @@ -4223,6 +4210,8 @@ theorem getLast_reverse {l : List α} (hl : l.reverse ≠ []) · simpa using hl' #align list.last_reverse List.getLast_reverse +set_option linter.deprecated false in +@[deprecated] theorem ilast'_mem : ∀ a l, @ilast' α a l ∈ a :: l | a, [] => by simp [ilast'] | a, b :: l => by rw [mem_cons]; exact Or.inr (ilast'_mem b l) @@ -4236,6 +4225,7 @@ theorem get_attach (L : List α) (i) : by rw [get_map] _ = L.get { val := i, isLt := _ } := by congr 2 <;> simp +set_option linter.deprecated false in @[simp, deprecated get_attach] theorem nthLe_attach (L : List α) (i) (H : i < L.attach.length) : (L.attach.nthLe i H).1 = L.nthLe i (length_attach L ▸ H) := get_attach .. diff --git a/Mathlib/Data/List/BigOperators/Basic.lean b/Mathlib/Data/List/BigOperators/Basic.lean index 454854f55a781..3259bb3d36049 100644 --- a/Mathlib/Data/List/BigOperators/Basic.lean +++ b/Mathlib/Data/List/BigOperators/Basic.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Floris van Doorn, Sébastien Gouëzel, Alex J. Best -/ import Mathlib.Data.List.BigOperators.Defs -import Mathlib.Data.Int.Order.Basic import Mathlib.Data.List.Forall2 +import Mathlib.Algebra.Divisibility.Basic +import Mathlib.Data.Int.Basic #align_import data.list.big_operators.basic from "leanprover-community/mathlib"@"6c5f73fd6f6cc83122788a80a27cdd54663609f4" @@ -230,8 +231,6 @@ theorem prod_set : #align list.prod_update_nth List.prod_set #align list.sum_update_nth List.sum_set -open MulOpposite - /-- We'd like to state this as `L.headI * L.tail.prod = L.prod`, but because `L.headI` relies on an inhabited instance to return a garbage value on the empty list, this is not possible. Instead, we write the statement in terms of `(L.get? 0).getD 1`. diff --git a/Mathlib/Data/List/BigOperators/Defs.lean b/Mathlib/Data/List/BigOperators/Defs.lean index 8eb866901171d..5ca1f50536123 100644 --- a/Mathlib/Data/List/BigOperators/Defs.lean +++ b/Mathlib/Data/List/BigOperators/Defs.lean @@ -3,7 +3,6 @@ Copyright (c) 2014 Parikshit Khanna. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Mario Carneiro -/ -import Mathlib.Data.List.Defs import Mathlib.Algebra.Group.Defs #align_import data.list.defs from "leanprover-community/mathlib"@"d2d8742b0c21426362a9dacebc6005db895ca963" diff --git a/Mathlib/Data/List/BigOperators/Lemmas.lean b/Mathlib/Data/List/BigOperators/Lemmas.lean index 39776f6122049..c43e0d8690c5d 100644 --- a/Mathlib/Data/List/BigOperators/Lemmas.lean +++ b/Mathlib/Data/List/BigOperators/Lemmas.lean @@ -9,12 +9,11 @@ import Mathlib.Algebra.Group.Opposite import Mathlib.Algebra.GroupPower.Basic import Mathlib.Algebra.GroupWithZero.Commute import Mathlib.Algebra.GroupWithZero.Divisibility -import Mathlib.Algebra.Order.WithZero +import Mathlib.Algebra.Order.Monoid.OrderDual import Mathlib.Algebra.Ring.Basic import Mathlib.Algebra.Ring.Divisibility.Basic import Mathlib.Algebra.Ring.Commute import Mathlib.Data.Int.Units -import Mathlib.Data.Set.Basic #align_import data.list.big_operators.lemmas from "leanprover-community/mathlib"@"f694c7dead66f5d4c80f446c796a5aad14707f0e" diff --git a/Mathlib/Data/List/Card.lean b/Mathlib/Data/List/Card.lean index 12133aca21ded..70c3d7cf81902 100644 --- a/Mathlib/Data/List/Card.lean +++ b/Mathlib/Data/List/Card.lean @@ -7,7 +7,7 @@ respects equivalence and is preserved by any mapping that is injective on its el It might make sense to remove this when we have a proper theory of finite sets. -/ -import Mathlib.Data.List.Basic +import Mathlib.Data.Nat.Order.Basic set_option autoImplicit true diff --git a/Mathlib/Data/List/Chain.lean b/Mathlib/Data/List/Chain.lean index 121900441ad38..71c05aa65aea6 100644 --- a/Mathlib/Data/List/Chain.lean +++ b/Mathlib/Data/List/Chain.lean @@ -3,8 +3,9 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kenny Lau, Yury Kudryashov -/ -import Mathlib.Data.List.Pairwise import Mathlib.Logic.Relation +import Mathlib.Data.List.Forall2 +import Mathlib.Data.List.Lex #align_import data.list.chain from "leanprover-community/mathlib"@"dd71334db81d0bd444af1ee339a29298bef40734" @@ -386,7 +387,7 @@ lemma chain'_join : ∀ {L : List (List α)}, [] ∉ L → rw [join, chain'_append, chain'_join hL.2, forall_mem_cons, chain'_cons] rw [mem_cons, not_or, ← Ne.def] at hL simp only [forall_mem_cons, and_assoc, join, head?_append_of_ne_nil _ hL.2.1.symm] - exact Iff.rfl.and (Iff.rfl.and $ Iff.rfl.and and_comm) + exact Iff.rfl.and (Iff.rfl.and <| Iff.rfl.and and_comm) /-- If `a` and `b` are related by the reflexive transitive closure of `r`, then there is an `r`-chain starting from `a` and ending on `b`. diff --git a/Mathlib/Data/List/Cycle.lean b/Mathlib/Data/List/Cycle.lean index dd05fdadd5d24..5da3f7a8ee732 100644 --- a/Mathlib/Data/List/Cycle.lean +++ b/Mathlib/Data/List/Cycle.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Data.Multiset.Sort import Mathlib.Data.Fintype.List import Mathlib.Data.List.Rotate diff --git a/Mathlib/Data/List/Dedup.lean b/Mathlib/Data/List/Dedup.lean index 4affc57b1cdde..396faee1fb8f2 100644 --- a/Mathlib/Data/List/Dedup.lean +++ b/Mathlib/Data/List/Dedup.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.List.Nodup +import Mathlib.Data.List.Count #align_import data.list.dedup from "leanprover-community/mathlib"@"d9e96a3e3e0894e93e10aff5244f4c96655bac1c" diff --git a/Mathlib/Data/List/Defs.lean b/Mathlib/Data/List/Defs.lean index 590cfc212c838..f6bfdc55ff56a 100644 --- a/Mathlib/Data/List/Defs.lean +++ b/Mathlib/Data/List/Defs.lean @@ -5,7 +5,6 @@ Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, M -/ import Mathlib.Init.Data.Nat.Notation import Mathlib.Control.Functor -import Mathlib.Logic.Basic import Mathlib.Data.SProd import Mathlib.Util.CompileInductive import Std.Tactic.Lint.Basic @@ -227,8 +226,8 @@ def permutationsAux.rec {C : List α → List α → Sort v} (H0 : ∀ is, C [] | [], is => H0 is | t :: ts, is => H1 t ts is (permutationsAux.rec H0 H1 ts (t :: is)) (permutationsAux.rec H0 H1 is []) - termination_by _ ts is => (length ts + length is, length ts) - decreasing_by simp_wf; simp [Nat.succ_add]; decreasing_tactic + termination_by ts is => (length ts + length is, length ts) + decreasing_by all_goals (simp_wf; omega) #align list.permutations_aux.rec List.permutationsAux.rec /-- An auxiliary function for defining `permutations`. `permutationsAux ts is` is the set of all @@ -516,7 +515,7 @@ These can also be written in terms of `List.zip` or `List.zipWith`. For example, `zipWith3 f xs ys zs` could also be written as `zipWith id (zipWith f xs ys) zs` or as -`(zip xs $ zip ys zs).map $ λ ⟨x, y, z⟩, f x y z`. +`(zip xs <| zip ys zs).map <| λ ⟨x, y, z⟩, f x y z`. -/ /-- Ternary version of `List.zipWith`. -/ diff --git a/Mathlib/Data/List/FinRange.lean b/Mathlib/Data/List/FinRange.lean index d7705ebaa3aa8..d78aa4b419456 100644 --- a/Mathlib/Data/List/FinRange.lean +++ b/Mathlib/Data/List/FinRange.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kenny Lau, Scott Morrison, Alex Keizer -/ import Mathlib.Data.List.OfFn -import Mathlib.Data.List.Perm +import Mathlib.Data.List.Range #align_import data.list.fin_range from "leanprover-community/mathlib"@"9003f28797c0664a49e4179487267c494477d853" @@ -52,7 +52,7 @@ theorem ofFn_id (n) : ofFn id = finRange n := #align list.of_fn_id List.ofFn_id theorem ofFn_eq_map {α n} {f : Fin n → α} : ofFn f = (finRange n).map f := by - rw [← ofFn_id, map_ofFn, Function.right_id] + rw [← ofFn_id, map_ofFn, Function.comp_id] #align list.of_fn_eq_map List.ofFn_eq_map theorem nodup_ofFn_ofInjective {α n} {f : Fin n → α} (hf : Function.Injective f) : diff --git a/Mathlib/Data/List/Infix.lean b/Mathlib/Data/List/Infix.lean index 142da69384874..509a7d44aa0c3 100644 --- a/Mathlib/Data/List/Infix.lean +++ b/Mathlib/Data/List/Infix.lean @@ -206,12 +206,12 @@ theorem suffix_iff_eq_append : l₁ <:+ l₂ ↔ take (length l₂ - length l₁ #align list.suffix_iff_eq_append List.suffix_iff_eq_append theorem prefix_iff_eq_take : l₁ <+: l₂ ↔ l₁ = take (length l₁) l₂ := - ⟨fun h => append_right_cancel <| (prefix_iff_eq_append.1 h).trans (take_append_drop _ _).symm, + ⟨fun h => append_cancel_right <| (prefix_iff_eq_append.1 h).trans (take_append_drop _ _).symm, fun e => e.symm ▸ take_prefix _ _⟩ #align list.prefix_iff_eq_take List.prefix_iff_eq_take theorem suffix_iff_eq_drop : l₁ <:+ l₂ ↔ l₁ = drop (length l₂ - length l₁) l₂ := - ⟨fun h => append_left_cancel <| (suffix_iff_eq_append.1 h).trans (take_append_drop _ _).symm, + ⟨fun h => append_cancel_left <| (suffix_iff_eq_append.1 h).trans (take_append_drop _ _).symm, fun e => e.symm ▸ drop_suffix _ _⟩ #align list.suffix_iff_eq_drop List.suffix_iff_eq_drop @@ -233,7 +233,7 @@ instance decidableSuffix [DecidableEq α] : ∀ l₁ l₂ : List α, Decidable ( @decidable_of_decidable_of_iff _ _ (@instDecidableOr _ _ _ (l₁.decidableSuffix l₂)) suffix_cons_iff.symm -termination_by decidableSuffix l₁ l₂ => (l₁, l₂) +termination_by l₁ l₂ => (l₁, l₂) #align list.decidable_suffix List.decidableSuffix instance decidableInfix [DecidableEq α] : ∀ l₁ l₂ : List α, Decidable (l₁ <:+: l₂) @@ -243,7 +243,7 @@ instance decidableInfix [DecidableEq α] : ∀ l₁ l₂ : List α, Decidable (l @decidable_of_decidable_of_iff _ _ (@instDecidableOr _ _ (l₁.decidablePrefix (b :: l₂)) (l₁.decidableInfix l₂)) infix_cons_iff.symm -termination_by decidableInfix l₁ l₂ => (l₁, l₂) +termination_by l₁ l₂ => (l₁, l₂) #align list.decidable_infix List.decidableInfix theorem prefix_take_le_iff {L : List (List (Option α))} (hm : m < L.length) : diff --git a/Mathlib/Data/List/Lattice.lean b/Mathlib/Data/List/Lattice.lean index b442e56bd2580..460b3ae35cfcb 100644 --- a/Mathlib/Data/List/Lattice.lean +++ b/Mathlib/Data/List/Lattice.lean @@ -4,8 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Mario Carneiro, Scott Morrison -/ -import Mathlib.Data.List.Count -import Mathlib.Data.List.Infix +import Mathlib.Data.List.Basic import Mathlib.Algebra.Order.Monoid.MinMax #align_import data.list.lattice from "leanprover-community/mathlib"@"dd71334db81d0bd444af1ee339a29298bef40734" @@ -150,7 +149,7 @@ theorem mem_of_mem_inter_right (h : a ∈ l₁ ∩ l₂) : a ∈ l₂ := by simp #align list.mem_of_mem_inter_right List.mem_of_mem_inter_right theorem mem_inter_of_mem_of_mem (h₁ : a ∈ l₁) (h₂ : a ∈ l₂) : a ∈ l₁ ∩ l₂ := - mem_filter_of_mem h₁ $ by simpa using h₂ + mem_filter_of_mem h₁ <| by simpa using h₂ #align list.mem_inter_of_mem_of_mem List.mem_inter_of_mem_of_mem #align list.mem_inter List.mem_inter_iff diff --git a/Mathlib/Data/List/Lemmas.lean b/Mathlib/Data/List/Lemmas.lean index 853f752b28860..aa26c971a4e99 100644 --- a/Mathlib/Data/List/Lemmas.lean +++ b/Mathlib/Data/List/Lemmas.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky, Yury Kudryashov -/ -import Mathlib.Data.Set.Function +import Mathlib.Data.Set.Image import Mathlib.Data.List.Basic import Mathlib.Init.Data.List.Lemmas diff --git a/Mathlib/Data/List/Nodup.lean b/Mathlib/Data/List/Nodup.lean index 9a92d4ed69d74..ab8cafa3a67b0 100644 --- a/Mathlib/Data/List/Nodup.lean +++ b/Mathlib/Data/List/Nodup.lean @@ -3,8 +3,6 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kenny Lau -/ -import Mathlib.Data.List.Lattice -import Mathlib.Data.List.Pairwise import Mathlib.Data.List.Forall2 import Mathlib.Data.Set.Pairwise.Basic import Mathlib.Init.Data.Fin.Basic diff --git a/Mathlib/Data/List/OfFn.lean b/Mathlib/Data/List/OfFn.lean index a4a9eda66be61..307a7fe8df725 100644 --- a/Mathlib/Data/List/OfFn.lean +++ b/Mathlib/Data/List/OfFn.lean @@ -5,7 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Data.Fin.Tuple.Basic import Mathlib.Data.List.Join -import Mathlib.Data.List.Pairwise +import Mathlib.Data.Set.Image #align_import data.list.of_fn from "leanprover-community/mathlib"@"bf27744463e9620ca4e4ebe951fe83530ae6949b" @@ -278,7 +278,7 @@ theorem ofFn_inj' {m n : ℕ} {f : Fin m → α} {g : Fin n → α} : /-- Note we can only state this when the two functions are indexed by defeq `n`. -/ theorem ofFn_injective {n : ℕ} : Function.Injective (ofFn : (Fin n → α) → List α) := fun f g h => - eq_of_heq $ by rw [ofFn_inj'] at h; cases h; rfl + eq_of_heq <| by rw [ofFn_inj'] at h; cases h; rfl #align list.of_fn_injective List.ofFn_injective /-- A special case of `List.ofFn_inj` for when the two functions are indexed by defeq `n`. -/ diff --git a/Mathlib/Data/List/Pairwise.lean b/Mathlib/Data/List/Pairwise.lean index 97611a4195dcd..949d14837bca1 100644 --- a/Mathlib/Data/List/Pairwise.lean +++ b/Mathlib/Data/List/Pairwise.lean @@ -3,10 +3,9 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.List.Count -import Mathlib.Data.List.Lex import Mathlib.Logic.Pairwise import Mathlib.Logic.Relation +import Mathlib.Data.List.Basic #align_import data.list.pairwise from "leanprover-community/mathlib"@"f694c7dead66f5d4c80f446c796a5aad14707f0e" diff --git a/Mathlib/Data/List/Perm.lean b/Mathlib/Data/List/Perm.lean index cb7aa7c2c7126..0493db1487451 100644 --- a/Mathlib/Data/List/Perm.lean +++ b/Mathlib/Data/List/Perm.lean @@ -5,7 +5,8 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Data.List.Dedup import Mathlib.Data.List.Permutation -import Mathlib.Data.List.Range +import Mathlib.Data.List.Pairwise +import Mathlib.Data.List.Lattice import Mathlib.Data.Nat.Factorial.Basic #align_import data.list.perm from "leanprover-community/mathlib"@"65a1391a0106c9204fe45bc73a039f056558cb83" @@ -746,7 +747,7 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) : theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp · exact IH.bind_right _ - · dsimp [permutations'] + · dsimp rw [bind_assoc, bind_assoc] apply Perm.bind_left intro l' _ diff --git a/Mathlib/Data/List/ProdSigma.lean b/Mathlib/Data/List/ProdSigma.lean index 8866709b6bd55..2bdeec741bf7e 100644 --- a/Mathlib/Data/List/ProdSigma.lean +++ b/Mathlib/Data/List/ProdSigma.lean @@ -3,6 +3,7 @@ Copyright (c) 2015 Leonardo de Moura. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Mario Carneiro -/ +import Mathlib.Data.Sigma.Basic import Mathlib.Data.List.BigOperators.Basic #align_import data.list.prod_sigma from "leanprover-community/mathlib"@"dd71334db81d0bd444af1ee339a29298bef40734" diff --git a/Mathlib/Data/List/Range.lean b/Mathlib/Data/List/Range.lean index 4caf130d65aef..3375cf12a5a25 100644 --- a/Mathlib/Data/List/Range.lean +++ b/Mathlib/Data/List/Range.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kenny Lau, Scott Morrison -/ import Mathlib.Data.List.Chain -import Mathlib.Data.List.Join import Mathlib.Data.List.Nodup import Mathlib.Data.List.Zip +import Mathlib.Data.List.Pairwise #align_import data.list.range from "leanprover-community/mathlib"@"7b78d1776212a91ecc94cf601f83bdcc46b04213" diff --git a/Mathlib/Data/List/Rotate.lean b/Mathlib/Data/List/Rotate.lean index 57eb4489f6762..88c80f3799d79 100644 --- a/Mathlib/Data/List/Rotate.lean +++ b/Mathlib/Data/List/Rotate.lean @@ -3,8 +3,8 @@ Copyright (c) 2019 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Yakov Pechersky -/ -import Mathlib.Data.List.Perm -import Mathlib.Data.List.Range +import Mathlib.Data.List.Nodup +import Mathlib.Data.List.Zip #align_import data.list.rotate from "leanprover-community/mathlib"@"f694c7dead66f5d4c80f446c796a5aad14707f0e" @@ -247,8 +247,8 @@ theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) : rw [tsub_lt_iff_left hm'] exact Nat.add_lt_add hlt hml conv_rhs => rw [add_comm m, ← mod_add_mod, mod_eq_sub_mod hm', mod_eq_of_lt this] - rw [← add_right_inj l.length, ← add_tsub_assoc_of_le, add_tsub_tsub_cancel, - add_tsub_cancel_of_le, add_comm] + rw [← add_right_inj l.length, ← add_tsub_assoc_of_le (α := ℕ), add_tsub_tsub_cancel (α := ℕ), + add_tsub_cancel_of_le (α := ℕ), add_comm] exacts [hm', hlt.le, hm] · rwa [tsub_lt_iff_left hm, length_drop, tsub_add_cancel_of_le hlt.le] #align list.nth_rotate List.get?_rotate @@ -291,7 +291,7 @@ theorem get_eq_get_rotate (l : List α) (n : ℕ) (k : Fin l.length) : rw [get_rotate] refine congr_arg l.get (Fin.eq_of_val_eq ?_) simp only [mod_add_mod] - rw [← add_mod_mod, add_right_comm, tsub_add_cancel_of_le, add_mod_left, mod_eq_of_lt] + rw [← add_mod_mod, add_right_comm, tsub_add_cancel_of_le (α := ℕ), add_mod_left, mod_eq_of_lt] exacts [k.2, (mod_lt _ (k.1.zero_le.trans_lt k.2)).le] set_option linter.deprecated false in @@ -340,7 +340,7 @@ theorem rotate_eq_iff {l l' : List α} {n : ℕ} : · rw [eq_nil_of_length_eq_zero hl.symm, rotate_nil, rotate_eq_nil_iff] · rcases (Nat.zero_le (n % l'.length)).eq_or_lt with hn | hn · simp [← hn] - · rw [mod_eq_of_lt (tsub_lt_self hl hn), tsub_add_cancel_of_le, mod_self, rotate_zero] + · rw [mod_eq_of_lt (tsub_lt_self hl hn), tsub_add_cancel_of_le (α := ℕ), mod_self, rotate_zero] exact (Nat.mod_lt _ hl).le #align list.rotate_eq_iff List.rotate_eq_iff @@ -376,7 +376,7 @@ theorem rotate_reverse (l : List α) (n : ℕ) : · simp_all! [length_reverse, ← rotate_rotate] · cases' l with x l · simp - · rw [Nat.mod_eq_of_lt, tsub_add_cancel_of_le, rotate_length] + · rw [Nat.mod_eq_of_lt, tsub_add_cancel_of_le (α := ℕ), rotate_length] · exact tsub_le_self · exact tsub_lt_self (by simp) (by simp_all!) #align list.rotate_reverse List.rotate_reverse @@ -444,8 +444,8 @@ theorem IsRotated.symm (h : l ~r l') : l' ~r l := by cases' l with hd tl · exists 0 · use (hd :: tl).length * n - n - rw [rotate_rotate, add_tsub_cancel_of_le, rotate_length_mul] - exact Nat.le_mul_of_pos_left (by simp) + rw [rotate_rotate, add_tsub_cancel_of_le (α := ℕ), rotate_length_mul] + exact Nat.le_mul_of_pos_left _ (by simp) #align list.is_rotated.symm List.IsRotated.symm theorem isRotated_comm : l ~r l' ↔ l' ~r l := diff --git a/Mathlib/Data/List/Sort.lean b/Mathlib/Data/List/Sort.lean index 825171cbafc60..34d35a51b4bdd 100644 --- a/Mathlib/Data/List/Sort.lean +++ b/Mathlib/Data/List/Sort.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ import Mathlib.Data.List.OfFn -import Mathlib.Data.List.Perm +import Mathlib.Data.List.Nodup #align_import data.list.sort from "leanprover-community/mathlib"@"f694c7dead66f5d4c80f446c796a5aad14707f0e" @@ -99,29 +99,29 @@ protected theorem Sorted.nodup {r : α → α → Prop} [IsIrrefl α r] {l : Lis Pairwise.nodup h #align list.sorted.nodup List.Sorted.nodup -theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ ~ l₂) (s₁ : Sorted r l₁) - (s₂ : Sorted r l₂) : l₁ = l₂ := by - induction' s₁ with a l₁ h₁ s₁ IH generalizing l₂ - · exact p.nil_eq - · have : a ∈ l₂ := p.subset (mem_cons_self _ _) +theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (hp : l₁ ~ l₂) (hs₁ : Sorted r l₁) + (hs₂ : Sorted r l₂) : l₁ = l₂ := by + induction' hs₁ with a l₁ h₁ hs₁ IH generalizing l₂ + · exact hp.nil_eq + · have : a ∈ l₂ := hp.subset (mem_cons_self _ _) rcases mem_split this with ⟨u₂, v₂, rfl⟩ - have p' := (perm_cons a).1 (p.trans perm_middle) - obtain rfl := IH p' (s₂.sublist <| by simp) + have hp' := (perm_cons a).1 (hp.trans perm_middle) + obtain rfl := IH hp' (hs₂.sublist <| by simp) change a :: u₂ ++ v₂ = u₂ ++ ([a] ++ v₂) rw [← append_assoc] congr have : ∀ x ∈ u₂, x = a := fun x m => - antisymm ((pairwise_append.1 s₂).2.2 _ m a (mem_cons_self _ _)) (h₁ _ (by simp [m])) + antisymm ((pairwise_append.1 hs₂).2.2 _ m a (mem_cons_self _ _)) (h₁ _ (by simp [m])) rw [(@eq_replicate _ a (length u₂ + 1) (a :: u₂)).2, - (@eq_replicate _ a (length u₂ + 1) (u₂ ++ [a])).2] <;> + (@eq_replicate _ a (length u₂ + 1) (u₂ ++ [a])).2] <;> constructor <;> simp [iff_true_intro this, or_comm] #align list.eq_of_perm_of_sorted List.eq_of_perm_of_sorted -theorem sublist_of_subperm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (p : l₁ <+~ l₂) - (s₁ : l₁.Sorted r) (s₂ : l₂.Sorted r) : l₁ <+ l₂ := by - let ⟨_, h, h'⟩ := p - rwa [← eq_of_perm_of_sorted h (s₂.sublist h') s₁] +theorem sublist_of_subperm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (hp : l₁ <+~ l₂) + (hs₁ : l₁.Sorted r) (hs₂ : l₂.Sorted r) : l₁ <+ l₂ := by + let ⟨_, h, h'⟩ := hp + rwa [← eq_of_perm_of_sorted h (hs₂.sublist h') hs₁] #align list.sublist_of_subperm_of_sorted List.sublist_of_subperm_of_sorted @[simp 1100] --Porting note: higher priority for linter @@ -366,7 +366,7 @@ def merge : List α → List α → List α | [], l' => l' | l, [] => l | a :: l, b :: l' => if a ≼ b then a :: merge l (b :: l') else b :: merge (a :: l) l' - termination_by merge l₁ l₂ => length l₁ + length l₂ + termination_by l₁ l₂ => length l₁ + length l₂ #align list.merge List.merge /-- Implementation of a merge sort algorithm to sort a list. -/ @@ -381,7 +381,7 @@ def mergeSort : List α → List α have := h.1 have := h.2 exact merge r (mergeSort ls.1) (mergeSort ls.2) - termination_by mergeSort l => length l + termination_by l => length l #align list.merge_sort List.mergeSort @[nolint unusedHavesSuffices] --Porting note: false positive @@ -401,7 +401,7 @@ theorem perm_merge : ∀ l l' : List α, merge r l l' ~ l ++ l' · simpa [merge, h] using perm_merge _ _ · suffices b :: merge r (a :: l) l' ~ a :: (l ++ b :: l') by simpa [merge, h] exact ((perm_merge _ _).cons _).trans ((swap _ _ _).trans (perm_middle.symm.cons _)) - termination_by perm_merge l₁ l₂ => length l₁ + length l₂ + termination_by l₁ l₂ => length l₁ + length l₂ #align list.perm_merge List.perm_merge theorem perm_mergeSort : ∀ l : List α, mergeSort r l ~ l @@ -414,7 +414,7 @@ theorem perm_mergeSort : ∀ l : List α, mergeSort r l ~ l apply (perm_merge r _ _).trans exact ((perm_mergeSort l₁).append (perm_mergeSort l₂)).trans (perm_split e).symm - termination_by perm_mergeSort l => length l + termination_by l => length l #align list.perm_merge_sort List.perm_mergeSort @[simp] @@ -452,7 +452,7 @@ theorem Sorted.merge : ∀ {l l' : List α}, Sorted r l → Sorted r l' → Sort assumption · exact _root_.trans ba (rel_of_sorted_cons h₁ _ bl) · exact rel_of_sorted_cons h₂ _ bl' - termination_by Sorted.merge l₁ l₂ _ _ => length l₁ + length l₂ + termination_by l₁ l₂ => length l₁ + length l₂ #align list.sorted.merge List.Sorted.merge variable (r) @@ -465,7 +465,7 @@ theorem sorted_mergeSort : ∀ l : List α, Sorted r (mergeSort r l) cases' length_split_lt e with h₁ h₂ rw [mergeSort_cons_cons r e] exact (sorted_mergeSort l₁).merge (sorted_mergeSort l₂) - termination_by sorted_mergeSort l => length l + termination_by l => length l #align list.sorted_merge_sort List.sorted_mergeSort theorem mergeSort_eq_self [IsAntisymm α r] {l : List α} : Sorted r l → mergeSort r l = l := diff --git a/Mathlib/Data/List/Sublists.lean b/Mathlib/Data/List/Sublists.lean index c85e3afad4e5c..59abb0ea8e642 100644 --- a/Mathlib/Data/List/Sublists.lean +++ b/Mathlib/Data/List/Sublists.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Data.Nat.Choose.Basic import Mathlib.Data.List.Perm +import Mathlib.Data.List.Range #align_import data.list.sublists from "leanprover-community/mathlib"@"ccad6d5093bd2f5c6ca621fc74674cce51355af6" diff --git a/Mathlib/Data/List/Sym.lean b/Mathlib/Data/List/Sym.lean index 8ff6e87a57ae7..6bc6081fa7efa 100644 --- a/Mathlib/Data/List/Sym.lean +++ b/Mathlib/Data/List/Sym.lean @@ -159,7 +159,7 @@ protected def sym : (n : ℕ) → List α → List (Sym α n) | 0, _ => [.nil] | _, [] => [] | n + 1, x :: xs => ((x :: xs).sym n |>.map fun p => x ::ₛ p) ++ xs.sym (n + 1) - termination_by _ n xs => n + xs.length + termination_by n xs => n + xs.length variable {xs ys : List α} {n : ℕ} @@ -187,7 +187,7 @@ theorem sym_map {β : Type*} (f : α → β) (n : ℕ) (xs : List α) : congr ext s simp only [Function.comp_apply, Sym.map_cons] - termination_by _ n xs => n + xs.length + termination_by n + xs.length protected theorem Sublist.sym (n : ℕ) {xs ys : List α} (h : xs <+ ys) : xs.sym n <+ ys.sym n := match n, h with @@ -202,7 +202,7 @@ protected theorem Sublist.sym (n : ℕ) {xs ys : List α} (h : xs <+ ys) : xs.sy apply Sublist.append · exact ((cons₂ a h).sym n).map _ · exact h.sym (n + 1) - termination_by _ n xs ys h => n + xs.length + ys.length + termination_by n + xs.length + ys.length theorem sym_sublist_sym_cons {a : α} : xs.sym n <+ (a :: xs).sym n := (sublist_cons a xs).sym n @@ -224,7 +224,7 @@ theorem mem_of_mem_of_mem_sym {n : ℕ} {xs : List α} {a : α} {z : Sym α n} · rw [mem_cons] right exact mem_of_mem_of_mem_sym ha hz - termination_by _ n xs _ _ _ _ => n + xs.length + termination_by n + xs.length theorem first_mem_of_cons_mem_sym {xs : List α} {n : ℕ} {a : α} {z : Sym α n} (h : a ::ₛ z ∈ xs.sym (n + 1)) : a ∈ xs := @@ -246,7 +246,7 @@ protected theorem Nodup.sym (n : ℕ) {xs : List α} (h : xs.Nodup) : (xs.sym n) obtain ⟨z, _hz, rfl⟩ := hz have := first_mem_of_cons_mem_sym hz' simp only [nodup_cons, this, not_true_eq_false, false_and] at h - termination_by _ n xs _ => n + xs.length + termination_by n + xs.length theorem length_sym {n : ℕ} {xs : List α} : (xs.sym n).length = Nat.multichoose xs.length n := @@ -257,7 +257,7 @@ theorem length_sym {n : ℕ} {xs : List α} : rw [List.sym, length_append, length_map, length_cons] rw [@length_sym n (x :: xs), @length_sym (n + 1) xs] rw [Nat.multichoose_succ_succ, length_cons, add_comm] - termination_by _ n xs => n + xs.length + termination_by n + xs.length end Sym diff --git a/Mathlib/Data/List/TFAE.lean b/Mathlib/Data/List/TFAE.lean index caf951b5ef08c..a102741f89bab 100644 --- a/Mathlib/Data/List/TFAE.lean +++ b/Mathlib/Data/List/TFAE.lean @@ -3,8 +3,10 @@ Copyright (c) 2018 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Simon Hudon -/ -import Mathlib.Data.List.Basic -import Mathlib.Init.Data.List.Basic +import Std.Data.List.Lemmas +import Std.Tactic.RCases +import Mathlib.Tactic.TypeStar +import Mathlib.Mathport.Rename #align_import data.list.tfae from "leanprover-community/mathlib"@"5a3e819569b0f12cbec59d740a2613018e7b8eec" @@ -58,15 +60,15 @@ theorem tfae_of_forall (b : Prop) (l : List Prop) (h : ∀ a ∈ l, a ↔ b) : T fun _a₁ h₁ _a₂ h₂ => (h _ h₁).trans (h _ h₂).symm #align list.tfae_of_forall List.tfae_of_forall -theorem tfae_of_cycle {a b} {l : List Prop} : - List.Chain (· → ·) a (b :: l) → (ilast' b l → a) → TFAE (a :: b :: l) := by - induction' l with c l IH generalizing a b <;> - simp only [tfae_cons_cons, tfae_singleton, and_true_iff, chain_cons, Chain.nil] at * - · intro a b - exact Iff.intro a b - rintro ⟨ab, ⟨bc, ch⟩⟩ la - have := IH ⟨bc, ch⟩ (ab ∘ la) - exact ⟨⟨ab, la ∘ (this.2 c (Mem.head _) _ (ilast'_mem _ _)).1 ∘ bc⟩, this⟩ +theorem tfae_of_cycle {a b} {l : List Prop} (h_chain : List.Chain (· → ·) a (b :: l)) + (h_last : getLastD l b → a) : TFAE (a :: b :: l) := by + induction l generalizing a b with + | nil => simp_all [tfae_cons_cons, iff_def] + | cons c l IH => + simp only [tfae_cons_cons, getLastD_cons, tfae_singleton, and_true, chain_cons, Chain.nil] at * + rcases h_chain with ⟨ab, ⟨bc, ch⟩⟩ + have := IH ⟨bc, ch⟩ (ab ∘ h_last) + exact ⟨⟨ab, h_last ∘ (this.2 c (.head _) _ (getLastD_mem_cons _ _)).1 ∘ bc⟩, this⟩ #align list.tfae_of_cycle List.tfae_of_cycle theorem TFAE.out {l} (h : TFAE l) (n₁ n₂) {a b} (h₁ : List.get? l n₁ = some a := by rfl) @@ -88,7 +90,7 @@ example (P₁ P₂ P₃ : ℕ → Prop) (H : ∀ n, [P₁ n, P₂ n, P₃ n].TFA -/ theorem forall_tfae {α : Type*} (l : List (α → Prop)) (H : ∀ a : α, (l.map (fun p ↦ p a)).TFAE) : (l.map (fun p ↦ ∀ a, p a)).TFAE := by - simp_rw [TFAE, List.forall_mem_map_iff] + simp only [TFAE, List.forall_mem_map_iff] intros p₁ hp₁ p₂ hp₂ exact forall_congr' fun a ↦ H a (p₁ a) (mem_map_of_mem (fun p ↦ p a) hp₁) (p₂ a) (mem_map_of_mem (fun p ↦ p a) hp₂) @@ -107,7 +109,7 @@ example (P₁ P₂ P₃ : ℕ → Prop) (H : ∀ n, [P₁ n, P₂ n, P₃ n].TFA -/ theorem exists_tfae {α : Type*} (l : List (α → Prop)) (H : ∀ a : α, (l.map (fun p ↦ p a)).TFAE) : (l.map (fun p ↦ ∃ a, p a)).TFAE := by - simp_rw [TFAE, List.forall_mem_map_iff] + simp only [TFAE, List.forall_mem_map_iff] intros p₁ hp₁ p₂ hp₂ exact exists_congr fun a ↦ H a (p₁ a) (mem_map_of_mem (fun p ↦ p a) hp₁) (p₂ a) (mem_map_of_mem (fun p ↦ p a) hp₂) diff --git a/Mathlib/Data/List/ToFinsupp.lean b/Mathlib/Data/List/ToFinsupp.lean index ef4a244f1ed17..d320e045d0c4f 100644 --- a/Mathlib/Data/List/ToFinsupp.lean +++ b/Mathlib/Data/List/ToFinsupp.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.Defs #align_import data.list.to_finsupp from "leanprover-community/mathlib"@"06a655b5fcfbda03502f9158bbf6c0f1400886f9" diff --git a/Mathlib/Data/MLList/BestFirst.lean b/Mathlib/Data/MLList/BestFirst.lean index d36620a4a961a..dfab0116eb78a 100644 --- a/Mathlib/Data/MLList/BestFirst.lean +++ b/Mathlib/Data/MLList/BestFirst.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Std.Data.MLList.Basic -import Mathlib.Data.Finset.Preimage import Mathlib.Data.Prod.Lex import Mathlib.Order.Estimator +import Mathlib.Data.Set.Finite /-! # Best first search diff --git a/Mathlib/Data/MLList/DepthFirst.lean b/Mathlib/Data/MLList/DepthFirst.lean index 984378c5cb8de..e1a2273bb506d 100644 --- a/Mathlib/Data/MLList/DepthFirst.lean +++ b/Mathlib/Data/MLList/DepthFirst.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Std.Data.MLList.Basic -import Mathlib.Control.Traversable.Basic +import Mathlib.Init.Control.Combinators /-! # Depth first search diff --git a/Mathlib/Data/Matrix/Basic.lean b/Mathlib/Data/Matrix/Basic.lean index d863e5ec54e0d..930b02894b162 100644 --- a/Mathlib/Data/Matrix/Basic.lean +++ b/Mathlib/Data/Matrix/Basic.lean @@ -2567,9 +2567,9 @@ theorem mul_submatrix_one [Fintype n] [Finite o] [NonAssocSemiring α] [Decidabl cases nonempty_fintype o let A := M.submatrix id e₁.symm have : M = A.submatrix id e₁ := by - simp only [submatrix_submatrix, Function.comp.right_id, submatrix_id_id, Equiv.symm_comp_self] + simp only [submatrix_submatrix, Function.comp_id, submatrix_id_id, Equiv.symm_comp_self] rw [this, submatrix_mul_equiv] - simp only [Matrix.mul_one, submatrix_submatrix, Function.comp.right_id, submatrix_id_id, + simp only [Matrix.mul_one, submatrix_submatrix, Function.comp_id, submatrix_id_id, Equiv.symm_comp_self] #align matrix.mul_submatrix_one Matrix.mul_submatrix_one @@ -2579,9 +2579,9 @@ theorem one_submatrix_mul [Fintype m] [Finite o] [NonAssocSemiring α] [Decidabl cases nonempty_fintype o let A := M.submatrix e₂.symm id have : M = A.submatrix e₂ id := by - simp only [submatrix_submatrix, Function.comp.right_id, submatrix_id_id, Equiv.symm_comp_self] + simp only [submatrix_submatrix, Function.comp_id, submatrix_id_id, Equiv.symm_comp_self] rw [this, submatrix_mul_equiv] - simp only [Matrix.one_mul, submatrix_submatrix, Function.comp.right_id, submatrix_id_id, + simp only [Matrix.one_mul, submatrix_submatrix, Function.comp_id, submatrix_id_id, Equiv.symm_comp_self] #align matrix.one_submatrix_mul Matrix.one_submatrix_mul diff --git a/Mathlib/Data/Matroid/Basic.lean b/Mathlib/Data/Matroid/Basic.lean index e6219c7b71259..330ac549e195a 100644 --- a/Mathlib/Data/Matroid/Basic.lean +++ b/Mathlib/Data/Matroid/Basic.lean @@ -270,7 +270,7 @@ theorem encard_diff_le_aux (exch : ExchangeProperty Base) (hB₁ : Base B₁) (h rw [← encard_diff_singleton_add_one he, ← encard_diff_singleton_add_one hf] exact add_le_add_right hencard 1 -termination_by _ => (B₂ \ B₁).encard +termination_by (B₂ \ B₁).encard /-- For any two sets `B₁`, `B₂` in a family with the exchange property, the differences `B₁ \ B₂` and `B₂ \ B₁` have the same `ℕ∞`-cardinality. -/ @@ -293,7 +293,7 @@ section aesop It uses a `[Matroid]` ruleset, and is allowed to fail. -/ macro (name := aesop_mat) "aesop_mat" c:Aesop.tactic_clause* : tactic => `(tactic| - aesop $c* (options := { terminal := true }) + aesop $c* (config := { terminal := true }) (rule_sets [$(Lean.mkIdent `Matroid):ident])) /- We add a number of trivial lemmas (deliberately specialized to statements in terms of the diff --git a/Mathlib/Data/Matroid/Dual.lean b/Mathlib/Data/Matroid/Dual.lean index 698b6a8d2b7f8..50ab9489e8a45 100644 --- a/Mathlib/Data/Matroid/Dual.lean +++ b/Mathlib/Data/Matroid/Dual.lean @@ -68,7 +68,7 @@ section dual exact disjoint_of_subset_left hB''₂.2 disjoint_compl_left indep_maximal := by rintro X - I'⟨hI'E, B, hB, hI'B⟩ hI'X - obtain ⟨I, hI⟩ := M.exists_basis (M.E \ X) + obtain ⟨I, hI⟩ := M.exists_basis (M.E \ X) obtain ⟨B', hB', hIB', hB'IB⟩ := hI.indep.exists_base_subset_union_base hB refine' ⟨(X \ B') ∩ M.E, ⟨_,subset_inter (subset_diff.mpr _) hI'E, (inter_subset_left _ _).trans (diff_subset _ _)⟩, _⟩ diff --git a/Mathlib/Data/Matroid/IndepAxioms.lean b/Mathlib/Data/Matroid/IndepAxioms.lean index 242f2b0e96b44..decdb9eb84ba2 100644 --- a/Mathlib/Data/Matroid/IndepAxioms.lean +++ b/Mathlib/Data/Matroid/IndepAxioms.lean @@ -127,7 +127,7 @@ attribute [pp_dot] Indep E have hfB' : f ∉ B := by (intro hfB; obtain rfl := hf.2 hfB; exact he.2 hf.1) refine' ⟨f, ⟨hf.1, hfB'⟩, by_contra (fun hnot ↦ _)⟩ - obtain ⟨x,hxB, hind⟩ := M.indep_aug hfB hnot ⟨hB, hBmax⟩ + obtain ⟨x,hxB, hind⟩ := M.indep_aug hfB hnot ⟨hB, hBmax⟩ simp only [mem_diff, mem_insert_iff, mem_singleton_iff, not_or, not_and, not_not] at hxB obtain rfl := hxB.2.2 hxB.1 rw [insert_comm, insert_diff_singleton, insert_eq_of_mem he.1] at hind diff --git a/Mathlib/Data/Multiset/Basic.lean b/Mathlib/Data/Multiset/Basic.lean index b847b159bf5ca..7e03fd0178e85 100644 --- a/Mathlib/Data/Multiset/Basic.lean +++ b/Mathlib/Data/Multiset/Basic.lean @@ -850,7 +850,7 @@ def strongInductionOn {p : Multiset α → Sort*} (s : Multiset α) (ih : ∀ s, p s := (ih s) fun t _h => strongInductionOn t ih -termination_by _ => card s +termination_by card s decreasing_by exact card_lt_card _h #align multiset.strong_induction_on Multiset.strongInductionOnₓ -- Porting note: reorderd universes @@ -877,8 +877,8 @@ def strongDownwardInduction {p : Multiset α → Sort*} {n : ℕ} card s ≤ n → p s := H s fun {t} ht _h => strongDownwardInduction H t ht -termination_by _ => n - card s -decreasing_by exact (tsub_lt_tsub_iff_left_of_le ht).2 (card_lt_card _h) +termination_by n - card s +decreasing_by simp_wf; have := (card_lt_card _h); omega -- Porting note: reorderd universes #align multiset.strong_downward_induction Multiset.strongDownwardInductionₓ @@ -1982,7 +1982,7 @@ theorem filter_zero : filter p 0 = 0 := theorem filter_congr {p q : α → Prop} [DecidablePred p] [DecidablePred q] {s : Multiset α} : (∀ x ∈ s, p x ↔ q x) → filter p s = filter q s := - Quot.inductionOn s fun _l h => congr_arg ofList <| filter_congr' $ by simpa using h + Quot.inductionOn s fun _l h => congr_arg ofList <| filter_congr' <| by simpa using h #align multiset.filter_congr Multiset.filter_congr @[simp] @@ -2010,19 +2010,19 @@ theorem monotone_filter_left : Monotone (filter p) := fun _s _t => filter_le_fil theorem monotone_filter_right (s : Multiset α) ⦃p q : α → Prop⦄ [DecidablePred p] [DecidablePred q] (h : ∀ b, p b → q b) : s.filter p ≤ s.filter q := - Quotient.inductionOn s fun l => (l.monotone_filter_right $ by simpa using h).subperm + Quotient.inductionOn s fun l => (l.monotone_filter_right <| by simpa using h).subperm #align multiset.monotone_filter_right Multiset.monotone_filter_right variable {p} @[simp] theorem filter_cons_of_pos {a : α} (s) : p a → filter p (a ::ₘ s) = a ::ₘ filter p s := - Quot.inductionOn s fun l h => congr_arg ofList <| List.filter_cons_of_pos l $ by simpa using h + Quot.inductionOn s fun l h => congr_arg ofList <| List.filter_cons_of_pos l <| by simpa using h #align multiset.filter_cons_of_pos Multiset.filter_cons_of_pos @[simp] theorem filter_cons_of_neg {a : α} (s) : ¬p a → filter p (a ::ₘ s) = filter p s := - Quot.inductionOn s fun l h => congr_arg ofList <| List.filter_cons_of_neg l $ by simpa using h + Quot.inductionOn s fun l h => congr_arg ofList <| List.filter_cons_of_neg l <| by simpa using h #align multiset.filter_cons_of_neg Multiset.filter_cons_of_neg @[simp] @@ -2045,13 +2045,13 @@ theorem mem_filter_of_mem {a : α} {l} (m : a ∈ l) (h : p a) : a ∈ filter p theorem filter_eq_self {s} : filter p s = s ↔ ∀ a ∈ s, p a := Quot.inductionOn s fun _l => Iff.trans ⟨fun h => (filter_sublist _).eq_of_length (@congr_arg _ _ _ _ card h), - congr_arg ofList⟩ $ + congr_arg ofList⟩ <| by simpa using List.filter_eq_self (p := (p ·)) #align multiset.filter_eq_self Multiset.filter_eq_self theorem filter_eq_nil {s} : filter p s = 0 ↔ ∀ a ∈ s, ¬p a := Quot.inductionOn s fun _l => - Iff.trans ⟨fun h => eq_nil_of_length_eq_zero (@congr_arg _ _ _ _ card h), congr_arg ofList⟩ $ + Iff.trans ⟨fun h => eq_nil_of_length_eq_zero (@congr_arg _ _ _ _ card h), congr_arg ofList⟩ <| by simpa using List.filter_eq_nil (p := (p ·)) #align multiset.filter_eq_nil Multiset.filter_eq_nil @@ -2443,12 +2443,12 @@ theorem count_zero (a : α) : count a 0 = 0 := @[simp] theorem count_cons_self (a : α) (s : Multiset α) : count a (a ::ₘ s) = count a s + 1 := - countP_cons_of_pos _ $ rfl + countP_cons_of_pos _ <| rfl #align multiset.count_cons_self Multiset.count_cons_self @[simp] theorem count_cons_of_ne {a b : α} (h : a ≠ b) (s : Multiset α) : count a (b ::ₘ s) = count a s := - countP_cons_of_neg _ $ h + countP_cons_of_neg _ <| h #align multiset.count_cons_of_ne Multiset.count_cons_of_ne theorem count_le_card (a : α) (s) : count a s ≤ card s := @@ -2640,7 +2640,7 @@ theorem count_map_eq_count [DecidableEq β] (f : α → β) (s : Multiset α) (hf : Set.InjOn f { x : α | x ∈ s }) (x) (H : x ∈ s) : (s.map f).count (f x) = s.count x := by suffices (filter (fun a : α => f x = f a) s).count x = card (filter (fun a : α => f x = f a) s) by rw [count, countP_map, ← this] - exact count_filter_of_pos $ rfl + exact count_filter_of_pos <| rfl · rw [eq_replicate_card.2 fun b hb => (hf H (mem_filter.1 hb).left _).symm] · simp only [count_replicate, eq_self_iff_true, if_true, card_replicate] · simp only [mem_filter, beq_iff_eq, and_imp, @eq_comm _ (f x), imp_self, implies_true] @@ -2728,7 +2728,7 @@ for more discussion. @[simp] theorem map_count_True_eq_filter_card (s : Multiset α) (p : α → Prop) [DecidablePred p] : (s.map p).count True = card (s.filter p) := by - simp only [count_eq_card_filter_eq, map_filter, card_map, Function.comp.left_id, + simp only [count_eq_card_filter_eq, map_filter, card_map, Function.id_comp, eq_true_eq_id, Function.comp_apply] #align multiset.map_count_true_eq_filter_card Multiset.map_count_True_eq_filter_card diff --git a/Mathlib/Data/Multiset/Fintype.lean b/Mathlib/Data/Multiset/Fintype.lean index a6b7a28c423ab..d79f1440e294b 100644 --- a/Mathlib/Data/Multiset/Fintype.lean +++ b/Mathlib/Data/Multiset/Fintype.lean @@ -5,7 +5,6 @@ Authors: Kyle Miller -/ import Mathlib.Algebra.BigOperators.Basic import Mathlib.Data.Fintype.Card -import Mathlib.Data.Prod.Lex #align_import data.multiset.fintype from "leanprover-community/mathlib"@"e3d9ab8faa9dea8f78155c6c27d62a621f4c152d" diff --git a/Mathlib/Data/Multiset/Nodup.lean b/Mathlib/Data/Multiset/Nodup.lean index 0eb95e696fbce..4cbd6db9a39db 100644 --- a/Mathlib/Data/Multiset/Nodup.lean +++ b/Mathlib/Data/Multiset/Nodup.lean @@ -6,6 +6,7 @@ Authors: Mario Carneiro import Mathlib.Data.List.Nodup import Mathlib.Data.Multiset.Bind import Mathlib.Data.Multiset.Range +import Mathlib.Data.List.Range #align_import data.multiset.nodup from "leanprover-community/mathlib"@"f694c7dead66f5d4c80f446c796a5aad14707f0e" @@ -272,7 +273,7 @@ theorem map_eq_map_of_bij_of_nodup (f : α → γ) (g : β → γ) {s : Multiset have : t = s.attach.map fun x => i x.1 x.2 · rw [ht.ext] · aesop - · exact hs.attach.map fun x y hxy ↦ Subtype.ext $ i_inj _ x.2 _ y.2 hxy + · exact hs.attach.map fun x y hxy ↦ Subtype.ext <| i_inj _ x.2 _ y.2 hxy calc s.map f = s.pmap (fun x _ => f x) fun _ => id := by rw [pmap_eq_map] _ = s.attach.map fun x => f x.1 := by rw [pmap_eq_map_attach] diff --git a/Mathlib/Data/Multiset/Powerset.lean b/Mathlib/Data/Multiset/Powerset.lean index 821f85d657157..bdf4ae74eb6ab 100644 --- a/Mathlib/Data/Multiset/Powerset.lean +++ b/Mathlib/Data/Multiset/Powerset.lean @@ -287,15 +287,15 @@ theorem powersetCard_mono (n : ℕ) {s t : Multiset α} (h : s ≤ t) : #align multiset.powerset_len_mono Multiset.powersetCard_mono @[simp] -theorem powersetCard_empty {α : Type*} (n : ℕ) {s : Multiset α} (h : card s < n) : +theorem powersetCard_eq_empty {α : Type*} (n : ℕ) {s : Multiset α} (h : card s < n) : powersetCard n s = 0 := card_eq_zero.mp (Nat.choose_eq_zero_of_lt h ▸ card_powersetCard _ _) -#align multiset.powerset_len_empty Multiset.powersetCard_empty +#align multiset.powerset_len_empty Multiset.powersetCard_eq_empty @[simp] theorem powersetCard_card_add (s : Multiset α) {i : ℕ} (hi : 0 < i) : s.powersetCard (card s + i) = 0 := - powersetCard_empty _ (lt_add_of_pos_right (card s) hi) + powersetCard_eq_empty _ (lt_add_of_pos_right (card s) hi) #align multiset.powerset_len_card_add Multiset.powersetCard_card_add theorem powersetCard_map {β : Type*} (f : α → β) (n : ℕ) (s : Multiset α) : diff --git a/Mathlib/Data/Multiset/Range.lean b/Mathlib/Data/Multiset/Range.lean index da32945ae2833..5976088952dc6 100644 --- a/Mathlib/Data/Multiset/Range.lean +++ b/Mathlib/Data/Multiset/Range.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.Multiset.Basic -import Mathlib.Data.List.Range #align_import data.multiset.range from "leanprover-community/mathlib"@"0a0ec35061ed9960bf0e7ffb0335f44447b58977" diff --git a/Mathlib/Data/MvPolynomial/Basic.lean b/Mathlib/Data/MvPolynomial/Basic.lean index 5bafaae1547a1..c86746c5ebd38 100644 --- a/Mathlib/Data/MvPolynomial/Basic.lean +++ b/Mathlib/Data/MvPolynomial/Basic.lean @@ -71,14 +71,10 @@ polynomial, multivariate polynomial, multivariable polynomial set_option autoImplicit true - noncomputable section -open BigOperators - open Set Function Finsupp AddMonoidAlgebra - -open BigOperators +open scoped BigOperators Pointwise universe u v w x @@ -578,7 +574,7 @@ section Coeff /-- The coefficient of the monomial `m` in the multi-variable polynomial `p`. -/ def coeff (m : σ →₀ ℕ) (p : MvPolynomial σ R) : R := - @FunLike.coe ((σ →₀ ℕ) →₀ R) _ _ _ p m + @DFunLike.coe ((σ →₀ ℕ) →₀ R) _ _ _ p m -- porting note: I changed this from `@CoeFun.coe _ _ (MonoidAlgebra.coeFun _ _) p m` because -- I think it should work better syntactically. They are defeq. #align mv_polynomial.coeff MvPolynomial.coeff @@ -597,8 +593,8 @@ theorem sum_def {A} [AddCommMonoid A] {p : MvPolynomial σ R} {b : (σ →₀ #align mv_polynomial.sum_def MvPolynomial.sum_def theorem support_mul [DecidableEq σ] (p q : MvPolynomial σ R) : - (p * q).support ⊆ p.support.biUnion fun a => q.support.biUnion fun b => {a + b} := by - convert AddMonoidAlgebra.support_mul p q + (p * q).support ⊆ p.support + q.support := + AddMonoidAlgebra.support_mul p q #align mv_polynomial.support_mul MvPolynomial.support_mul @[ext] @@ -760,6 +756,7 @@ theorem support_sdiff_support_subset_support_add [DecidableEq σ] (p q : MvPolyn simp [hm.2, hm.1] #align mv_polynomial.support_sdiff_support_subset_support_add MvPolynomial.support_sdiff_support_subset_support_add +open scoped symmDiff in theorem support_symmDiff_support_subset_support_add [DecidableEq σ] (p q : MvPolynomial σ R) : p.support ∆ q.support ⊆ (p + q).support := by rw [symmDiff_def, Finset.sup_eq_union] @@ -772,23 +769,15 @@ theorem support_symmDiff_support_subset_support_add [DecidableEq σ] (p q : MvPo theorem coeff_mul_monomial' (m) (s : σ →₀ ℕ) (r : R) (p : MvPolynomial σ R) : coeff m (p * monomial s r) = if s ≤ m then coeff (m - s) p * r else 0 := by classical - obtain rfl | hr := eq_or_ne r 0 - · simp only [monomial_zero, coeff_zero, mul_zero, ite_self] - haveI : Nontrivial R := nontrivial_of_ne _ _ hr split_ifs with h · conv_rhs => rw [← coeff_mul_monomial _ s] congr with t rw [tsub_add_cancel_of_le h] - · rw [← not_mem_support_iff] - intro hm - apply h - have H := support_mul _ _ hm - simp only [Finset.mem_biUnion] at H - rcases H with ⟨j, _hj, i', hi', H⟩ - rw [support_monomial, if_neg hr, Finset.mem_singleton] at hi' - subst i' - rw [Finset.mem_singleton] at H - subst m + · contrapose! h + rw [← mem_support_iff] at h + obtain ⟨j, -, rfl⟩ : ∃ j ∈ support p, j + s = m := by + simpa [Finset.add_singleton] + using Finset.add_subset_add_left support_monomial_subset <| support_mul _ _ h exact le_add_left le_rfl #align mv_polynomial.coeff_mul_monomial' MvPolynomial.coeff_mul_monomial' @@ -855,7 +844,7 @@ theorem C_dvd_iff_dvd_coeff (r : R) (φ : MvPolynomial σ R) : C r ∣ φ ↔ @[simp] lemma isRegular_X : IsRegular (X n : MvPolynomial σ R) := by suffices : IsLeftRegular (X n : MvPolynomial σ R) - · exact ⟨this, this.right_of_commute $ Commute.all _⟩ + · exact ⟨this, this.right_of_commute <| Commute.all _⟩ intro P Q (hPQ : (X n) * P = (X n) * Q) ext i rw [← coeff_X_mul i n P, hPQ, coeff_X_mul i n Q] @@ -1425,7 +1414,7 @@ def mapAlgHom [CommSemiring S₂] [Algebra R S₁] [Algebra R S₂] (f : S₁ have h₂ : algebraMap R (MvPolynomial σ S₂) r = C (algebraMap R S₂ r) := rfl simp_rw [OneHom.toFun_eq_coe] -- porting note: we're missing some `simp` lemmas like `MonoidHom.coe_toOneHom` - change @FunLike.coe (_ →+* _) _ _ _ _ _ = _ + change @DFunLike.coe (_ →+* _) _ _ _ _ _ = _ rw [h₁, h₂, map, eval₂Hom_C, RingHom.comp_apply, AlgHom.coe_toRingHom, AlgHom.commutes] } #align mv_polynomial.map_alg_hom MvPolynomial.mapAlgHom diff --git a/Mathlib/Data/MvPolynomial/Monad.lean b/Mathlib/Data/MvPolynomial/Monad.lean index e86633666d89c..bb55915f823c7 100644 --- a/Mathlib/Data/MvPolynomial/Monad.lean +++ b/Mathlib/Data/MvPolynomial/Monad.lean @@ -202,7 +202,7 @@ theorem join₂_comp_map (f : R →+* MvPolynomial σ S) : join₂.comp (map f) #align mv_polynomial.join₂_comp_map MvPolynomial.join₂_comp_map theorem aeval_id_rename (f : σ → MvPolynomial τ R) (p : MvPolynomial σ R) : - aeval id (rename f p) = aeval f p := by rw [aeval_rename, Function.comp.left_id] + aeval id (rename f p) = aeval f p := by rw [aeval_rename, Function.id_comp] #align mv_polynomial.aeval_id_rename MvPolynomial.aeval_id_rename @[simp] diff --git a/Mathlib/Data/MvPolynomial/Variables.lean b/Mathlib/Data/MvPolynomial/Variables.lean index 384db34fd52d0..e7cb03688a252 100644 --- a/Mathlib/Data/MvPolynomial/Variables.lean +++ b/Mathlib/Data/MvPolynomial/Variables.lean @@ -159,29 +159,18 @@ theorem degrees_sum {ι : Type*} [DecidableEq σ] (s : Finset ι) (f : ι → Mv theorem degrees_mul (p q : MvPolynomial σ R) : (p * q).degrees ≤ p.degrees + q.degrees := by classical - refine' Finset.sup_le fun b hb => _ - have := support_mul p q hb - simp only [Finset.mem_biUnion, Finset.mem_singleton] at this - rcases this with ⟨a₁, h₁, a₂, h₂, rfl⟩ + refine (Finset.sup_mono <| support_mul p q).trans <| Finset.sup_add_le.2 fun a ha b hb ↦ ?_ rw [Finsupp.toMultiset_add] - exact add_le_add (Finset.le_sup h₁) (Finset.le_sup h₂) + exact add_le_add (Finset.le_sup ha) (Finset.le_sup hb) #align mv_polynomial.degrees_mul MvPolynomial.degrees_mul theorem degrees_prod {ι : Type*} (s : Finset ι) (f : ι → MvPolynomial σ R) : - (∏ i in s, f i).degrees ≤ ∑ i in s, (f i).degrees := by - classical - refine' s.induction _ _ - · simp only [Finset.prod_empty, Finset.sum_empty, degrees_one, le_refl] - · intro i s his ih - rw [Finset.prod_insert his, Finset.sum_insert his] - exact le_trans (degrees_mul _ _) (add_le_add_left ih _) + (∏ i in s, f i).degrees ≤ ∑ i in s, (f i).degrees := + Finset.le_prod_of_submultiplicative (Multiplicative.ofAdd ∘ degrees) degrees_one degrees_mul _ _ #align mv_polynomial.degrees_prod MvPolynomial.degrees_prod -theorem degrees_pow (p : MvPolynomial σ R) : ∀ n : ℕ, (p ^ n).degrees ≤ n • p.degrees - | 0 => by rw [pow_zero, degrees_one]; exact Multiset.zero_le _ - | n + 1 => by - rw [pow_succ, add_smul, add_comm, one_smul] - exact le_trans (degrees_mul _ _) (add_le_add_left (degrees_pow _ n) _) +theorem degrees_pow (p : MvPolynomial σ R) (n : ℕ) : (p ^ n).degrees ≤ n • p.degrees := by + simpa using degrees_prod (Finset.range n) fun _ ↦ p #align mv_polynomial.degrees_pow MvPolynomial.degrees_pow theorem mem_degrees {p : MvPolynomial σ R} {i : σ} : diff --git a/Mathlib/Data/Nat/Basic.lean b/Mathlib/Data/Nat/Basic.lean index d1e8dea049591..8c618ee81bc4c 100644 --- a/Mathlib/Data/Nat/Basic.lean +++ b/Mathlib/Data/Nat/Basic.lean @@ -3,45 +3,26 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Init.Data.Nat.Lemmas -import Mathlib.Order.Basic -import Mathlib.Algebra.GroupWithZero.Defs +import Mathlib.Algebra.Group.TypeTags import Mathlib.Algebra.Ring.Defs -import Mathlib.Tactic.PushNeg -import Mathlib.Tactic.Use +import Mathlib.Algebra.GroupWithZero.Defs #align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b" /-! -# Basic operations on the natural numbers +# Basic instances for the natural numbers This file contains: -- instances on the natural numbers -- some basic lemmas about natural numbers -- extra recursors: - * `le_rec_on`, `le_induction`: recursion and induction principles starting at non-zero numbers - * `decreasing_induction`: recursion growing downwards - * `le_rec_on'`, `decreasing_induction'`: versions with slightly weaker assumptions - * `strong_rec'`: recursion based on strong inequalities -- decidability instances on predicates about the natural numbers - -Many theorems that used to live in this file have been moved to `Data.Nat.Order`, -so that this file requires fewer imports. -For each section here there is a corresponding section in that file with additional results. -It may be possible to move some of these results here, by tweaking their proofs. - - +* Algebraic instances on the natural numbers +* Basic lemmas about natural numbers that require more imports than available in + `Data.Nat.Defs`. -/ - -universe u v +open Multiplicative namespace Nat -/-! ### instances -/ - -instance nontrivial : Nontrivial ℕ := - ⟨⟨0, 1, Nat.zero_ne_one⟩⟩ +/-! ### Instances -/ instance commSemiring : CommSemiring ℕ where add := Nat.add @@ -72,7 +53,6 @@ instance commSemiring : CommSemiring ℕ where /-! Extra instances to short-circuit type class resolution and ensure computability -/ - instance addCommMonoid : AddCommMonoid ℕ := inferInstance @@ -103,888 +83,24 @@ instance distrib : Distrib ℕ := instance semiring : Semiring ℕ := inferInstance -protected theorem nsmul_eq_mul (m n : ℕ) : m • n = m * n := - rfl -#align nat.nsmul_eq_mul Nat.nsmul_eq_mul - --- Moved to core -#align nat.eq_of_mul_eq_mul_right Nat.eq_of_mul_eq_mul_right - instance cancelCommMonoidWithZero : CancelCommMonoidWithZero ℕ := { (inferInstance : CommMonoidWithZero ℕ) with mul_left_cancel_of_ne_zero := fun h1 h2 => Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero h1) h2 } #align nat.cancel_comm_monoid_with_zero Nat.cancelCommMonoidWithZero -attribute [simp] - Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero - -- Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1 - -- Nat.bit1_ne_bit0 - -variable {m n k : ℕ} - -/-! -### Recursion and `forall`/`exists` --/ - --- Porting note: --- this doesn't work as a simp lemma in Lean 4 --- @[simp] -theorem and_forall_succ {p : ℕ → Prop} : (p 0 ∧ ∀ n, p (n + 1)) ↔ ∀ n, p n := - ⟨fun h n => Nat.casesOn n h.1 h.2, fun h => ⟨h _, fun _ => h _⟩⟩ -#align nat.and_forall_succ Nat.and_forall_succ - --- Porting note: --- this doesn't work as a simp lemma in Lean 4 --- @[simp] -theorem or_exists_succ {p : ℕ → Prop} : (p 0 ∨ ∃ n, p (n + 1)) ↔ ∃ n, p n := - ⟨fun h => h.elim (fun h0 => ⟨0, h0⟩) fun ⟨n, hn⟩ => ⟨n + 1, hn⟩, by - rintro ⟨_ | n, hn⟩ - exacts [Or.inl hn, Or.inr ⟨n, hn⟩]⟩ -#align nat.or_exists_succ Nat.or_exists_succ - -/-! ### `succ` -/ - - -theorem _root_.LT.lt.nat_succ_le {n m : ℕ} (h : n < m) : succ n ≤ m := - succ_le_of_lt h -#align has_lt.lt.nat_succ_le LT.lt.nat_succ_le - --- Moved to Std -#align nat.succ_eq_one_add Nat.succ_eq_one_add - -theorem eq_of_lt_succ_of_not_lt {a b : ℕ} (h1 : a < b + 1) (h2 : ¬a < b) : a = b := - have h3 : a ≤ b := le_of_lt_succ h1 - Or.elim (eq_or_lt_of_not_lt h2) (fun h => h) fun h => absurd h (not_lt_of_ge h3) -#align nat.eq_of_lt_succ_of_not_lt Nat.eq_of_lt_succ_of_not_lt - -theorem eq_of_le_of_lt_succ {n m : ℕ} (h₁ : n ≤ m) (h₂ : m < n + 1) : m = n := - Nat.le_antisymm (le_of_succ_le_succ h₂) h₁ -#align nat.eq_of_le_of_lt_succ Nat.eq_of_le_of_lt_succ - --- Moved to Std -#align nat.one_add Nat.one_add - -theorem succ_pos' {n : ℕ} : 0 < succ n := - succ_pos n -#align nat.succ_pos' Nat.succ_pos' - --- Moved to Std -#align nat.succ_inj' Nat.succ_inj' - -theorem succ_injective : Function.Injective Nat.succ := fun _ _ => succ.inj -#align nat.succ_injective Nat.succ_injective - -theorem succ_ne_succ {n m : ℕ} : succ n ≠ succ m ↔ n ≠ m := - succ_injective.ne_iff -#align nat.succ_ne_succ Nat.succ_ne_succ - --- Porting note: no longer a simp lemma, as simp can prove this -theorem succ_succ_ne_one (n : ℕ) : n.succ.succ ≠ 1 := - succ_ne_succ.mpr n.succ_ne_zero -#align nat.succ_succ_ne_one Nat.succ_succ_ne_one - -@[simp] -theorem one_lt_succ_succ (n : ℕ) : 1 < n.succ.succ := - succ_lt_succ <| succ_pos n -#align nat.one_lt_succ_succ Nat.one_lt_succ_succ - --- Porting note: Nat.succ_le_succ_iff is in Std - -#align nat.max_succ_succ Nat.succ_max_succ - -theorem not_succ_lt_self {n : ℕ} : ¬succ n < n := - not_lt_of_ge (Nat.le_succ _) -#align nat.not_succ_lt_self Nat.not_succ_lt_self - -theorem lt_succ_iff {m n : ℕ} : m < succ n ↔ m ≤ n := - ⟨le_of_lt_succ, lt_succ_of_le⟩ -#align nat.lt_succ_iff Nat.lt_succ_iff - -theorem succ_le_iff {m n : ℕ} : succ m ≤ n ↔ m < n := - ⟨lt_of_succ_le, succ_le_of_lt⟩ -#align nat.succ_le_iff Nat.succ_le_iff - -theorem lt_iff_add_one_le {m n : ℕ} : m < n ↔ m + 1 ≤ n := by rw [succ_le_iff] -#align nat.lt_iff_add_one_le Nat.lt_iff_add_one_le - --- Just a restatement of `Nat.lt_succ_iff` using `+1`. -theorem lt_add_one_iff {a b : ℕ} : a < b + 1 ↔ a ≤ b := - lt_succ_iff -#align nat.lt_add_one_iff Nat.lt_add_one_iff - --- A flipped version of `lt_add_one_iff`. -theorem lt_one_add_iff {a b : ℕ} : a < 1 + b ↔ a ≤ b := by simp only [add_comm, lt_succ_iff] -#align nat.lt_one_add_iff Nat.lt_one_add_iff - --- This is true reflexively, by the definition of `≤` on ℕ, --- but it's still useful to have, to convince Lean to change the syntactic type. -theorem add_one_le_iff {a b : ℕ} : a + 1 ≤ b ↔ a < b := - Iff.refl _ -#align nat.add_one_le_iff Nat.add_one_le_iff - -theorem one_add_le_iff {a b : ℕ} : 1 + a ≤ b ↔ a < b := by simp only [add_comm, add_one_le_iff] -#align nat.one_add_le_iff Nat.one_add_le_iff - -theorem of_le_succ {n m : ℕ} (H : n ≤ m.succ) : n ≤ m ∨ n = m.succ := - H.lt_or_eq_dec.imp le_of_lt_succ id -#align nat.of_le_succ Nat.of_le_succ - -#align nat.succ_lt_succ_iff Nat.succ_lt_succ_iff - -theorem div_le_iff_le_mul_add_pred {m n k : ℕ} (n0 : 0 < n) : m / n ≤ k ↔ m ≤ n * k + (n - 1) := by - rw [← lt_succ_iff, div_lt_iff_lt_mul n0, succ_mul, mul_comm] - cases n - · cases n0 - - exact lt_succ_iff -#align nat.div_le_iff_le_mul_add_pred Nat.div_le_iff_le_mul_add_pred - -theorem two_lt_of_ne : ∀ {n}, n ≠ 0 → n ≠ 1 → n ≠ 2 → 2 < n - | 0, h, _, _ => (h rfl).elim - | 1, _, h, _ => (h rfl).elim - | 2, _, _, h => (h rfl).elim - -- Porting note: was `by decide` - | n + 3, _, _, _ => by rw [Nat.lt_iff_add_one_le]; convert Nat.le_add_left 3 n -#align nat.two_lt_of_ne Nat.two_lt_of_ne - -theorem forall_lt_succ {P : ℕ → Prop} {n : ℕ} : (∀ m < n + 1, P m) ↔ (∀ m < n, P m) ∧ P n := by - simp only [lt_succ_iff, Decidable.le_iff_eq_or_lt, forall_eq_or_imp, and_comm] -#align nat.forall_lt_succ Nat.forall_lt_succ - -theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by - rw [← not_iff_not] - push_neg - exact forall_lt_succ -#align nat.exists_lt_succ Nat.exists_lt_succ - -/-! ### `add` -/ - --- Sometimes a bare `Nat.add` or similar appears as a consequence of unfolding --- during pattern matching. These lemmas package them back up as typeclass --- mediated operations. -@[simp] -theorem add_def {a b : ℕ} : Nat.add a b = a + b := - rfl -#align nat.add_def Nat.add_def - -@[simp] -theorem mul_def {a b : ℕ} : Nat.mul a b = a * b := - rfl -#align nat.mul_def Nat.mul_def - -theorem exists_eq_add_of_le (h : m ≤ n) : ∃ k : ℕ, n = m + k := - ⟨n - m, (add_sub_of_le h).symm⟩ -#align nat.exists_eq_add_of_le Nat.exists_eq_add_of_le - -theorem exists_eq_add_of_le' (h : m ≤ n) : ∃ k : ℕ, n = k + m := - ⟨n - m, (Nat.sub_add_cancel h).symm⟩ -#align nat.exists_eq_add_of_le' Nat.exists_eq_add_of_le' - -theorem exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 := - ⟨n - (m + 1), by rw [Nat.add_right_comm, add_sub_of_le h]⟩ -#align nat.exists_eq_add_of_lt Nat.exists_eq_add_of_lt - -/-! ### `pred` -/ - -@[simp] -theorem add_succ_sub_one (n m : ℕ) : n + succ m - 1 = n + m := by rw [add_succ, Nat.add_one_sub_one] -#align nat.add_succ_sub_one Nat.add_succ_sub_one - -@[simp] -theorem succ_add_sub_one (n m : ℕ) : succ n + m - 1 = n + m := by rw [succ_add, Nat.add_one_sub_one] -#align nat.succ_add_sub_one Nat.succ_add_sub_one - -theorem pred_eq_sub_one (n : ℕ) : pred n = n - 1 := - rfl -#align nat.pred_eq_sub_one Nat.pred_eq_sub_one - -theorem pred_eq_of_eq_succ {m n : ℕ} (H : m = n.succ) : m.pred = n := by simp [H] -#align nat.pred_eq_of_eq_succ Nat.pred_eq_of_eq_succ - -@[simp] -theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by - cases n <;> constructor <;> rintro ⟨⟩ <;> rfl -#align nat.pred_eq_succ_iff Nat.pred_eq_succ_iff - -theorem pred_sub (n m : ℕ) : pred n - m = pred (n - m) := by - rw [← Nat.sub_one, Nat.sub_sub, one_add, sub_succ] -#align nat.pred_sub Nat.pred_sub - --- Moved to Std -#align nat.le_pred_of_lt Nat.le_pred_of_lt - -theorem le_of_pred_lt {m n : ℕ} : pred m < n → m ≤ n := - match m with - | 0 => le_of_lt - | _ + 1 => id -#align nat.le_of_pred_lt Nat.le_of_pred_lt - -theorem self_add_sub_one (n : ℕ) : n + (n - 1) = 2 * n - 1 := by - cases n - · rfl - · rw [two_mul] - convert (add_succ_sub_one (Nat.succ _) _).symm - -theorem sub_one_add_self (n : ℕ) : (n - 1) + n = 2 * n - 1 := - add_comm _ n ▸ self_add_sub_one n - -theorem self_add_pred (n : ℕ) : n + pred n = (2 * n).pred := - self_add_sub_one n - -theorem pred_add_self (n : ℕ) : pred n + n = (2 * n).pred := - sub_one_add_self n - -/-- This ensures that `simp` succeeds on `pred (n + 1) = n`. -/ -@[simp] -theorem pred_one_add (n : ℕ) : pred (1 + n) = n := by rw [add_comm, add_one, Nat.pred_succ] -#align nat.pred_one_add Nat.pred_one_add - -/-! ### `mul` -/ - - -theorem two_mul_ne_two_mul_add_one {n m} : 2 * n ≠ 2 * m + 1 := - mt (congr_arg (· % 2)) - (by rw [add_comm, add_mul_mod_self_left, mul_mod_right, mod_eq_of_lt] <;> simp) -#align nat.two_mul_ne_two_mul_add_one Nat.two_mul_ne_two_mul_add_one - -theorem mul_ne_mul_left {a b c : ℕ} (ha : 0 < a) : b * a ≠ c * a ↔ b ≠ c := - (mul_left_injective₀ ha.ne').ne_iff -#align nat.mul_ne_mul_left Nat.mul_ne_mul_left - -theorem mul_ne_mul_right {a b c : ℕ} (ha : 0 < a) : a * b ≠ a * c ↔ b ≠ c := - (mul_right_injective₀ ha.ne').ne_iff -#align nat.mul_ne_mul_right Nat.mul_ne_mul_right - -theorem mul_right_eq_self_iff {a b : ℕ} (ha : 0 < a) : a * b = a ↔ b = 1 := - suffices a * b = a * 1 ↔ b = 1 by rwa [mul_one] at this - mul_right_inj' ha.ne' -#align nat.mul_right_eq_self_iff Nat.mul_right_eq_self_iff - -theorem mul_left_eq_self_iff {a b : ℕ} (hb : 0 < b) : a * b = b ↔ a = 1 := by - rw [mul_comm, Nat.mul_right_eq_self_iff hb] -#align nat.mul_left_eq_self_iff Nat.mul_left_eq_self_iff - -theorem lt_succ_iff_lt_or_eq {n i : ℕ} : n < i.succ ↔ n < i ∨ n = i := - lt_succ_iff.trans Decidable.le_iff_lt_or_eq -#align nat.lt_succ_iff_lt_or_eq Nat.lt_succ_iff_lt_or_eq - -set_option push_neg.use_distrib true in -/-- The product of two natural numbers is greater than 1 if and only if - at least one of them is greater than 1 and both are positive. -/ -lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by - constructor <;> intro h - · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h' - obtain rfl | rfl | h' := h' - · simp at h - · simp at h - · exact (Nat.mul_le_mul h'.1 h'.2).not_lt h - · obtain hm | hn := h.2.2 - · exact Nat.mul_lt_mul hm h.2.1 Nat.zero_lt_one - · exact Nat.mul_lt_mul' h.1 hn h.1 - -/-! -### Recursion and induction principles - -This section is here due to dependencies -- the lemmas here require some of the lemmas -proved above, and some of the results in later sections depend on the definitions in this section. --/ - --- Porting note: The type ascriptions of these two theorems need to be changed, --- as mathport wrote a lambda that wasn't there in mathlib3, that prevents `simp` applying them. - -@[simp] -theorem rec_zero {C : ℕ → Sort u} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) : - Nat.rec h0 h 0 = h0 := - rfl -#align nat.rec_zero Nat.rec_zero - -@[simp] -theorem rec_add_one {C : ℕ → Sort u} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) (n : ℕ) : - Nat.rec h0 h (n + 1) = h n (Nat.rec h0 h n) := - rfl -#align nat.rec_add_one Nat.rec_add_one - -/-- Recursion starting at a non-zero number: given a map `C k → C (k+1)` for each `k`, -there is a map from `C n` to each `C m`, `n ≤ m`. For a version where the assumption is only made -when `k ≥ n`, see `leRecOn`. -/ -@[elab_as_elim] -def leRecOn {C : ℕ → Sort u} {n : ℕ} : ∀ {m : ℕ}, n ≤ m → (∀ {k}, C k → C (k + 1)) → C n → C m - | 0, H, _, x => Eq.recOn (Nat.eq_zero_of_le_zero H) x - | m + 1, H, next, x => - Or.by_cases (of_le_succ H) (fun h : n ≤ m => next <| leRecOn h (@next) x) - fun h : n = m + 1 => Eq.recOn h x -#align nat.le_rec_on Nat.leRecOn - -theorem leRecOn_self {C : ℕ → Sort u} {n} {h : n ≤ n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) : - (leRecOn h next x : C n) = x := by - cases n <;> unfold leRecOn Eq.recOn - · simp - · unfold Or.by_cases - rw [dif_neg (Nat.not_succ_le_self _)] -#align nat.le_rec_on_self Nat.leRecOn_self - -theorem leRecOn_succ {C : ℕ → Sort u} {n m} (h1 : n ≤ m) {h2 : n ≤ m + 1} {next} (x : C n) : - (leRecOn h2 (@next) x : C (m + 1)) = next (leRecOn h1 (@next) x : C m) := by - conv => - lhs - rw [leRecOn, Or.by_cases, dif_pos h1] -#align nat.le_rec_on_succ Nat.leRecOn_succ - -theorem leRecOn_succ' {C : ℕ → Sort u} {n} {h : n ≤ n + 1} {next : ∀ {k}, C k → C (k + 1)} - (x : C n) : - (leRecOn h next x : C (n + 1)) = next x := by rw [leRecOn_succ (le_refl n), leRecOn_self] -#align nat.le_rec_on_succ' Nat.leRecOn_succ' - -theorem leRecOn_trans {C : ℕ → Sort u} {n m k} (hnm : n ≤ m) (hmk : m ≤ k) {next} (x : C n) : - (leRecOn (le_trans hnm hmk) (@next) x : C k) = leRecOn hmk (@next) (leRecOn hnm (@next) x) := by - induction' hmk with k hmk ih - · rw [leRecOn_self] - - rw [leRecOn_succ (le_trans hnm hmk), ih, leRecOn_succ] -#align nat.le_rec_on_trans Nat.leRecOn_trans - -theorem leRecOn_succ_left {C : ℕ → Sort u} {n m} (h1 : n ≤ m) (h2 : n + 1 ≤ m) - {next : ∀ {k}, C k → C (k + 1)} (x : C n) : - (leRecOn h2 next (next x) : C m) = (leRecOn h1 next x : C m) := by - rw [Subsingleton.elim h1 (le_trans (le_succ n) h2), leRecOn_trans (le_succ n) h2, leRecOn_succ'] -#align nat.le_rec_on_succ_left Nat.leRecOn_succ_left - -theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1)) - (Hnext : ∀ n, Function.Injective (@next n)) : - Function.Injective (@leRecOn C n m hnm next) := by - induction' hnm with m hnm ih - · intro x y H - rwa [leRecOn_self, leRecOn_self] at H - - intro x y H - rw [leRecOn_succ hnm, leRecOn_succ hnm] at H - exact ih (Hnext _ H) -#align nat.le_rec_on_injective Nat.leRecOn_injective - -theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1)) - (Hnext : ∀ n, Function.Surjective (@next n)) : - Function.Surjective (@leRecOn C n m hnm next) := by - induction' hnm with m hnm ih - · intro x - use x - rw [leRecOn_self] - - intro x - rcases Hnext _ x with ⟨w, rfl⟩ - rcases ih w with ⟨x, rfl⟩ - use x - rw [leRecOn_succ] -#align nat.le_rec_on_surjective Nat.leRecOn_surjective +/-! ### Extra lemmas -/ -/-- Recursion principle based on `<`. -/ -@[elab_as_elim] -protected def strongRec' {p : ℕ → Sort u} (H : ∀ n, (∀ m, m < n → p m) → p n) : ∀ n : ℕ, p n - | n => H n fun m _ => Nat.strongRec' H m -#align nat.strong_rec' Nat.strongRec' - -/-- Recursion principle based on `<` applied to some natural number. -/ -@[elab_as_elim] -def strongRecOn' {P : ℕ → Sort*} (n : ℕ) (h : ∀ n, (∀ m, m < n → P m) → P n) : P n := - Nat.strongRec' h n -#align nat.strong_rec_on' Nat.strongRecOn' - -theorem strongRecOn'_beta {P : ℕ → Sort*} {h} {n : ℕ} : - (strongRecOn' n h : P n) = h n fun m _ => (strongRecOn' m h : P m) := by - simp only [strongRecOn'] - rw [Nat.strongRec'] -#align nat.strong_rec_on_beta' Nat.strongRecOn'_beta - -/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`. -To use in an induction proof, the syntax is `induction n, hn using Nat.le_induction` (or the same -for `induction'`). -/ -@[elab_as_elim] -theorem le_induction {m} {P : ∀ (n : Nat) (_ : m ≤ n), Prop} (base : P m le_rfl) - (succ : ∀ (n : Nat) (hn : m ≤ n), P n hn → P (n + 1) (hn.trans <| Nat.le_succ _)) : - ∀ (n : Nat) (hn : m ≤ n), P n hn := by - apply Nat.le.rec - · exact base - · intros n hn - apply succ n hn -#align nat.le_induction Nat.le_induction - -/-- Decreasing induction: if `P (k+1)` implies `P k`, then `P n` implies `P m` for all `m ≤ n`. -Also works for functions to `Sort*`. For a version assuming only the assumption for `k < n`, see -`decreasing_induction'`. -/ -@[elab_as_elim] -def decreasingInduction {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n) - (hP : P n) : P m := - leRecOn mn (fun {k} ih hsk => ih <| h k hsk) (fun h => h) hP -#align nat.decreasing_induction Nat.decreasingInduction - -@[simp] -theorem decreasingInduction_self {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {n : ℕ} (nn : n ≤ n) - (hP : P n) : - (decreasingInduction h nn hP : P n) = hP := by - dsimp only [decreasingInduction] - rw [leRecOn_self] -#align nat.decreasing_induction_self Nat.decreasingInduction_self - -theorem decreasingInduction_succ {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n) - (msn : m ≤ n + 1) (hP : P (n + 1)) : - (decreasingInduction h msn hP : P m) = decreasingInduction h mn (h n hP) := by - dsimp only [decreasingInduction] - rw [leRecOn_succ] -#align nat.decreasing_induction_succ Nat.decreasingInduction_succ - -@[simp] -theorem decreasingInduction_succ' {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m : ℕ} - (msm : m ≤ m + 1) (hP : P (m + 1)) : (decreasingInduction h msm hP : P m) = h m hP := by - dsimp only [decreasingInduction] - rw [leRecOn_succ'] -#align nat.decreasing_induction_succ' Nat.decreasingInduction_succ' - -theorem decreasingInduction_trans {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n k : ℕ} - (mn : m ≤ n) (nk : n ≤ k) (hP : P k) : - (decreasingInduction h (le_trans mn nk) hP : P m) = - decreasingInduction h mn (decreasingInduction h nk hP) := by - induction' nk with k nk ih - · rw [decreasingInduction_self] - · rw [decreasingInduction_succ h (le_trans mn nk), ih, decreasingInduction_succ] -#align nat.decreasing_induction_trans Nat.decreasingInduction_trans - -theorem decreasingInduction_succ_left {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} - (smn : m + 1 ≤ n) (mn : m ≤ n) (hP : P n) : - (decreasingInduction h mn hP : P m) = h m (decreasingInduction h smn hP) := by - rw [Subsingleton.elim mn (le_trans (le_succ m) smn), decreasingInduction_trans, - decreasingInduction_succ'] - apply Nat.le_succ -#align nat.decreasing_induction_succ_left Nat.decreasingInduction_succ_left - -/-- Given `P : ℕ → ℕ → Sort*`, if for all `a b : ℕ` we can extend `P` from the rectangle -strictly below `(a,b)` to `P a b`, then we have `P n m` for all `n m : ℕ`. -Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible, -since this produces equation lemmas. -/ -@[elab_as_elim] -def strongSubRecursion {P : ℕ → ℕ → Sort*} (H : ∀ a b, (∀ x y, x < a → y < b → P x y) → P a b) : - ∀ n m : ℕ, P n m - | n, m => H n m fun x y _ _ => strongSubRecursion H x y -#align nat.strong_sub_recursion Nat.strongSubRecursion - -/-- Given `P : ℕ → ℕ → Sort*`, if we have `P i 0` and `P 0 i` for all `i : ℕ`, -and for any `x y : ℕ` we can extend `P` from `(x,y+1)` and `(x+1,y)` to `(x+1,y+1)` -then we have `P n m` for all `n m : ℕ`. -Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible, -since this produces equation lemmas. -/ -@[elab_as_elim] -def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ a : ℕ, P a 0) (H0b : ∀ b : ℕ, P 0 b) - (H : ∀ x y : ℕ, P x y.succ → P x.succ y → P x.succ y.succ) : ∀ n m : ℕ, P n m - | a, 0 => Ha0 a - | 0, b => H0b b - | Nat.succ a, Nat.succ b => H _ _ (pincerRecursion Ha0 H0b H _ _) (pincerRecursion Ha0 H0b H _ _) -termination_by pincerRecursion Ha0 Hab H n m => n + m -#align nat.pincer_recursion Nat.pincerRecursion - -/-- Recursion starting at a non-zero number: given a map `C k → C (k+1)` for each `k ≥ n`, -there is a map from `C n` to each `C m`, `n ≤ m`. -/ -@[elab_as_elim] -def leRecOn' {C : ℕ → Sort*} {n : ℕ} : - ∀ {m : ℕ}, n ≤ m → (∀ ⦃k⦄, n ≤ k → C k → C (k + 1)) → C n → C m - | 0, H, _, x => Eq.recOn (Nat.eq_zero_of_le_zero H) x - | m + 1, H, next, x => - Or.by_cases (of_le_succ H) (fun h : n ≤ m => next h <| leRecOn' h next x) - fun h : n = m + 1 => Eq.recOn h x -#align nat.le_rec_on' Nat.leRecOn' - -/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`. -Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/ -@[elab_as_elim] -def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k) - (mn : m ≤ n) (hP : P n) : - P m := by - revert h hP - refine' leRecOn' mn _ _ - · intro n mn ih h hP - apply ih - · exact fun k hk => h k (Nat.lt.step hk) - · exact h n (lt_succ_self n) mn hP - · intro _ hP - exact hP -#align nat.decreasing_induction' Nat.decreasingInduction' - -/-! ### `div` -/ - -attribute [simp] Nat.div_self - -/-- A version of `Nat.div_lt_self` using successors, rather than additional hypotheses. -/ -theorem div_lt_self' (n b : ℕ) : (n + 1) / (b + 2) < n + 1 := - Nat.div_lt_self (Nat.succ_pos n) (Nat.succ_lt_succ (Nat.succ_pos _)) -#align nat.div_lt_self' Nat.div_lt_self' - -theorem le_div_iff_mul_le' {x y : ℕ} {k : ℕ} (k0 : 0 < k) : x ≤ y / k ↔ x * k ≤ y := - le_div_iff_mul_le k0 -#align nat.le_div_iff_mul_le' Nat.le_div_iff_mul_le' - -theorem div_lt_iff_lt_mul' {x y : ℕ} {k : ℕ} (k0 : 0 < k) : x / k < y ↔ x < y * k := - lt_iff_lt_of_le_iff_le <| le_div_iff_mul_le' k0 -#align nat.div_lt_iff_lt_mul' Nat.div_lt_iff_lt_mul' - -theorem one_le_div_iff {a b : ℕ} (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by - rw [le_div_iff_mul_le hb, one_mul] -#align nat.one_le_div_iff Nat.one_le_div_iff - -theorem div_lt_one_iff {a b : ℕ} (hb : 0 < b) : a / b < 1 ↔ a < b := - lt_iff_lt_of_le_iff_le <| one_le_div_iff hb -#align nat.div_lt_one_iff Nat.div_lt_one_iff - -protected theorem div_le_div_right {n m : ℕ} (h : n ≤ m) {k : ℕ} : n / k ≤ m / k := - ((Nat.eq_zero_or_pos k).elim fun k0 => by simp [k0]) fun hk => - (le_div_iff_mul_le' hk).2 <| le_trans (Nat.div_mul_le_self _ _) h -#align nat.div_le_div_right Nat.div_le_div_right - -theorem lt_of_div_lt_div {m n k : ℕ} : m / k < n / k → m < n := - lt_imp_lt_of_le_imp_le fun h => Nat.div_le_div_right h -#align nat.lt_of_div_lt_div Nat.lt_of_div_lt_div - -protected theorem div_pos {a b : ℕ} (hba : b ≤ a) (hb : 0 < b) : 0 < a / b := - Nat.pos_of_ne_zero fun h => - lt_irrefl a - (calc - a = a % b := by simpa [h] using (mod_add_div a b).symm - _ < b := Nat.mod_lt a hb - _ ≤ a := hba - ) -#align nat.div_pos Nat.div_pos - -theorem lt_mul_of_div_lt {a b c : ℕ} (h : a / c < b) (w : 0 < c) : a < b * c := - lt_of_not_ge <| not_le_of_gt h ∘ (Nat.le_div_iff_mul_le w).2 -#align nat.lt_mul_of_div_lt Nat.lt_mul_of_div_lt - -theorem mul_div_le_mul_div_assoc (a b c : ℕ) : a * (b / c) ≤ a * b / c := - if hc0 : c = 0 then by simp [hc0] - else - (Nat.le_div_iff_mul_le (Nat.pos_of_ne_zero hc0)).2 - (by rw [mul_assoc]; exact Nat.mul_le_mul_left _ (Nat.div_mul_le_self _ _)) -#align nat.mul_div_le_mul_div_assoc Nat.mul_div_le_mul_div_assoc - -protected theorem eq_mul_of_div_eq_right {a b c : ℕ} (H1 : b ∣ a) (H2 : a / b = c) : a = b * c := by - rw [← H2, Nat.mul_div_cancel' H1] -#align nat.eq_mul_of_div_eq_right Nat.eq_mul_of_div_eq_right - -protected theorem div_eq_iff_eq_mul_right {a b c : ℕ} (H : 0 < b) (H' : b ∣ a) : - a / b = c ↔ a = b * c := - ⟨Nat.eq_mul_of_div_eq_right H', Nat.div_eq_of_eq_mul_right H⟩ -#align nat.div_eq_iff_eq_mul_right Nat.div_eq_iff_eq_mul_right - -protected theorem div_eq_iff_eq_mul_left {a b c : ℕ} (H : 0 < b) (H' : b ∣ a) : - a / b = c ↔ a = c * b := by - rw [mul_comm] - exact Nat.div_eq_iff_eq_mul_right H H' -#align nat.div_eq_iff_eq_mul_left Nat.div_eq_iff_eq_mul_left - -protected theorem eq_mul_of_div_eq_left {a b c : ℕ} (H1 : b ∣ a) (H2 : a / b = c) : a = c * b := by - rw [mul_comm, Nat.eq_mul_of_div_eq_right H1 H2] -#align nat.eq_mul_of_div_eq_left Nat.eq_mul_of_div_eq_left - -protected theorem mul_div_cancel_left' {a b : ℕ} (Hd : a ∣ b) : a * (b / a) = b := by - rw [mul_comm, Nat.div_mul_cancel Hd] -#align nat.mul_div_cancel_left' Nat.mul_div_cancel_left' - -#align nat.mul_div_mul_left Nat.mul_div_mul_left -#align nat.mul_div_mul_right Nat.mul_div_mul_right - -theorem lt_div_mul_add {a b : ℕ} (hb : 0 < b) : a < a / b * b + b := by - rw [← Nat.succ_mul, ← Nat.div_lt_iff_lt_mul hb] - exact Nat.lt_succ_self _ -#align nat.lt_div_mul_add Nat.lt_div_mul_add - -@[simp] -protected theorem div_left_inj {a b d : ℕ} (hda : d ∣ a) (hdb : d ∣ b) : a / d = b / d ↔ a = b := by - refine ⟨fun h => ?_, congr_arg fun n => n / d⟩ - rw [← Nat.mul_div_cancel' hda, ← Nat.mul_div_cancel' hdb, h] -#align nat.div_left_inj Nat.div_left_inj - -theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) : - (m / n) * (k / l) = (m * k) / (n * l) := by - obtain ⟨x, rfl⟩ := hmn - obtain ⟨y, rfl⟩ := hkl - rcases n.eq_zero_or_pos with rfl | hn - · simp - rcases l.eq_zero_or_pos with rfl | hl - · simp - rw [Nat.mul_div_cancel_left _ hn, Nat.mul_div_cancel_left _ hl, mul_assoc n, Nat.mul_left_comm x, - ← mul_assoc n, Nat.mul_div_cancel_left _ (Nat.mul_pos hn hl)] -#align nat.div_mul_div_comm Nat.div_mul_div_comm - -protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by - rcases c.eq_zero_or_pos with rfl | hc - · simp - rcases a.eq_zero_or_pos with rfl | ha - · simp [Nat.zero_pow hc] - refine (Nat.div_eq_of_eq_mul_right (pos_pow_of_pos c ha) ?_).symm - rw [← Nat.mul_pow, Nat.mul_div_cancel_left' h] - -/-! ### `mod`, `dvd` -/ - - -theorem mod_eq_iff_lt {a b : ℕ} (h : b ≠ 0) : a % b = a ↔ a < b := by - cases b - contradiction - exact ⟨fun h => h.ge.trans_lt (mod_lt _ (succ_pos _)), mod_eq_of_lt⟩ -#align nat.mod_eq_iff_lt Nat.mod_eq_iff_lt - -@[simp] -theorem mod_succ_eq_iff_lt {a b : ℕ} : a % b.succ = a ↔ a < b.succ := - mod_eq_iff_lt (succ_ne_zero _) -#align nat.mod_succ_eq_iff_lt Nat.mod_succ_eq_iff_lt - -@[simp] -theorem mod_succ (n : ℕ) : n % n.succ = n := - Nat.mod_eq_of_lt (Nat.lt_succ_self _) - --- Porting note `Nat.div_add_mod` is now in core. - -theorem mod_add_div' (m k : ℕ) : m % k + m / k * k = m := by - rw [mul_comm] - exact mod_add_div _ _ -#align nat.mod_add_div' Nat.mod_add_div' - -theorem div_add_mod' (m k : ℕ) : m / k * k + m % k = m := by - rw [mul_comm] - exact div_add_mod _ _ -#align nat.div_add_mod' Nat.div_add_mod' - -/-- See also `Nat.divModEquiv` for a similar statement as an `Equiv`. -/ -protected theorem div_mod_unique {n k m d : ℕ} (h : 0 < k) : - n / k = d ∧ n % k = m ↔ m + k * d = n ∧ m < k := - ⟨fun ⟨e₁, e₂⟩ => e₁ ▸ e₂ ▸ ⟨mod_add_div _ _, mod_lt _ h⟩, fun ⟨h₁, h₂⟩ => - h₁ ▸ by - rw [add_mul_div_left _ _ h, add_mul_mod_self_left] - simp [div_eq_of_lt, mod_eq_of_lt, h₂]⟩ -#align nat.div_mod_unique Nat.div_mod_unique - -protected theorem dvd_add_left {k m n : ℕ} (h : k ∣ n) : k ∣ m + n ↔ k ∣ m := - (Nat.dvd_add_iff_left h).symm -#align nat.dvd_add_left Nat.dvd_add_left - -protected theorem dvd_add_right {k m n : ℕ} (h : k ∣ m) : k ∣ m + n ↔ k ∣ n := - (Nat.dvd_add_iff_right h).symm -#align nat.dvd_add_right Nat.dvd_add_right - -protected theorem mul_dvd_mul_iff_left {a b c : ℕ} (ha : 0 < a) : a * b ∣ a * c ↔ b ∣ c := - exists_congr fun d => by rw [mul_assoc, mul_right_inj' ha.ne'] -#align nat.mul_dvd_mul_iff_left Nat.mul_dvd_mul_iff_left - -protected theorem mul_dvd_mul_iff_right {a b c : ℕ} (hc : 0 < c) : a * c ∣ b * c ↔ a ∣ b := - exists_congr fun d => by rw [Nat.mul_right_comm, mul_left_inj' hc.ne'] -#align nat.mul_dvd_mul_iff_right Nat.mul_dvd_mul_iff_right - -#align nat.dvd_one Nat.dvd_one - -@[simp] -theorem mod_mod_of_dvd (n : Nat) {m k : Nat} (h : m ∣ k) : n % k % m = n % m := by - conv_rhs => rw [← mod_add_div n k] - rcases h with ⟨t, rfl⟩ - rw [mul_assoc, add_mul_mod_self_left] -#align nat.mod_mod_of_dvd Nat.mod_mod_of_dvd - --- Moved to Std -#align nat.mod_mod Nat.mod_mod -#align nat.mod_add_mod Nat.mod_add_mod -#align nat.add_mod_mod Nat.add_mod_mod -#align nat.add_mod Nat.add_mod - -theorem add_mod_eq_add_mod_right {m n k : ℕ} (i : ℕ) (H : m % n = k % n) : - (m + i) % n = (k + i) % n := by - rw [← mod_add_mod, ← mod_add_mod k, H] -#align nat.add_mod_eq_add_mod_right Nat.add_mod_eq_add_mod_right - -theorem add_mod_eq_add_mod_left {m n k : ℕ} (i : ℕ) (H : m % n = k % n) : - (i + m) % n = (i + k) % n := by - rw [add_comm, add_mod_eq_add_mod_right _ H, add_comm] -#align nat.add_mod_eq_add_mod_left Nat.add_mod_eq_add_mod_left - --- Moved to Std -#align nat.mul_mod Nat.mul_mod - -theorem mul_dvd_of_dvd_div {a b c : ℕ} (hab : c ∣ b) (h : a ∣ b / c) : c * a ∣ b := - have h1 : ∃ d, b / c = a * d := h - let ⟨d, hd⟩ := h1 - have h3 : b = a * d * c := Nat.eq_mul_of_div_eq_left hab hd - -- Porting note: was `cc` - show ∃ d, b = c * a * d from ⟨d, by rwa [mul_comm, ← mul_assoc] at h3⟩ -#align nat.mul_dvd_of_dvd_div Nat.mul_dvd_of_dvd_div - -theorem eq_of_dvd_of_div_eq_one {a b : ℕ} (w : a ∣ b) (h : b / a = 1) : a = b := by - rw [← Nat.div_mul_cancel w, h, one_mul] -#align nat.eq_of_dvd_of_div_eq_one Nat.eq_of_dvd_of_div_eq_one - -theorem eq_zero_of_dvd_of_div_eq_zero {a b : ℕ} (w : a ∣ b) (h : b / a = 0) : b = 0 := by - rw [← Nat.div_mul_cancel w, h, zero_mul] -#align nat.eq_zero_of_dvd_of_div_eq_zero Nat.eq_zero_of_dvd_of_div_eq_zero - -theorem div_le_div_left {a b c : ℕ} (h₁ : c ≤ b) (h₂ : 0 < c) : a / b ≤ a / c := - (Nat.le_div_iff_mul_le h₂).2 <| le_trans (Nat.mul_le_mul_left _ h₁) (div_mul_le_self _ _) -#align nat.div_le_div_left Nat.div_le_div_left - -theorem lt_iff_le_pred : ∀ {m n : ℕ}, 0 < n → (m < n ↔ m ≤ n - 1) - | _, _ + 1, _ => lt_succ_iff -#align nat.lt_iff_le_pred Nat.lt_iff_le_pred - --- Moved to Std -#align nat.mul_div_le Nat.mul_div_le - -theorem lt_mul_div_succ (m : ℕ) {n : ℕ} (n0 : 0 < n) : m < n * (m / n + 1) := by - rw [mul_comm, ← Nat.div_lt_iff_lt_mul' n0] - exact lt_succ_self _ -#align nat.lt_mul_div_succ Nat.lt_mul_div_succ - --- TODO: Std4 claimed this name but flipped the order of multiplication -theorem mul_add_mod' (a b c : ℕ) : (a * b + c) % b = c % b := by rw [mul_comm, Nat.mul_add_mod] -#align nat.mul_add_mod Nat.mul_add_mod' - -theorem mul_add_mod_of_lt {a b c : ℕ} (h : c < b) : (a * b + c) % b = c := by - rw [Nat.mul_add_mod', Nat.mod_eq_of_lt h] -#align nat.mul_add_mod_of_lt Nat.mul_add_mod_of_lt - -theorem pred_eq_self_iff {n : ℕ} : n.pred = n ↔ n = 0 := by - cases n <;> simp [(Nat.succ_ne_self _).symm] -#align nat.pred_eq_self_iff Nat.pred_eq_self_iff - -/-! ### `find` -/ - - -section Find - -variable {p q : ℕ → Prop} [DecidablePred p] [DecidablePred q] - -theorem find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n < m, ¬p n := by - constructor - · rintro rfl - exact ⟨Nat.find_spec h, fun _ => Nat.find_min h⟩ - · rintro ⟨hm, hlt⟩ - exact le_antisymm (Nat.find_min' h hm) (not_lt.1 <| imp_not_comm.1 (hlt _) <| Nat.find_spec h) -#align nat.find_eq_iff Nat.find_eq_iff - -@[simp] -theorem find_lt_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h < n ↔ ∃ m < n, p m := - ⟨fun h2 => ⟨Nat.find h, h2, Nat.find_spec h⟩, - fun ⟨_, hmn, hm⟩ => (Nat.find_min' h hm).trans_lt hmn⟩ -#align nat.find_lt_iff Nat.find_lt_iff - -@[simp] -theorem find_le_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h ≤ n ↔ ∃ m ≤ n, p m := by - simp only [exists_prop, ← lt_succ_iff, find_lt_iff] -#align nat.find_le_iff Nat.find_le_iff - -@[simp] -theorem le_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n ≤ Nat.find h ↔ ∀ m < n, ¬p m := by - simp_rw [← not_lt, find_lt_iff, not_exists, not_and] -#align nat.le_find_iff Nat.le_find_iff - -@[simp] -theorem lt_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n < Nat.find h ↔ ∀ m ≤ n, ¬p m := by - simp only [← succ_le_iff, le_find_iff, succ_le_succ_iff] -#align nat.lt_find_iff Nat.lt_find_iff - -@[simp] -theorem find_eq_zero (h : ∃ n : ℕ, p n) : Nat.find h = 0 ↔ p 0 := by simp [find_eq_iff] -#align nat.find_eq_zero Nat.find_eq_zero - -theorem find_mono (h : ∀ n, q n → p n) {hp : ∃ n, p n} {hq : ∃ n, q n} : - Nat.find hp ≤ Nat.find hq := - Nat.find_min' _ (h _ (Nat.find_spec hq)) -#align nat.find_mono Nat.find_mono - -theorem find_le {h : ∃ n, p n} (hn : p n) : Nat.find h ≤ n := - (Nat.find_le_iff _ _).2 ⟨n, le_rfl, hn⟩ -#align nat.find_le Nat.find_le - -theorem find_comp_succ (h₁ : ∃ n, p n) (h₂ : ∃ n, p (n + 1)) (h0 : ¬p 0) : - Nat.find h₁ = Nat.find h₂ + 1 := by - refine' (find_eq_iff _).2 ⟨Nat.find_spec h₂, fun n hn => _⟩ - cases' n with n - exacts [h0, @Nat.find_min (fun n => p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)] -#align nat.find_comp_succ Nat.find_comp_succ - -end Find - -/-! ### `find_greatest` -/ - - -section FindGreatest - -/-- `find_greatest P b` is the largest `i ≤ bound` such that `P i` holds, or `0` if no such `i` -exists -/ -protected def findGreatest (P : ℕ → Prop) [DecidablePred P] : ℕ → ℕ - | 0 => 0 - | n + 1 => if P (n + 1) then n + 1 else Nat.findGreatest P n -#align nat.find_greatest Nat.findGreatest - -variable {P Q : ℕ → Prop} [DecidablePred P] {b : ℕ} - -@[simp] -theorem findGreatest_zero : Nat.findGreatest P 0 = 0 := - rfl -#align nat.find_greatest_zero Nat.findGreatest_zero - -theorem findGreatest_succ (n : ℕ) : - Nat.findGreatest P (n + 1) = if P (n + 1) then n + 1 else Nat.findGreatest P n := - rfl -#align nat.find_greatest_succ Nat.findGreatest_succ - -@[simp] -theorem findGreatest_eq : ∀ {b}, P b → Nat.findGreatest P b = b - | 0, _ => rfl - | n + 1, h => by simp [Nat.findGreatest, h] -#align nat.find_greatest_eq Nat.findGreatest_eq - -@[simp] -theorem findGreatest_of_not (h : ¬P (b + 1)) : - Nat.findGreatest P (b + 1) = Nat.findGreatest P b := by - simp [Nat.findGreatest, h] -#align nat.find_greatest_of_not Nat.findGreatest_of_not - -end FindGreatest - -/-! ### decidability of predicates -/ - --- To work around lean4#2552, we use `match` instead of `if/casesOn` with decidable instances. -instance decidableBallLT : - ∀ (n : Nat) (P : ∀ k, k < n → Prop) [∀ n h, Decidable (P n h)], Decidable (∀ n h, P n h) -| 0, _, _ => isTrue fun _ => (by cases ·) -| (n+1), P, H => - match decidableBallLT n (P · <| lt_succ_of_lt ·) with - | isFalse h => isFalse (h fun _ _ => · _ _) - | isTrue h => - match H n Nat.le.refl with - | isFalse p => isFalse (p <| · _ _) - | isTrue p => isTrue fun _ h' => (Nat.le_of_lt_succ h').lt_or_eq_dec.elim (h _) (· ▸ p) -#align nat.decidable_ball_lt Nat.decidableBallLT - --- To verify we don't have a regression on the speed, we put a difficult example. --- any regression should take a huge amount of heartbeats -- we are currently at 187621. --- For reference, the instance using `casesOn` took 44544 for 4; this one takes 1299 for 4. -example : ∀ a, a < 25 → ∀ b, b < 25 → ∀ c, c < 25 → a ^ 2 + b ^ 2 + c ^ 2 ≠ 7 := by decide - -instance decidableForallFin {n : ℕ} (P : Fin n → Prop) [DecidablePred P] : - Decidable (∀ i, P i) := - decidable_of_iff (∀ k h, P ⟨k, h⟩) ⟨fun a ⟨k, h⟩ => a k h, fun a k h => a ⟨k, h⟩⟩ -#align nat.decidable_forall_fin Nat.decidableForallFin +protected lemma nsmul_eq_mul (m n : ℕ) : m • n = m * n := rfl +#align nat.nsmul_eq_mul Nat.nsmul_eq_mul -instance decidableBallLe (n : ℕ) (P : ∀ k ≤ n, Prop) [∀ n h, Decidable (P n h)] : - Decidable (∀ n h, P n h) := - decidable_of_iff (∀ (k) (h : k < succ n), P k (le_of_lt_succ h)) - ⟨fun a k h => a k (lt_succ_of_le h), fun a k _ => a k _⟩ -#align nat.decidable_ball_le Nat.decidableBallLe +section Multiplicative -instance decidableExistsLT {P : ℕ → Prop} [h : DecidablePred P] : - DecidablePred fun n => ∃ m : ℕ, m < n ∧ P m - | 0 => isFalse (by simp) - | n + 1 => - @decidable_of_decidable_of_iff _ _ (@instDecidableOr _ _ (decidableExistsLT n) (h n)) - (by simp only [lt_succ_iff_lt_or_eq, or_and_right, exists_or, exists_eq_left]; apply Iff.refl) -#align nat.decidable_exists_lt Nat.decidableExistsLT +lemma toAdd_pow (a : Multiplicative ℕ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b := mul_comm _ _ +#align nat.to_add_pow Nat.toAdd_pow -instance decidableExistsLe {P : ℕ → Prop} [DecidablePred P] : - DecidablePred fun n => ∃ m : ℕ, m ≤ n ∧ P m := - fun n => decidable_of_iff (∃ m, m < n + 1 ∧ P m) - (exists_congr fun _ => and_congr_left' lt_succ_iff) -#align nat.decidable_exists_le Nat.decidableExistsLe +@[simp] lemma ofAdd_mul (a b : ℕ) : ofAdd (a * b) = ofAdd a ^ b := (toAdd_pow _ _).symm +#align nat.of_add_mul Nat.ofAdd_mul +end Multiplicative end Nat diff --git a/Mathlib/Data/Nat/Bits.lean b/Mathlib/Data/Nat/Bits.lean index e4ce421787d94..adb59a59c105f 100644 --- a/Mathlib/Data/Nat/Bits.lean +++ b/Mathlib/Data/Nat/Bits.lean @@ -7,6 +7,7 @@ import Mathlib.Init.Data.Nat.Bitwise import Mathlib.Init.Data.List.Basic import Mathlib.Algebra.Group.Basic import Mathlib.Data.Nat.Basic +import Mathlib.Tactic.Convert #align_import data.nat.bits from "leanprover-community/mathlib"@"d012cd09a9b256d870751284dd6a29882b0be105" diff --git a/Mathlib/Data/Nat/Bitwise.lean b/Mathlib/Data/Nat/Bitwise.lean index 2223d72162f89..84178596552fc 100644 --- a/Mathlib/Data/Nat/Bitwise.lean +++ b/Mathlib/Data/Nat/Bitwise.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel, Alex Keizer -/ import Mathlib.Data.List.Basic -import Mathlib.Data.Nat.Size +import Mathlib.Data.Nat.Bits +import Mathlib.Data.Nat.Pow import Mathlib.Tactic.Set #align_import data.nat.bitwise from "leanprover-community/mathlib"@"6afc9b06856ad973f6a2619e3e8a0a8d537a58f2" diff --git a/Mathlib/Data/Nat/Cast/Basic.lean b/Mathlib/Data/Nat/Cast/Basic.lean index 309c993b28bac..35c4a9b799eba 100644 --- a/Mathlib/Data/Nat/Cast/Basic.lean +++ b/Mathlib/Data/Nat/Cast/Basic.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Divisibility.Basic -import Mathlib.Algebra.Group.Hom.Basic +import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.TypeTags import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Data.Nat.Basic @@ -26,6 +27,8 @@ the natural numbers into an additive monoid with a one (`Nat.cast`). -- where `simp [map_zero]` should suffice. (Similarly for `map_one`.) -- See https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/simp.20regression.20with.20MonoidHomClass +open Additive Multiplicative + variable {α β : Type*} namespace Nat @@ -43,29 +46,49 @@ theorem coe_castAddMonoidHom [AddMonoidWithOne α] : (castAddMonoidHom α : ℕ rfl #align nat.coe_cast_add_monoid_hom Nat.coe_castAddMonoidHom -@[simp, norm_cast] -theorem cast_mul [NonAssocSemiring α] (m n : ℕ) : ((m * n : ℕ) : α) = m * n := by +section NonAssocSemiring +variable [NonAssocSemiring α] + +@[simp, norm_cast] lemma cast_mul (m n : ℕ) : ((m * n : ℕ) : α) = m * n := by induction n <;> simp [mul_succ, mul_add, *] #align nat.cast_mul Nat.cast_mul +variable (α) in /-- `Nat.cast : ℕ → α` as a `RingHom` -/ -def castRingHom (α : Type*) [NonAssocSemiring α] : ℕ →+* α := +def castRingHom : ℕ →+* α := { castAddMonoidHom α with toFun := Nat.cast, map_one' := cast_one, map_mul' := cast_mul } #align nat.cast_ring_hom Nat.castRingHom -@[simp] -theorem coe_castRingHom [NonAssocSemiring α] : (castRingHom α : ℕ → α) = Nat.cast := - rfl +@[simp, norm_cast] lemma coe_castRingHom : (castRingHom α : ℕ → α) = Nat.cast := rfl #align nat.coe_cast_ring_hom Nat.coe_castRingHom +lemma _root_.nsmul_eq_mul' (a : α) (n : ℕ) : n • a = a * n := by + induction' n with n ih <;> [rw [zero_nsmul, Nat.cast_zero, mul_zero]; + rw [succ_nsmul', ih, Nat.cast_succ, mul_add, mul_one]] +#align nsmul_eq_mul' nsmul_eq_mul' +@[simp] lemma _root_.nsmul_eq_mul (n : ℕ) (a : α) : n • a = n * a := by + induction' n with n ih <;> [rw [zero_nsmul, Nat.cast_zero, zero_mul]; + rw [succ_nsmul', ih, Nat.cast_succ, add_mul, one_mul]] +#align nsmul_eq_mul nsmul_eq_mul + +end NonAssocSemiring + +section Semiring +variable [Semiring α] {m n : ℕ} + +@[simp, norm_cast] +lemma cast_pow (m : ℕ) : ∀ n : ℕ, ↑(m ^ n) = (m ^ n : α) + | 0 => by simp + | n + 1 => by rw [_root_.pow_succ', _root_.pow_succ', cast_mul, cast_pow m n] +#align nat.cast_pow Nat.cast_pow -theorem coe_nat_dvd [Semiring α] {m n : ℕ} (h : m ∣ n) : (m : α) ∣ (n : α) := - map_dvd (Nat.castRingHom α) h +lemma coe_nat_dvd (h : m ∣ n) : (m : α) ∣ (n : α) := map_dvd (Nat.castRingHom α) h #align nat.coe_nat_dvd Nat.coe_nat_dvd alias _root_.Dvd.dvd.natCast := coe_nat_dvd +end Semiring end Nat section AddMonoidHomClass @@ -73,7 +96,7 @@ section AddMonoidHomClass variable {A B F : Type*} [AddMonoidWithOne B] theorem ext_nat' [AddMonoid A] [AddMonoidHomClass F ℕ A] (f g : F) (h : f 1 = g 1) : f = g := - FunLike.ext f g <| by + DFunLike.ext f g <| by intro n induction n with | zero => simp_rw [Nat.zero_eq, map_zero f, map_zero g] @@ -101,6 +124,14 @@ theorem map_natCast' {A} [AddMonoidWithOne A] [AddMonoidHomClass F A B] (f : F) rw [Nat.cast_add, map_add, Nat.cast_add, map_natCast' f h n, Nat.cast_one, h, Nat.cast_one] #align map_nat_cast' map_natCast' +@[simp] lemma nsmul_one {A} [AddMonoidWithOne A] : ∀ n : ℕ, n • (1 : A) = n := by + let f : ℕ →+ A := + { toFun := fun n ↦ n • (1 : A) + map_zero' := zero_nsmul _ + map_add' := add_nsmul _ } + exact eq_natCast' f $ by simp +#align nsmul_one nsmul_one + end AddMonoidHomClass section MonoidWithZeroHomClass @@ -110,7 +141,7 @@ variable {A F : Type*} [MulZeroOneClass A] /-- If two `MonoidWithZeroHom`s agree on the positive naturals they are equal. -/ theorem ext_nat'' [MonoidWithZeroHomClass F ℕ A] (f g : F) (h_pos : ∀ {n : ℕ}, 0 < n → f n = g n) : f = g := by - apply FunLike.ext + apply DFunLike.ext rintro (_ | n) · simp [map_zero f, map_zero g] · exact h_pos n.succ_pos @@ -180,6 +211,92 @@ instance Nat.uniqueRingHom {R : Type*} [NonAssocSemiring R] : Unique (ℕ →+* default := Nat.castRingHom R uniq := RingHom.eq_natCast' +section Monoid +variable (α) [Monoid α] [AddMonoid α] + +/-- Additive homomorphisms from `ℕ` are defined by the image of `1`. -/ +def multiplesHom : α ≃ (ℕ →+ α) where + toFun x := + { toFun := fun n ↦ n • x + map_zero' := zero_nsmul x + map_add' := fun _ _ ↦ add_nsmul _ _ _ } + invFun f := f 1 + left_inv := one_nsmul + right_inv f := AddMonoidHom.ext_nat <| one_nsmul (f 1) +#align multiples_hom multiplesHom + +/-- Monoid homomorphisms from `Multiplicative ℕ` are defined by the image +of `Multiplicative.ofAdd 1`. -/ +@[to_additive existing multiplesHom] +def powersHom : α ≃ (Multiplicative ℕ →* α) := + Additive.ofMul.trans <| (multiplesHom _).trans <| AddMonoidHom.toMultiplicative'' + +variable {α} + +-- TODO: can `to_additive` generate the following lemmas automatically? + +lemma multiplesHom_apply (x : α) (n : ℕ) : multiplesHom α x n = n • x := rfl +#align multiples_hom_apply multiplesHom_apply + +@[to_additive existing (attr := simp) multiplesHom_apply] +lemma powersHom_apply (x : α) (n : Multiplicative ℕ) : + powersHom α x n = x ^ Multiplicative.toAdd n := rfl +#align powers_hom_apply powersHom_apply + +lemma multiplesHom_symm_apply (f : ℕ →+ α) : (multiplesHom α).symm f = f 1 := rfl +#align multiples_hom_symm_apply multiplesHom_symm_apply + +@[to_additive existing (attr := simp) multiplesHom_symm_apply] +lemma powersHom_symm_apply (f : Multiplicative ℕ →* α) : + (powersHom α).symm f = f (Multiplicative.ofAdd 1) := rfl +#align powers_hom_symm_apply powersHom_symm_apply + +lemma MonoidHom.apply_mnat (f : Multiplicative ℕ →* α) (n : Multiplicative ℕ) : + f n = f (Multiplicative.ofAdd 1) ^ (Multiplicative.toAdd n) := by + rw [← powersHom_symm_apply, ← powersHom_apply, Equiv.apply_symm_apply] +#align monoid_hom.apply_mnat MonoidHom.apply_mnat + +@[ext] +lemma MonoidHom.ext_mnat ⦃f g : Multiplicative ℕ →* α⦄ + (h : f (Multiplicative.ofAdd 1) = g (Multiplicative.ofAdd 1)) : f = g := + MonoidHom.ext fun n ↦ by rw [f.apply_mnat, g.apply_mnat, h] +#align monoid_hom.ext_mnat MonoidHom.ext_mnat + +lemma AddMonoidHom.apply_nat (f : ℕ →+ α) (n : ℕ) : f n = n • f 1 := by + rw [← multiplesHom_symm_apply, ← multiplesHom_apply, Equiv.apply_symm_apply] +#align add_monoid_hom.apply_nat AddMonoidHom.apply_nat + +end Monoid + +section CommMonoid +variable (α) [CommMonoid α] [AddCommMonoid α] + +/-- If `α` is commutative, `multiplesHom` is an additive equivalence. -/ +def multiplesAddHom : α ≃+ (ℕ →+ α) := + { multiplesHom α with map_add' := fun a b ↦ AddMonoidHom.ext fun n ↦ by simp [nsmul_add] } +#align multiples_add_hom multiplesAddHom + +/-- If `α` is commutative, `powersHom` is a multiplicative equivalence. -/ +def powersMulHom : α ≃* (Multiplicative ℕ →* α) := + { powersHom α with map_mul' := fun a b ↦ MonoidHom.ext fun n ↦ by simp [mul_pow] } +#align powers_mul_hom powersMulHom + +@[simp] lemma multiplesAddHom_apply (x : α) (n : ℕ) : multiplesAddHom α x n = n • x := rfl +#align multiples_add_hom_apply multiplesAddHom_apply + +@[simp] +lemma powersMulHom_apply (x : α) (n : Multiplicative ℕ) : powersMulHom α x n = x ^ toAdd n := rfl +#align powers_mul_hom_apply powersMulHom_apply + +@[simp] lemma multiplesAddHom_symm_apply (f : ℕ →+ α) : (multiplesAddHom α).symm f = f 1 := rfl +#align multiples_add_hom_symm_apply multiplesAddHom_symm_apply + +@[simp] lemma powersMulHom_symm_apply (f : Multiplicative ℕ →* α) : + (powersMulHom α).symm f = f (ofAdd 1) := rfl +#align powers_mul_hom_symm_apply powersMulHom_symm_apply + +end CommMonoid + namespace Pi variable {π : α → Type*} [∀ a, NatCast (π a)] diff --git a/Mathlib/Data/Nat/Cast/Commute.lean b/Mathlib/Data/Nat/Cast/Commute.lean index 48309d0c0b493..2eddc9008581e 100644 --- a/Mathlib/Data/Nat/Cast/Commute.lean +++ b/Mathlib/Data/Nat/Cast/Commute.lean @@ -3,7 +3,6 @@ Copyright (c) 2014 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Nat.Cast.Basic import Mathlib.Algebra.GroupWithZero.Commute import Mathlib.Algebra.Ring.Commute @@ -20,26 +19,84 @@ namespace Nat section Commute -theorem cast_commute [NonAssocSemiring α] (n : ℕ) (x : α) : Commute (n : α) x := by +variable [NonAssocSemiring α] + +theorem cast_commute (n : ℕ) (x : α) : Commute (n : α) x := by induction n with | zero => rw [Nat.cast_zero]; exact Commute.zero_left x | succ n ihn => rw [Nat.cast_succ]; exact ihn.add_left (Commute.one_left x) #align nat.cast_commute Nat.cast_commute -theorem _root_.Commute.ofNat_left [NonAssocSemiring α] (n : ℕ) [n.AtLeastTwo] (x : α) : - Commute (OfNat.ofNat n) x := +theorem _root_.Commute.ofNat_left (n : ℕ) [n.AtLeastTwo] (x : α) : Commute (OfNat.ofNat n) x := n.cast_commute x -theorem cast_comm [NonAssocSemiring α] (n : ℕ) (x : α) : (n : α) * x = x * n := +theorem cast_comm (n : ℕ) (x : α) : (n : α) * x = x * n := (cast_commute n x).eq #align nat.cast_comm Nat.cast_comm -theorem commute_cast [NonAssocSemiring α] (x : α) (n : ℕ) : Commute x n := +theorem commute_cast (x : α) (n : ℕ) : Commute x n := (n.cast_commute x).symm #align nat.commute_cast Nat.commute_cast -theorem _root_.Commute.ofNat_right [NonAssocSemiring α] (x : α) (n : ℕ) [n.AtLeastTwo] : - Commute x (OfNat.ofNat n) := +theorem _root_.Commute.ofNat_right (x : α) (n : ℕ) [n.AtLeastTwo] : Commute x (OfNat.ofNat n) := n.commute_cast x end Commute +end Nat + +namespace SemiconjBy +variable [Semiring α] {a x y : α} + +@[simp] +lemma cast_nat_mul_right (h : SemiconjBy a x y) (n : ℕ) : SemiconjBy a (n * x) (n * y) := + SemiconjBy.mul_right (Nat.commute_cast _ _) h +#align semiconj_by.cast_nat_mul_right SemiconjBy.cast_nat_mul_right + +@[simp] +lemma cast_nat_mul_left (h : SemiconjBy a x y) (n : ℕ) : SemiconjBy (n * a) x y := + SemiconjBy.mul_left (Nat.cast_commute _ _) h +#align semiconj_by.cast_nat_mul_left SemiconjBy.cast_nat_mul_left + +@[simp] +lemma cast_nat_mul_cast_nat_mul (h : SemiconjBy a x y) (m n : ℕ) : + SemiconjBy (m * a) (n * x) (n * y) := + (h.cast_nat_mul_left m).cast_nat_mul_right n +#align semiconj_by.cast_nat_mul_cast_nat_mul SemiconjBy.cast_nat_mul_cast_nat_mul + +end SemiconjBy + +namespace Commute +variable [Semiring α] {a b : α} + +@[simp] lemma cast_nat_mul_right (h : Commute a b) (n : ℕ) : Commute a (n * b) := + SemiconjBy.cast_nat_mul_right h n +#align commute.cast_nat_mul_right Commute.cast_nat_mul_right + +@[simp] lemma cast_nat_mul_left (h : Commute a b) (n : ℕ) : Commute (n * a) b := + SemiconjBy.cast_nat_mul_left h n +#align commute.cast_nat_mul_left Commute.cast_nat_mul_left + +@[simp] lemma cast_nat_mul_cast_nat_mul (h : Commute a b) (m n : ℕ) : Commute (m * a) (n * b) := + SemiconjBy.cast_nat_mul_cast_nat_mul h m n +#align commute.cast_nat_mul_cast_nat_mul Commute.cast_nat_mul_cast_nat_mul + +variable (a) (m n : ℕ) + +-- Porting note: `simp` can prove this using `Commute.refl`, `Commute.cast_nat_mul_right` +-- @[simp] +lemma self_cast_nat_mul : Commute a (n * a) := (Commute.refl a).cast_nat_mul_right n +#align commute.self_cast_nat_mul Commute.self_cast_nat_mul + +-- Porting note: `simp` can prove this using `Commute.refl`, `Commute.cast_nat_mul_left` +-- @[simp] +lemma cast_nat_mul_self : Commute (n * a) a := (Commute.refl a).cast_nat_mul_left n +#align commute.cast_nat_mul_self Commute.cast_nat_mul_self + +-- Porting note: `simp` can prove this using `Commute.refl`, `Commute.cast_nat_mul_left`, +-- `Commute.cast_nat_mul_right` +-- @[simp] +lemma self_cast_nat_mul_cast_nat_mul : Commute (m * a) (n * a) := + (Commute.refl a).cast_nat_mul_cast_nat_mul m n +#align commute.self_cast_nat_mul_cast_nat_mul Commute.self_cast_nat_mul_cast_nat_mul + +end Commute diff --git a/Mathlib/Data/Nat/Cast/Defs.lean b/Mathlib/Data/Nat/Cast/Defs.lean index 0ebe740d851d8..e2a184c21c213 100644 --- a/Mathlib/Data/Nat/Cast/Defs.lean +++ b/Mathlib/Data/Nat/Cast/Defs.lean @@ -45,7 +45,7 @@ class Nat.AtLeastTwo (n : ℕ) : Prop where prop : n ≥ 2 instance instNatAtLeastTwo : Nat.AtLeastTwo (n + 2) where - prop := Nat.succ_le_succ $ Nat.succ_le_succ $ Nat.zero_le _ + prop := Nat.succ_le_succ <| Nat.succ_le_succ <| Nat.zero_le _ lemma Nat.AtLeastTwo.ne_zero (n : ℕ) [h : n.AtLeastTwo] : n ≠ 0 := by rintro rfl; exact absurd h.1 (by decide) @@ -58,7 +58,7 @@ instance is what makes things like `37 : R` type check. Note that `0` and `1` a because they are recognized as terms of `R` (at least when `R` is an `AddMonoidWithOne`) through `Zero` and `One`, respectively. -/ @[nolint unusedArguments] -instance instOfNat [NatCast R] [Nat.AtLeastTwo n] : OfNat R n where +instance instOfNatAtLeastTwo [NatCast R] [Nat.AtLeastTwo n] : OfNat R n where ofNat := n.cast library_note "no_index around OfNat.ofNat" @@ -159,7 +159,7 @@ protected def binCast [Zero R] [One R] [Add R] : ℕ → R | n + 1 => if (n + 1) % 2 = 0 then (Nat.binCast ((n + 1) / 2)) + (Nat.binCast ((n + 1) / 2)) else (Nat.binCast ((n + 1) / 2)) + (Nat.binCast ((n + 1) / 2)) + 1 -decreasing_by (exact Nat.div_lt_self (Nat.succ_pos n) (Nat.le_refl 2)) +decreasing_by all_goals { simp_wf; omega } #align nat.bin_cast Nat.binCast @[simp] @@ -172,10 +172,10 @@ theorem binCast_eq [AddMonoidWithOne R] (n : ℕ) : (Nat.binCast n : R) = ((n : rw [Nat.binCast] by_cases h : (k + 1) % 2 = 0 · rw [← Nat.mod_add_div (succ k) 2] - rw [if_pos h, hk _ $ Nat.div_lt_self (Nat.succ_pos k) (Nat.le_refl 2), ← Nat.cast_add] + rw [if_pos h, hk _ <| Nat.div_lt_self (Nat.succ_pos k) (Nat.le_refl 2), ← Nat.cast_add] rw [Nat.succ_eq_add_one, h, Nat.zero_add, Nat.succ_mul, Nat.one_mul] · rw [← Nat.mod_add_div (succ k) 2] - rw [if_neg h, hk _ $ Nat.div_lt_self (Nat.succ_pos k) (Nat.le_refl 2), ← Nat.cast_add] + rw [if_neg h, hk _ <| Nat.div_lt_self (Nat.succ_pos k) (Nat.le_refl 2), ← Nat.cast_add] have h1 := Or.resolve_left (Nat.mod_two_eq_zero_or_one (succ k)) h rw [h1, Nat.add_comm 1, Nat.succ_mul, Nat.one_mul] simp only [Nat.cast_add, Nat.cast_one] diff --git a/Mathlib/Data/Nat/Cast/Field.lean b/Mathlib/Data/Nat/Cast/Field.lean index 2c9d2175ad90d..37f1da0b5613c 100644 --- a/Mathlib/Data/Nat/Cast/Field.lean +++ b/Mathlib/Data/Nat/Cast/Field.lean @@ -49,6 +49,10 @@ section LinearOrderedSemifield variable [LinearOrderedSemifield α] +lemma cast_inv_le_one : ∀ n : ℕ, (n⁻¹ : α) ≤ 1 + | 0 => by simp + | n + 1 => inv_le_one $ by simp [Nat.cast_nonneg] + /-- Natural division is always less than division in the field. -/ theorem cast_div_le {m n : ℕ} : ((m / n : ℕ) : α) ≤ m / n := by cases n diff --git a/Mathlib/Data/Nat/Cast/Prod.lean b/Mathlib/Data/Nat/Cast/Prod.lean index 0c343dc575ed9..54f2a15a5cf44 100644 --- a/Mathlib/Data/Nat/Cast/Prod.lean +++ b/Mathlib/Data/Nat/Cast/Prod.lean @@ -3,7 +3,6 @@ Copyright (c) 2014 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Nat.Cast.Basic import Mathlib.Algebra.Group.Prod #align_import data.nat.cast.prod from "leanprover-community/mathlib"@"ee0c179cd3c8a45aa5bffbf1b41d8dbede452865" diff --git a/Mathlib/Data/Nat/Cast/Synonym.lean b/Mathlib/Data/Nat/Cast/Synonym.lean index d1b26a5b8f558..9ab3eb0e1f62c 100644 --- a/Mathlib/Data/Nat/Cast/Synonym.lean +++ b/Mathlib/Data/Nat/Cast/Synonym.lean @@ -3,7 +3,7 @@ Copyright (c) 2014 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Nat.Cast.Basic +import Mathlib.Data.Nat.Cast.Defs import Mathlib.Order.Synonym #align_import data.nat.cast.basic from "leanprover-community/mathlib"@"acebd8d49928f6ed8920e502a6c90674e75bd441" diff --git a/Mathlib/Data/Nat/Choose/Basic.lean b/Mathlib/Data/Nat/Choose/Basic.lean index a5e9b5806199d..6c35936e40bd6 100644 --- a/Mathlib/Data/Nat/Choose/Basic.lean +++ b/Mathlib/Data/Nat/Choose/Basic.lean @@ -233,25 +233,40 @@ theorem choose_mul_succ_eq (n k : ℕ) : n.choose k * (n + 1) = (n + 1).choose k #align nat.choose_mul_succ_eq Nat.choose_mul_succ_eq theorem ascFactorial_eq_factorial_mul_choose (n k : ℕ) : - n.ascFactorial k = k ! * (n + k).choose k := by + (n + 1).ascFactorial k = k ! * (n + k).choose k := by rw [mul_comm] apply mul_right_cancel₀ (factorial_ne_zero (n + k - k)) - rw [choose_mul_factorial_mul_factorial, add_tsub_cancel_right, ← factorial_mul_ascFactorial, - mul_comm] - exact Nat.le_add_left k n + rw [choose_mul_factorial_mul_factorial <| Nat.le_add_left k n, add_tsub_cancel_right, + ← factorial_mul_ascFactorial, mul_comm] #align nat.asc_factorial_eq_factorial_mul_choose Nat.ascFactorial_eq_factorial_mul_choose +theorem ascFactorial_eq_factorial_mul_choose' (n k : ℕ) : + n.ascFactorial k = k ! * (n + k - 1).choose k := by + cases n + · cases k + · rw [ascFactorial_zero, choose_zero_right, factorial_zero, mul_one] + · simp only [zero_ascFactorial, zero_eq, zero_add, ge_iff_le, succ_sub_succ_eq_sub, + nonpos_iff_eq_zero, tsub_zero, choose_succ_self, mul_zero] + rw [ascFactorial_eq_factorial_mul_choose] + simp only [ge_iff_le, succ_add_sub_one] + theorem factorial_dvd_ascFactorial (n k : ℕ) : k ! ∣ n.ascFactorial k := - ⟨(n + k).choose k, ascFactorial_eq_factorial_mul_choose _ _⟩ + ⟨(n + k - 1).choose k, ascFactorial_eq_factorial_mul_choose' _ _⟩ #align nat.factorial_dvd_asc_factorial Nat.factorial_dvd_ascFactorial theorem choose_eq_asc_factorial_div_factorial (n k : ℕ) : - (n + k).choose k = n.ascFactorial k / k ! := by + (n + k).choose k = (n + 1).ascFactorial k / k ! := by apply mul_left_cancel₀ (factorial_ne_zero k) rw [← ascFactorial_eq_factorial_mul_choose] exact (Nat.mul_div_cancel' <| factorial_dvd_ascFactorial _ _).symm #align nat.choose_eq_asc_factorial_div_factorial Nat.choose_eq_asc_factorial_div_factorial +theorem choose_eq_asc_factorial_div_factorial' (n k : ℕ) : + (n + k - 1).choose k = n.ascFactorial k / k ! := by + apply mul_left_cancel₀ (factorial_ne_zero k) + rw [← ascFactorial_eq_factorial_mul_choose'] + exact (Nat.mul_div_cancel' <| factorial_dvd_ascFactorial _ _).symm + theorem descFactorial_eq_factorial_mul_choose (n k : ℕ) : n.descFactorial k = k ! * n.choose k := by obtain h | h := Nat.lt_or_ge n k · rw [descFactorial_eq_zero_iff_lt.2 h, choose_eq_zero_of_lt h, mul_zero] @@ -362,7 +377,7 @@ def multichoose : ℕ → ℕ → ℕ | 0, _ + 1 => 0 | n + 1, k + 1 => multichoose n (k + 1) + multichoose (n + 1) k - termination_by multichoose a b => (a, b) + termination_by a b => (a, b) #align nat.multichoose Nat.multichoose @[simp] @@ -405,8 +420,8 @@ theorem multichoose_eq : ∀ n k : ℕ, multichoose n k = (n + k - 1).choose k have : (n + 1) + k < (n + 1) + (k + 1) := add_lt_add_left (Nat.lt_succ_self _) _ erw [multichoose_succ_succ, add_comm, Nat.succ_add_sub_one, ← add_assoc, Nat.choose_succ_succ] simp [multichoose_eq n (k+1), multichoose_eq (n+1) k] - termination_by multichoose_eq a b => a + b - decreasing_by { assumption } + termination_by a b => a + b + decreasing_by all_goals assumption #align nat.multichoose_eq Nat.multichoose_eq end Nat diff --git a/Mathlib/Data/Nat/Choose/Bounds.lean b/Mathlib/Data/Nat/Choose/Bounds.lean index c3a464fad8a52..f40ad4fd8ffe9 100644 --- a/Mathlib/Data/Nat/Choose/Bounds.lean +++ b/Mathlib/Data/Nat/Choose/Bounds.lean @@ -3,9 +3,12 @@ Copyright (c) 2021 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Eric Rodriguez -/ -import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Algebra.Order.Field.Basic +import Mathlib.Algebra.Order.Ring.CharZero +import Mathlib.Data.Nat.Cast.Order import Mathlib.Data.Nat.Choose.Basic +import Mathlib.Algebra.Order.Ring.CharZero +import Mathlib.Data.Nat.Cast.Order #align_import data.nat.choose.bounds from "leanprover-community/mathlib"@"550b58538991c8977703fdeb7c9d51a5aa27df11" diff --git a/Mathlib/Data/Nat/Choose/Central.lean b/Mathlib/Data/Nat/Choose/Central.lean index 95b68c78116e8..7792fe88d8230 100644 --- a/Mathlib/Data/Nat/Choose/Central.lean +++ b/Mathlib/Data/Nat/Choose/Central.lean @@ -40,7 +40,7 @@ theorem centralBinom_eq_two_mul_choose (n : ℕ) : centralBinom n = (2 * n).choo #align nat.central_binom_eq_two_mul_choose Nat.centralBinom_eq_two_mul_choose theorem centralBinom_pos (n : ℕ) : 0 < centralBinom n := - choose_pos (Nat.le_mul_of_pos_left zero_lt_two) + choose_pos (Nat.le_mul_of_pos_left _ zero_lt_two) #align nat.central_binom_pos Nat.centralBinom_pos theorem centralBinom_ne_zero (n : ℕ) : centralBinom n ≠ 0 := @@ -62,7 +62,7 @@ theorem choose_le_centralBinom (r n : ℕ) : choose (2 * n) r ≤ centralBinom n theorem two_le_centralBinom (n : ℕ) (n_pos : 0 < n) : 2 ≤ centralBinom n := calc - 2 ≤ 2 * n := le_mul_of_pos_right n_pos + 2 ≤ 2 * n := Nat.le_mul_of_pos_right _ n_pos _ = (2 * n).choose 1 := (choose_one_right (2 * n)).symm _ ≤ centralBinom n := choose_le_centralBinom 1 n #align nat.two_le_central_binom Nat.two_le_centralBinom @@ -92,7 +92,7 @@ theorem four_pow_lt_mul_centralBinom (n : ℕ) (n_big : 4 ≤ n) : 4 ^ n < n * c · norm_num [centralBinom, choose] obtain ⟨n, rfl⟩ : ∃ m, n = m + 1 := Nat.exists_eq_succ_of_ne_zero (Nat.not_eq_zero_of_lt hn) calc - 4 ^ (n + 1) < 4 * (n * centralBinom n) := lt_of_eq_of_lt pow_succ' $ + 4 ^ (n + 1) < 4 * (n * centralBinom n) := lt_of_eq_of_lt pow_succ' <| (mul_lt_mul_left <| zero_lt_four' ℕ).mpr (IH n n.lt_succ_self (Nat.le_of_lt_succ hn)) _ ≤ 2 * (2 * n + 1) * centralBinom n := by rw [← mul_assoc]; linarith _ = (n + 1) * centralBinom (n + 1) := (succ_mul_centralBinom_succ n).symm @@ -112,7 +112,7 @@ theorem four_pow_le_two_mul_self_mul_centralBinom : calc 4 ^ (n+4) ≤ (n+4) * centralBinom (n+4) := (four_pow_lt_mul_centralBinom _ le_add_self).le _ ≤ 2 * (n+4) * centralBinom (n+4) := by - rw [mul_assoc]; refine' le_mul_of_pos_left zero_lt_two + rw [mul_assoc]; refine' Nat.le_mul_of_pos_left _ zero_lt_two #align nat.four_pow_le_two_mul_self_mul_central_binom Nat.four_pow_le_two_mul_self_mul_centralBinom theorem two_dvd_centralBinom_succ (n : ℕ) : 2 ∣ centralBinom (n + 1) := by diff --git a/Mathlib/Data/Nat/Choose/Multinomial.lean b/Mathlib/Data/Nat/Choose/Multinomial.lean index c312b8cd49e36..cf08da5dca7ed 100644 --- a/Mathlib/Data/Nat/Choose/Multinomial.lean +++ b/Mathlib/Data/Nat/Choose/Multinomial.lean @@ -27,10 +27,8 @@ This file defines the multinomial coefficient and several small lemma's for mani -/ - -open BigOperators Nat - -open BigOperators +open Finset +open scoped BigOperators Nat namespace Nat @@ -60,9 +58,23 @@ theorem multinomial_nil : multinomial ∅ f = 1 := by rfl #align nat.multinomial_nil Nat.multinomial_nil -@[simp] -theorem multinomial_singleton : multinomial {a} f = 1 := by - simp [multinomial, Nat.div_self (factorial_pos (f a))] +variable {s f} + +lemma multinomial_cons (ha : a ∉ s) (f : α → ℕ) : + multinomial (s.cons a ha) f = (f a + ∑ i in s, f i).choose (f a) * multinomial s f := by + rw [multinomial, Nat.div_eq_iff_eq_mul_left _ (prod_factorial_dvd_factorial_sum _ _), prod_cons, + multinomial, mul_assoc, mul_left_comm _ (f a)!, + Nat.div_mul_cancel (prod_factorial_dvd_factorial_sum _ _), ← mul_assoc, Nat.choose_symm_add, + Nat.add_choose_mul_factorial_mul_factorial, Finset.sum_cons] + exact prod_pos fun i _ ↦ by positivity + +lemma multinomial_insert [DecidableEq α] (ha : a ∉ s) (f : α → ℕ) : + multinomial (insert a s) f = (f a + ∑ i in s, f i).choose (f a) * multinomial s f := by + rw [← cons_eq_insert _ _ ha, multinomial_cons] +#align nat.multinomial_insert Nat.multinomial_insert + +@[simp] lemma multinomial_singleton (a : α) (f : α → ℕ) : multinomial {a} f = 1 := by + rw [← cons_empty, multinomial_cons]; simp #align nat.multinomial_singleton Nat.multinomial_singleton @[simp] @@ -74,17 +86,6 @@ theorem multinomial_insert_one [DecidableEq α] (h : a ∉ s) (h₁ : f a = 1) : rw [Nat.mul_div_assoc _ (prod_factorial_dvd_factorial_sum _ _)] #align nat.multinomial_insert_one Nat.multinomial_insert_one -theorem multinomial_insert [DecidableEq α] (h : a ∉ s) : - multinomial (insert a s) f = (f a + s.sum f).choose (f a) * multinomial s f := by - rw [choose_eq_factorial_div_factorial (le.intro rfl)] - simp only [multinomial, Nat.add_sub_cancel_left, Finset.sum_insert h, Finset.prod_insert h, - Function.comp_apply] - rw [div_mul_div_comm ((f a).factorial_mul_factorial_dvd_factorial_add (s.sum f)) - (prod_factorial_dvd_factorial_sum _ _), - mul_comm (f a)! (s.sum f)!, mul_assoc, mul_comm _ (s.sum f)!, - Nat.mul_div_mul_left _ _ (factorial_pos _)] -#align nat.multinomial_insert Nat.multinomial_insert - theorem multinomial_congr {f g : α → ℕ} (h : ∀ a ∈ s, f a = g a) : multinomial s f = multinomial s g := by simp only [multinomial]; congr 1 @@ -107,7 +108,7 @@ theorem binomial_eq [DecidableEq α] (h : a ≠ b) : theorem binomial_eq_choose [DecidableEq α] (h : a ≠ b) : multinomial {a, b} f = (f a + f b).choose (f a) := by - simp [binomial_eq _ h, choose_eq_factorial_div_factorial (Nat.le_add_right _ _)] + simp [binomial_eq h, choose_eq_factorial_div_factorial (Nat.le_add_right _ _)] #align nat.binomial_eq_choose Nat.binomial_eq_choose theorem binomial_spec [DecidableEq α] (hab : a ≠ b) : @@ -118,7 +119,7 @@ theorem binomial_spec [DecidableEq α] (hab : a ≠ b) : @[simp] theorem binomial_one [DecidableEq α] (h : a ≠ b) (h₁ : f a = 1) : multinomial {a, b} f = (f b).succ := by - simp [multinomial_insert_one {b} f (Finset.not_mem_singleton.mpr h) h₁] + simp [multinomial_insert_one (Finset.not_mem_singleton.mpr h) h₁] #align nat.binomial_one Nat.binomial_one theorem binomial_succ_succ [DecidableEq α] (h : a ≠ b) : @@ -135,7 +136,7 @@ theorem binomial_succ_succ [DecidableEq α] (h : a ≠ b) : theorem succ_mul_binomial [DecidableEq α] (h : a ≠ b) : (f a + f b).succ * multinomial {a, b} f = (f a).succ * multinomial {a, b} (Function.update f a (f a).succ) := by - rw [binomial_eq_choose _ h, binomial_eq_choose _ h, mul_comm (f a).succ, Function.update_same, + rw [binomial_eq_choose h, binomial_eq_choose h, mul_comm (f a).succ, Function.update_same, Function.update_noteq (ne_comm.mp h)] rw [succ_mul_choose_eq (f a + f b) (f a), succ_add (f a) (f b)] #align nat.succ_mul_binomial Nat.succ_mul_binomial @@ -180,11 +181,10 @@ theorem multinomial_update (a : α) (f : α →₀ ℕ) : simp only [multinomial_eq] classical by_cases h : a ∈ f.support - · rw [← Finset.insert_erase h, Nat.multinomial_insert _ f (Finset.not_mem_erase a _), + · rw [← Finset.insert_erase h, Nat.multinomial_insert (Finset.not_mem_erase a _), Finset.add_sum_erase _ f h, support_update_zero] congr 1 - exact - Nat.multinomial_congr _ fun _ h => (Function.update_noteq (Finset.mem_erase.1 h).1 0 f).symm + exact Nat.multinomial_congr fun _ h ↦ (Function.update_noteq (mem_erase.1 h).1 0 f).symm rw [not_mem_support_iff] at h rw [h, Nat.choose_zero_right, one_mul, ← h, update_self] #align finsupp.multinomial_update Finsupp.multinomial_update @@ -249,7 +249,7 @@ theorem sum_pow_of_commute [Semiring R] (x : α → R) convert @Nat.cast_one R _ · rw [_root_.pow_succ, zero_mul] -- Porting note : Lean cannot infer this instance by itself - haveI : IsEmpty (Finset.sym (∅ : Finset α) (succ n)) := Finset.instIsEmpty + haveI : IsEmpty (Finset.sym (∅ : Finset α) n.succ) := Finset.instIsEmpty apply (Fintype.sum_empty _).symm intro n; specialize ih (hc.mono <| s.subset_insert a) rw [sum_insert ha, (Commute.sum_right s _ _ _).add_pow, sum_range]; swap diff --git a/Mathlib/Data/Nat/Choose/Sum.lean b/Mathlib/Data/Nat/Choose/Sum.lean index 061ac12398ff5..5f643f900aa68 100644 --- a/Mathlib/Data/Nat/Choose/Sum.lean +++ b/Mathlib/Data/Nat/Choose/Sum.lean @@ -127,7 +127,7 @@ theorem four_pow_le_two_mul_add_one_mul_central_binom (n : ℕ) : 4 ^ n ≤ (2 * n + 1) * choose (2 * n) n := calc 4 ^ n = (1 + 1) ^ (2 * n) := by norm_num [pow_mul] - _ = ∑ m in range (2 * n + 1), choose (2 * n) m := by simp [add_pow] + _ = ∑ m in range (2 * n + 1), choose (2 * n) m := by set_option simprocs false in simp [add_pow] _ ≤ ∑ m in range (2 * n + 1), choose (2 * n) (2 * n / 2) := by gcongr; apply choose_le_middle _ = (2 * n + 1) * choose (2 * n) n := by simp #align nat.four_pow_le_two_mul_add_one_mul_central_binom Nat.four_pow_le_two_mul_add_one_mul_central_binom diff --git a/Mathlib/Data/Nat/Defs.lean b/Mathlib/Data/Nat/Defs.lean new file mode 100644 index 0000000000000..e3bc8e7f99df8 --- /dev/null +++ b/Mathlib/Data/Nat/Defs.lean @@ -0,0 +1,814 @@ +/- +Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro +-/ +import Mathlib.Init.Data.Nat.Lemmas +import Mathlib.Logic.Function.Basic +import Mathlib.Logic.Nontrivial.Defs +import Mathlib.Tactic.Cases +import Mathlib.Tactic.PushNeg +import Mathlib.Tactic.Use + +#align_import data.nat.basic from "leanprover-community/mathlib"@"bd835ef554f37ef9b804f0903089211f89cb370b" + +/-! +# Basic operations on the natural numbers + +This file contains: +* some basic lemmas about natural numbers +* extra recursors: + * `leRecOn`, `le_induction`: recursion and induction principles starting at non-zero numbers + * `decreasing_induction`: recursion growing downwards + * `le_rec_on'`, `decreasing_induction'`: versions with slightly weaker assumptions + * `strong_rec'`: recursion based on strong inequalities +* decidability instances on predicates about the natural numbers + +Many theorems that used to live in this file have been moved to `Data.Nat.Order`, so that +this file requires fewer imports. For each section here there is a corresponding section in +that file with additional results. It may be possible to move some of these results here, +by tweaking their proofs. +-/ + +open Function + +namespace Nat +variable {a b c d m n k : ℕ} {p q : ℕ → Prop} + +instance nontrivial : Nontrivial ℕ := ⟨⟨0, 1, Nat.zero_ne_one⟩⟩ + +attribute [simp] Nat.not_lt_zero Nat.succ_ne_zero Nat.succ_ne_self Nat.zero_ne_one Nat.one_ne_zero + -- Nat.zero_ne_bit1 Nat.bit1_ne_zero Nat.bit0_ne_one Nat.one_ne_bit0 Nat.bit0_ne_bit1 + -- Nat.bit1_ne_bit0 + +/-! ### `succ`, `pred` -/ + +lemma succ_pos' : 0 < succ n := succ_pos n +#align nat.succ_pos' Nat.succ_pos' + +alias succ_inj := succ_inj' +#align nat.succ_inj' Nat.succ_inj + +lemma succ_injective : Injective Nat.succ := @succ.inj +#align nat.succ_injective Nat.succ_injective + +lemma succ_ne_succ : succ m ≠ succ n ↔ m ≠ n := succ_injective.ne_iff +#align nat.succ_ne_succ Nat.succ_ne_succ + +-- Porting note: no longer a simp lemma, as simp can prove this +lemma succ_succ_ne_one (n : ℕ) : n.succ.succ ≠ 1 := by simp +#align nat.succ_succ_ne_one Nat.succ_succ_ne_one + +@[simp] lemma one_lt_succ_succ (n : ℕ) : 1 < n.succ.succ := succ_lt_succ <| succ_pos n +#align nat.one_lt_succ_succ Nat.one_lt_succ_succ + +-- Moved to Std +#align nat.succ_le_succ_iff Nat.succ_le_succ_iff +#align nat.succ_lt_succ_iff Nat.succ_lt_succ_iff +#align nat.le_pred_of_lt Nat.le_pred_of_lt +#align nat.max_succ_succ Nat.succ_max_succ + +alias _root_.LT.lt.nat_succ_le := succ_le_of_lt +#align has_lt.lt.nat_succ_le LT.lt.nat_succ_le + +lemma not_succ_lt_self : ¬ succ n < n := not_lt_of_ge n.le_succ +#align nat.not_succ_lt_self Nat.not_succ_lt_self + +lemma lt_succ_iff : m < succ n ↔ m ≤ n := ⟨le_of_lt_succ, lt_succ_of_le⟩ +#align nat.lt_succ_iff Nat.lt_succ_iff + +lemma succ_le_iff : succ m ≤ n ↔ m < n := ⟨lt_of_succ_le, succ_le_of_lt⟩ +#align nat.succ_le_iff Nat.succ_le_iff + +lemma le_succ_iff : m ≤ n.succ ↔ m ≤ n ∨ m = n.succ := by + refine ⟨fun hmn ↦ (lt_or_eq_of_le hmn).imp_left le_of_lt_succ, ?_⟩ + rintro (hmn | rfl) + · exact le_succ_of_le hmn + · rfl + +alias ⟨of_le_succ, _⟩ := le_succ_iff +#align nat.of_le_succ Nat.of_le_succ + +lemma lt_succ_iff_lt_or_eq : m < n.succ ↔ m < n ∨ m = n := lt_succ_iff.trans Nat.le_iff_lt_or_eq +#align nat.lt_succ_iff_lt_or_eq Nat.lt_succ_iff_lt_or_eq + +lemma eq_of_lt_succ_of_not_lt (hmn : m < n + 1) (h : ¬ m < n) : m = n := + (lt_succ_iff_lt_or_eq.1 hmn).resolve_left h +#align nat.eq_of_lt_succ_of_not_lt Nat.eq_of_lt_succ_of_not_lt + +lemma eq_of_le_of_lt_succ (h₁ : n ≤ m) (h₂ : m < n + 1) : m = n := + Nat.le_antisymm (le_of_succ_le_succ h₂) h₁ +#align nat.eq_of_le_of_lt_succ Nat.eq_of_le_of_lt_succ + +lemma lt_iff_le_pred : ∀ {n}, 0 < n → (m < n ↔ m ≤ n - 1) | _ + 1, _ => lt_succ_iff +#align nat.lt_iff_le_pred Nat.lt_iff_le_pred + +lemma le_of_pred_lt : ∀ {m}, pred m < n → m ≤ n + | 0 => le_of_lt + | _ + 1 => id +#align nat.le_of_pred_lt Nat.le_of_pred_lt + +lemma lt_iff_add_one_le : m < n ↔ m + 1 ≤ n := by rw [succ_le_iff] +#align nat.lt_iff_add_one_le Nat.lt_iff_add_one_le + +-- Just a restatement of `Nat.lt_succ_iff` using `+1`. +lemma lt_add_one_iff : m < n + 1 ↔ m ≤ n := lt_succ_iff +#align nat.lt_add_one_iff Nat.lt_add_one_iff + +-- A flipped version of `lt_add_one_iff`. +lemma lt_one_add_iff : m < 1 + n ↔ m ≤ n := by simp only [Nat.add_comm, lt_succ_iff] +#align nat.lt_one_add_iff Nat.lt_one_add_iff + +-- This is true reflexively, by the definition of `≤` on ℕ, +-- but it's still useful to have, to convince Lean to change the syntactic type. +lemma add_one_le_iff : m + 1 ≤ n ↔ m < n := Iff.rfl +#align nat.add_one_le_iff Nat.add_one_le_iff + +lemma one_add_le_iff : 1 + m ≤ n ↔ m < n := by simp only [Nat.add_comm, add_one_le_iff] +#align nat.one_add_le_iff Nat.one_add_le_iff + +lemma one_le_iff_ne_zero : 1 ≤ n ↔ n ≠ 0 := Nat.pos_iff_ne_zero +#align nat.one_le_iff_ne_zero Nat.one_le_iff_ne_zero + +lemma one_lt_iff_ne_zero_and_ne_one : ∀ {n : ℕ}, 1 < n ↔ n ≠ 0 ∧ n ≠ 1 + | 0 => by decide + | 1 => by decide + | n + 2 => by simp +#align nat.one_lt_iff_ne_zero_and_ne_one Nat.one_lt_iff_ne_zero_and_ne_one + +lemma le_one_iff_eq_zero_or_eq_one : ∀ {n : ℕ}, n ≤ 1 ↔ n = 0 ∨ n = 1 := by simp [le_succ_iff] + +-- Moved to Std +#align nat.succ_eq_one_add Nat.succ_eq_one_add +#align nat.one_add Nat.one_add + +lemma pred_eq_sub_one (n : ℕ) : pred n = n - 1 := rfl +#align nat.pred_eq_sub_one Nat.pred_eq_sub_one + +/-- This ensures that `simp` succeeds on `pred (n + 1) = n`. -/ +@[simp] +lemma pred_one_add (n : ℕ) : pred (1 + n) = n := by rw [Nat.add_comm, add_one, Nat.pred_succ] +#align nat.pred_one_add Nat.pred_one_add + +lemma pred_eq_self_iff : n.pred = n ↔ n = 0 := by cases n <;> simp [(Nat.succ_ne_self _).symm] +#align nat.pred_eq_self_iff Nat.pred_eq_self_iff + +lemma pred_eq_of_eq_succ (H : m = n.succ) : m.pred = n := by simp [H] +#align nat.pred_eq_of_eq_succ Nat.pred_eq_of_eq_succ + +@[simp] lemma pred_eq_succ_iff : pred n = succ m ↔ n = m + 2 := by + cases n <;> constructor <;> rintro ⟨⟩ <;> rfl +#align nat.pred_eq_succ_iff Nat.pred_eq_succ_iff + +-- Porting note: this doesn't work as a simp lemma in Lean 4 +lemma and_forall_succ : p 0 ∧ (∀ n, p (n + 1)) ↔ ∀ n, p n := + ⟨fun h n ↦ Nat.casesOn n h.1 h.2, fun h ↦ ⟨h _, fun _ ↦ h _⟩⟩ +#align nat.and_forall_succ Nat.and_forall_succ + +-- Porting note: this doesn't work as a simp lemma in Lean 4 +lemma or_exists_succ : p 0 ∨ (∃ n, p (n + 1)) ↔ ∃ n, p n := + ⟨fun h ↦ h.elim (fun h0 ↦ ⟨0, h0⟩) fun ⟨n, hn⟩ ↦ ⟨n + 1, hn⟩, by + rintro ⟨_ | n, hn⟩ + exacts [Or.inl hn, Or.inr ⟨n, hn⟩]⟩ +#align nat.or_exists_succ Nat.or_exists_succ + +lemma forall_lt_succ : (∀ m < n + 1, p m) ↔ (∀ m < n, p m) ∧ p n := by + simp only [lt_succ_iff, Nat.le_iff_lt_or_eq, or_comm, forall_eq_or_imp, and_comm] +#align nat.forall_lt_succ Nat.forall_lt_succ + +lemma exists_lt_succ : (∃ m < n + 1, p m) ↔ (∃ m < n, p m) ∨ p n := by + rw [← not_iff_not] + push_neg + exact forall_lt_succ +#align nat.exists_lt_succ Nat.exists_lt_succ + +lemma two_lt_of_ne : ∀ {n}, n ≠ 0 → n ≠ 1 → n ≠ 2 → 2 < n + | 0, h, _, _ => (h rfl).elim + | 1, _, h, _ => (h rfl).elim + | 2, _, _, h => (h rfl).elim + -- Porting note: was `by decide` + | n + 3, _, _, _ => le_add_left 3 n +#align nat.two_lt_of_ne Nat.two_lt_of_ne + +/-! ### `pred` -/ + +@[simp] lemma add_succ_sub_one (m n : ℕ) : m + succ n - 1 = m + n := rfl +#align nat.add_succ_sub_one Nat.add_succ_sub_one + +@[simp] +lemma succ_add_sub_one (n m : ℕ) : succ m + n - 1 = m + n := by rw [succ_add, Nat.add_one_sub_one] +#align nat.succ_add_sub_one Nat.succ_add_sub_one + +lemma pred_sub (n m : ℕ) : pred n - m = pred (n - m) := by + rw [← Nat.sub_one, Nat.sub_sub, one_add, sub_succ] +#align nat.pred_sub Nat.pred_sub + +lemma self_add_sub_one : ∀ n, n + (n - 1) = 2 * n - 1 + | 0 => rfl + | n + 1 => by rw [Nat.two_mul]; exact (add_succ_sub_one (Nat.succ _) _).symm + +lemma sub_one_add_self (n : ℕ) : (n - 1) + n = 2 * n - 1 := Nat.add_comm _ n ▸ self_add_sub_one n + +lemma self_add_pred (n : ℕ) : n + pred n = (2 * n).pred := self_add_sub_one n +lemma pred_add_self (n : ℕ) : pred n + n = (2 * n).pred := sub_one_add_self n + +/-! ### `add` -/ + +-- Sometimes a bare `Nat.add` or similar appears as a consequence of unfolding during pattern +-- matching. These lemmas package them back up as typeclass mediated operations. +@[simp] lemma add_def : Nat.add m n = m + n := rfl +#align nat.add_def Nat.add_def + +lemma exists_eq_add_of_le (h : m ≤ n) : ∃ k : ℕ, n = m + k := ⟨n - m, (add_sub_of_le h).symm⟩ +#align nat.exists_eq_add_of_le Nat.exists_eq_add_of_le + +lemma exists_eq_add_of_le' (h : m ≤ n) : ∃ k : ℕ, n = k + m := ⟨n - m, (Nat.sub_add_cancel h).symm⟩ +#align nat.exists_eq_add_of_le' Nat.exists_eq_add_of_le' + +lemma exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 := + ⟨n - (m + 1), by rw [Nat.add_right_comm, add_sub_of_le h]⟩ +#align nat.exists_eq_add_of_lt Nat.exists_eq_add_of_lt + +/-! ### `mul` -/ + +@[simp] lemma mul_def : Nat.mul m n = m * n := rfl +#align nat.mul_def Nat.mul_def + +-- Moved to core +#align nat.eq_of_mul_eq_mul_right Nat.eq_of_mul_eq_mul_right + +lemma two_mul_ne_two_mul_add_one : 2 * n ≠ 2 * m + 1 := + mt (congr_arg (· % 2)) + (by rw [Nat.add_comm, add_mul_mod_self_left, mul_mod_right, mod_eq_of_lt] <;> simp) +#align nat.two_mul_ne_two_mul_add_one Nat.two_mul_ne_two_mul_add_one + +-- TODO: Replace `Nat.mul_right_cancel_iff` with `Nat.mul_left_inj` +protected lemma mul_left_inj (ha : a ≠ 0) : b * a = c * a ↔ b = c := + Nat.mul_right_cancel_iff (Nat.pos_iff_ne_zero.2 ha) _ _ + +-- TODO: Replace `Nat.mul_left_cancel_iff` with `Nat.mul_right_inj` +protected lemma mul_right_inj (ha : a ≠ 0) : a * b = a * c ↔ b = c := + Nat.mul_left_cancel_iff (Nat.pos_iff_ne_zero.2 ha) _ _ + +protected lemma mul_ne_mul_left (ha : a ≠ 0) : b * a ≠ c * a ↔ b ≠ c := (Nat.mul_left_inj ha).not +#align nat.mul_ne_mul_left Nat.mul_ne_mul_left + +protected lemma mul_ne_mul_right (ha : a ≠ 0) : a * b ≠ a * c ↔ b ≠ c := (Nat.mul_right_inj ha).not +#align nat.mul_ne_mul_right Nat.mul_ne_mul_right + +lemma mul_eq_left (ha : a ≠ 0) : a * b = a ↔ b = 1 := by simpa using Nat.mul_right_inj ha (c := 1) +lemma mul_eq_right (hb : b ≠ 0) : a * b = b ↔ a = 1 := by simpa using Nat.mul_left_inj hb (c := 1) + +-- TODO: Deprecate +lemma mul_right_eq_self_iff (ha : 0 < a) : a * b = a ↔ b = 1 := mul_eq_left $ ne_of_gt ha +#align nat.mul_right_eq_self_iff Nat.mul_right_eq_self_iff + +lemma mul_left_eq_self_iff (hb : 0 < b) : a * b = b ↔ a = 1 := mul_eq_right $ ne_of_gt hb +#align nat.mul_left_eq_self_iff Nat.mul_left_eq_self_iff + +set_option push_neg.use_distrib true in +/-- The product of two natural numbers is greater than 1 if and only if + at least one of them is greater than 1 and both are positive. -/ +lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by + constructor <;> intro h + · by_contra h'; push_neg at h'; simp [Nat.le_zero] at h' + obtain rfl | rfl | h' := h' + · simp at h + · simp at h + · exact Nat.not_lt_of_le (Nat.mul_le_mul h'.1 h'.2) h + · obtain hm | hn := h.2.2 + · exact Nat.mul_lt_mul_of_lt_of_le' hm h.2.1 Nat.zero_lt_one + · exact Nat.mul_lt_mul_of_le_of_lt h.1 hn h.1 + +/-! ### `div` -/ + +attribute [simp] Nat.div_self + +lemma div_le_iff_le_mul_add_pred (hb : 0 < b) : a / b ≤ c ↔ a ≤ b * c + (b - 1) := by + rw [← lt_succ_iff, div_lt_iff_lt_mul hb, succ_mul, Nat.mul_comm]; cases hb <;> exact lt_succ_iff +#align nat.div_le_iff_le_mul_add_pred Nat.div_le_iff_le_mul_add_pred + +/-- A version of `Nat.div_lt_self` using successors, rather than additional hypotheses. -/ +lemma div_lt_self' (a b : ℕ) : (a + 1) / (b + 2) < a + 1 := + Nat.div_lt_self (Nat.succ_pos _) (Nat.succ_lt_succ (Nat.succ_pos _)) +#align nat.div_lt_self' Nat.div_lt_self' + +lemma le_div_iff_mul_le' (hb : 0 < b) : a ≤ c / b ↔ a * b ≤ c := le_div_iff_mul_le hb +#align nat.le_div_iff_mul_le' Nat.le_div_iff_mul_le' + +lemma div_lt_iff_lt_mul' (hb : 0 < b) : a / b < c ↔ a < c * b := by + simp only [← not_le, le_div_iff_mul_le' hb] +#align nat.div_lt_iff_lt_mul' Nat.div_lt_iff_lt_mul' + +lemma one_le_div_iff (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by rw [le_div_iff_mul_le hb, Nat.one_mul] +#align nat.one_le_div_iff Nat.one_le_div_iff + +lemma div_lt_one_iff (hb : 0 < b) : a / b < 1 ↔ a < b := by simp only [← not_le, one_le_div_iff hb] +#align nat.div_lt_one_iff Nat.div_lt_one_iff + +protected lemma div_le_div_right (h : a ≤ b) : a / c ≤ b / c := + (c.eq_zero_or_pos.elim fun hc ↦ by simp [hc]) fun hc ↦ + (le_div_iff_mul_le' hc).2 <| le_trans (Nat.div_mul_le_self _ _) h +#align nat.div_le_div_right Nat.div_le_div_right + +lemma lt_of_div_lt_div (h : a / c < b / c) : a < b := + Nat.lt_of_not_le fun hab ↦ Nat.not_le_of_lt h $ Nat.div_le_div_right hab +#align nat.lt_of_div_lt_div Nat.lt_of_div_lt_div + +protected lemma div_pos (hba : b ≤ a) (hb : 0 < b) : 0 < a / b := + Nat.pos_of_ne_zero fun h ↦ lt_irrefl a $ + calc + a = a % b := by simpa [h] using (mod_add_div a b).symm + _ < b := mod_lt a hb + _ ≤ a := hba +#align nat.div_pos Nat.div_pos + +lemma lt_mul_of_div_lt (h : a / c < b) (hc : 0 < c) : a < b * c := + lt_of_not_ge <| not_le_of_gt h ∘ (Nat.le_div_iff_mul_le hc).2 +#align nat.lt_mul_of_div_lt Nat.lt_mul_of_div_lt + +lemma mul_div_le_mul_div_assoc (a b c : ℕ) : a * (b / c) ≤ a * b / c := + if hc0 : c = 0 then by simp [hc0] else + (Nat.le_div_iff_mul_le (Nat.pos_of_ne_zero hc0)).2 + (by rw [Nat.mul_assoc]; exact Nat.mul_le_mul_left _ (Nat.div_mul_le_self _ _)) +#align nat.mul_div_le_mul_div_assoc Nat.mul_div_le_mul_div_assoc + +protected lemma eq_mul_of_div_eq_right (H1 : b ∣ a) (H2 : a / b = c) : a = b * c := by + rw [← H2, Nat.mul_div_cancel' H1] +#align nat.eq_mul_of_div_eq_right Nat.eq_mul_of_div_eq_right + +protected lemma div_eq_iff_eq_mul_right (H : 0 < b) (H' : b ∣ a) : a / b = c ↔ a = b * c := + ⟨Nat.eq_mul_of_div_eq_right H', Nat.div_eq_of_eq_mul_right H⟩ +#align nat.div_eq_iff_eq_mul_right Nat.div_eq_iff_eq_mul_right + +protected lemma div_eq_iff_eq_mul_left (H : 0 < b) (H' : b ∣ a) : a / b = c ↔ a = c * b := by + rw [Nat.mul_comm]; exact Nat.div_eq_iff_eq_mul_right H H' +#align nat.div_eq_iff_eq_mul_left Nat.div_eq_iff_eq_mul_left + +protected lemma eq_mul_of_div_eq_left (H1 : b ∣ a) (H2 : a / b = c) : a = c * b := by + rw [Nat.mul_comm, Nat.eq_mul_of_div_eq_right H1 H2] +#align nat.eq_mul_of_div_eq_left Nat.eq_mul_of_div_eq_left + +protected lemma mul_div_cancel_left' (Hd : a ∣ b) : a * (b / a) = b := by + rw [Nat.mul_comm, Nat.div_mul_cancel Hd] +#align nat.mul_div_cancel_left' Nat.mul_div_cancel_left' + +#align nat.mul_div_mul_left Nat.mul_div_mul_left +#align nat.mul_div_mul_right Nat.mul_div_mul_right + +lemma lt_div_mul_add (hb : 0 < b) : a < a / b * b + b := by + rw [← Nat.succ_mul, ← Nat.div_lt_iff_lt_mul hb]; exact Nat.lt_succ_self _ +#align nat.lt_div_mul_add Nat.lt_div_mul_add + +@[simp] +protected lemma div_left_inj (hda : d ∣ a) (hdb : d ∣ b) : a / d = b / d ↔ a = b := by + refine ⟨fun h ↦ ?_, congr_arg fun b ↦ b / d⟩ + rw [← Nat.mul_div_cancel' hda, ← Nat.mul_div_cancel' hdb, h] +#align nat.div_left_inj Nat.div_left_inj + +lemma div_mul_div_comm : b ∣ a → d ∣ c → (a / b) * (c / d) = (a * c) / (b * d) := by + rintro ⟨x, rfl⟩ ⟨y, rfl⟩ + obtain rfl | hb := b.eq_zero_or_pos + · simp + obtain rfl | hd := d.eq_zero_or_pos + · simp + rw [Nat.mul_div_cancel_left _ hb, Nat.mul_div_cancel_left _ hd, Nat.mul_assoc b, + Nat.mul_left_comm x, ← Nat.mul_assoc b, Nat.mul_div_cancel_left _ (Nat.mul_pos hb hd)] +#align nat.div_mul_div_comm Nat.div_mul_div_comm + +protected lemma div_pow (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by + obtain rfl | hc := c.eq_zero_or_pos + · simp + obtain rfl | ha := a.eq_zero_or_pos + · simp [Nat.zero_pow hc] + refine (Nat.div_eq_of_eq_mul_right (pos_pow_of_pos c ha) ?_).symm + rw [← Nat.mul_pow, Nat.mul_div_cancel_left' h] + +/-! +### Recursion and induction principles + +This section is here due to dependencies -- the lemmas here require some of the lemmas +proved above, and some of the results in later sections depend on the definitions in this section. +-/ + +-- Porting note: The type ascriptions of these two lemmas need to be changed, +-- as mathport wrote a lambda that wasn't there in mathlib3, that prevents `simp` applying them. + +@[simp] +lemma rec_zero {C : ℕ → Sort*} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) : Nat.rec h0 h 0 = h0 := rfl +#align nat.rec_zero Nat.rec_zero + +@[simp] lemma rec_add_one {C : ℕ → Sort*} (h0 : C 0) (h : ∀ n, C n → C (n + 1)) (n : ℕ) : + Nat.rec h0 h (n + 1) = h n (Nat.rec h0 h n) := rfl +#align nat.rec_add_one Nat.rec_add_one + +/-- Recursion starting at a non-zero number: given a map `C k → C (k+1)` for each `k ≥ n`, +there is a map from `C n` to each `C m`, `n ≤ m`. -/ +@[elab_as_elim] +def leRecOn' {C : ℕ → Sort*} : ∀ {m}, n ≤ m → (∀ ⦃k⦄, n ≤ k → C k → C (k + 1)) → C n → C m + | 0, H, _, x => Eq.recOn (Nat.eq_zero_of_le_zero H) x + | m + 1, H, next, x => (le_succ_iff.1 H).by_cases (fun h : n ≤ m ↦ next h <| leRecOn' h next x) + fun h : n = m + 1 ↦ Eq.recOn h x +#align nat.le_rec_on' Nat.leRecOn' + +/-- Recursion starting at a non-zero number: given a map `C k → C (k + 1)` for each `k`, +there is a map from `C n` to each `C m`, `n ≤ m`. For a version where the assumption is only made +when `k ≥ n`, see `Nat.leRecOn'`. -/ +@[elab_as_elim] +def leRecOn {C : ℕ → Sort*} {n : ℕ} : ∀ {m}, n ≤ m → (∀ {k}, C k → C (k + 1)) → C n → C m + | 0, H, _, x => Eq.recOn (Nat.eq_zero_of_le_zero H) x + | m + 1, H, next, x => (le_succ_iff.1 H).by_cases (fun h : n ≤ m ↦ next <| leRecOn h next x) + fun h : n = m + 1 ↦ Eq.recOn h x +#align nat.le_rec_on Nat.leRecOn + +lemma leRecOn_self {C : ℕ → Sort*} {n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) : + (leRecOn n.le_refl next x : C n) = x := by cases n <;> simp [leRecOn, Or.by_cases, dif_neg] +#align nat.le_rec_on_self Nat.leRecOn_self + +lemma leRecOn_succ {C : ℕ → Sort*} {n m} (h1 : n ≤ m) {h2 : n ≤ m + 1} {next} (x : C n) : + (leRecOn h2 next x : C (m + 1)) = next (leRecOn h1 next x : C m) := by + conv => + lhs + rw [leRecOn, Or.by_cases, dif_pos h1] +#align nat.le_rec_on_succ Nat.leRecOn_succ + +lemma leRecOn_succ' {C : ℕ → Sort*} {n} {h : n ≤ n + 1} {next : ∀ {k}, C k → C (k + 1)} (x : C n) : + (leRecOn h next x : C (n + 1)) = next x := by rw [leRecOn_succ (le_refl n), leRecOn_self] +#align nat.le_rec_on_succ' Nat.leRecOn_succ' + +lemma leRecOn_trans {C : ℕ → Sort*} {n m k} (hnm : n ≤ m) (hmk : m ≤ k) {next} (x : C n) : + (leRecOn (le_trans hnm hmk) (@next) x : C k) = leRecOn hmk (@next) (leRecOn hnm (@next) x) := by + induction' hmk with k hmk ih + · rw [leRecOn_self] + · rw [leRecOn_succ (le_trans hnm hmk), ih, leRecOn_succ] +#align nat.le_rec_on_trans Nat.leRecOn_trans + +lemma leRecOn_succ_left {C : ℕ → Sort*} {n m} (h1 : n ≤ m) (h2 : n + 1 ≤ m) + {next : ∀ {k}, C k → C (k + 1)} (x : C n) : + (leRecOn h2 next (next x) : C m) = (leRecOn h1 next x : C m) := by + rw [Subsingleton.elim h1 (le_trans (le_succ n) h2), leRecOn_trans (le_succ n) h2, leRecOn_succ'] +#align nat.le_rec_on_succ_left Nat.leRecOn_succ_left + +lemma leRecOn_injective {C : ℕ → Sort*} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1)) + (Hnext : ∀ n, Injective (@next n)) : Injective (@leRecOn C n m hnm next) := by + induction' hnm with m hnm ih + · intro x y H + rwa [leRecOn_self, leRecOn_self] at H + intro x y H + rw [leRecOn_succ hnm, leRecOn_succ hnm] at H + exact ih (Hnext _ H) +#align nat.le_rec_on_injective Nat.leRecOn_injective + +lemma leRecOn_surjective {C : ℕ → Sort*} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1)) + (Hnext : ∀ n, Surjective (@next n)) : Surjective (@leRecOn C n m hnm next) := by + induction' hnm with m hnm ih + · intro x + use x + rw [leRecOn_self] + intro x + obtain ⟨w, rfl⟩ := Hnext _ x + obtain ⟨x, rfl⟩ := ih w + use x + rw [leRecOn_succ] +#align nat.le_rec_on_surjective Nat.leRecOn_surjective + +/-- Recursion principle based on `<`. -/ +@[elab_as_elim] +protected def strongRec' {p : ℕ → Sort*} (H : ∀ n, (∀ m, m < n → p m) → p n) : ∀ n : ℕ, p n + | n => H n fun m _ ↦ Nat.strongRec' H m +#align nat.strong_rec' Nat.strongRec' + +/-- Recursion principle based on `<` applied to some natural number. -/ +@[elab_as_elim] +def strongRecOn' {P : ℕ → Sort*} (n : ℕ) (h : ∀ n, (∀ m, m < n → P m) → P n) : P n := + Nat.strongRec' h n +#align nat.strong_rec_on' Nat.strongRecOn' + +lemma strongRecOn'_beta {P : ℕ → Sort*} {h} : + (strongRecOn' n h : P n) = h n fun m _ ↦ (strongRecOn' m h : P m) := by + simp only [strongRecOn']; rw [Nat.strongRec'] +#align nat.strong_rec_on_beta' Nat.strongRecOn'_beta + +/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `leRecOn`. +To use in an induction proof, the syntax is `induction n, hn using Nat.le_induction` (or the same +for `induction'`). -/ +@[elab_as_elim] +lemma le_induction {m : ℕ} {P : ∀ n, m ≤ n → Prop} (base : P m m.le_refl) + (succ : ∀ n hmn, P n hmn → P (n + 1) (le_succ_of_le hmn)) : ∀ n hmn, P n hmn := fun n hmn ↦ by + apply Nat.le.rec + · exact base + · intros n hn + apply succ n hn +#align nat.le_induction Nat.le_induction + +/-- Decreasing induction: if `P (k+1)` implies `P k`, then `P n` implies `P m` for all `m ≤ n`. +Also works for functions to `Sort*`. For m version assuming only the assumption for `k < n`, see +`decreasing_induction'`. -/ +@[elab_as_elim] +def decreasingInduction {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) (mn : m ≤ n) (hP : P n) : P m := + leRecOn mn (fun {k} ih hsk ↦ ih <| h k hsk) (fun h ↦ h) hP +#align nat.decreasing_induction Nat.decreasingInduction + +@[simp] +lemma decreasingInduction_self {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) (nn : n ≤ n) + (hP : P n) : + (decreasingInduction h nn hP : P n) = hP := by + dsimp only [decreasingInduction] + rw [leRecOn_self] +#align nat.decreasing_induction_self Nat.decreasingInduction_self + +lemma decreasingInduction_succ {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) (mn : m ≤ n) + (msn : m ≤ n + 1) (hP : P (n + 1)) : + (decreasingInduction h msn hP : P m) = decreasingInduction h mn (h n hP) := by + dsimp only [decreasingInduction]; rw [leRecOn_succ] +#align nat.decreasing_induction_succ Nat.decreasingInduction_succ + +@[simp] +lemma decreasingInduction_succ' {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m : ℕ} + (msm : m ≤ m + 1) (hP : P (m + 1)) : decreasingInduction h msm hP = h m hP := by + dsimp only [decreasingInduction]; rw [leRecOn_succ'] +#align nat.decreasing_induction_succ' Nat.decreasingInduction_succ' + +lemma decreasingInduction_trans {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) + (hmn : m ≤ n) (hnk : n ≤ k) (hP : P k) : + (decreasingInduction h (le_trans hmn hnk) hP : P m) = + decreasingInduction h hmn (decreasingInduction h hnk hP) := by + induction' hnk with k hnk ih + · rw [decreasingInduction_self] + · rw [decreasingInduction_succ h (le_trans hmn hnk), ih, decreasingInduction_succ] +#align nat.decreasing_induction_trans Nat.decreasingInduction_trans + +lemma decreasingInduction_succ_left {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) + (smn : m + 1 ≤ n) (mn : m ≤ n) (hP : P n) : + decreasingInduction h mn hP = h m (decreasingInduction h smn hP) := by + rw [Subsingleton.elim mn (le_trans (le_succ m) smn), decreasingInduction_trans, + decreasingInduction_succ'] + apply Nat.le_succ +#align nat.decreasing_induction_succ_left Nat.decreasingInduction_succ_left + +/-- Given `P : ℕ → ℕ → Sort*`, if for all `m n : ℕ` we can extend `P` from the rectangle +strictly below `(m, n)` to `P m n`, then we have `P n m` for all `n m : ℕ`. +Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible, +since this produces equation lemmas. -/ +@[elab_as_elim] +def strongSubRecursion {P : ℕ → ℕ → Sort*} (H : ∀ m n, (∀ x y, x < m → y < n → P x y) → P m n) : + ∀ n m : ℕ, P n m + | n, m => H n m fun x y _ _ ↦ strongSubRecursion H x y +#align nat.strong_sub_recursion Nat.strongSubRecursion + +/-- Given `P : ℕ → ℕ → Sort*`, if we have `P m 0` and `P 0 n` for all `m n : ℕ`, and for any +`m n : ℕ` we can extend `P` from `(m, n + 1)` and `(m + 1, n)` to `(m + 1, n + 1)` then we have +`P m n` for all `m n : ℕ`. + +Note that for non-`Prop` output it is preferable to use the equation compiler directly if possible, +since this produces equation lemmas. -/ +@[elab_as_elim] +def pincerRecursion {P : ℕ → ℕ → Sort*} (Ha0 : ∀ m : ℕ, P m 0) (H0b : ∀ n : ℕ, P 0 n) + (H : ∀ x y : ℕ, P x y.succ → P x.succ y → P x.succ y.succ) : ∀ n m : ℕ, P n m + | m, 0 => Ha0 m + | 0, n => H0b n + | Nat.succ m, Nat.succ n => H _ _ (pincerRecursion Ha0 H0b H _ _) (pincerRecursion Ha0 H0b H _ _) +termination_by n m => n + m +#align nat.pincer_recursion Nat.pincerRecursion + +/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`. +Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/ +@[elab_as_elim] +def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k) + (mn : m ≤ n) (hP : P n) : P m := by + revert h hP + refine' leRecOn' mn _ _ + · intro n mn ih h hP + apply ih + · exact fun k hk ↦ h k (Nat.lt.step hk) + · exact h n (lt_succ_self n) mn hP + · intro _ hP + exact hP +#align nat.decreasing_induction' Nat.decreasingInduction' + +/-! ### `mod`, `dvd` -/ + +lemma mod_eq_iff_lt (hn : n ≠ 0) : m % n = m ↔ m < n := + ⟨fun h ↦ by rw [← h]; exact mod_lt _ $ Nat.pos_iff_ne_zero.2 hn, mod_eq_of_lt⟩ +#align nat.mod_eq_iff_lt Nat.mod_eq_iff_lt + +@[simp] +lemma mod_succ_eq_iff_lt : m % n.succ = m ↔ m < n.succ := + mod_eq_iff_lt (succ_ne_zero _) +#align nat.mod_succ_eq_iff_lt Nat.mod_succ_eq_iff_lt + +@[simp] lemma mod_succ (n : ℕ) : n % n.succ = n := mod_eq_of_lt n.lt_succ_self + +-- Porting note `Nat.div_add_mod` is now in core. + +lemma mod_add_div' (a b : ℕ) : a % b + a / b * b = a := by rw [Nat.mul_comm]; exact mod_add_div _ _ +#align nat.mod_add_div' Nat.mod_add_div' + +lemma div_add_mod' (a b : ℕ) : a / b * b + a % b = a := by rw [Nat.mul_comm]; exact div_add_mod _ _ +#align nat.div_add_mod' Nat.div_add_mod' + +/-- See also `Nat.divModEquiv` for a similar statement as an `Equiv`. -/ +protected lemma div_mod_unique (h : 0 < b) : + a / b = d ∧ a % b = c ↔ c + b * d = a ∧ c < b := + ⟨fun ⟨e₁, e₂⟩ ↦ e₁ ▸ e₂ ▸ ⟨mod_add_div _ _, mod_lt _ h⟩, fun ⟨h₁, h₂⟩ ↦ h₁ ▸ by + rw [add_mul_div_left _ _ h, add_mul_mod_self_left]; simp [div_eq_of_lt, mod_eq_of_lt, h₂]⟩ +#align nat.div_mod_unique Nat.div_mod_unique + +-- TODO: Replace `Nat.dvd_add_iff_left` +protected lemma dvd_add_left (h : a ∣ c) : a ∣ b + c ↔ a ∣ b := (Nat.dvd_add_iff_left h).symm +#align nat.dvd_add_left Nat.dvd_add_left + +protected lemma dvd_add_right (h : a ∣ b) : a ∣ b + c ↔ a ∣ c := (Nat.dvd_add_iff_right h).symm +#align nat.dvd_add_right Nat.dvd_add_right + +protected lemma mul_dvd_mul_iff_left (ha : 0 < a) : a * b ∣ a * c ↔ b ∣ c := + exists_congr fun d ↦ by rw [Nat.mul_assoc, Nat.mul_right_inj $ ne_of_gt ha] +#align nat.mul_dvd_mul_iff_left Nat.mul_dvd_mul_iff_left + +protected lemma mul_dvd_mul_iff_right (hc : 0 < c) : a * c ∣ b * c ↔ a ∣ b := + exists_congr fun d ↦ by rw [Nat.mul_right_comm, Nat.mul_left_inj $ ne_of_gt hc] +#align nat.mul_dvd_mul_iff_right Nat.mul_dvd_mul_iff_right + +#align nat.dvd_one Nat.dvd_one + +@[simp] lemma mod_mod_of_dvd (a : ℕ) (h : c ∣ b) : a % b % c = a % c := by + conv_rhs => rw [← mod_add_div a b] + obtain ⟨x, rfl⟩ := h + rw [Nat.mul_assoc, add_mul_mod_self_left] +#align nat.mod_mod_of_dvd Nat.mod_mod_of_dvd + +-- Moved to Std +#align nat.mod_mod Nat.mod_mod +#align nat.mod_add_mod Nat.mod_add_mod +#align nat.add_mod_mod Nat.add_mod_mod +#align nat.add_mod Nat.add_mod + +lemma add_mod_eq_add_mod_right (c : ℕ) (H : a % d = b % d) : (a + c) % d = (b + c) % d := by + rw [← mod_add_mod, ← mod_add_mod b, H] +#align nat.add_mod_eq_add_mod_right Nat.add_mod_eq_add_mod_right + +lemma add_mod_eq_add_mod_left (c : ℕ) (H : a % d = b % d) : (c + a) % d = (c + b) % d := by + rw [Nat.add_comm, add_mod_eq_add_mod_right _ H, Nat.add_comm] +#align nat.add_mod_eq_add_mod_left Nat.add_mod_eq_add_mod_left + +-- Moved to Std +#align nat.mul_mod Nat.mul_mod + +lemma mul_dvd_of_dvd_div (hcb : c ∣ b) (h : a ∣ b / c) : c * a ∣ b := + have ⟨d, hd⟩ := h + ⟨d, by simpa [Nat.mul_comm, Nat.mul_left_comm] using Nat.eq_mul_of_div_eq_left hcb hd⟩ +#align nat.mul_dvd_of_dvd_div Nat.mul_dvd_of_dvd_div + +lemma eq_of_dvd_of_div_eq_one (hab : a ∣ b) (h : b / a = 1) : a = b := by + rw [← Nat.div_mul_cancel hab, h, Nat.one_mul] +#align nat.eq_of_dvd_of_div_eq_one Nat.eq_of_dvd_of_div_eq_one + +lemma eq_zero_of_dvd_of_div_eq_zero (hab : a ∣ b) (h : b / a = 0) : b = 0 := by + rw [← Nat.div_mul_cancel hab, h, Nat.zero_mul] +#align nat.eq_zero_of_dvd_of_div_eq_zero Nat.eq_zero_of_dvd_of_div_eq_zero + +lemma div_le_div_left (hcb : c ≤ b) (hc : 0 < c) : a / b ≤ a / c := + (Nat.le_div_iff_mul_le hc).2 <| le_trans (Nat.mul_le_mul_left _ hcb) (div_mul_le_self _ _) +#align nat.div_le_div_left Nat.div_le_div_left + +-- Moved to Std +#align nat.mul_div_le Nat.mul_div_le + +lemma lt_mul_div_succ (a : ℕ) (hb : 0 < b) : a < b * (a / b + 1) := by + rw [Nat.mul_comm, ← Nat.div_lt_iff_lt_mul' hb] + exact lt_succ_self _ +#align nat.lt_mul_div_succ Nat.lt_mul_div_succ + +-- TODO: Std4 claimed this name but flipped the order of multiplication +lemma mul_add_mod' (a b c : ℕ) : (a * b + c) % b = c % b := by rw [Nat.mul_comm, Nat.mul_add_mod] +#align nat.mul_add_mod Nat.mul_add_mod' + +lemma mul_add_mod_of_lt (h : c < b) : (a * b + c) % b = c := by + rw [Nat.mul_add_mod', Nat.mod_eq_of_lt h] +#align nat.mul_add_mod_of_lt Nat.mul_add_mod_of_lt + +/-! ### `find` -/ + +section Find +variable [DecidablePred p] [DecidablePred q] + +lemma find_eq_iff (h : ∃ n : ℕ, p n) : Nat.find h = m ↔ p m ∧ ∀ n < m, ¬ p n := by + constructor + · rintro rfl + exact ⟨Nat.find_spec h, fun _ ↦ Nat.find_min h⟩ + · rintro ⟨hm, hlt⟩ + exact le_antisymm (Nat.find_min' h hm) (not_lt.1 <| imp_not_comm.1 (hlt _) <| Nat.find_spec h) +#align nat.find_eq_iff Nat.find_eq_iff + +@[simp] lemma find_lt_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h < n ↔ ∃ m < n, p m := + ⟨fun h2 ↦ ⟨Nat.find h, h2, Nat.find_spec h⟩, + fun ⟨_, hmn, hm⟩ ↦ Nat.lt_of_le_of_lt (Nat.find_min' h hm) hmn⟩ +#align nat.find_lt_iff Nat.find_lt_iff + +@[simp] lemma find_le_iff (h : ∃ n : ℕ, p n) (n : ℕ) : Nat.find h ≤ n ↔ ∃ m ≤ n, p m := by + simp only [exists_prop, ← lt_succ_iff, find_lt_iff] +#align nat.find_le_iff Nat.find_le_iff + +@[simp] lemma le_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n ≤ Nat.find h ↔ ∀ m < n, ¬ p m := by + simp only [← not_lt, find_lt_iff, not_exists, not_and] +#align nat.le_find_iff Nat.le_find_iff + +@[simp] lemma lt_find_iff (h : ∃ n : ℕ, p n) (n : ℕ) : n < Nat.find h ↔ ∀ m ≤ n, ¬ p m := by + simp only [← succ_le_iff, le_find_iff, succ_le_succ_iff] +#align nat.lt_find_iff Nat.lt_find_iff + +@[simp] lemma find_eq_zero (h : ∃ n : ℕ, p n) : Nat.find h = 0 ↔ p 0 := by simp [find_eq_iff] +#align nat.find_eq_zero Nat.find_eq_zero + +lemma find_mono (h : ∀ n, q n → p n) {hp : ∃ n, p n} {hq : ∃ n, q n} : Nat.find hp ≤ Nat.find hq := + Nat.find_min' _ (h _ (Nat.find_spec hq)) +#align nat.find_mono Nat.find_mono + +lemma find_le {h : ∃ n, p n} (hn : p n) : Nat.find h ≤ n := + (Nat.find_le_iff _ _).2 ⟨n, le_refl _, hn⟩ +#align nat.find_le Nat.find_le + +lemma find_comp_succ (h₁ : ∃ n, p n) (h₂ : ∃ n, p (n + 1)) (h0 : ¬ p 0) : + Nat.find h₁ = Nat.find h₂ + 1 := by + refine' (find_eq_iff _).2 ⟨Nat.find_spec h₂, fun n hn ↦ _⟩ + cases' n with n + exacts [h0, @Nat.find_min (fun n ↦ p (n + 1)) _ h₂ _ (succ_lt_succ_iff.1 hn)] +#align nat.find_comp_succ Nat.find_comp_succ + +end Find + +/-! ### `find_greatest` -/ + +section FindGreatest + +/-- `find_greatest P n` is the largest `i ≤ bound` such that `P i` holds, or `0` if no such `i` +exists -/ +def findGreatest (P : ℕ → Prop) [DecidablePred P] : ℕ → ℕ + | 0 => 0 + | n + 1 => if P (n + 1) then n + 1 else Nat.findGreatest P n +#align nat.find_greatest Nat.findGreatest + +variable {P Q : ℕ → Prop} [DecidablePred P] {n : ℕ} + +@[simp] lemma findGreatest_zero : Nat.findGreatest P 0 = 0 := rfl +#align nat.find_greatest_zero Nat.findGreatest_zero + +lemma findGreatest_succ (n : ℕ) : + Nat.findGreatest P (n + 1) = if P (n + 1) then n + 1 else Nat.findGreatest P n := rfl +#align nat.find_greatest_succ Nat.findGreatest_succ + +@[simp] lemma findGreatest_eq : ∀ {n}, P n → Nat.findGreatest P n = n + | 0, _ => rfl + | n + 1, h => by simp [Nat.findGreatest, h] +#align nat.find_greatest_eq Nat.findGreatest_eq + +@[simp] +lemma findGreatest_of_not (h : ¬ P (n + 1)) : findGreatest P (n + 1) = findGreatest P n := by + simp [Nat.findGreatest, h] +#align nat.find_greatest_of_not Nat.findGreatest_of_not + +end FindGreatest + +/-! ### Decidability of predicates -/ + +-- To work around lean4#2552, we use `match` instead of `if/casesOn` with decidable instances. +instance decidableBallLT : + ∀ (n : Nat) (P : ∀ k, k < n → Prop) [∀ n h, Decidable (P n h)], Decidable (∀ n h, P n h) +| 0, _, _ => isTrue fun _ ↦ (by cases ·) +| n + 1, P, H => + match decidableBallLT n (P · <| lt_succ_of_lt ·) with + | isFalse h => isFalse (h fun _ _ ↦ · _ _) + | isTrue h => + match H n Nat.le.refl with + | isFalse p => isFalse (p <| · _ _) + | isTrue p => isTrue fun _ h' ↦ (lt_succ_iff_lt_or_eq.1 h').elim (h _) fun hn ↦ hn ▸ p +#align nat.decidable_ball_lt Nat.decidableBallLT + +-- To verify we don't have a regression on the speed, we put a difficult example. +-- any regression should take a huge amount of heartbeats -- we are currently at 187621. +-- For reference, the instance using `casesOn` took 44544 for 4; this one takes 1299 for 4. +example : ∀ m, m < 25 → ∀ n, n < 25 → ∀ c, c < 25 → m ^ 2 + n ^ 2 + c ^ 2 ≠ 7 := by decide + +instance decidableForallFin (P : Fin n → Prop) [DecidablePred P] : Decidable (∀ i, P i) := + decidable_of_iff (∀ k h, P ⟨k, h⟩) ⟨fun m ⟨k, h⟩ ↦ m k h, fun m k h ↦ m ⟨k, h⟩⟩ +#align nat.decidable_forall_fin Nat.decidableForallFin + +instance decidableBallLe (n : ℕ) (P : ∀ k ≤ n, Prop) [∀ n h, Decidable (P n h)] : + Decidable (∀ n h, P n h) := + decidable_of_iff (∀ (k) (h : k < succ n), P k (le_of_lt_succ h)) + ⟨fun m k h ↦ m k (lt_succ_of_le h), fun m k _ ↦ m k _⟩ +#align nat.decidable_ball_le Nat.decidableBallLe + +instance decidableExistsLT [h : DecidablePred p] : DecidablePred fun n ↦ ∃ m : ℕ, m < n ∧ p m + | 0 => isFalse (by simp) + | n + 1 => + @decidable_of_decidable_of_iff _ _ (@instDecidableOr _ _ (decidableExistsLT n) (h n)) + (by simp only [lt_succ_iff_lt_or_eq, or_and_right, exists_or, exists_eq_left]) +#align nat.decidable_exists_lt Nat.decidableExistsLT + +instance decidableExistsLe [DecidablePred p] : DecidablePred fun n ↦ ∃ m : ℕ, m ≤ n ∧ p m := + fun n ↦ decidable_of_iff (∃ m, m < n + 1 ∧ p m) + (exists_congr fun _ ↦ and_congr_left' lt_succ_iff) +#align nat.decidable_exists_le Nat.decidableExistsLe + +end Nat diff --git a/Mathlib/Data/Nat/Digits.lean b/Mathlib/Data/Nat/Digits.lean index af18ab0eb595e..095f725864278 100644 --- a/Mathlib/Data/Nat/Digits.lean +++ b/Mathlib/Data/Nat/Digits.lean @@ -559,7 +559,7 @@ theorem sub_one_mul_sum_div_pow_eq_sub_sum_digits ← Nat.one_add] at ih have := sum_singleton (fun x ↦ ofDigits p <| tl.drop x) tl.length rw [← Ico_succ_singleton, List.drop_length, ofDigits] at this - have h₁ : 1 ≤ tl.length := List.length_pos.mpr h' + have h₁ : 1 ≤ tl.length := List.length_pos.mpr h' rw [← sum_range_add_sum_Ico _ <| h₁, ← add_zero (∑ x in Ico _ _, ofDigits p (tl.drop x)), ← this, sum_Ico_consecutive _ h₁ <| le_succ tl.length, ← sum_Ico_add _ 0 tl.length 1, Ico_zero_eq_range, mul_add, mul_add, ih, range_one, sum_singleton, List.drop, ofDigits, diff --git a/Mathlib/Data/Nat/EvenOddRec.lean b/Mathlib/Data/Nat/EvenOddRec.lean index 6036ef01b99e4..34b38b9565055 100644 --- a/Mathlib/Data/Nat/EvenOddRec.lean +++ b/Mathlib/Data/Nat/EvenOddRec.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Stuart Presnell. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Stuart Presnell -/ -import Mathlib.Data.Nat.Basic import Mathlib.Init.Data.Nat.Bitwise #align_import data.nat.even_odd_rec from "leanprover-community/mathlib"@"18a5306c091183ac90884daa9373fa3b178e8607" diff --git a/Mathlib/Data/Nat/Factorial/Basic.lean b/Mathlib/Data/Nat/Factorial/Basic.lean index 14afd1fc03435..44d7f93559dde 100644 --- a/Mathlib/Data/Nat/Factorial/Basic.lean +++ b/Mathlib/Data/Nat/Factorial/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Chris Hughes, Floris van Doorn, Yaël Dillies -/ -import Mathlib.Data.Nat.Basic import Mathlib.Data.Nat.Pow import Mathlib.Tactic.GCongr.Core import Mathlib.Tactic.Common @@ -18,9 +17,10 @@ This file defines the factorial, along with the ascending and descending variant ## Main declarations * `Nat.factorial`: The factorial. -* `Nat.ascFactorial`: The ascending factorial. Note that it runs from `n + 1` to `n + k` - and *not* from `n` to `n + k - 1`. We might want to change that in the future. -* `Nat.descFactorial`: The descending factorial. It runs from `n - k` to `n`. +* `Nat.ascFactorial`: The ascending factorial. It is the product of natural numbers from `n` to + `n + k - 1`. +* `Nat.descFactorial`: The descending factorial. It is the product of natural numbers from + `n - k + 1` to `n`. -/ @@ -207,6 +207,14 @@ theorem factorial_mul_pow_sub_le_factorial {n m : ℕ} (hnm : n ≤ m) : n ! * n _ ≤ _ := by simpa [hnm] using @Nat.factorial_mul_pow_le_factorial n (m - n) #align nat.factorial_mul_pow_sub_le_factorial Nat.factorial_mul_pow_sub_le_factorial +lemma factorial_le_pow : ∀ n, n ! ≤ n ^ n + | 0 => le_rfl + | n + 1 => + calc + _ ≤ (n + 1) * n ^ n := mul_le_mul_left' n.factorial_le_pow _ + _ ≤ (n + 1) * (n + 1) ^ n := mul_le_mul_left' (Nat.pow_le_pow_left n.le_succ _) _ + _ = _ := by rw [pow_succ'] + end Factorial /-! ### Ascending and descending factorials -/ @@ -214,12 +222,11 @@ end Factorial section AscFactorial -/-- `n.ascFactorial k = (n + k)! / n!` (as seen in `Nat.ascFactorial_eq_div`), but implemented -recursively to allow for "quick" computation when using `norm_num`. This is closely related to -`ascPochhammer`, but much less general. -/ +/-- `n.ascFactorial k = n (n + 1) ⋯ (n + k - 1)`. This is closely related to `ascPochhammer`, but +much less general. -/ def ascFactorial (n : ℕ) : ℕ → ℕ | 0 => 1 - | k + 1 => (n + k + 1) * ascFactorial n k + | k + 1 => (n + k) * ascFactorial n k #align nat.asc_factorial Nat.ascFactorial @[simp] @@ -227,87 +234,107 @@ theorem ascFactorial_zero (n : ℕ) : n.ascFactorial 0 = 1 := rfl #align nat.asc_factorial_zero Nat.ascFactorial_zero -@[simp] -theorem zero_ascFactorial (k : ℕ) : (0 : ℕ).ascFactorial k = k ! := by - induction' k with t ht - · rfl - rw [ascFactorial, ht, zero_add, Nat.factorial_succ] -#align nat.zero_asc_factorial Nat.zero_ascFactorial - -theorem ascFactorial_succ {n k : ℕ} : n.ascFactorial (k + 1) = (n + k + 1) * n.ascFactorial k := +theorem ascFactorial_succ {n k : ℕ} : n.ascFactorial k.succ = (n + k) * n.ascFactorial k := rfl #align nat.asc_factorial_succ Nat.ascFactorial_succ +theorem zero_ascFactorial : ∀ (k : ℕ), (0 : ℕ).ascFactorial k.succ = 0 + | 0 => by + rw [ascFactorial_succ, ascFactorial_zero, zero_add, zero_mul] + | (k+1) => by + rw [ascFactorial_succ, zero_ascFactorial k, mul_zero] + +@[simp] +theorem one_ascFactorial : ∀ (k : ℕ), (1 : ℕ).ascFactorial k = k.factorial + | 0 => ascFactorial_zero 1 + | (k+1) => by + rw [ascFactorial_succ, one_ascFactorial k, add_comm, factorial_succ] + theorem succ_ascFactorial (n : ℕ) : - ∀ k, (n + 1) * n.succ.ascFactorial k = (n + k + 1) * n.ascFactorial k + ∀ k, n * n.succ.ascFactorial k = (n + k) * n.ascFactorial k | 0 => by rw [add_zero, ascFactorial_zero, ascFactorial_zero] | k + 1 => by rw [ascFactorial, mul_left_comm, succ_ascFactorial n k, ascFactorial, succ_add, ← add_assoc] #align nat.succ_asc_factorial Nat.succ_ascFactorial -/-- `n.ascFactorial k = (n + k)! / n!` but without ℕ-division. See `Nat.ascFactorial_eq_div` for -the version with ℕ-division. -/ -theorem factorial_mul_ascFactorial (n : ℕ) : ∀ k, n ! * n.ascFactorial k = (n + k)! - | 0 => by simp +/-- `(n + 1).ascFactorial k = (n + k) ! / n !` but without ℕ-division. See +`Nat.ascFactorial_eq_div` for the version with ℕ-division. -/ +theorem factorial_mul_ascFactorial (n : ℕ) : ∀ k, n ! * (n + 1).ascFactorial k = (n + k)! + | 0 => by + rw [add_zero, ascFactorial_zero, mul_one] | k + 1 => by - rw [ascFactorial_succ, mul_left_comm, factorial_mul_ascFactorial n k, ← add_assoc, factorial] + rw [ascFactorial_succ, ← add_assoc, factorial_succ, mul_comm (n + 1 + k), ← mul_assoc, + factorial_mul_ascFactorial n k, mul_comm, add_right_comm] #align nat.factorial_mul_asc_factorial Nat.factorial_mul_ascFactorial +/-- `n.ascFactorial k = (n + k - 1)! / (n - 1)!` for `n > 0` but without ℕ-division. See +`Nat.ascFactorial_eq_div` for the version with ℕ-division. Consider using +`factorial_mul_ascFactorial` to avoid complications of ℕ-subtraction. -/ +theorem factorial_mul_ascFactorial' (n k : ℕ) (h : 0 < n) : + (n - 1) ! * n.ascFactorial k = (n + k - 1)! := by + rw [Nat.sub_add_comm h, Nat.sub_one] + nth_rw 2 [Nat.eq_add_of_sub_eq h rfl] + rw [Nat.sub_one, factorial_mul_ascFactorial] + /-- Avoid in favor of `Nat.factorial_mul_ascFactorial` if you can. ℕ-division isn't worth it. -/ -theorem ascFactorial_eq_div (n k : ℕ) : n.ascFactorial k = (n + k)! / n ! := by +theorem ascFactorial_eq_div (n k : ℕ) : (n + 1).ascFactorial k = (n + k)! / n ! := by apply mul_left_cancel₀ n.factorial_ne_zero rw [factorial_mul_ascFactorial] - exact (Nat.mul_div_cancel' <| factorial_dvd_factorial <| le.intro rfl).symm + exact (Nat.mul_div_cancel_left' <| factorial_dvd_factorial <| le_add_right n k).symm + +/-- Avoid in favor of `Nat.factorial_mul_ascFactorial` if you can. -/ +theorem ascFactorial_eq_div' (n k : ℕ) (h : 0 < n) : + n.ascFactorial k = (n + k - 1)! / (n - 1) ! := by + apply mul_left_cancel₀ (n-1).factorial_ne_zero + rw [factorial_mul_ascFactorial' _ _ h] + exact (Nat.mul_div_cancel_left' <| factorial_dvd_factorial <| Nat.sub_le_sub_right + (le_add_right n k) 1).symm #align nat.asc_factorial_eq_div Nat.ascFactorial_eq_div -theorem ascFactorial_of_sub {n k : ℕ} (h : k < n) : - (n - k) * (n - k).ascFactorial k = (n - (k + 1)).ascFactorial (k + 1) := by - let t := n - (k + 1) - suffices h' : n - k = t + 1 by rw [h', succ_ascFactorial, ascFactorial_succ] - rw [← tsub_tsub_assoc (succ_le_of_lt h) (succ_pos k), succ_sub_one] +theorem ascFactorial_of_sub {n k : ℕ}: + (n - k) * (n - k + 1).ascFactorial k = (n - k).ascFactorial (k + 1) := by + rw [succ_ascFactorial, ascFactorial_succ] #align nat.asc_factorial_of_sub Nat.ascFactorial_of_sub -theorem pow_succ_le_ascFactorial (n : ℕ) : ∀ k : ℕ, (n + 1) ^ k ≤ n.ascFactorial k +theorem pow_succ_le_ascFactorial (n : ℕ) : ∀ k : ℕ, n ^ k ≤ n.ascFactorial k | 0 => by rw [ascFactorial_zero, pow_zero] | k + 1 => by - rw [pow_succ, mul_comm] - exact Nat.mul_le_mul (Nat.add_le_add_right le_self_add _) (pow_succ_le_ascFactorial _ k) + rw [pow_succ, mul_comm, ascFactorial_succ, ← succ_ascFactorial] + exact Nat.mul_le_mul (Nat.le_refl n) + ((pow_le_pow_of_le_left (le_succ n) k).trans (pow_succ_le_ascFactorial n.succ k)) #align nat.pow_succ_le_asc_factorial Nat.pow_succ_le_ascFactorial -theorem pow_lt_ascFactorial' (n k : ℕ) : (n + 1) ^ (k + 2) < n.ascFactorial (k + 2) := by +theorem pow_lt_ascFactorial' (n k : ℕ) : (n + 1) ^ (k + 2) < (n + 1).ascFactorial (k + 2) := by rw [pow_succ, ascFactorial, mul_comm] - exact - Nat.mul_lt_mul (Nat.add_lt_add_right (Nat.lt_add_of_pos_right succ_pos') 1) - (pow_succ_le_ascFactorial n _) (pow_pos succ_pos' _) + exact Nat.mul_lt_mul_of_lt_of_le' (lt_add_of_pos_right (n + 1) (succ_pos k)) + (pow_succ_le_ascFactorial n.succ _) (NeZero.pos ((n + 1) ^ (k + 1))) #align nat.pow_lt_asc_factorial' Nat.pow_lt_ascFactorial' -theorem pow_lt_ascFactorial (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → (n + 1) ^ k < n.ascFactorial k +theorem pow_lt_ascFactorial (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → (n + 1) ^ k < (n + 1).ascFactorial k | 0 => by rintro ⟨⟩ | 1 => by intro; contradiction | k + 2 => fun _ => pow_lt_ascFactorial' n k #align nat.pow_lt_asc_factorial Nat.pow_lt_ascFactorial -theorem ascFactorial_le_pow_add (n : ℕ) : ∀ k : ℕ, n.ascFactorial k ≤ (n + k) ^ k +theorem ascFactorial_le_pow_add (n : ℕ) : ∀ k : ℕ, (n+1).ascFactorial k ≤ (n + k) ^ k | 0 => by rw [ascFactorial_zero, pow_zero] | k + 1 => by - rw [ascFactorial_succ, pow_succ, ← add_assoc, mul_comm _ (succ (n + k))] - exact - Nat.mul_le_mul_of_nonneg_left - ((ascFactorial_le_pow_add _ k).trans (Nat.pow_le_pow_left (le_succ _) _)) + rw [ascFactorial_succ, pow_succ, mul_comm, ← add_assoc, add_right_comm n 1 k] + exact Nat.mul_le_mul_right _ + ((ascFactorial_le_pow_add _ k).trans (Nat.pow_le_pow_of_le_left (le_succ _) _)) #align nat.asc_factorial_le_pow_add Nat.ascFactorial_le_pow_add -theorem ascFactorial_lt_pow_add (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → n.ascFactorial k < (n + k) ^ k +theorem ascFactorial_lt_pow_add (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → (n + 1).ascFactorial k < (n + k) ^ k | 0 => by rintro ⟨⟩ | 1 => by intro; contradiction | k + 2 => fun _ => by - rw [ascFactorial_succ, pow_succ] - rw [add_assoc n (k + 1) 1, mul_comm <| (n + (k + 2)) ^ (k + 1)] - exact mul_lt_mul_of_pos_left ((ascFactorial_le_pow_add n _).trans_lt $ - Nat.pow_lt_pow_left (lt_add_one _) k.succ_ne_zero) (succ_pos _) + rw [pow_succ, mul_comm, ascFactorial_succ, succ_add_eq_add_succ n (k + 1)] + exact Nat.mul_lt_mul_of_le_of_lt le_rfl ((ascFactorial_le_pow_add n _).trans_lt + (pow_lt_pow_left (@lt_add_one ℕ _ _ _ _ _ _ _) (zero_le _) k.succ_ne_zero)) (succ_pos _) #align nat.asc_factorial_lt_pow_add Nat.ascFactorial_lt_pow_add -theorem ascFactorial_pos (n k : ℕ) : 0 < n.ascFactorial k := - (pow_pos (succ_pos n) k).trans_le (pow_succ_le_ascFactorial n k) +theorem ascFactorial_pos (n k : ℕ) : 0 < (n + 1).ascFactorial k := + (pow_pos (succ_pos n) k).trans_le (pow_succ_le_ascFactorial (n + 1) k) #align nat.asc_factorial_pos Nat.ascFactorial_pos end AscFactorial @@ -371,13 +398,22 @@ theorem descFactorial_eq_zero_iff_lt {n : ℕ} : ∀ {k : ℕ}, n.descFactorial alias ⟨_, descFactorial_of_lt⟩ := descFactorial_eq_zero_iff_lt #align nat.desc_factorial_of_lt Nat.descFactorial_of_lt -theorem add_descFactorial_eq_ascFactorial (n : ℕ) : - ∀ k : ℕ, (n + k).descFactorial k = n.ascFactorial k +theorem add_descFactorial_eq_ascFactorial (n : ℕ) : ∀ k : ℕ, + (n + k).descFactorial k = (n + 1).ascFactorial k | 0 => by rw [ascFactorial_zero, descFactorial_zero] - | succ k => by rw [Nat.add_succ, succ_descFactorial_succ, ascFactorial_succ, - add_descFactorial_eq_ascFactorial _ k] + | succ k => by + rw [Nat.add_succ, succ_descFactorial_succ, ascFactorial_succ, + add_descFactorial_eq_ascFactorial _ k, Nat.add_right_comm] #align nat.add_desc_factorial_eq_asc_factorial Nat.add_descFactorial_eq_ascFactorial +theorem add_descFactorial_eq_ascFactorial' (n : ℕ) : + ∀ k : ℕ, (n + k - 1).descFactorial k = n.ascFactorial k + | 0 => by rw [ascFactorial_zero, descFactorial_zero] + | succ k => by + rw [descFactorial_succ, ascFactorial_succ, ← succ_add_eq_add_succ, + add_descFactorial_eq_ascFactorial' _ k, ← succ_ascFactorial, succ_add_sub_one, + Nat.add_sub_cancel] + /-- `n.descFactorial k = n! / (n - k)!` but without ℕ-division. See `Nat.descFactorial_eq_div` for the version using ℕ-division. -/ theorem factorial_mul_descFactorial : ∀ {n k : ℕ}, k ≤ n → (n - k)! * n.descFactorial k = n ! @@ -401,9 +437,9 @@ theorem pow_sub_le_descFactorial (n : ℕ) : ∀ k : ℕ, (n + 1 - k) ^ k ≤ n. | 0 => by rw [descFactorial_zero, pow_zero] | k + 1 => by rw [descFactorial_succ, pow_succ, succ_sub_succ, mul_comm] - apply Nat.mul_le_mul_of_nonneg_left - exact (le_trans (Nat.pow_le_pow_left (tsub_le_tsub_right (le_succ _) _) k) - (pow_sub_le_descFactorial n k)) + apply Nat.mul_le_mul_left + exact (le_trans (Nat.pow_le_pow_left (tsub_le_tsub_right (le_succ _) _) k) + (pow_sub_le_descFactorial n k)) #align nat.pow_sub_le_desc_factorial Nat.pow_sub_le_descFactorial theorem pow_sub_lt_descFactorial' {n : ℕ} : @@ -443,7 +479,7 @@ theorem descFactorial_lt_pow {n : ℕ} (hn : 1 ≤ n) : ∀ {k : ℕ}, 2 ≤ k | 1 => by intro; contradiction | k + 2 => fun _ => by rw [descFactorial_succ, pow_succ', mul_comm, mul_comm n] - exact Nat.mul_lt_mul' (descFactorial_le_pow _ _) (tsub_lt_self hn k.zero_lt_succ) + exact Nat.mul_lt_mul_of_le_of_lt (descFactorial_le_pow _ _) (tsub_lt_self hn k.zero_lt_succ) (pow_pos (Nat.lt_of_succ_le hn) _) #align nat.desc_factorial_lt_pow Nat.descFactorial_lt_pow diff --git a/Mathlib/Data/Nat/Factorial/Cast.lean b/Mathlib/Data/Nat/Factorial/Cast.lean index 77f9d8cd4e6f8..ba0a529f91c3c 100644 --- a/Mathlib/Data/Nat/Factorial/Cast.lean +++ b/Mathlib/Data/Nat/Factorial/Cast.lean @@ -31,8 +31,8 @@ section Semiring variable [Semiring S] (a b : ℕ) -- Porting note: added type ascription around a + 1 -theorem cast_ascFactorial : (a.ascFactorial b : S) = (ascPochhammer S b).eval (a + 1 : S) := by - rw [← ascPochhammer_nat_eq_ascFactorial, ascPochhammer_eval_cast, Nat.cast_add, Nat.cast_one] +theorem cast_ascFactorial : (a.ascFactorial b : S) = (ascPochhammer S b).eval (a : S) := by + rw [← ascPochhammer_nat_eq_ascFactorial, ascPochhammer_eval_cast] #align nat.cast_asc_factorial Nat.cast_ascFactorial -- Porting note: added type ascription around a - (b - 1) @@ -49,7 +49,7 @@ theorem cast_descFactorial : #align nat.cast_desc_factorial Nat.cast_descFactorial theorem cast_factorial : (a ! : S) = (ascPochhammer S a).eval 1 := by - rw [← zero_ascFactorial, cast_ascFactorial, cast_zero, zero_add] + rw [← one_ascFactorial, cast_ascFactorial, cast_one] #align nat.cast_factorial Nat.cast_factorial end Semiring diff --git a/Mathlib/Data/Nat/Factorial/DoubleFactorial.lean b/Mathlib/Data/Nat/Factorial/DoubleFactorial.lean index 1bda3a8a658b5..f80fd446f4f9c 100644 --- a/Mathlib/Data/Nat/Factorial/DoubleFactorial.lean +++ b/Mathlib/Data/Nat/Factorial/DoubleFactorial.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jake Levinson -/ import Mathlib.Data.Nat.Factorial.Basic -import Mathlib.Algebra.BigOperators.Order +import Mathlib.Algebra.BigOperators.Basic import Mathlib.Tactic.Ring +import Mathlib.Tactic.Positivity.Core #align_import data.nat.factorial.double_factorial from "leanprover-community/mathlib"@"7daeaf3072304c498b653628add84a88d0e78767" @@ -57,7 +58,7 @@ theorem factorial_eq_mul_doubleFactorial : ∀ n : ℕ, (n + 1)! = (n + 1)‼ * lemma doubleFactorial_le_factorial : ∀ n, n‼ ≤ n ! | 0 => le_rfl | n + 1 => by - rw [factorial_eq_mul_doubleFactorial]; exact le_mul_of_pos_right n.doubleFactorial_pos + rw [factorial_eq_mul_doubleFactorial]; exact Nat.le_mul_of_pos_right _ n.doubleFactorial_pos theorem doubleFactorial_two_mul : ∀ n : ℕ, (2 * n)‼ = 2 ^ n * n ! | 0 => rfl diff --git a/Mathlib/Data/Nat/Factorial/SuperFactorial.lean b/Mathlib/Data/Nat/Factorial/SuperFactorial.lean index 104b5946767dc..5079136b1baae 100644 --- a/Mathlib/Data/Nat/Factorial/SuperFactorial.lean +++ b/Mathlib/Data/Nat/Factorial/SuperFactorial.lean @@ -102,7 +102,7 @@ theorem superFactorial_dvd_vandermonde_det {n : ℕ} (v : Fin (n + 1) → ℤ) : let m := inf' univ ⟨0, mem_univ _⟩ v let w' := fun i ↦ (v i - m).toNat have hw' : ∀ i, (w' i : ℤ) = v i - m := fun i ↦ Int.toNat_sub_of_le (inf'_le _ (mem_univ _)) - have h := Matrix.det_eval_matrixOfPolynomials_eq_det_vandermonde (fun i ↦ ↑(w' i)) + have h := Matrix.det_eval_matrixOfPolynomials_eq_det_vandermonde (fun i ↦ ↑(w' i)) (fun i => descPochhammer ℤ i) (fun i => descPochhammer_natDegree ℤ i) (fun i => monic_descPochhammer ℤ i) diff --git a/Mathlib/Data/Nat/Factorization/Basic.lean b/Mathlib/Data/Nat/Factorization/Basic.lean index bee9a51e38009..a78cffcd131d0 100644 --- a/Mathlib/Data/Nat/Factorization/Basic.lean +++ b/Mathlib/Data/Nat/Factorization/Basic.lean @@ -9,6 +9,7 @@ import Mathlib.Data.Nat.PrimeFin import Mathlib.NumberTheory.Padics.PadicVal import Mathlib.Data.Nat.Interval import Mathlib.Tactic.IntervalCases +import Mathlib.Algebra.GroupPower.Order #align_import data.nat.factorization.basic from "leanprover-community/mathlib"@"f694c7dead66f5d4c80f446c796a5aad14707f0e" @@ -157,7 +158,7 @@ theorem factorization_one_right (n : ℕ) : n.factorization 1 = 0 := #align nat.factorization_one_right Nat.factorization_one_right theorem dvd_of_factorization_pos {n p : ℕ} (hn : n.factorization p ≠ 0) : p ∣ n := - dvd_of_mem_factors $ mem_primeFactors_iff_mem_factors.1 $ mem_support_iff.2 hn + dvd_of_mem_factors <| mem_primeFactors_iff_mem_factors.1 <| mem_support_iff.2 hn #align nat.dvd_of_factorization_pos Nat.dvd_of_factorization_pos theorem Prime.factorization_pos_of_dvd {n p : ℕ} (hp : p.Prime) (hn : n ≠ 0) (h : p ∣ n) : @@ -390,7 +391,8 @@ theorem ord_compl_mul (a b p : ℕ) : ord_compl[p] (a * b) = ord_compl[p] a * or /-- A crude upper bound on `n.factorization p` -/ theorem factorization_lt {n : ℕ} (p : ℕ) (hn : n ≠ 0) : n.factorization p < n := by by_cases pp : p.Prime - · exact (pow_lt_pow_iff_right pp.one_lt).1 $ (ord_proj_le p hn).trans_lt $ lt_pow_self pp.one_lt _ + · exact (pow_lt_pow_iff_right pp.one_lt).1 <| (ord_proj_le p hn).trans_lt <| + lt_pow_self pp.one_lt _ · simpa only [factorization_eq_zero_of_non_prime n pp] using hn.bot_lt #align nat.factorization_lt Nat.factorization_lt @@ -690,8 +692,8 @@ theorem Ico_filter_pow_dvd_eq {n p b : ℕ} (pp : p.Prime) (hn : n ≠ 0) (hb : ext x simp only [Finset.mem_filter, mem_Ico, mem_Icc, and_congr_left_iff, and_congr_right_iff] rintro h1 - - exact iff_of_true (lt_of_pow_dvd_right hn pp.two_le h1) $ - (pow_le_pow_iff_right pp.one_lt).1 $ (le_of_dvd hn.bot_lt h1).trans hb + exact iff_of_true (lt_of_pow_dvd_right hn pp.two_le h1) <| + (pow_le_pow_iff_right pp.one_lt).1 <| (le_of_dvd hn.bot_lt h1).trans hb #align nat.Ico_filter_pow_dvd_eq Nat.Ico_filter_pow_dvd_eq /-! ### Factorization and coprimes -/ diff --git a/Mathlib/Data/Nat/Factorization/PrimePow.lean b/Mathlib/Data/Nat/Factorization/PrimePow.lean index 4a076491ff7d8..0ba90c0af0008 100644 --- a/Mathlib/Data/Nat/Factorization/PrimePow.lean +++ b/Mathlib/Data/Nat/Factorization/PrimePow.lean @@ -50,7 +50,7 @@ theorem isPrimePow_iff_factorization_eq_single {n : ℕ} : rintro rfl simp_all only [Finsupp.single_eq_zero, eq_comm, Nat.factorization_zero, hk.ne'] rw [Nat.eq_pow_of_factorization_eq_single hn0 hn] - exact ⟨Nat.prime_of_mem_primeFactors $ + exact ⟨Nat.prime_of_mem_primeFactors <| Finsupp.mem_support_iff.2 (by simp [hn, hk.ne'] : n.factorization p ≠ 0), hk, rfl⟩ #align is_prime_pow_iff_factorization_eq_single isPrimePow_iff_factorization_eq_single diff --git a/Mathlib/Data/Nat/Factors.lean b/Mathlib/Data/Nat/Factors.lean index 6df8f4bd0361b..91b8b05053732 100644 --- a/Mathlib/Data/Nat/Factors.lean +++ b/Mathlib/Data/Nat/Factors.lean @@ -6,6 +6,7 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro import Mathlib.Data.Nat.Prime import Mathlib.Data.List.Prime import Mathlib.Data.List.Sort +import Mathlib.Data.List.Chain #align_import data.nat.factors from "leanprover-community/mathlib"@"008205aa645b3f194c1da47025c5f110c8406eab" diff --git a/Mathlib/Data/Nat/Fib/Basic.lean b/Mathlib/Data/Nat/Fib/Basic.lean index 905e749542abf..1135f70bc0dfe 100644 --- a/Mathlib/Data/Nat/Fib/Basic.lean +++ b/Mathlib/Data/Nat/Fib/Basic.lean @@ -128,12 +128,12 @@ theorem fib_add_two_strictMono : StrictMono fun n => fib (n + 2) := by #align nat.fib_add_two_strict_mono Nat.fib_add_two_strictMono lemma fib_strictMonoOn : StrictMonoOn fib (Set.Ici 2) - | _m + 2, _, _n + 2, _, hmn => fib_add_two_strictMono $ lt_of_add_lt_add_right hmn + | _m + 2, _, _n + 2, _, hmn => fib_add_two_strictMono <| lt_of_add_lt_add_right hmn lemma fib_lt_fib {m : ℕ} (hm : 2 ≤ m) : ∀ {n}, fib m < fib n ↔ m < n | 0 => by simp [hm] | 1 => by simp [hm] - | n + 2 => fib_strictMonoOn.lt_iff_lt hm $ by simp + | n + 2 => fib_strictMonoOn.lt_iff_lt hm <| by simp theorem le_fib_self {n : ℕ} (five_le_n : 5 ≤ n) : n ≤ fib n := by induction' five_le_n with n five_le_n IH @@ -152,7 +152,7 @@ lemma le_fib_add_one : ∀ n, n ≤ fib n + 1 | 2 => le_rfl | 3 => le_rfl | 4 => le_rfl - | _n + 5 => (le_fib_self le_add_self).trans $ le_succ _ + | _n + 5 => (le_fib_self le_add_self).trans <| le_succ _ /-- Subsequent Fibonacci numbers are coprime, see https://proofwiki.org/wiki/Consecutive_Fibonacci_Numbers_are_Coprime -/ @@ -193,7 +193,7 @@ theorem fib_two_mul_add_two (n : ℕ) : rw [fib_add_two, fib_two_mul, fib_two_mul_add_one] -- porting note: A bunch of issues similar to [this zulip thread](https://github.com/leanprover-community/mathlib4/pull/1576) with `zify` have : fib n ≤ 2 * fib (n + 1) := - le_trans (fib_le_fib_succ) (mul_comm 2 _ ▸ le_mul_of_pos_right two_pos) + le_trans (fib_le_fib_succ) (mul_comm 2 _ ▸ Nat.le_mul_of_pos_right _ two_pos) zify [this] ring diff --git a/Mathlib/Data/Nat/Fib/Zeckendorf.lean b/Mathlib/Data/Nat/Fib/Zeckendorf.lean index f88cd9f552728..eb441d88752e3 100644 --- a/Mathlib/Data/Nat/Fib/Zeckendorf.lean +++ b/Mathlib/Data/Nat/Fib/Zeckendorf.lean @@ -36,7 +36,7 @@ open scoped BigOperators -- TODO: The `local` attribute makes this not considered as an instance by linters @[nolint defLemma docBlame] local instance : IsTrans ℕ fun a b ↦ b + 2 ≤ a where - trans _a _b _c hba hcb := hcb.trans $ le_self_add.trans hba + trans _a _b _c hba hcb := hcb.trans <| le_self_add.trans hba namespace List @@ -50,11 +50,11 @@ def IsZeckendorfRep (l : List ℕ) : Prop := (l ++ [0]).Chain' (fun a b ↦ b + lemma IsZeckendorfRep.sum_fib_lt : ∀ {n l}, IsZeckendorfRep l → (∀ a ∈ (l ++ [0]).head?, a < n) → (l.map fib).sum < fib n - | n, [], _, hn => fib_pos.2 $ hn _ rfl + | n, [], _, hn => fib_pos.2 <| hn _ rfl | n, a :: l, hl, hn => by simp only [IsZeckendorfRep, cons_append, chain'_iff_pairwise, pairwise_cons] at hl have : ∀ b, b ∈ head? (l ++ [0]) → b < a - 1 := - fun b hb ↦ lt_tsub_iff_right.2 $ hl.1 _ $ mem_of_mem_head? hb + fun b hb ↦ lt_tsub_iff_right.2 <| hl.1 _ <| mem_of_mem_head? hb simp only [mem_append, mem_singleton, ← chain'_iff_pairwise, or_imp, forall_and, forall_eq, zero_add] at hl simp only [map, List.sum_cons] @@ -71,20 +71,20 @@ variable {l : List ℕ} {a m n : ℕ} def greatestFib (n : ℕ) : ℕ := (n + 1).findGreatest (fun k ↦ fib k ≤ n) lemma fib_greatestFib_le (n : ℕ) : fib (greatestFib n) ≤ n := - findGreatest_spec (P := (fun k ↦ fib k ≤ n)) (zero_le _) $ zero_le _ + findGreatest_spec (P := (fun k ↦ fib k ≤ n)) (zero_le _) <| zero_le _ lemma greatestFib_mono : Monotone greatestFib := - fun _a _b hab ↦ findGreatest_mono (fun _k ↦ hab.trans') $ add_le_add_right hab _ + fun _a _b hab ↦ findGreatest_mono (fun _k ↦ hab.trans') <| add_le_add_right hab _ @[simp] lemma le_greatestFib : m ≤ greatestFib n ↔ fib m ≤ n := - ⟨fun h ↦ (fib_mono h).trans $ fib_greatestFib_le _, - fun h ↦ le_findGreatest (m.le_fib_add_one.trans $ add_le_add_right h _) h⟩ + ⟨fun h ↦ (fib_mono h).trans <| fib_greatestFib_le _, + fun h ↦ le_findGreatest (m.le_fib_add_one.trans <| add_le_add_right h _) h⟩ @[simp] lemma greatestFib_lt : greatestFib m < n ↔ m < fib n := lt_iff_lt_of_le_iff_le le_greatestFib lemma lt_fib_greatestFib_add_one (n : ℕ) : n < fib (greatestFib n + 1) := - greatestFib_lt.1 $ lt_succ_self _ + greatestFib_lt.1 <| lt_succ_self _ @[simp] lemma greatestFib_fib : ∀ {n}, n ≠ 1 → greatestFib (fib n) = n | 0, _ => rfl @@ -107,7 +107,7 @@ lemma greatestFib_sub_fib_greatestFib_le_greatestFib (hn : n ≠ 0) : · simpa [← succ_le_iff] using hn.bot_lt private lemma zeckendorf_aux (hm : 0 < m) : m - fib (greatestFib m) < m := -tsub_lt_self hm $ fib_pos.2 $ findGreatest_pos.2 ⟨1, zero_lt_one, le_add_self, hm⟩ +tsub_lt_self hm <| fib_pos.2 <| findGreatest_pos.2 ⟨1, zero_lt_one, le_add_self, hm⟩ /-- The Zeckendorf representation of a natural number. @@ -116,7 +116,7 @@ Note: For unfolding, you should use the equational lemmas `Nat.zeckendorf_zero` def zeckendorf : ℕ → List ℕ | 0 => [] | m@(n + 1) => let a := greatestFib m - have := zeckendorf_aux (n.succ_pos.trans_eq $ Eq.symm ‹_›) + have := zeckendorf_aux (n.succ_pos.trans_eq <| Eq.symm ‹_›) a :: zeckendorf (m - fib a) @[simp] lemma zeckendorf_zero : zeckendorf 0 = [] := rfl @@ -157,7 +157,7 @@ lemma zeckendorf_sum_fib : ∀ {l}, IsZeckendorfRep l → zeckendorf (l.map fib) add_tsub_cancel_left, zeckendorf_sum_fib hl.2] simp only [add_comm, add_assoc, greatestFib, findGreatest_eq_iff, ne_eq, ha.ne', not_false_eq_true, le_add_iff_nonneg_left, _root_.zero_le, forall_true_left, not_le, true_and] - refine ⟨le_add_of_le_right $ le_fib_add_one _, fun n hn _ ↦ ?_⟩ + refine ⟨le_add_of_le_right <| le_fib_add_one _, fun n hn _ ↦ ?_⟩ rw [add_comm, ← List.sum_cons, ← map_cons] exact hl'.sum_fib_lt (by simpa) @@ -175,6 +175,6 @@ def zeckendorfEquiv : ℕ ≃ {l // IsZeckendorfRep l} where toFun n := ⟨zeckendorf n, isZeckendorfRep_zeckendorf _⟩ invFun l := (map fib l).sum left_inv := sum_zeckendorf_fib - right_inv l := Subtype.ext $ zeckendorf_sum_fib l.2 + right_inv l := Subtype.ext <| zeckendorf_sum_fib l.2 end Nat diff --git a/Mathlib/Data/Nat/ForSqrt.lean b/Mathlib/Data/Nat/ForSqrt.lean index cc60bdfbc1620..da515c5b44b49 100644 --- a/Mathlib/Data/Nat/ForSqrt.lean +++ b/Mathlib/Data/Nat/ForSqrt.lean @@ -3,8 +3,8 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Johannes Hölzl, Mario Carneiro -/ - -import Mathlib.Data.Nat.Size +import Mathlib.Algebra.GroupWithZero.Basic +import Mathlib.Data.Nat.Order.Basic import Mathlib.Tactic.Common /-! @@ -90,7 +90,7 @@ lemma sqrt.lt_iter_succ_sq (n guess : ℕ) (hn : n < (guess + 1) * (guess + 1)) show guess + n / guess + 2 = (guess + n / guess + 1) + 1 from rfl] have aux_lemma {a : ℕ} : a ≤ 2 * ((a + 1) / 2) := by rw [mul_comm] - exact (add_le_add_iff_right 2).1 $ succ_le_of_lt $ @lt_div_mul_add (a + 1) 2 zero_lt_two + exact (add_le_add_iff_right 2).1 <| succ_le_of_lt <| @lt_div_mul_add (a + 1) 2 zero_lt_two refine lt_of_lt_of_le ?_ (act_rel_act_of_rel _ aux_lemma) rw [add_assoc, mul_add] exact add_lt_add_left (lt_mul_div_succ _ (lt_of_le_of_lt (Nat.zero_le m) h)) _ diff --git a/Mathlib/Data/Nat/GCD/BigOperators.lean b/Mathlib/Data/Nat/GCD/BigOperators.lean index af1b58fc71d07..63663c4e6bac5 100644 --- a/Mathlib/Data/Nat/GCD/BigOperators.lean +++ b/Mathlib/Data/Nat/GCD/BigOperators.lean @@ -3,7 +3,6 @@ Copyright (c) 2014 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ -import Mathlib.Data.Nat.GCD.Basic import Mathlib.Algebra.BigOperators.Basic #align_import data.nat.gcd.big_operators from "leanprover-community/mathlib"@"008205aa645b3f194c1da47025c5f110c8406eab" diff --git a/Mathlib/Data/Nat/Hyperoperation.lean b/Mathlib/Data/Nat/Hyperoperation.lean index ad4daea7483e7..650b9ea88f566 100644 --- a/Mathlib/Data/Nat/Hyperoperation.lean +++ b/Mathlib/Data/Nat/Hyperoperation.lean @@ -39,7 +39,7 @@ def hyperoperation : ℕ → ℕ → ℕ → ℕ | 2, _, 0 => 0 | _ + 3, _, 0 => 1 | n + 1, m, k + 1 => hyperoperation n m (hyperoperation (n + 1) m k) - termination_by hyperoperation a b c => (a, b, c) + termination_by a b c => (a, b, c) #align hyperoperation hyperoperation -- Basic hyperoperation lemmas diff --git a/Mathlib/Data/Nat/Log.lean b/Mathlib/Data/Nat/Log.lean index d3fb023e114d6..4fe19f47a0422 100644 --- a/Mathlib/Data/Nat/Log.lean +++ b/Mathlib/Data/Nat/Log.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon, Yaël Dillies -/ import Mathlib.Data.Nat.Pow +import Mathlib.Data.Set.Intervals.Basic #align_import data.nat.log from "leanprover-community/mathlib"@"3e00d81bdcbf77c8188bbd18f5524ddc3ed8cac6" diff --git a/Mathlib/Data/Nat/MaxPowDiv.lean b/Mathlib/Data/Nat/MaxPowDiv.lean index 6dd0a360b57c9..78352f6d78971 100644 --- a/Mathlib/Data/Nat/MaxPowDiv.lean +++ b/Mathlib/Data/Nat/MaxPowDiv.lean @@ -3,8 +3,9 @@ Copyright (c) 2023 Matthew Robert Ballard. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Matthew Robert Ballard -/ - -import Mathlib.Data.Nat.Pow +import Mathlib.Algebra.Divisibility.Units +import Mathlib.Algebra.Order.WithZero +import Mathlib.Data.Nat.Order.Basic import Mathlib.Tactic.Common /-! diff --git a/Mathlib/Data/Nat/ModEq.lean b/Mathlib/Data/Nat/ModEq.lean index 4f0d0831b943d..ec4f39b901d25 100644 --- a/Mathlib/Data/Nat/ModEq.lean +++ b/Mathlib/Data/Nat/ModEq.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Data.Int.GCD import Mathlib.Data.Int.Order.Lemmas +import Mathlib.Logic.Basic import Mathlib.Tactic.NormNum import Mathlib.Tactic.GCongr.Core @@ -105,7 +106,8 @@ theorem mod_modEq (a n) : a % n ≡ a [MOD n] := namespace ModEq -lemma of_dvd (d : m ∣ n) (h : a ≡ b [MOD n]) : a ≡ b [MOD m] := modEq_of_dvd $ d.natCast.trans h.dvd +lemma of_dvd (d : m ∣ n) (h : a ≡ b [MOD n]) : a ≡ b [MOD m] := + modEq_of_dvd <| d.natCast.trans h.dvd #align nat.modeq.of_dvd Nat.ModEq.of_dvd protected theorem mul_left' (c : ℕ) (h : a ≡ b [MOD n]) : c * a ≡ c * b [MOD c * n] := by @@ -224,10 +226,10 @@ theorem of_div (h : a / c ≡ b / c [MOD m / c]) (ha : c ∣ a) (ha : c ∣ b) ( end ModEq -lemma modEq_sub (h : b ≤ a) : a ≡ b [MOD a - b] := (modEq_of_dvd $ by rw [Int.ofNat_sub h]).symm +lemma modEq_sub (h : b ≤ a) : a ≡ b [MOD a - b] := (modEq_of_dvd <| by rw [Int.ofNat_sub h]).symm #align nat.modeq_sub Nat.modEq_sub -lemma modEq_one : a ≡ b [MOD 1] := modEq_of_dvd $ one_dvd _ +lemma modEq_one : a ≡ b [MOD 1] := modEq_of_dvd <| one_dvd _ #align nat.modeq_one Nat.modEq_one @[simp] lemma modEq_zero_iff : a ≡ b [MOD 0] ↔ a = b := by rw [ModEq, mod_zero, mod_zero] @@ -272,9 +274,9 @@ lemma eq_of_abs_lt (h : a ≡ b [MOD m]) (h2 : |(b : ℤ) - a| < m) : a = b := b #align nat.modeq.eq_of_abs_lt Nat.ModEq.eq_of_abs_lt lemma eq_of_lt_of_lt (h : a ≡ b [MOD m]) (ha : a < m) (hb : b < m) : a = b := - h.eq_of_abs_lt $ abs_sub_lt_iff.2 - ⟨(sub_le_self _ $ Int.coe_nat_nonneg _).trans_lt $ Int.ofNat_lt.2 hb, - (sub_le_self _ $ Int.coe_nat_nonneg _).trans_lt $ Int.ofNat_lt.2 ha⟩ + h.eq_of_abs_lt <| abs_sub_lt_iff.2 + ⟨(sub_le_self _ <| Int.coe_nat_nonneg _).trans_lt <| Int.ofNat_lt.2 hb, + (sub_le_self _ <| Int.coe_nat_nonneg _).trans_lt <| Int.ofNat_lt.2 ha⟩ #align nat.modeq.eq_of_lt_of_lt Nat.ModEq.eq_of_lt_of_lt /-- To cancel a common factor `c` from a `ModEq` we must divide the modulus `m` by `gcd m c` -/ @@ -302,12 +304,12 @@ lemma cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [MOD m]) : a ≡ b lemma cancel_left_div_gcd' (hm : 0 < m) (hcd : c ≡ d [MOD m]) (h : c * a ≡ d * b [MOD m]) : a ≡ b [MOD m / gcd m c] := - (h.trans $ hcd.symm.mul_right b).cancel_left_div_gcd hm + (h.trans <| hcd.symm.mul_right b).cancel_left_div_gcd hm #align nat.modeq.cancel_left_div_gcd' Nat.ModEq.cancel_left_div_gcd' lemma cancel_right_div_gcd' (hm : 0 < m) (hcd : c ≡ d [MOD m]) (h : a * c ≡ b * d [MOD m]) : a ≡ b [MOD m / gcd m c] := - (h.trans $ hcd.symm.mul_left b).cancel_right_div_gcd hm + (h.trans <| hcd.symm.mul_left b).cancel_right_div_gcd hm #align nat.modeq.cancel_right_div_gcd' Nat.ModEq.cancel_right_div_gcd' /-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/ @@ -322,7 +324,7 @@ lemma cancel_left_of_coprime (hmc : gcd m c = 1) (h : c * a ≡ c * b [MOD m]) : /-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/ lemma cancel_right_of_coprime (hmc : gcd m c = 1) (h : a * c ≡ b * c [MOD m]) : a ≡ b [MOD m] := - cancel_left_of_coprime hmc $ by simpa [mul_comm] using h + cancel_left_of_coprime hmc <| by simpa [mul_comm] using h #align nat.modeq.cancel_right_of_coprime Nat.ModEq.cancel_right_of_coprime end ModEq diff --git a/Mathlib/Data/Nat/Order/Basic.lean b/Mathlib/Data/Nat/Order/Basic.lean index 3d62c7d35d091..960ed715e5d2c 100644 --- a/Mathlib/Data/Nat/Order/Basic.lean +++ b/Mathlib/Data/Nat/Order/Basic.lean @@ -5,7 +5,7 @@ Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Data.Nat.Basic -import Mathlib.Data.Nat.Bits +import Mathlib.Init.Data.Nat.Bitwise #align_import data.nat.order.basic from "leanprover-community/mathlib"@"3ed3f98a1e836241990d3d308f1577e434977130" @@ -16,7 +16,9 @@ import Mathlib.Data.Nat.Bits We also have a variety of lemmas which have been deferred from `Data.Nat.Basic` because it is easier to prove them with this ordered semiring instance available. -You may find that some theorems can be moved back to `Data.Nat.Basic` by modifying their proofs. +### TODO + +Move most of the theorems to `Data.Nat.Defs` by modifying their proofs. -/ @@ -80,21 +82,6 @@ variable {m n k l : ℕ} /-! ### Equalities and inequalities involving zero and one -/ -theorem one_le_iff_ne_zero : 1 ≤ n ↔ n ≠ 0 := - Nat.add_one_le_iff.trans pos_iff_ne_zero -#align nat.one_le_iff_ne_zero Nat.one_le_iff_ne_zero - -theorem one_lt_iff_ne_zero_and_ne_one : ∀ {n : ℕ}, 1 < n ↔ n ≠ 0 ∧ n ≠ 1 - | 0 => by decide - | 1 => by decide - | n + 2 => by simp -#align nat.one_lt_iff_ne_zero_and_ne_one Nat.one_lt_iff_ne_zero_and_ne_one - -theorem le_one_iff_eq_zero_or_eq_one : ∀ {n : ℕ}, n ≤ 1 ↔ n = 0 ∨ n = 1 - | 0 => by decide - | 1 => by decide - | n + 2 => by simp - #align nat.mul_ne_zero Nat.mul_ne_zero -- Porting note: already in Std @@ -288,18 +275,10 @@ theorem le_mul_self : ∀ n : ℕ, n ≤ n * n | n + 1 => by simp #align nat.le_mul_self Nat.le_mul_self -theorem le_mul_of_pos_left (h : 0 < n) : m ≤ n * m := by - conv => - lhs - rw [← one_mul m] - exact mul_le_mul_of_nonneg_right h.nat_succ_le (zero_le _) +-- Moved to Std #align nat.le_mul_of_pos_left Nat.le_mul_of_pos_left -theorem le_mul_of_pos_right (h : 0 < n) : m ≤ m * n := by - conv => - lhs - rw [← mul_one m] - exact mul_le_mul_of_nonneg_left h.nat_succ_le (zero_le _) +-- Moved to Std #align nat.le_mul_of_pos_right Nat.le_mul_of_pos_right theorem mul_self_inj : m * m = n * n ↔ m = n := @@ -322,7 +301,7 @@ theorem add_sub_one_le_mul (hm : m ≠ 0) (hn : n ≠ 0) : m + n - 1 ≤ m * n : cases m · cases hm rfl · rw [succ_add, Nat.add_one_sub_one, succ_mul] - exact add_le_add_right (le_mul_of_one_le_right' $ succ_le_iff.2 $ pos_iff_ne_zero.2 hn) _ + exact add_le_add_right (le_mul_of_one_le_right' <| succ_le_iff.2 <| pos_iff_ne_zero.2 hn) _ #align nat.add_sub_one_le_mul Nat.add_sub_one_le_mul /-! @@ -350,8 +329,8 @@ theorem diag_induction (P : ℕ → ℕ → Prop) (ha : ∀ a, P (a + 1) (a + 1) have _ : a + (b + 1) < (a + 1) + (b + 1) := by simp apply diag_induction P ha hb hd a (b + 1) apply lt_of_le_of_lt (Nat.le_succ _) h - termination_by _ a b c => a + b - decreasing_by { assumption } + termination_by a b c => a + b + decreasing_by all_goals assumption #align nat.diag_induction Nat.diag_induction /-- A subset of `ℕ` containing `k : ℕ` and closed under `Nat.succ` contains every `n ≥ k`. -/ @@ -476,7 +455,7 @@ theorem not_dvd_of_pos_of_lt (h1 : 0 < n) (h2 : n < m) : ¬m ∣ n := by rintro ⟨k, rfl⟩ rcases Nat.eq_zero_or_pos k with (rfl | hk) · exact lt_irrefl 0 h1 - · exact not_lt.2 (le_mul_of_pos_right hk) h2 + · exact not_lt.2 (Nat.le_mul_of_pos_right _ hk) h2 #align nat.not_dvd_of_pos_of_lt Nat.not_dvd_of_pos_of_lt /-- If `m` and `n` are equal mod `k`, `m - n` is zero mod `k`. -/ diff --git a/Mathlib/Data/Nat/PSub.lean b/Mathlib/Data/Nat/PSub.lean index d57e17bc20e07..1c668a0a194f8 100644 --- a/Mathlib/Data/Nat/PSub.lean +++ b/Mathlib/Data/Nat/PSub.lean @@ -3,8 +3,8 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Option.Basic import Mathlib.Algebra.Group.Basic +import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Data.Nat.Basic #align_import data.nat.psub from "leanprover-community/mathlib"@"70d50ecfd4900dd6d328da39ab7ebd516abe4025" diff --git a/Mathlib/Data/Nat/Parity.lean b/Mathlib/Data/Nat/Parity.lean index 1af9d26002a70..5cb5d0e1c995c 100644 --- a/Mathlib/Data/Nat/Parity.lean +++ b/Mathlib/Data/Nat/Parity.lean @@ -3,9 +3,9 @@ Copyright (c) 2019 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Benjamin Davidson -/ -import Mathlib.Data.Nat.ModEq -import Mathlib.Data.Nat.Prime import Mathlib.Algebra.Parity +import Mathlib.Data.Nat.Bits +import Mathlib.Data.Nat.ModEq #align_import data.nat.parity from "leanprover-community/mathlib"@"48fb5b5280e7c81672afc9524185ae994553ebf4" @@ -305,7 +305,7 @@ theorem iterate_bit0 (hf : Involutive f) (n : ℕ) : f^[bit0 n] = id := by #align function.involutive.iterate_bit0 Function.Involutive.iterate_bit0 theorem iterate_bit1 (hf : Involutive f) (n : ℕ) : f^[bit1 n] = f := by - rw [bit1, ← succ_eq_add_one, iterate_succ, hf.iterate_bit0, comp.left_id] + rw [bit1, ← succ_eq_add_one, iterate_succ, hf.iterate_bit0, id_comp] #align function.involutive.iterate_bit1 Function.Involutive.iterate_bit1 end @@ -320,7 +320,7 @@ theorem iterate_even (hf : Involutive f) (hn : Even n) : f^[n] = id := by theorem iterate_odd (hf : Involutive f) (hn : Odd n) : f^[n] = f := by rcases hn with ⟨m, rfl⟩ - rw [iterate_add, hf.iterate_two_mul, comp.left_id, iterate_one] + rw [iterate_add, hf.iterate_two_mul, id_comp, iterate_one] #align function.involutive.iterate_odd Function.Involutive.iterate_odd theorem iterate_eq_self (hf : Involutive f) (hne : f ≠ id) : f^[n] = f ↔ Odd n := diff --git a/Mathlib/Data/Nat/Periodic.lean b/Mathlib/Data/Nat/Periodic.lean index ab9d965291b46..ade898c4de8bf 100644 --- a/Mathlib/Data/Nat/Periodic.lean +++ b/Mathlib/Data/Nat/Periodic.lean @@ -5,6 +5,7 @@ Authors: Bolton Bailey -/ import Mathlib.Algebra.Periodic import Mathlib.Data.Nat.Count +import Mathlib.Data.Nat.GCD.Basic import Mathlib.Data.Nat.Interval #align_import data.nat.periodic from "leanprover-community/mathlib"@"dc6c365e751e34d100e80fe6e314c3c3e0fd2988" diff --git a/Mathlib/Data/Nat/Pow.lean b/Mathlib/Data/Nat/Pow.lean index b2df1c6ac4d24..dc50206a8ab5b 100644 --- a/Mathlib/Data/Nat/Pow.lean +++ b/Mathlib/Data/Nat/Pow.lean @@ -184,7 +184,7 @@ theorem pow_dvd_pow_iff_pow_le_pow {k l : ℕ} : ∀ {x : ℕ}, 0 < x → (x ^ k · intro a cases' x with x · simp - · have le := (pow_le_pow_iff_right $ by simp).mp a + · have le := (pow_le_pow_iff_right <| by simp).mp a use (x + 2) ^ (l - k) rw [← pow_add, add_comm k, tsub_add_cancel_of_le le] #align nat.pow_dvd_pow_iff_pow_le_pow Nat.pow_dvd_pow_iff_pow_le_pow diff --git a/Mathlib/Data/Nat/Prime.lean b/Mathlib/Data/Nat/Prime.lean index b0c086aa962c9..24521deafe239 100644 --- a/Mathlib/Data/Nat/Prime.lean +++ b/Mathlib/Data/Nat/Prime.lean @@ -213,25 +213,20 @@ theorem Prime.not_dvd_one {p : ℕ} (pp : Prime p) : ¬p ∣ 1 := Irreducible.not_dvd_one pp #align nat.prime.not_dvd_one Nat.Prime.not_dvd_one -theorem not_prime_mul {a b : ℕ} (a1 : 1 < a) (b1 : 1 < b) : ¬Prime (a * b) := fun h => - ne_of_lt (Nat.mul_lt_mul_of_pos_left b1 (lt_of_succ_lt a1)) <| by - simpa using (dvd_prime_two_le h a1).1 (dvd_mul_right _ _) -#align nat.not_prime_mul Nat.not_prime_mul - -theorem not_prime_mul' {a b n : ℕ} (h : a * b = n) (h₁ : 1 < a) (h₂ : 1 < b) : ¬Prime n := by - rw [← h] - exact not_prime_mul h₁ h₂ -#align nat.not_prime_mul' Nat.not_prime_mul' - theorem prime_mul_iff {a b : ℕ} : Nat.Prime (a * b) ↔ a.Prime ∧ b = 1 ∨ b.Prime ∧ a = 1 := by simp only [iff_self_iff, irreducible_mul_iff, ← irreducible_iff_nat_prime, Nat.isUnit_iff] #align nat.prime_mul_iff Nat.prime_mul_iff +theorem not_prime_mul {a b : ℕ} (a1 : a ≠ 1) (b1 : b ≠ 1) : ¬Prime (a * b) := by + simp [prime_mul_iff, _root_.not_or, *] +#align nat.not_prime_mul Nat.not_prime_mul + +theorem not_prime_mul' {a b n : ℕ} (h : a * b = n) (h₁ : a ≠ 1) (h₂ : b ≠ 1) : ¬Prime n := + h ▸ not_prime_mul h₁ h₂ +#align nat.not_prime_mul' Nat.not_prime_mul' + theorem Prime.dvd_iff_eq {p a : ℕ} (hp : p.Prime) (a1 : a ≠ 1) : a ∣ p ↔ p = a := by - refine' - ⟨_, by - rintro rfl - rfl⟩ + refine ⟨?_, by rintro rfl; rfl⟩ rintro ⟨j, rfl⟩ rcases prime_mul_iff.mp hp with (⟨_, rfl⟩ | ⟨_, rfl⟩) · exact mul_one _ @@ -255,7 +250,7 @@ def minFacAux (n : ℕ) : ℕ → ℕ else have := minFac_lemma n k h minFacAux n (k + 2) -termination_by _ n k => sqrt n + 2 - k +termination_by k => sqrt n + 2 - k #align nat.min_fac_aux Nat.minFacAux /-- Returns the smallest prime factor of `n ≠ 1`. -/ @@ -306,7 +301,7 @@ theorem minFacAux_has_prop {n : ℕ} (n2 : 2 ≤ n) : have := a _ le_rfl (dvd_of_mul_right_dvd d') rw [e] at this exact absurd this (by contradiction) - termination_by _ n _ k => sqrt n + 2 - k + termination_by k => sqrt n + 2 - k #align nat.min_fac_aux_has_prop Nat.minFacAux_has_prop theorem minFac_has_prop {n : ℕ} (n1 : n ≠ 1) : minFacProp n (minFac n) := by diff --git a/Mathlib/Data/Nat/PrimeFin.lean b/Mathlib/Data/Nat/PrimeFin.lean index 50f85ef00af29..57efcd0fb94a5 100644 --- a/Mathlib/Data/Nat/PrimeFin.lean +++ b/Mathlib/Data/Nat/PrimeFin.lean @@ -54,7 +54,7 @@ lemma pos_of_mem_primeFactors (hp : p ∈ n.primeFactors) : 0 < p := (prime_of_mem_primeFactors hp).pos lemma le_of_mem_primeFactors (h : p ∈ n.primeFactors) : p ≤ n := - le_of_dvd (mem_primeFactors.1 h).2.2.bot_lt $ dvd_of_mem_primeFactors h + le_of_dvd (mem_primeFactors.1 h).2.2.bot_lt <| dvd_of_mem_primeFactors h @[simp] lemma primeFactors_zero : primeFactors 0 = ∅ := rfl @[simp] lemma primeFactors_one : primeFactors 1 = ∅ := rfl @@ -64,7 +64,7 @@ lemma le_of_mem_primeFactors (h : p ∈ n.primeFactors) : p ≤ n := · contrapose! rintro hn obtain ⟨p, hp, hpn⟩ := exists_prime_and_dvd hn.2 - exact Nonempty.ne_empty $ ⟨_, mem_primeFactors.2 ⟨hp, hpn, hn.1⟩⟩ + exact Nonempty.ne_empty <| ⟨_, mem_primeFactors.2 ⟨hp, hpn, hn.1⟩⟩ · rintro (rfl | rfl) <;> simp @[simp] @@ -96,7 +96,7 @@ lemma primeFactors_gcd (ha : a ≠ 0) (hb : b ≠ 0) : protected lemma Coprime.disjoint_primeFactors (hab : Coprime a b) : Disjoint a.primeFactors b.primeFactors := - List.disjoint_toFinset_iff_disjoint.2 $ coprime_factors_disjoint hab + List.disjoint_toFinset_iff_disjoint.2 <| coprime_factors_disjoint hab lemma primeFactors_pow_succ (n k : ℕ) : (n ^ (k + 1)).primeFactors = n.primeFactors := by rcases eq_or_ne n 0 with (rfl | hn) diff --git a/Mathlib/Data/Nat/Size.lean b/Mathlib/Data/Nat/Size.lean index 606a5e1e4a053..f79694e589bb0 100644 --- a/Mathlib/Data/Nat/Size.lean +++ b/Mathlib/Data/Nat/Size.lean @@ -3,8 +3,8 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Data.Nat.Pow import Mathlib.Data.Nat.Bits +import Mathlib.Algebra.GroupPower.Order #align_import data.nat.size from "leanprover-community/mathlib"@"18a5306c091183ac90884daa9373fa3b178e8607" diff --git a/Mathlib/Data/Nat/Sqrt.lean b/Mathlib/Data/Nat/Sqrt.lean index a56d4127ff713..ad7f8a9eeea3e 100644 --- a/Mathlib/Data/Nat/Sqrt.lean +++ b/Mathlib/Data/Nat/Sqrt.lean @@ -5,7 +5,6 @@ Authors: Leonardo de Moura, Johannes Hölzl, Mario Carneiro -/ import Mathlib.Algebra.Parity import Mathlib.Data.Int.Order.Basic -import Mathlib.Data.Nat.Size import Mathlib.Data.Nat.ForSqrt #align_import data.nat.sqrt from "leanprover-community/mathlib"@"ba2245edf0c8bb155f1569fd9b9492a9b384cde6" @@ -57,9 +56,9 @@ private theorem sqrt_isSqrt (n : ℕ) : IsSqrt n (sqrt n) := by rw [lt_add_one_iff, add_assoc, ← mul_two] refine le_trans (div_add_mod' (n + 2) 2).ge ?_ rw [add_comm, add_le_add_iff_right, add_mod_right] - simp only [zero_lt_two, add_div_right, succ_mul_succ_eq] + simp only [zero_lt_two, add_div_right, succ_mul_succ] refine le_trans (b := 1) ?_ ?_ - · exact (lt_succ.1 $ mod_lt n zero_lt_two) + · exact (lt_succ.1 <| mod_lt n zero_lt_two) · simp only [le_add_iff_nonneg_left]; exact zero_le _ theorem sqrt_le (n : ℕ) : sqrt n * sqrt n ≤ n := diff --git a/Mathlib/Data/Nat/Squarefree.lean b/Mathlib/Data/Nat/Squarefree.lean index c24c4e80bf022..866a77ca42c90 100644 --- a/Mathlib/Data/Nat/Squarefree.lean +++ b/Mathlib/Data/Nat/Squarefree.lean @@ -5,7 +5,6 @@ Authors: Aaron Anderson -/ import Mathlib.Algebra.Squarefree import Mathlib.Data.Nat.Factorization.PrimePow -import Mathlib.Data.Nat.PrimeNormNum import Mathlib.RingTheory.Int.Basic #align_import data.nat.squarefree from "leanprover-community/mathlib"@"3c1368cac4abd5a5cbe44317ba7e87379d51ed88" @@ -60,7 +59,7 @@ theorem _root_.Squarefree.natFactorization_le_one {n : ℕ} (p : ℕ) (hn : Squa lemma factorization_eq_one_of_squarefree (hn : Squarefree n) (hp : p.Prime) (hpn : p ∣ n) : factorization n p = 1 := - (hn.natFactorization_le_one _).antisymm $ (hp.dvd_iff_one_le_factorization hn.ne_zero).1 hpn + (hn.natFactorization_le_one _).antisymm <| (hp.dvd_iff_one_le_factorization hn.ne_zero).1 hpn theorem squarefree_of_factorization_le_one {n : ℕ} (hn : n ≠ 0) (hn' : ∀ p, n.factorization p ≤ 1) : Squarefree n := by @@ -127,7 +126,7 @@ def minSqFacAux : ℕ → ℕ → Option ℕ lt_of_le_of_lt (Nat.sub_le_sub_right (Nat.sqrt_le_sqrt <| Nat.div_le_self _ _) k) this if k ∣ n' then some k else minSqFacAux n' (k + 2) else minSqFacAux n (k + 2) -termination_by _ n k => sqrt n + 2 - k +termination_by n k => sqrt n + 2 - k #align nat.min_sq_fac_aux Nat.minSqFacAux /-- Returns the smallest prime factor `p` of `n` such that `p^2 ∣ n`, or `none` if there is no @@ -202,7 +201,7 @@ theorem minSqFacAux_has_prop {n : ℕ} (k) (n0 : 0 < n) (i) (e : k = 2 * i + 3) · specialize IH (n / k) (div_dvd_of_dvd dk) dkk exact minSqFacProp_div _ (pk dk) dk (mt (Nat.dvd_div_iff dk).2 dkk) IH · exact IH n (dvd_refl _) dk -termination_by _ => n.sqrt + 2 - k +termination_by n.sqrt + 2 - k #align nat.min_sq_fac_aux_has_prop Nat.minSqFacAux_has_prop theorem minSqFac_has_prop (n : ℕ) : MinSqFacProp n (minSqFac n) := by @@ -389,12 +388,12 @@ theorem coprime_of_squarefree_mul {m n : ℕ} (h : Squarefree (m * n)) : m.Copri theorem squarefree_mul_iff {m n : ℕ} : Squarefree (m * n) ↔ m.Coprime n ∧ Squarefree m ∧ Squarefree n := - ⟨fun h => ⟨coprime_of_squarefree_mul h, (squarefree_mul $ coprime_of_squarefree_mul h).mp h⟩, + ⟨fun h => ⟨coprime_of_squarefree_mul h, (squarefree_mul <| coprime_of_squarefree_mul h).mp h⟩, fun h => (squarefree_mul h.1).mpr h.2⟩ lemma coprime_div_gcd_of_squarefree (hm : Squarefree m) (hn : n ≠ 0) : Coprime (m / gcd m n) n := by have : Coprime (m / gcd m n) (gcd m n) := - coprime_of_squarefree_mul $ by simpa [Nat.div_mul_cancel, gcd_dvd_left] + coprime_of_squarefree_mul <| by simpa [Nat.div_mul_cancel, gcd_dvd_left] simpa [Nat.div_mul_cancel, gcd_dvd_right] using (coprime_div_gcd_div_gcd (m := m) (gcd_ne_zero_right hn).bot_lt).mul_right this @@ -414,14 +413,14 @@ lemma primeFactors_div_gcd (hm : Squarefree m) (hn : n ≠ 0) : primeFactors (m / m.gcd n) = primeFactors m \ primeFactors n := by ext p have : m / m.gcd n ≠ 0 := - (Nat.div_ne_zero_iff $ gcd_ne_zero_right hn).2 $ gcd_le_left _ hm.ne_zero.bot_lt + (Nat.div_ne_zero_iff <| gcd_ne_zero_right hn).2 <| gcd_le_left _ hm.ne_zero.bot_lt simp only [mem_primeFactors, ne_eq, this, not_false_eq_true, and_true, not_and, mem_sdiff, hm.ne_zero, hn, dvd_div_iff (gcd_dvd_left _ _)] - refine ⟨fun hp ↦ ⟨⟨hp.1, dvd_of_mul_left_dvd hp.2⟩, fun _ hpn ↦ hp.1.not_unit $ hm _ $ + refine ⟨fun hp ↦ ⟨⟨hp.1, dvd_of_mul_left_dvd hp.2⟩, fun _ hpn ↦ hp.1.not_unit <| hm _ <| (mul_dvd_mul_right (dvd_gcd (dvd_of_mul_left_dvd hp.2) hpn) _).trans hp.2⟩, fun hp ↦ ⟨hp.1.1, Coprime.mul_dvd_of_dvd_of_dvd ?_ (gcd_dvd_left _ _) hp.1.2⟩⟩ rw [coprime_comm, hp.1.1.coprime_iff_not_dvd] - exact fun hpn ↦ hp.2 hp.1.1 $ hpn.trans $ gcd_dvd_right _ _ + exact fun hpn ↦ hp.2 hp.1.1 <| hpn.trans <| gcd_dvd_right _ _ lemma prod_primeFactors_invOn_squarefree : Set.InvOn (fun n : ℕ ↦ (factorization n).support) (fun s ↦ ∏ p in s, p) @@ -431,7 +430,7 @@ lemma prod_primeFactors_invOn_squarefree : theorem prod_primeFactors_sdiff_of_squarefree {n : ℕ} (hn : Squarefree n) {t : Finset ℕ} (ht : t ⊆ n.primeFactors) : ∏ a in (n.primeFactors \ t), a = n / ∏ a in t, a := by - refine symm $ Nat.div_eq_of_eq_mul_left (Finset.prod_pos + refine symm <| Nat.div_eq_of_eq_mul_left (Finset.prod_pos fun p hp => (prime_of_mem_factors (List.mem_toFinset.mp (ht hp))).pos) ?_ rw [Finset.prod_sdiff ht, prod_primeFactors_of_squarefree hn] diff --git a/Mathlib/Data/Nat/SuccPred.lean b/Mathlib/Data/Nat/SuccPred.lean index d937d70d353eb..4a366bbef6165 100644 --- a/Mathlib/Data/Nat/SuccPred.lean +++ b/Mathlib/Data/Nat/SuccPred.lean @@ -18,6 +18,7 @@ In this file, we show that `ℕ` is both an archimedean `succOrder` and an archi open Function Order namespace Nat +variable {m n : ℕ} -- so that Lean reads `Nat.succ` through `succ_order.succ` @[reducible] @@ -66,6 +67,8 @@ theorem pred_iterate (a : ℕ) : ∀ n, pred^[n] a = a - n exact congr_arg _ (pred_iterate a n) #align nat.pred_iterate Nat.pred_iterate +lemma le_succ_iff_eq_or_le : m ≤ n.succ ↔ m = n.succ ∨ m ≤ n := Order.le_succ_iff_eq_or_le + instance : IsSuccArchimedean ℕ := ⟨fun {a} {b} h => ⟨b - a, by rw [succ_eq_succ, succ_iterate, add_tsub_cancel_of_le h]⟩⟩ @@ -79,16 +82,16 @@ lemma forall_ne_zero_iff (P : ℕ → Prop) : /-! ### Covering relation -/ -protected theorem covby_iff_succ_eq {m n : ℕ} : m ⋖ n ↔ m + 1 = n := - succ_eq_iff_covby.symm -#align nat.covby_iff_succ_eq Nat.covby_iff_succ_eq +protected theorem covBy_iff_succ_eq {m n : ℕ} : m ⋖ n ↔ m + 1 = n := + succ_eq_iff_covBy.symm +#align nat.covby_iff_succ_eq Nat.covBy_iff_succ_eq end Nat @[simp, norm_cast] -theorem Fin.coe_covby_iff {n : ℕ} {a b : Fin n} : (a : ℕ) ⋖ b ↔ a ⋖ b := +theorem Fin.coe_covBy_iff {n : ℕ} {a b : Fin n} : (a : ℕ) ⋖ b ↔ a ⋖ b := and_congr_right' ⟨fun h _c hc => h hc, fun h c ha hb => @h ⟨c, hb.trans b.prop⟩ ha hb⟩ -#align fin.coe_covby_iff Fin.coe_covby_iff +#align fin.coe_covby_iff Fin.coe_covBy_iff -alias ⟨_, Covby.coe_fin⟩ := Fin.coe_covby_iff -#align covby.coe_fin Covby.coe_fin +alias ⟨_, CovBy.coe_fin⟩ := Fin.coe_covBy_iff +#align covby.coe_fin CovBy.coe_fin diff --git a/Mathlib/Data/Nat/WithBot.lean b/Mathlib/Data/Nat/WithBot.lean index 7de807e457a8a..89d6a3b181e03 100644 --- a/Mathlib/Data/Nat/WithBot.lean +++ b/Mathlib/Data/Nat/WithBot.lean @@ -35,7 +35,7 @@ theorem add_eq_zero_iff {n m : WithBot ℕ} : n + m = 0 ↔ n = 0 ∧ m = 0 := b theorem add_eq_one_iff {n m : WithBot ℕ} : n + m = 1 ↔ n = 0 ∧ m = 1 ∨ n = 1 ∧ m = 0 := by rcases n, m with ⟨_ | _, _ | _⟩ any_goals refine' ⟨fun h => Option.noConfusion h, fun h => _⟩; - aesop (simp_options := { decide := true }) + aesop (simp_config := { decide := true }) repeat' erw [WithBot.coe_eq_coe] exact Nat.add_eq_one_iff #align nat.with_bot.add_eq_one_iff Nat.WithBot.add_eq_one_iff @@ -44,7 +44,7 @@ theorem add_eq_two_iff {n m : WithBot ℕ} : n + m = 2 ↔ n = 0 ∧ m = 2 ∨ n = 1 ∧ m = 1 ∨ n = 2 ∧ m = 0 := by rcases n, m with ⟨_ | _, _ | _⟩ any_goals refine' ⟨fun h => Option.noConfusion h, fun h => _⟩; - aesop (simp_options := { decide := true }) + aesop (simp_config := { decide := true }) repeat' erw [WithBot.coe_eq_coe] exact Nat.add_eq_two_iff #align nat.with_bot.add_eq_two_iff Nat.WithBot.add_eq_two_iff @@ -53,7 +53,7 @@ theorem add_eq_three_iff {n m : WithBot ℕ} : n + m = 3 ↔ n = 0 ∧ m = 3 ∨ n = 1 ∧ m = 2 ∨ n = 2 ∧ m = 1 ∨ n = 3 ∧ m = 0 := by rcases n, m with ⟨_ | _, _ | _⟩ any_goals refine' ⟨fun h => Option.noConfusion h, fun h => _⟩; - aesop (simp_options := { decide := true }) + aesop (simp_config := { decide := true }) repeat' erw [WithBot.coe_eq_coe] exact Nat.add_eq_three_iff #align nat.with_bot.add_eq_three_iff Nat.WithBot.add_eq_three_iff @@ -64,16 +64,7 @@ theorem coe_nonneg {n : ℕ} : 0 ≤ (n : WithBot ℕ) := by #align nat.with_bot.coe_nonneg Nat.WithBot.coe_nonneg @[simp] -theorem lt_zero_iff (n : WithBot ℕ) : n < 0 ↔ n = ⊥ := by - refine' Option.casesOn n _ _ - exact of_eq_true (eq_true_of_decide (Eq.refl true)) - intro n - refine' ⟨fun h => _, fun h => _⟩ - exfalso - · rw [WithBot.some_eq_coe] at h - exact not_le_of_lt h WithBot.coe_nonneg - · rw [h] - exact of_eq_true (eq_true_of_decide (Eq.refl true)) +theorem lt_zero_iff {n : WithBot ℕ} : n < 0 ↔ n = ⊥ := WithBot.lt_coe_bot #align nat.with_bot.lt_zero_iff Nat.WithBot.lt_zero_iff theorem one_le_iff_zero_lt {x : WithBot ℕ} : 1 ≤ x ↔ 0 < x := by diff --git a/Mathlib/Data/Num/Basic.lean b/Mathlib/Data/Num/Basic.lean index 3db4b2541c1f2..efe85fdf0efd0 100644 --- a/Mathlib/Data/Num/Basic.lean +++ b/Mathlib/Data/Num/Basic.lean @@ -3,10 +3,12 @@ Copyright (c) 2014 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Mario Carneiro -/ +import Lean.Linter.Deprecated +import Std.Tactic.CoeExt import Mathlib.Mathport.Rename import Mathlib.Init.Data.Nat.Bitwise import Mathlib.Init.Data.Int.Basic -import Lean.Linter.Deprecated +import Mathlib.Init.ZeroOne #align_import data.num.basic from "leanprover-community/mathlib"@"c4658a649d216f57e99621708b09dcb3dcccbd23" /-! diff --git a/Mathlib/Data/Num/Lemmas.lean b/Mathlib/Data/Num/Lemmas.lean index 9aa0fff361729..af93718fd0a87 100644 --- a/Mathlib/Data/Num/Lemmas.lean +++ b/Mathlib/Data/Num/Lemmas.lean @@ -6,7 +6,6 @@ Authors: Mario Carneiro import Mathlib.Data.Num.Bitwise import Mathlib.Data.Int.CharZero import Mathlib.Data.Nat.Bitwise -import Mathlib.Data.Nat.GCD.Basic import Mathlib.Data.Nat.PSub import Mathlib.Data.Nat.Size diff --git a/Mathlib/Data/Num/Prime.lean b/Mathlib/Data/Num/Prime.lean index 24e7f27a6dd0a..dbc7f6d46c50c 100644 --- a/Mathlib/Data/Num/Prime.lean +++ b/Mathlib/Data/Num/Prime.lean @@ -76,7 +76,8 @@ theorem minFac_to_nat (n : PosNum) : (minFac n : ℕ) = Nat.minFac n := by calc (n : ℕ) + (n : ℕ) + 1 ≤ (n : ℕ) + (n : ℕ) + (n : ℕ) := by simp _ = (n : ℕ) * (1 + 1 + 1) := by simp only [mul_add, mul_one] - _ < _ := by simp [mul_lt_mul] + _ < _ := by + set_option simprocs false in simp [mul_lt_mul] · rw [minFac, Nat.minFac_eq, if_pos] · rfl simp diff --git a/Mathlib/Data/Option/Defs.lean b/Mathlib/Data/Option/Defs.lean index 7d315c0c52ce9..8ad18723f50b3 100644 --- a/Mathlib/Data/Option/Defs.lean +++ b/Mathlib/Data/Option/Defs.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Init.Algebra.Classes +import Mathlib.Tactic.TypeStar #align_import data.option.defs from "leanprover-community/mathlib"@"c4658a649d216f57e99621708b09dcb3dcccbd23" diff --git a/Mathlib/Data/Option/NAry.lean b/Mathlib/Data/Option/NAry.lean index 6dc5fccaa8a27..66d91ab7148c5 100644 --- a/Mathlib/Data/Option/NAry.lean +++ b/Mathlib/Data/Option/NAry.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Data.Option.Basic +import Mathlib.Init.Function #align_import data.option.n_ary from "leanprover-community/mathlib"@"995b47e555f1b6297c7cf16855f1023e355219fb" diff --git a/Mathlib/Data/Ordmap/Ordnode.lean b/Mathlib/Data/Ordmap/Ordnode.lean index 39b3f358e77e3..8f1477784ccb2 100644 --- a/Mathlib/Data/Ordmap/Ordnode.lean +++ b/Mathlib/Data/Ordmap/Ordnode.lean @@ -6,7 +6,7 @@ Authors: Mario Carneiro import Mathlib.Order.Compare import Mathlib.Data.List.Defs import Mathlib.Data.Nat.PSub -import Mathlib.Init.Data.Nat.Bitwise +import Mathlib.Data.Option.Basic #align_import data.ordmap.ordnode from "leanprover-community/mathlib"@"dd71334db81d0bd444af1ee339a29298bef40734" @@ -882,7 +882,7 @@ def ofAscListAux₁ : ∀ l : List α, ℕ → Ordnode α × { l' : List α // l have := Nat.le_succ_of_le h let (r, ⟨zs, h'⟩) := ofAscListAux₁ ys (s <<< 1) (link l y r, ⟨zs, le_trans h' (le_of_lt this)⟩) - termination_by ofAscListAux₁ l => l.length + termination_by l => l.length #align ordnode.of_asc_list_aux₁ Ordnode.ofAscListAux₁ /-- Auxiliary definition for `ofAscList`. -/ @@ -893,7 +893,7 @@ def ofAscListAux₂ : List α → Ordnode α → ℕ → Ordnode α | (r, ⟨ys, h⟩) => have := Nat.lt_succ_of_le h ofAscListAux₂ ys (link l x r) (s <<< 1) - termination_by ofAscListAux₂ l => l.length + termination_by l => l.length #align ordnode.of_asc_list_aux₂ Ordnode.ofAscListAux₂ /-- O(n). Build a set from a list which is already sorted. Performs no comparisons. diff --git a/Mathlib/Data/PEquiv.lean b/Mathlib/Data/PEquiv.lean index 4f4518e8ea511..6f506c2d78535 100644 --- a/Mathlib/Data/PEquiv.lean +++ b/Mathlib/Data/PEquiv.lean @@ -3,6 +3,7 @@ Copyright (c) 2019 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ +import Mathlib.Data.Option.Basic import Mathlib.Data.Set.Basic #align_import data.pequiv from "leanprover-community/mathlib"@"7c3269ca3fa4c0c19e4d127cd7151edbdbf99ed4" @@ -65,7 +66,7 @@ variable {α : Type u} {β : Type v} {γ : Type w} {δ : Type x} open Function Option -instance : FunLike (α ≃. β) α fun _ => Option β := +instance : FunLike (α ≃. β) α (Option β) := { coe := toFun coe_injective' := by rintro ⟨f₁, f₂, hf⟩ ⟨g₁, g₂, hg⟩ (rfl : f₁ = g₁) @@ -81,11 +82,11 @@ theorem coe_mk_apply (f₁ : α → Option β) (f₂ : β → Option α) (h) (x #align pequiv.coe_mk_apply PEquiv.coe_mk_apply @[ext] theorem ext {f g : α ≃. β} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align pequiv.ext PEquiv.ext theorem ext_iff {f g : α ≃. β} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align pequiv.ext_iff PEquiv.ext_iff /-- The identity map as a partial equivalence. -/ diff --git a/Mathlib/Data/PFun.lean b/Mathlib/Data/PFun.lean index 04e1ff2901bd9..12602121d474a 100644 --- a/Mathlib/Data/PFun.lean +++ b/Mathlib/Data/PFun.lean @@ -702,7 +702,7 @@ theorem prodMap_id_id : (PFun.id α).prodMap (PFun.id β) = PFun.id _ := theorem prodMap_comp_comp (f₁ : α →. β) (f₂ : β →. γ) (g₁ : δ →. ε) (g₂ : ε →. ι) : (f₂.comp f₁).prodMap (g₂.comp g₁) = (f₂.prodMap g₂).comp (f₁.prodMap g₁) := -- by -- Porting note: was `by tidy`, below is a golf'd version of the `tidy?` proof - ext $ λ ⟨_, _⟩ ⟨_, _⟩ => + ext <| λ ⟨_, _⟩ ⟨_, _⟩ => ⟨λ ⟨⟨⟨h1l1, h1l2⟩, ⟨h1r1, h1r2⟩⟩, h2⟩ => ⟨⟨⟨h1l1, h1r1⟩, ⟨h1l2, h1r2⟩⟩, h2⟩, λ ⟨⟨⟨h1l1, h1r1⟩, ⟨h1l2, h1r2⟩⟩, h2⟩ => ⟨⟨⟨h1l1, h1l2⟩, ⟨h1r1, h1r2⟩⟩, h2⟩⟩ #align pfun.prod_map_comp_comp PFun.prodMap_comp_comp diff --git a/Mathlib/Data/PNat/Basic.lean b/Mathlib/Data/PNat/Basic.lean index 2116a40ab5c4d..57913101d6cfd 100644 --- a/Mathlib/Data/PNat/Basic.lean +++ b/Mathlib/Data/PNat/Basic.lean @@ -9,6 +9,7 @@ import Mathlib.Data.Nat.Order.Basic import Mathlib.Data.Set.Basic import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.Order.Positive.Ring +import Mathlib.Order.Hom.Basic #align_import data.pnat.basic from "leanprover-community/mathlib"@"172bf2812857f5e56938cc148b7a539f52f84ca9" diff --git a/Mathlib/Data/PNat/Defs.lean b/Mathlib/Data/PNat/Defs.lean index 8ca1595b1193a..e8c48e332bed9 100644 --- a/Mathlib/Data/PNat/Defs.lean +++ b/Mathlib/Data/PNat/Defs.lean @@ -5,10 +5,10 @@ Authors: Mario Carneiro, Neil Strickland -/ import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Algebra.NeZero -import Mathlib.Data.Nat.Cast.Defs import Mathlib.Order.Basic import Mathlib.Tactic.Coe import Mathlib.Tactic.Lift +import Mathlib.Init.Data.Int.Order #align_import data.pnat.defs from "leanprover-community/mathlib"@"c4658a649d216f57e99621708b09dcb3dcccbd23" @@ -207,7 +207,7 @@ instance : WellFoundedRelation ℕ+ := /-- Strong induction on `ℕ+`. -/ def strongInductionOn {p : ℕ+ → Sort*} (n : ℕ+) : (∀ k, (∀ m, m < k → p m) → p k) → p n | IH => IH _ fun a _ => strongInductionOn a IH -termination_by _ => n.1 +termination_by n.1 #align pnat.strong_induction_on PNat.strongInductionOn /-- We define `m % k` and `m / k` in the same way as for `ℕ` diff --git a/Mathlib/Data/PNat/Factors.lean b/Mathlib/Data/PNat/Factors.lean index f6aa5604b88b9..41a602c485b9b 100644 --- a/Mathlib/Data/PNat/Factors.lean +++ b/Mathlib/Data/PNat/Factors.lean @@ -222,12 +222,10 @@ theorem prod_add (u v : PrimeMultiset) : (u + v).prod = u.prod * v.prod := by exact Multiset.prod_add _ _ #align prime_multiset.prod_add PrimeMultiset.prod_add --- Porting note: Need to replace ^ with Pow.pow to get the original mathlib statement -theorem prod_smul (d : ℕ) (u : PrimeMultiset) : (d • u).prod = Pow.pow u.prod d := by - induction' d with n ih - · rfl - · have : ∀ n' : ℕ, Pow.pow (prod u) n' = Monoid.npow n' (prod u) := fun _ ↦ rfl - rw [succ_nsmul, prod_add, ih, this, this, Monoid.npow_succ, mul_comm] +theorem prod_smul (d : ℕ) (u : PrimeMultiset) : (d • u).prod = u.prod ^ d := by + induction d with + | zero => simp only [Nat.zero_eq, zero_nsmul, pow_zero, prod_zero] + | succ n ih => rw [succ_nsmul, prod_add, ih, pow_succ, mul_comm] #align prime_multiset.prod_smul PrimeMultiset.prod_smul end PrimeMultiset @@ -303,7 +301,7 @@ theorem factorMultiset_mul (n m : ℕ+) : #align pnat.factor_multiset_mul PNat.factorMultiset_mul theorem factorMultiset_pow (n : ℕ+) (m : ℕ) : - factorMultiset (Pow.pow n m) = m • factorMultiset n := by + factorMultiset (n ^ m) = m • factorMultiset n := by let u := factorMultiset n have : n = u.prod := (prod_factorMultiset n).symm rw [this, ← PrimeMultiset.prod_smul] @@ -389,7 +387,7 @@ theorem factorMultiset_lcm (m n : ℕ+) : /-- The number of occurrences of p in the factor multiset of m is the same as the p-adic valuation of m. -/ theorem count_factorMultiset (m : ℕ+) (p : Nat.Primes) (k : ℕ) : - Pow.pow (p : ℕ+) k ∣ m ↔ k ≤ m.factorMultiset.count p := by + (p : ℕ+) ^ k ∣ m ↔ k ≤ m.factorMultiset.count p := by intros rw [Multiset.le_count_iff_replicate_le, ← factorMultiset_le_iff, factorMultiset_pow, factorMultiset_ofPrime] diff --git a/Mathlib/Data/PSigma/Order.lean b/Mathlib/Data/PSigma/Order.lean index 881ca4a5ebe33..8f8a71b1f2f2d 100644 --- a/Mathlib/Data/PSigma/Order.lean +++ b/Mathlib/Data/PSigma/Order.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Sigma.Lex import Mathlib.Order.BoundedOrder import Mathlib.Mathport.Notation import Init.NotationExtra +import Mathlib.Data.Sigma.Basic #align_import data.psigma.order from "leanprover-community/mathlib"@"62a5626868683c104774de8d85b9855234ac807c" diff --git a/Mathlib/Data/Part.lean b/Mathlib/Data/Part.lean index 58e7448331311..545c51cd48034 100644 --- a/Mathlib/Data/Part.lean +++ b/Mathlib/Data/Part.lean @@ -400,9 +400,7 @@ instance : PartialOrder (Part instance : OrderBot (Part α) where bot := none - bot_le := by - introv x - rintro ⟨⟨_⟩, _⟩ + bot_le := by rintro x _ ⟨⟨_⟩, _⟩ theorem le_total_of_le_of_le {x y : Part α} (z : Part α) (hx : x ≤ z) (hy : y ≤ z) : x ≤ y ∨ y ≤ x := by diff --git a/Mathlib/Data/Pi/Algebra.lean b/Mathlib/Data/Pi/Algebra.lean index eb8fd0d8b5ab2..9953b88b30014 100644 --- a/Mathlib/Data/Pi/Algebra.lean +++ b/Mathlib/Data/Pi/Algebra.lean @@ -368,7 +368,7 @@ theorem extend_mul [Mul γ] (f : α → β) (g₁ g₂ : α → γ) (e₁ e₂ : funext x simp only [not_exists, extend_def, Pi.mul_apply, apply_dite₂, dite_eq_ite, ite_self] -- Porting note: The Lean3 statement was --- `funext $ λ _, by convert (apply_dite2 (*) _ _ _ _ _).symm` +-- `funext <| λ _, by convert (apply_dite2 (*) _ _ _ _ _).symm` -- which converts to -- `funext fun _ => by convert (apply_dite₂ (· * ·) _ _ _ _ _).symm` -- However this does not work, and we're not sure why. @@ -382,7 +382,7 @@ theorem extend_inv [Inv γ] (f : α → β) (g : α → γ) (e : β → γ) : funext x simp only [not_exists, extend_def, Pi.inv_apply, apply_dite Inv.inv] -- Porting note: The Lean3 statement was --- `funext $ λ _, by convert (apply_dite has_inv.inv _ _ _).symm` +-- `funext <| λ _, by convert (apply_dite has_inv.inv _ _ _).symm` -- which converts to -- `funext fun _ => by convert (apply_dite Inv.inv _ _ _).symm` -- However this does not work, and we're not sure why. @@ -396,7 +396,7 @@ theorem extend_div [Div γ] (f : α → β) (g₁ g₂ : α → γ) (e₁ e₂ : funext x simp [Function.extend_def, apply_dite₂] -- Porting note: The Lean3 statement was --- `funext $ λ _, by convert (apply_dite2 (/) _ _ _ _ _).symm` +-- `funext <| λ _, by convert (apply_dite2 (/) _ _ _ _ _).symm` -- which converts to -- `funext fun _ => by convert (apply_dite₂ (· / ·) _ _ _ _ _).symm` -- However this does not work, and we're not sure why. diff --git a/Mathlib/Data/Polynomial/AlgebraMap.lean b/Mathlib/Data/Polynomial/AlgebraMap.lean index faab8e9287bb4..d79ad7744f01f 100644 --- a/Mathlib/Data/Polynomial/AlgebraMap.lean +++ b/Mathlib/Data/Polynomial/AlgebraMap.lean @@ -534,4 +534,28 @@ theorem aeval_endomorphism {M : Type*} [CommRing R] [AddCommGroup M] [Module R M exact map_sum (LinearMap.applyₗ v) _ _ #align polynomial.aeval_endomorphism Polynomial.aeval_endomorphism +section StableSubmodule + +variable {M : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] + {q : Submodule R M} {m : M} (hm : m ∈ q) (p : R[X]) + +lemma aeval_apply_smul_mem_of_le_comap' + [Semiring A] [Algebra R A] [Module A M] [IsScalarTower R A M] (a : A) + (hq : q ≤ q.comap (Algebra.lsmul R R M a)) : + aeval a p • m ∈ q := by + refine p.induction_on (M := fun f ↦ aeval a f • m ∈ q) (by simpa) (fun f₁ f₂ h₁ h₂ ↦ ?_) + (fun n t hmq ↦ ?_) + · simp_rw [map_add, add_smul] + exact Submodule.add_mem q h₁ h₂ + · dsimp only at hmq ⊢ + rw [pow_succ, mul_left_comm, map_mul, aeval_X, mul_smul] + rw [← q.map_le_iff_le_comap] at hq + exact hq ⟨_, hmq, rfl⟩ + +lemma aeval_apply_smul_mem_of_le_comap (f : Module.End R M) (hq : q ≤ q.comap f) : + aeval f p m ∈ q := + aeval_apply_smul_mem_of_le_comap' hm p f hq + +end StableSubmodule + end Polynomial diff --git a/Mathlib/Data/Polynomial/Basic.lean b/Mathlib/Data/Polynomial/Basic.lean index 1de8bc4ede5b5..5d85efa1e41ca 100644 --- a/Mathlib/Data/Polynomial/Basic.lean +++ b/Mathlib/Data/Polynomial/Basic.lean @@ -673,7 +673,7 @@ theorem coeff_ofFinsupp (p) : coeff (⟨p⟩ : R[X]) = p := by rw [coeff] theorem coeff_injective : Injective (coeff : R[X] → ℕ → R) := by rintro ⟨p⟩ ⟨q⟩ -- Porting note: `ofFinsupp.injEq` is required. - simp only [coeff, FunLike.coe_fn_eq, imp_self, ofFinsupp.injEq] + simp only [coeff, DFunLike.coe_fn_eq, imp_self, ofFinsupp.injEq] #align polynomial.coeff_injective Polynomial.coeff_injective @[simp] @@ -823,11 +823,10 @@ theorem forall_eq_iff_forall_eq : (∀ f g : R[X], f = g) ↔ ∀ a b : R, a = b #align polynomial.forall_eq_iff_forall_eq Polynomial.forall_eq_iff_forall_eq theorem ext_iff {p q : R[X]} : p = q ↔ ∀ n, coeff p n = coeff q n := by - rcases p with ⟨⟩ - rcases q with ⟨⟩ - -- Porting note: Was `simp [coeff, FunLike.ext_iff]` - simp only [ofFinsupp.injEq, coeff._eq_1] - exact FunLike.ext_iff (F := ℕ →₀ R) + rcases p with ⟨f : ℕ →₀ R⟩ + rcases q with ⟨g : ℕ →₀ R⟩ + -- Porting note: Was `simp [coeff, DFunLike.ext_iff]` + simpa [coeff] using DFunLike.ext_iff (f := f) (g := g) #align polynomial.ext_iff Polynomial.ext_iff @[ext] @@ -856,7 +855,7 @@ theorem addHom_ext {M : Type*} [AddMonoid M] {f g : R[X] →+ M} @[ext high] theorem addHom_ext' {M : Type*} [AddMonoid M] {f g : R[X] →+ M} (h : ∀ n, f.comp (monomial n).toAddMonoidHom = g.comp (monomial n).toAddMonoidHom) : f = g := - addHom_ext fun n => FunLike.congr_fun (h n) + addHom_ext fun n => DFunLike.congr_fun (h n) #align polynomial.add_hom_ext' Polynomial.addHom_ext' @[ext high] @@ -1213,6 +1212,10 @@ theorem monomial_neg (n : ℕ) (a : R) : monomial n (-a) = -monomial n a := by rw [eq_neg_iff_add_eq_zero, ← monomial_add, neg_add_self, monomial_zero_right] #align polynomial.monomial_neg Polynomial.monomial_neg +theorem monomial_sub (n : ℕ) : monomial n (a - b) = monomial n a - monomial n b := by + rw [sub_eq_add_neg, monomial_add, monomial_neg] + rfl + @[simp] theorem support_neg {p : R[X]} : (-p).support = p.support := by rcases p with ⟨⟩ diff --git a/Mathlib/Data/Polynomial/Coeff.lean b/Mathlib/Data/Polynomial/Coeff.lean index 5f41638c9610b..f75c5db1b26f8 100644 --- a/Mathlib/Data/Polynomial/Coeff.lean +++ b/Mathlib/Data/Polynomial/Coeff.lean @@ -3,10 +3,10 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker -/ +import Mathlib.Algebra.MonoidAlgebra.Support +import Mathlib.Algebra.Regular.Basic import Mathlib.Data.Polynomial.Basic -import Mathlib.Data.Finset.NatAntidiagonal import Mathlib.Data.Nat.Choose.Sum -import Mathlib.Algebra.Regular.Pow #align_import data.polynomial.coeff from "leanprover-community/mathlib"@"2651125b48fc5c170ab1111afd0817c903b1fc6c" @@ -66,6 +66,14 @@ theorem support_smul [Monoid S] [DistribMulAction S R] (r : S) (p : R[X]) : simp [hi] #align polynomial.support_smul Polynomial.support_smul +open scoped Pointwise in +theorem card_support_mul_le : (p * q).support.card ≤ p.support.card * q.support.card := by + calc (p * q).support.card + _ = (p.toFinsupp * q.toFinsupp).support.card := by rw [← support_toFinsupp, toFinsupp_mul] + _ ≤ (p.toFinsupp.support + q.toFinsupp.support).card := + Finset.card_le_card (AddMonoidAlgebra.support_mul p.toFinsupp q.toFinsupp) + _ ≤ p.support.card * q.support.card := Finset.card_image₂_le .. + /-- `Polynomial.sum` as a linear map. -/ @[simps] def lsum {R A M : Type*} [Semiring R] [Semiring A] [AddCommMonoid M] [Module R A] [Module R M] @@ -310,15 +318,14 @@ theorem mul_X_pow_eq_zero {p : R[X]} {n : ℕ} (H : p * X ^ n = 0) : p = 0 := ext fun k => (coeff_mul_X_pow p n k).symm.trans <| ext_iff.1 H (k + n) #align polynomial.mul_X_pow_eq_zero Polynomial.mul_X_pow_eq_zero -@[simp] theorem isRegular_X : IsRegular (X : R[X]) := by - suffices : IsLeftRegular (X : R[X]) - · exact ⟨this, this.right_of_commute commute_X⟩ - intro P Q (hPQ : X * P = X * Q) +theorem isRegular_X_pow (n : ℕ) : IsRegular (X ^ n : R[X]) := by + suffices : IsLeftRegular (X^n : R[X]) + · exact ⟨this, this.right_of_commute (fun p => commute_X_pow p n)⟩ + intro P Q (hPQ : X^n * P = X^n * Q) ext i - rw [← coeff_X_mul P i, hPQ, coeff_X_mul Q i] + rw [← coeff_X_pow_mul P n i, hPQ, coeff_X_pow_mul Q n i] --- TODO Unify this with `Polynomial.Monic.isRegular` -theorem isRegular_X_pow (n : ℕ) : IsRegular (X ^ n : R[X]) := isRegular_X.pow n +@[simp] theorem isRegular_X : IsRegular (X : R[X]) := pow_one (X : R[X]) ▸ isRegular_X_pow 1 theorem coeff_X_add_C_pow (r : R) (n k : ℕ) : ((X + C r) ^ n).coeff k = r ^ (n - k) * (n.choose k : R) := by diff --git a/Mathlib/Data/Polynomial/Degree/CardPowDegree.lean b/Mathlib/Data/Polynomial/Degree/CardPowDegree.lean index 99474b5b3dd54..f375daa2ee1e1 100644 --- a/Mathlib/Data/Polynomial/Degree/CardPowDegree.lean +++ b/Mathlib/Data/Polynomial/Degree/CardPowDegree.lean @@ -5,6 +5,7 @@ Authors: Anne Baanen -/ import Mathlib.Algebra.Order.EuclideanAbsoluteValue import Mathlib.Data.Polynomial.FieldDivision +import Mathlib.Algebra.GroupPower.Order #align_import data.polynomial.degree.card_pow_degree from "leanprover-community/mathlib"@"85d9f2189d9489f9983c0d01536575b0233bd305" diff --git a/Mathlib/Data/Polynomial/Degree/Definitions.lean b/Mathlib/Data/Polynomial/Degree/Definitions.lean index 0c9b6bda9e3e2..69cfeeed41f14 100644 --- a/Mathlib/Data/Polynomial/Degree/Definitions.lean +++ b/Mathlib/Data/Polynomial/Degree/Definitions.lean @@ -9,6 +9,7 @@ import Mathlib.Data.Nat.WithBot import Mathlib.Data.Polynomial.Monomial import Mathlib.Data.Polynomial.Coeff import Mathlib.Data.Nat.Cast.WithTop +import Mathlib.Data.Nat.SuccPred #align_import data.polynomial.degree.definitions from "leanprover-community/mathlib"@"808ea4ebfabeb599f21ec4ae87d6dc969597887f" @@ -563,25 +564,32 @@ end Ring section Semiring -variable [Semiring R] +variable [Semiring R] {p : R[X]} /-- The second-highest coefficient, or 0 for constants -/ def nextCoeff (p : R[X]) : R := if p.natDegree = 0 then 0 else p.coeff (p.natDegree - 1) #align polynomial.next_coeff Polynomial.nextCoeff +lemma nextCoeff_eq_zero : + p.nextCoeff = 0 ↔ p.natDegree = 0 ∨ 0 < p.natDegree ∧ p.coeff (p.natDegree - 1) = 0 := by + simp [nextCoeff, or_iff_not_imp_left, pos_iff_ne_zero]; aesop + +lemma nextCoeff_ne_zero : p.nextCoeff ≠ 0 ↔ p.natDegree ≠ 0 ∧ p.coeff (p.natDegree - 1) ≠ 0 := by + simp [nextCoeff] + @[simp] theorem nextCoeff_C_eq_zero (c : R) : nextCoeff (C c) = 0 := by rw [nextCoeff] simp #align polynomial.next_coeff_C_eq_zero Polynomial.nextCoeff_C_eq_zero -theorem nextCoeff_of_pos_natDegree (p : R[X]) (hp : 0 < p.natDegree) : +theorem nextCoeff_of_natDegree_pos (hp : 0 < p.natDegree) : nextCoeff p = p.coeff (p.natDegree - 1) := by rw [nextCoeff, if_neg] contrapose! hp simpa -#align polynomial.next_coeff_of_pos_nat_degree Polynomial.nextCoeff_of_pos_natDegree +#align polynomial.next_coeff_of_pos_nat_degree Polynomial.nextCoeff_of_natDegree_pos variable {p q : R[X]} {ι : Type*} @@ -681,6 +689,13 @@ theorem leadingCoeff_eq_zero_iff_deg_eq_bot : leadingCoeff p = 0 ↔ degree p = rw [leadingCoeff_eq_zero, degree_eq_bot] #align polynomial.leading_coeff_eq_zero_iff_deg_eq_bot Polynomial.leadingCoeff_eq_zero_iff_deg_eq_bot +lemma natDegree_le_pred (hf : p.natDegree ≤ n) (hn : p.coeff n = 0) : p.natDegree ≤ n - 1 := by + obtain _ | n := n + · exact hf + · refine (Nat.le_succ_iff_eq_or_le.1 hf).resolve_left fun h ↦ ?_ + rw [← h, coeff_natDegree, leadingCoeff_eq_zero] at hn + aesop + theorem natDegree_mem_support_of_nonzero (H : p ≠ 0) : p.natDegree ∈ p.support := by rw [mem_support_iff] exact (not_congr leadingCoeff_eq_zero).mpr H @@ -1180,6 +1195,9 @@ theorem eq_C_of_natDegree_eq_zero (h : natDegree p = 0) : p = C (coeff p 0) := eq_C_of_natDegree_le_zero h.le #align polynomial.eq_C_of_nat_degree_eq_zero Polynomial.eq_C_of_natDegree_eq_zero +lemma natDegree_eq_zero {p : R[X]} : p.natDegree = 0 ↔ ∃ x, C x = p := + ⟨fun h ↦ ⟨_, (eq_C_of_natDegree_eq_zero h).symm⟩, by aesop⟩ + theorem eq_C_coeff_zero_iff_natDegree_eq_zero : p = C (p.coeff 0) ↔ p.natDegree = 0 := ⟨fun h ↦ by rw [h, natDegree_C], eq_C_of_natDegree_eq_zero⟩ @@ -1478,7 +1496,7 @@ theorem natDegree_X_add_C (x : R) : (X + C x).natDegree = 1 := @[simp] theorem nextCoeff_X_add_C [Semiring S] (c : S) : nextCoeff (X + C c) = c := by nontriviality S - simp [nextCoeff_of_pos_natDegree] + simp [nextCoeff_of_natDegree_pos] #align polynomial.next_coeff_X_add_C Polynomial.nextCoeff_X_add_C theorem degree_X_pow_add_C {n : ℕ} (hn : 0 < n) (a : R) : degree ((X : R[X]) ^ n + C a) = n := by diff --git a/Mathlib/Data/Polynomial/Degree/Lemmas.lean b/Mathlib/Data/Polynomial/Degree/Lemmas.lean index 90965bb8c1969..2d48ec51101f6 100644 --- a/Mathlib/Data/Polynomial/Degree/Lemmas.lean +++ b/Mathlib/Data/Polynomial/Degree/Lemmas.lean @@ -186,7 +186,7 @@ theorem coeff_pow_eq_ite_of_natDegree_le_of_le {o : ℕ} coeff (p ^ m) o = if o = m * n then (coeff p n) ^ m else 0 := by rcases eq_or_ne o (m * n) with rfl | h · simpa only [ite_true] using coeff_pow_of_natDegree_le pn - · simpa only [h, ite_false] using coeff_eq_zero_of_natDegree_lt $ + · simpa only [h, ite_false] using coeff_eq_zero_of_natDegree_lt <| lt_of_le_of_lt (natDegree_pow_le_of_le m pn) (lt_of_le_of_ne mno h.symm) theorem coeff_add_eq_left_of_lt (qn : q.natDegree < n) : (p + q).coeff n = p.coeff n := @@ -315,6 +315,12 @@ theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} : simp [h, h2, h3] -- simp doesn't rewrite in the hypothesis for some reason tauto +theorem natDegree_pos_of_nextCoeff_ne_zero (h : p.nextCoeff ≠ 0) : 0 < p.natDegree := by + rw [nextCoeff] at h + by_cases hpz : p.natDegree = 0 + · simp_all only [ne_eq, zero_le, ite_true, not_true_eq_false] + · apply Nat.zero_lt_of_ne_zero hpz + end Degree end Semiring @@ -349,7 +355,7 @@ end Ring section NoZeroDivisors -variable [Semiring R] [NoZeroDivisors R] {p q : R[X]} +variable [Semiring R] [NoZeroDivisors R] {p q : R[X]} {a : R} theorem degree_mul_C (a0 : a ≠ 0) : (p * C a).degree = p.degree := by rw [degree_mul, degree_C a0, add_zero] @@ -371,6 +377,24 @@ theorem natDegree_C_mul (a0 : a ≠ 0) : (C a * p).natDegree = p.natDegree := by set_option linter.uppercaseLean3 false in #align polynomial.nat_degree_C_mul Polynomial.natDegree_C_mul +@[simp] +lemma nextCoeff_C_mul_X_add_C (ha : a ≠ 0) (c : R) : nextCoeff (C a * X + C c) = c := by + rw [nextCoeff_of_natDegree_pos] <;> simp [ha] + +lemma natDegree_eq_one : p.natDegree = 1 ↔ ∃ a ≠ 0, ∃ b, C a * X + C b = p := by + refine ⟨fun hp ↦ ⟨p.coeff 1, fun h ↦ ?_, p.coeff 0, ?_⟩, ?_⟩ + · rw [← hp, coeff_natDegree, leadingCoeff_eq_zero] at h + aesop + · ext n + obtain _ | _ | n := n + · simp + · simp + · simp only [coeff_add, coeff_mul_X, coeff_C_succ, add_zero] + rw [coeff_eq_zero_of_natDegree_lt] + simp [hp] + · rintro ⟨a, ha, b, rfl⟩ + simp [ha] + theorem natDegree_comp : natDegree (p.comp q) = natDegree p * natDegree q := by by_cases q0 : q.natDegree = 0 · rw [degree_le_zero_iff.mp (natDegree_eq_zero_iff_degree_le_zero.mp q0), comp_C, natDegree_C, diff --git a/Mathlib/Data/Polynomial/Derivative.lean b/Mathlib/Data/Polynomial/Derivative.lean index 1607e96ec8487..83a739a0835ed 100644 --- a/Mathlib/Data/Polynomial/Derivative.lean +++ b/Mathlib/Data/Polynomial/Derivative.lean @@ -5,6 +5,7 @@ Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker -/ import Mathlib.Algebra.GroupPower.IterateHom import Mathlib.Data.Polynomial.Eval +import Mathlib.GroupTheory.GroupAction.Ring #align_import data.polynomial.derivative from "leanprover-community/mathlib"@"bbeb185db4ccee8ed07dc48449414ebfa39cb821" diff --git a/Mathlib/Data/Polynomial/Div.lean b/Mathlib/Data/Polynomial/Div.lean index aacb58a264d39..096b31bc35546 100644 --- a/Mathlib/Data/Polynomial/Div.lean +++ b/Mathlib/Data/Polynomial/Div.lean @@ -3,10 +3,10 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker -/ -import Mathlib.Data.Polynomial.AlgebraMap import Mathlib.Data.Polynomial.Inductions import Mathlib.Data.Polynomial.Monic import Mathlib.RingTheory.Multiplicity +import Mathlib.RingTheory.Ideal.Operations #align_import data.polynomial.div from "leanprover-community/mathlib"@"e1e7190efdcefc925cb36f257a8362ef22944204" @@ -112,7 +112,7 @@ noncomputable def divModByMonicAux : ∀ (_p : R[X]) {q : R[X]}, Monic q → R[X let dm := divModByMonicAux (p - q * z) hq ⟨z + dm.1, dm.2⟩ else ⟨0, p⟩ - termination_by divModByMonicAux p q hq => p + termination_by p q hq => p #align polynomial.div_mod_by_monic_aux Polynomial.divModByMonicAux /-- `divByMonic` gives the quotient of `p` by a monic polynomial `q`. -/ @@ -160,7 +160,7 @@ theorem degree_modByMonic_lt [Nontrivial R] : dsimp rw [dif_pos hq, if_neg h, Classical.not_not.1 hp] exact lt_of_le_of_ne bot_le (Ne.symm (mt degree_eq_bot.1 hq.ne_zero))) - termination_by degree_modByMonic_lt p q hq => p + termination_by p q hq => p #align polynomial.degree_mod_by_monic_lt Polynomial.degree_modByMonic_lt theorem natDegree_modByMonic_lt (p : R[X]) {q : R[X]} (hmq : Monic q) (hq : q ≠ 1) : @@ -256,7 +256,7 @@ theorem modByMonic_eq_sub_mul_div : unfold modByMonic divByMonic divModByMonicAux dsimp rw [dif_pos hq, if_neg h, dif_pos hq, if_neg h, mul_zero, sub_zero] - termination_by modByMonic_eq_sub_mul_div p q hq => p + termination_by p q hq => p #align polynomial.mod_by_monic_eq_sub_mul_div Polynomial.modByMonic_eq_sub_mul_div theorem modByMonic_add_div (p : R[X]) {q : R[X]} (hq : Monic q) : p %ₘ q + q * (p /ₘ q) = p := diff --git a/Mathlib/Data/Polynomial/EraseLead.lean b/Mathlib/Data/Polynomial/EraseLead.lean index d2bbe05b6cba3..154ce702c058d 100644 --- a/Mathlib/Data/Polynomial/EraseLead.lean +++ b/Mathlib/Data/Polynomial/EraseLead.lean @@ -1,10 +1,10 @@ /- Copyright (c) 2020 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Damiano Testa +Authors: Damiano Testa, Alex Meiburg -/ import Mathlib.Algebra.BigOperators.Fin -import Mathlib.Data.Polynomial.Degree.Definitions +import Mathlib.Data.Polynomial.Degree.Lemmas #align_import data.polynomial.erase_lead from "leanprover-community/mathlib"@"fa256f00ce018e7b40e1dc756e403c86680bf448" @@ -111,17 +111,36 @@ theorem eraseLead_support_card_lt (h : f ≠ 0) : (eraseLead f).support.card < f exact card_lt_card (erase_ssubset <| natDegree_mem_support_of_nonzero h) #align polynomial.erase_lead_support_card_lt Polynomial.eraseLead_support_card_lt -theorem eraseLead_card_support {c : ℕ} (fc : f.support.card = c) : - f.eraseLead.support.card = c - 1 := by - by_cases f0 : f = 0 - · rw [← fc, f0, eraseLead_zero, support_zero, card_empty] - · rw [eraseLead_support, card_erase_of_mem (natDegree_mem_support_of_nonzero f0), fc] -#align polynomial.erase_lead_card_support Polynomial.eraseLead_card_support +theorem card_support_eraseLead_add_one (h : f ≠ 0) : + f.eraseLead.support.card + 1 = f.support.card := by + set c := f.support.card with hc + cases h₁ : c + case zero => + by_contra + exact h (card_support_eq_zero.mp h₁) + case succ => + rw [eraseLead_support, card_erase_of_mem (natDegree_mem_support_of_nonzero h), ← hc, h₁] + rfl + +@[simp] +theorem card_support_eraseLead : f.eraseLead.support.card = f.support.card - 1 := by + by_cases hf : f = 0 + · rw [hf, eraseLead_zero, support_zero, card_empty] + · rw [← card_support_eraseLead_add_one hf, add_tsub_cancel_right] -theorem eraseLead_card_support' {c : ℕ} (fc : f.support.card = c + 1) : - f.eraseLead.support.card = c := - eraseLead_card_support fc -#align polynomial.erase_lead_card_support' Polynomial.eraseLead_card_support' +theorem card_support_eraseLead' {c : ℕ} (fc : f.support.card = c + 1) : + f.eraseLead.support.card = c := by + rw [card_support_eraseLead, fc, add_tsub_cancel_right] +#align polynomial.erase_lead_card_support' Polynomial.card_support_eraseLead' + +theorem card_support_eq_one_of_eraseLead_eq_zero (h₀ : f ≠ 0) (h₁ : f.eraseLead = 0) : + f.support.card = 1 := + (card_support_eq_zero.mpr h₁ ▸ card_support_eraseLead_add_one h₀).symm + +theorem card_support_le_one_of_eraseLead_eq_zero (h : f.eraseLead = 0) : f.support.card ≤ 1 := by + by_cases hpz : f = 0 + case pos => simp [hpz] + case neg => exact le_of_eq (card_support_eq_one_of_eraseLead_eq_zero hpz h) @[simp] theorem eraseLead_monomial (i : ℕ) (r : R) : eraseLead (monomial i r) = 0 := by @@ -156,6 +175,9 @@ theorem eraseLead_C_mul_X_pow (r : R) (n : ℕ) : eraseLead (C r * X ^ n) = 0 := set_option linter.uppercaseLean3 false in #align polynomial.erase_lead_C_mul_X_pow Polynomial.eraseLead_C_mul_X_pow +@[simp] lemma eraseLead_C_mul_X (r : R) : eraseLead (C r * X) = 0 := by + simpa using eraseLead_C_mul_X_pow _ 1 + theorem eraseLead_add_of_natDegree_lt_left {p q : R[X]} (pq : q.natDegree < p.natDegree) : (p + q).eraseLead = p.eraseLead + q := by ext n @@ -192,6 +214,11 @@ theorem eraseLead_natDegree_lt (f0 : 2 ≤ f.support.card) : (eraseLead f).natDe natDegree_mem_support_of_nonzero <| eraseLead_ne_zero f0 #align polynomial.erase_lead_nat_degree_lt Polynomial.eraseLead_natDegree_lt +theorem natDegree_pos_of_eraseLead_ne_zero (h : f.eraseLead ≠ 0) : 0 < f.natDegree := by + by_contra h₂ + rw [eq_C_of_natDegree_eq_zero (Nat.eq_zero_of_not_pos h₂)] at h + simp at h + theorem eraseLead_natDegree_lt_or_eraseLead_eq_zero (f : R[X]) : (eraseLead f).natDegree < f.natDegree ∨ f.eraseLead = 0 := by by_cases h : f.support.card ≤ 1 @@ -208,6 +235,48 @@ theorem eraseLead_natDegree_le (f : R[X]) : (eraseLead f).natDegree ≤ f.natDeg · simp only [h, natDegree_zero, zero_le] #align polynomial.erase_lead_nat_degree_le Polynomial.eraseLead_natDegree_le +lemma natDegree_eraseLead (h : f.nextCoeff ≠ 0) : f.eraseLead.natDegree = f.natDegree - 1 := by + have := natDegree_pos_of_nextCoeff_ne_zero h + refine f.eraseLead_natDegree_le.antisymm $ le_natDegree_of_ne_zero ?_ + rwa [eraseLead_coeff_of_ne _ (tsub_lt_self _ _).ne, ← nextCoeff_of_natDegree_pos] + all_goals positivity + +lemma natDegree_eraseLead_add_one (h : f.nextCoeff ≠ 0) : + f.eraseLead.natDegree + 1 = f.natDegree := by + rw [natDegree_eraseLead h, tsub_add_cancel_of_le] + exact natDegree_pos_of_nextCoeff_ne_zero h + +theorem natDegree_eraseLead_le_of_nextCoeff_eq_zero (h : f.nextCoeff = 0) : + f.eraseLead.natDegree ≤ f.natDegree - 2 := by + refine natDegree_le_pred (n := f.natDegree - 1) (eraseLead_natDegree_le f) ?_ + rw [nextCoeff_eq_zero, natDegree_eq_zero] at h + obtain ⟨a, rfl⟩ | ⟨hf, h⟩ := h + · simp + rw [eraseLead_coeff_of_ne _ (tsub_lt_self hf zero_lt_one).ne, ← nextCoeff_of_natDegree_pos hf] + simp [nextCoeff_eq_zero, h, eq_zero_or_pos] + +lemma two_le_natDegree_of_nextCoeff_eraseLead (hlead : f.eraseLead ≠ 0) (hnext : f.nextCoeff = 0) : + 2 ≤ f.natDegree := by + contrapose! hlead + rw [Nat.lt_succ_iff, Nat.le_one_iff_eq_zero_or_eq_one, natDegree_eq_zero, natDegree_eq_one] + at hlead + obtain ⟨a, rfl⟩ | ⟨a, ha, b, rfl⟩ := hlead + · simp + · rw [nextCoeff_C_mul_X_add_C ha] at hnext + subst b + simp + +theorem leadingCoeff_eraseLead_eq_nextCoeff (h : f.nextCoeff ≠ 0) : + f.eraseLead.leadingCoeff = f.nextCoeff := by + have := natDegree_pos_of_nextCoeff_ne_zero h + rw [leadingCoeff, nextCoeff, natDegree_eraseLead h, if_neg, + eraseLead_coeff_of_ne _ (tsub_lt_self _ _).ne] + all_goals positivity + +theorem nextCoeff_eq_zero_of_eraseLead_eq_zero (h : f.eraseLead = 0) : f.nextCoeff = 0 := by + by_contra h₂ + exact leadingCoeff_ne_zero.mp (leadingCoeff_eraseLead_eq_nextCoeff h₂ ▸ h₂) h + end EraseLead /-- An induction lemma for polynomials. It takes a natural number `N` as a parameter, that is @@ -230,7 +299,7 @@ theorem induction_with_natDegree_le (P : R[X] → Prop) (N : ℕ) (P_0 : P 0) cases c · convert P_C_mul_pow f.natDegree f.leadingCoeff ?_ df using 1 · convert zero_add (C (leadingCoeff f) * X ^ f.natDegree) - rw [← card_support_eq_zero, eraseLead_card_support f0] + rw [← card_support_eq_zero, card_support_eraseLead' f0] · rw [leadingCoeff_ne_zero, Ne.def, ← card_support_eq_zero, f0] exact zero_ne_one.symm refine' P_C_add f.eraseLead _ _ _ _ _ @@ -240,7 +309,7 @@ theorem induction_with_natDegree_le (P : R[X] → Prop) (N : ℕ) (P_0 : P 0) rintro rfl simp at f0 · exact (natDegree_C_mul_X_pow_le f.leadingCoeff f.natDegree).trans df - · exact hc _ (eraseLead_natDegree_le_aux.trans df) (eraseLead_card_support f0) + · exact hc _ (eraseLead_natDegree_le_aux.trans df) (card_support_eraseLead' f0) · refine' P_C_mul_pow _ _ _ df rw [Ne.def, leadingCoeff_eq_zero, ← card_support_eq_zero, f0] exact Nat.succ_ne_zero _ @@ -312,7 +381,7 @@ theorem card_support_eq {n : ℕ} : induction' n with n hn generalizing f · exact fun hf => ⟨0, 0, fun x => x.elim0, fun x => x.elim0, card_support_eq_zero.mp hf⟩ · intro h - obtain ⟨k, x, hk, hx, hf⟩ := hn (eraseLead_card_support' h) + obtain ⟨k, x, hk, hx, hf⟩ := hn (card_support_eraseLead' h) have H : ¬∃ k : Fin n, Fin.castSucc k = Fin.last n := by rintro ⟨i, hi⟩ exact i.castSucc_lt_last.ne hi diff --git a/Mathlib/Data/Polynomial/Eval.lean b/Mathlib/Data/Polynomial/Eval.lean index 68b30c846ebf7..6d1dadbbd8fd3 100644 --- a/Mathlib/Data/Polynomial/Eval.lean +++ b/Mathlib/Data/Polynomial/Eval.lean @@ -1092,7 +1092,7 @@ theorem coe_evalRingHom (r : R) : (evalRingHom r : R[X] → R) = eval r := #align polynomial.coe_eval_ring_hom Polynomial.coe_evalRingHom theorem evalRingHom_zero : evalRingHom 0 = constantCoeff := - FunLike.ext _ _ fun p => p.coeff_zero_eq_eval_zero.symm + DFunLike.ext _ _ fun p => p.coeff_zero_eq_eval_zero.symm #align polynomial.eval_ring_hom_zero Polynomial.evalRingHom_zero @[simp] diff --git a/Mathlib/Data/Polynomial/FieldDivision.lean b/Mathlib/Data/Polynomial/FieldDivision.lean index 00de40dde6d43..aae30ec043ebe 100644 --- a/Mathlib/Data/Polynomial/FieldDivision.lean +++ b/Mathlib/Data/Polynomial/FieldDivision.lean @@ -12,7 +12,7 @@ import Mathlib.RingTheory.EuclideanDomain /-! # Theory of univariate polynomials -This file starts looking like the ring theory of $ R[X] $ +This file starts looking like the ring theory of $R[X]$ -/ @@ -507,7 +507,7 @@ theorem exists_root_of_degree_eq_one (h : degree p = 1) : ∃ x, IsRoot p x := have : p.coeff 1 ≠ 0 := by have h' := natDegree_eq_of_degree_eq_some h change natDegree p = 1 at h'; rw [← h'] - exact mt leadingCoeff_eq_zero.1 fun h0 => by simp [h0] at h; contradiction + exact mt leadingCoeff_eq_zero.1 fun h0 => by simp [h0] at h conv in p => rw [eq_X_add_C_of_degree_le_one (show degree p ≤ 1 by rw [h])] simp [IsRoot, mul_div_cancel' _ this]⟩ #align polynomial.exists_root_of_degree_eq_one Polynomial.exists_root_of_degree_eq_one @@ -590,7 +590,7 @@ theorem prime_of_degree_eq_one (hp1 : degree p = 1) : Prime p := by classical have : Prime (normalize p) := Monic.prime_of_degree_eq_one (hp1 ▸ degree_normalize) - (monic_normalize fun hp0 => absurd hp1 (hp0.symm ▸ by simp [degree_zero, ← WithBot.coe_one])) + (monic_normalize fun hp0 => absurd hp1 (hp0.symm ▸ by simp [degree_zero])) exact (normalize_associated _).prime this #align polynomial.prime_of_degree_eq_one Polynomial.prime_of_degree_eq_one diff --git a/Mathlib/Data/Polynomial/Identities.lean b/Mathlib/Data/Polynomial/Identities.lean index c6c004e61fb29..7057049efcbdb 100644 --- a/Mathlib/Data/Polynomial/Identities.lean +++ b/Mathlib/Data/Polynomial/Identities.lean @@ -83,8 +83,8 @@ def binomExpansion (f : R[X]) (x y : R) : congr · rw [← eval_eq_sum] · rw [derivative_eval] - exact Finset.sum_mul.symm - · exact Finset.sum_mul.symm + exact (Finset.sum_mul ..).symm + · exact (Finset.sum_mul ..).symm #align polynomial.binom_expansion Polynomial.binomExpansion /-- `x^n - y^n` can be expressed as `z * (x - y)` for some `z` in the ring. diff --git a/Mathlib/Data/Polynomial/Inductions.lean b/Mathlib/Data/Polynomial/Inductions.lean index ef91eb3f944ee..c9a22116f9375 100644 --- a/Mathlib/Data/Polynomial/Inductions.lean +++ b/Mathlib/Data/Polynomial/Inductions.lean @@ -163,7 +163,7 @@ noncomputable def recOnHorner {M : R[X] → Sort*} (p : R[X]) (M0 : M 0) MC _ _ (coeff_mul_X_zero _) hcp0 (if hpX0 : divX p = 0 then show M (divX p * X) by rw [hpX0, zero_mul]; exact M0 else MX (divX p) hpX0 (recOnHorner _ M0 MC MX)) -termination_by _ => p.degree +termination_by p.degree #align polynomial.rec_on_horner Polynomial.recOnHorner /-- A property holds for all polynomials of positive `degree` with coefficients in a semiring `R` diff --git a/Mathlib/Data/Polynomial/Lifts.lean b/Mathlib/Data/Polynomial/Lifts.lean index 5784ea8113149..87ca2c997ac7e 100644 --- a/Mathlib/Data/Polynomial/Lifts.lean +++ b/Mathlib/Data/Polynomial/Lifts.lean @@ -148,8 +148,7 @@ theorem monomial_mem_lifts_and_degree_eq {s : S} {n : ℕ} (hl : monomial n s obtain ⟨q, hq⟩ := hl replace hq := (ext_iff.1 hq) n have hcoeff : f (q.coeff n) = s := by - simp? [coeff_monomial] at hq says - simp only [coeff_map, coeff_monomial, ite_true] at hq + simp? [coeff_monomial] at hq says simp only [coeff_map, coeff_monomial, ↓reduceIte] at hq exact hq use monomial n (q.coeff n) constructor diff --git a/Mathlib/Data/Polynomial/Module.lean b/Mathlib/Data/Polynomial/Module.lean index b97638bb474f3..f31110fa11fd2 100644 --- a/Mathlib/Data/Polynomial/Module.lean +++ b/Mathlib/Data/Polynomial/Module.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.RingTheory.Adjoin.Tower +import Mathlib.RingTheory.Finiteness +import Mathlib.Data.Polynomial.AlgebraMap #align_import data.polynomial.module from "leanprover-community/mathlib"@"63417e01fbc711beaf25fa73b6edb395c0cfddd0" @@ -69,6 +70,9 @@ lemma of_aeval_smul (f : R[X]) (m : M) : of R M a (aeval a f • m) = f • of R @[simp] lemma of_symm_smul (f : R[X]) (m : AEval R M a) : (of R M a).symm (f • m) = aeval a f • (of R M a).symm m := rfl +@[simp] lemma C_smul (t : R) (m : AEval R M a) : C t • m = t • m := + (of R M a).symm.injective <| by simp + lemma X_smul_of (m : M) : (X : R[X]) • (of R M a m) = of R M a (a • m) := by rw [← of_aeval_smul, aeval_X] @@ -79,12 +83,57 @@ lemma of_symm_X_smul (m : AEval R M a) : instance instIsScalarTowerOrigPolynomial : IsScalarTower R R[X] <| AEval R M a where smul_assoc r f m := by apply (of R M a).symm.injective - rw [of_symm_smul, map_smul, smul_assoc] - rfl + rw [of_symm_smul, map_smul, smul_assoc, map_smul, of_symm_smul] instance instFinitePolynomial [Finite R M] : Finite R[X] <| AEval R M a := Finite.of_restrictScalars_finite R _ _ +section Submodule + +variable {p : Submodule R M} (hp : p ≤ p.comap (Algebra.lsmul R R M a)) + {q : Submodule R[X] <| AEval R M a} + +variable (R M) in +/-- We can turn an `R[X]`-submodule into an `R`-submodule by forgetting the action of `X`. -/ +def comapSubmodule : + CompleteLatticeHom (Submodule R[X] <| AEval R M a) (Submodule R M) := + (Submodule.orderIsoMapComap (of R M a)).symm.toCompleteLatticeHom.comp <| + Submodule.restrictScalarsLatticeHom R R[X] (AEval R M a) + +@[simp] lemma mem_comapSubmodule {x : M} : + x ∈ comapSubmodule R M a q ↔ of R M a x ∈ q := + Iff.rfl + +@[simp] lemma comapSubmodule_le_comap : + comapSubmodule R M a q ≤ (comapSubmodule R M a q).comap (Algebra.lsmul R R M a) := by + intro m hm + simpa only [Submodule.mem_comap, Algebra.lsmul_coe, mem_comapSubmodule, ← X_smul_of] using + q.smul_mem (X : R[X]) hm + +/-- An `R`-submodule which is stable under the action of `a` can be promoted to an +`R[X]`-submodule. -/ +def mapSubmodule : Submodule R[X] <| AEval R M a := + { toAddSubmonoid := p.toAddSubmonoid.map (of R M a) + smul_mem' := by + rintro f - ⟨m : M, h : m ∈ p, rfl⟩ + simp only [AddSubsemigroup.mem_carrier, AddSubmonoid.mem_toSubsemigroup, AddSubmonoid.mem_map, + Submodule.mem_toAddSubmonoid] + exact ⟨aeval a f • m, aeval_apply_smul_mem_of_le_comap' h f a hp, of_aeval_smul a f m⟩ } + +@[simp] lemma mem_mapSubmodule {m : AEval R M a} : + m ∈ mapSubmodule a hp ↔ (of R M a).symm m ∈ p := + ⟨fun ⟨_, hm, hm'⟩ ↦ hm'.symm ▸ hm, fun hm ↦ ⟨(of R M a).symm m, hm, rfl⟩⟩ + +@[simp] lemma mapSubmodule_comapSubmodule (h := comapSubmodule_le_comap a) : + mapSubmodule a (p := comapSubmodule R M a q) h = q := by + ext; simp + +@[simp] lemma comapSubmodule_mapSubmodule : + comapSubmodule R M a (mapSubmodule a hp) = p := by + ext; simp + +end Submodule + end AEval variable (φ : M →ₗ[R] M) @@ -154,8 +203,8 @@ namespace PolynomialModule noncomputable instance : Module S (PolynomialModule R M) := Finsupp.module ℕ M -instance funLike : FunLike (PolynomialModule R M) ℕ fun _ => M := - Finsupp.funLike +instance instFunLike : FunLike (PolynomialModule R M) ℕ M := + Finsupp.instFunLike instance : CoeFun (PolynomialModule R M) fun _ => ℕ → M := Finsupp.coeFun diff --git a/Mathlib/Data/Polynomial/PartialFractions.lean b/Mathlib/Data/Polynomial/PartialFractions.lean index b976fe3099efa..940e83d3519e9 100644 --- a/Mathlib/Data/Polynomial/PartialFractions.lean +++ b/Mathlib/Data/Polynomial/PartialFractions.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Buzzard, Sidharth Hariharan -/ import Mathlib.Data.Polynomial.Div -import Mathlib.Data.ZMod.Basic import Mathlib.Logic.Function.Basic import Mathlib.RingTheory.Localization.FractionRing import Mathlib.Tactic.FieldSimp diff --git a/Mathlib/Data/Polynomial/RingDivision.lean b/Mathlib/Data/Polynomial/RingDivision.lean index fe180e2893dc3..abad7efccf72f 100644 --- a/Mathlib/Data/Polynomial/RingDivision.lean +++ b/Mathlib/Data/Polynomial/RingDivision.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker, Johan Commelin -/ -import Mathlib.Algebra.CharZero.Infinite import Mathlib.Data.Polynomial.AlgebraMap import Mathlib.Data.Polynomial.Degree.Lemmas import Mathlib.Data.Polynomial.Div @@ -15,7 +14,7 @@ import Mathlib.Algebra.Polynomial.BigOperators /-! # Theory of univariate polynomials -This file starts looking like the ring theory of $ R[X] $ +This file starts looking like the ring theory of $R[X]$ ## Main definitions @@ -599,7 +598,7 @@ theorem exists_multiset_roots [DecidableEq R] : ⟨0, (degree_eq_natDegree hp).symm ▸ WithBot.coe_le_coe.2 (Nat.zero_le _), by intro a rw [count_zero, rootMultiplicity_eq_zero (not_exists.mp h a)]⟩ -termination_by _ p _ => natDegree p +termination_by p => natDegree p decreasing_by { simp_wf apply (Nat.cast_lt (α := WithBot ℕ)).mp @@ -1073,8 +1072,8 @@ theorem aroots_one [CommRing S] [IsDomain S] [Algebra T S] : @[simp] theorem aroots_neg [CommRing S] [IsDomain S] [Algebra T S] (p : T[X]) : - (-p).aroots S = p.aroots S := - by rw [aroots, Polynomial.map_neg, roots_neg] + (-p).aroots S = p.aroots S := by + rw [aroots, Polynomial.map_neg, roots_neg] @[simp] theorem aroots_C_mul [CommRing S] [IsDomain S] [Algebra T S] @@ -1258,12 +1257,43 @@ theorem leadingCoeff_divByMonic_X_sub_C (p : R[X]) (hp : degree p ≠ 0) (a : R) leadingCoeff (p /ₘ (X - C a)) = leadingCoeff p := by nontriviality cases' hp.lt_or_lt with hd hd - · rw [degree_eq_bot.mp <| (Nat.WithBot.lt_zero_iff _).mp hd, zero_divByMonic] + · rw [degree_eq_bot.mp <| Nat.WithBot.lt_zero_iff.mp hd, zero_divByMonic] refine' leadingCoeff_divByMonic_of_monic (monic_X_sub_C a) _ rwa [degree_X_sub_C, Nat.WithBot.one_le_iff_zero_lt] set_option linter.uppercaseLean3 false in #align polynomial.leading_coeff_div_by_monic_X_sub_C Polynomial.leadingCoeff_divByMonic_X_sub_C +theorem eq_of_dvd_of_natDegree_le_of_leadingCoeff {p q : R[X]} (hpq : p ∣ q) + (h₁ : q.natDegree ≤ p.natDegree) (h₂ : p.leadingCoeff = q.leadingCoeff) : + p = q := by + by_cases hq : q = 0 + · rwa [hq, leadingCoeff_zero, leadingCoeff_eq_zero, ← hq] at h₂ + replace h₁ := (natDegree_le_of_dvd hpq hq).antisymm h₁ + obtain ⟨u, rfl⟩ := hpq + replace hq := mul_ne_zero_iff.mp hq + rw [natDegree_mul hq.1 hq.2, self_eq_add_right] at h₁ + rw [eq_C_of_natDegree_eq_zero h₁, leadingCoeff_mul, leadingCoeff_C, + eq_comm, mul_eq_left₀ (leadingCoeff_ne_zero.mpr hq.1)] at h₂ + rw [eq_C_of_natDegree_eq_zero h₁, h₂, map_one, mul_one] + +theorem associated_of_dvd_of_natDegree_le_of_leadingCoeff {p q : R[X]} (hpq : p ∣ q) + (h₁ : q.natDegree ≤ p.natDegree) (h₂ : q.leadingCoeff ∣ p.leadingCoeff) : + Associated p q := + have ⟨r, hr⟩ := hpq + have ⟨u, hu⟩ := associated_of_dvd_dvd ⟨leadingCoeff r, hr ▸ leadingCoeff_mul p r⟩ h₂ + ⟨Units.map C.toMonoidHom u, eq_of_dvd_of_natDegree_le_of_leadingCoeff + (by rwa [Units.mul_right_dvd]) (by simpa [natDegree_mul_C] using h₁) (by simpa using hu)⟩ + +theorem associated_of_dvd_of_natDegree_le {K} [Field K] {p q : K[X]} (hpq : p ∣ q) (hq : q ≠ 0) + (h₁ : q.natDegree ≤ p.natDegree) : Associated p q := + associated_of_dvd_of_natDegree_le_of_leadingCoeff hpq h₁ + (IsUnit.dvd (by rwa [← leadingCoeff_ne_zero, ← isUnit_iff_ne_zero] at hq)) + +theorem associated_of_dvd_of_degree_eq {K} [Field K] {p q : K[X]} (hpq : p ∣ q) + (h₁ : p.degree = q.degree) : Associated p q := + (Classical.em (q = 0)).elim (fun hq ↦ (show p = q by simpa [hq] using h₁) ▸ Associated.refl p) + (associated_of_dvd_of_natDegree_le hpq · (natDegree_le_natDegree h₁.ge)) + theorem eq_leadingCoeff_mul_of_monic_of_dvd_of_natDegree_le {R} [CommRing R] {p q : R[X]} (hp : p.Monic) (hdiv : p ∣ q) (hdeg : q.natDegree ≤ p.natDegree) : q = C q.leadingCoeff * p := by diff --git a/Mathlib/Data/Prod/Basic.lean b/Mathlib/Data/Prod/Basic.lean index b2077a027cfc6..e4f80495392f7 100644 --- a/Mathlib/Data/Prod/Basic.lean +++ b/Mathlib/Data/Prod/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ -import Mathlib.Init.Core import Mathlib.Init.Function import Mathlib.Logic.Function.Basic import Mathlib.Tactic.Inhabit @@ -226,12 +225,6 @@ theorem snd_eq_iff : ∀ {p : α × β} {x : β}, p.2 = x ↔ p = (p.1, x) variable {r : α → α → Prop} {s : β → β → Prop} {x y : α × β} -theorem lex_def (r : α → α → Prop) (s : β → β → Prop) {p q : α × β} : - Prod.Lex r s p q ↔ r p.1 q.1 ∨ p.1 = q.1 ∧ s p.2 q.2 := - ⟨fun h ↦ by cases h <;> simp [*], fun h ↦ - match p, q, h with - | (a, b), (c, d), Or.inl h => Lex.left _ _ h - | (a, b), (c, d), Or.inr ⟨e, h⟩ => by subst e; exact Lex.right _ h⟩ #align prod.lex_def Prod.lex_def lemma lex_iff : Prod.Lex r s x y ↔ r x.1 y.1 ∨ x.1 = y.1 ∧ s x.2 y.2 := lex_def _ _ @@ -303,7 +296,7 @@ instance IsTrichotomous [IsTrichotomous α r] [IsTrichotomous β s] : obtain hij | rfl | hji := trichotomous_of r i j { exact Or.inl (Lex.left _ _ hij) } { exact (trichotomous_of (s) a b).imp3 (Lex.right _) (congr_arg _) (Lex.right _) } - { exact Or.inr (Or.inr $ Lex.left _ _ hji) }⟩ + { exact Or.inr (Or.inr <| Lex.left _ _ hji) }⟩ end Prod diff --git a/Mathlib/Data/Prod/PProd.lean b/Mathlib/Data/Prod/PProd.lean index f52fa0ed21b59..b2d08a413243c 100644 --- a/Mathlib/Data/Prod/PProd.lean +++ b/Mathlib/Data/Prod/PProd.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Logic.Basic +import Mathlib.Init.Function #align_import data.prod.pprod from "leanprover-community/mathlib"@"c4658a649d216f57e99621708b09dcb3dcccbd23" diff --git a/Mathlib/Data/Prod/TProd.lean b/Mathlib/Data/Prod/TProd.lean index 3133a6173ee3f..0a9d0066fce5e 100644 --- a/Mathlib/Data/Prod/TProd.lean +++ b/Mathlib/Data/Prod/TProd.lean @@ -109,7 +109,7 @@ theorem elim_mk : ∀ (l : List ι) (f : ∀ i, α i) {i : ι} (hi : i ∈ l), ( · subst hji simp · rw [TProd.elim_of_ne _ hji, snd_mk, elim_mk is] - termination_by elim_mk l f j hj => l.length + termination_by l f j hj => l.length #align list.tprod.elim_mk List.TProd.elim_mk @[ext] diff --git a/Mathlib/Data/QPF/Multivariate/Constructions/Cofix.lean b/Mathlib/Data/QPF/Multivariate/Constructions/Cofix.lean index 56dc69b12e1a1..7472bc43c25c7 100644 --- a/Mathlib/Data/QPF/Multivariate/Constructions/Cofix.lean +++ b/Mathlib/Data/QPF/Multivariate/Constructions/Cofix.lean @@ -403,9 +403,9 @@ theorem liftR_map_last [lawful : LawfulMvFunctor F] dsimp apply eq_of_drop_last_eq · dsimp - simp only [prod_map_id, dropFun_prod, dropFun_appendFun, dropFun_diag, id_comp, + simp only [prod_map_id, dropFun_prod, dropFun_appendFun, dropFun_diag, TypeVec.id_comp, dropFun_toSubtype] - erw [toSubtype_of_subtype_assoc, id_comp] + erw [toSubtype_of_subtype_assoc, TypeVec.id_comp] clear liftR_map_last q mvf lawful F x R f g hh h b c ext (i x) : 2 induction i with @@ -413,7 +413,7 @@ theorem liftR_map_last [lawful : LawfulMvFunctor F] | fs _ ih => apply ih simp only [lastFun_from_append1_drop_last, lastFun_toSubtype, lastFun_appendFun, - lastFun_subtypeVal, comp.left_id, lastFun_comp, lastFun_prod] + lastFun_subtypeVal, Function.id_comp, lastFun_comp, lastFun_prod] ext1 rfl liftR_map _ _ _ _ (toSubtype _ ⊚ fromAppend1DropLast ⊚ c ⊚ b) hh diff --git a/Mathlib/Data/Rat/Cast/Defs.lean b/Mathlib/Data/Rat/Cast/Defs.lean index d6f44bc29ef98..3c8aa76a0ef3b 100644 --- a/Mathlib/Data/Rat/Cast/Defs.lean +++ b/Mathlib/Data/Rat/Cast/Defs.lean @@ -199,7 +199,7 @@ variable {M₀ : Type*} [MonoidWithZero M₀] [MonoidWithZeroHomClass F ℚ M₀ /-- If `f` and `g` agree on the integers then they are equal `φ`. -/ theorem ext_rat' (h : ∀ m : ℤ, f m = g m) : f = g := - (FunLike.ext f g) fun r => by + (DFunLike.ext f g) fun r => by rw [← r.num_div_den, div_eq_mul_inv, map_mul, map_mul, h, ← Int.cast_ofNat, eq_on_inv₀ f g] apply h @@ -211,14 +211,14 @@ See note [partially-applied ext lemmas] for why `comp` is used here. -/ @[ext] theorem ext_rat {f g : ℚ →*₀ M₀} (h : f.comp (Int.castRingHom ℚ : ℤ →*₀ ℚ) = g.comp (Int.castRingHom ℚ)) : f = g := - ext_rat' <| FunLike.congr_fun h + ext_rat' <| DFunLike.congr_fun h #align monoid_with_zero_hom.ext_rat MonoidWithZeroHom.ext_rat /-- Positive integer values of a morphism `φ` and its value on `-1` completely determine `φ`. -/ theorem ext_rat_on_pnat (same_on_neg_one : f (-1) = g (-1)) (same_on_pnat : ∀ n : ℕ, 0 < n → f n = g n) : f = g := ext_rat' <| - FunLike.congr_fun <| + DFunLike.congr_fun <| show (f : ℚ →*₀ M₀).comp (Int.castRingHom ℚ : ℤ →*₀ ℚ) = (g : ℚ →*₀ M₀).comp (Int.castRingHom ℚ : ℤ →*₀ ℚ) diff --git a/Mathlib/Data/Rat/Cast/Order.lean b/Mathlib/Data/Rat/Cast/Order.lean index 6d6d58e8cac10..dca14071e4ef7 100644 --- a/Mathlib/Data/Rat/Cast/Order.lean +++ b/Mathlib/Data/Rat/Cast/Order.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Data.Rat.Cast.CharZero import Mathlib.Data.Rat.Order +import Mathlib.Data.Set.Intervals.OrderEmbedding import Mathlib.Algebra.Order.Field.Basic #align_import data.rat.cast from "leanprover-community/mathlib"@"acebd8d49928f6ed8920e502a6c90674e75bd441" @@ -98,51 +99,51 @@ theorem cast_abs {q : ℚ} : ((|q| : ℚ) : K) = |(q : K)| := by simp [abs_eq_ma open Set @[simp] -theorem preimage_cast_Icc (a b : ℚ) : (↑) ⁻¹' Icc (a : K) b = Icc a b := by - ext x - simp +theorem preimage_cast_Icc (a b : ℚ) : (↑) ⁻¹' Icc (a : K) b = Icc a b := + castOrderEmbedding.preimage_Icc .. #align rat.preimage_cast_Icc Rat.preimage_cast_Icc @[simp] -theorem preimage_cast_Ico (a b : ℚ) : (↑) ⁻¹' Ico (a : K) b = Ico a b := by - ext x - simp +theorem preimage_cast_Ico (a b : ℚ) : (↑) ⁻¹' Ico (a : K) b = Ico a b := + castOrderEmbedding.preimage_Ico .. #align rat.preimage_cast_Ico Rat.preimage_cast_Ico @[simp] -theorem preimage_cast_Ioc (a b : ℚ) : (↑) ⁻¹' Ioc (a : K) b = Ioc a b := by - ext x - simp +theorem preimage_cast_Ioc (a b : ℚ) : (↑) ⁻¹' Ioc (a : K) b = Ioc a b := + castOrderEmbedding.preimage_Ioc a b #align rat.preimage_cast_Ioc Rat.preimage_cast_Ioc @[simp] -theorem preimage_cast_Ioo (a b : ℚ) : (↑) ⁻¹' Ioo (a : K) b = Ioo a b := by - ext x - simp +theorem preimage_cast_Ioo (a b : ℚ) : (↑) ⁻¹' Ioo (a : K) b = Ioo a b := + castOrderEmbedding.preimage_Ioo a b #align rat.preimage_cast_Ioo Rat.preimage_cast_Ioo @[simp] -theorem preimage_cast_Ici (a : ℚ) : (↑) ⁻¹' Ici (a : K) = Ici a := by - ext x - simp +theorem preimage_cast_Ici (a : ℚ) : (↑) ⁻¹' Ici (a : K) = Ici a := + castOrderEmbedding.preimage_Ici a #align rat.preimage_cast_Ici Rat.preimage_cast_Ici @[simp] -theorem preimage_cast_Iic (a : ℚ) : (↑) ⁻¹' Iic (a : K) = Iic a := by - ext x - simp +theorem preimage_cast_Iic (a : ℚ) : (↑) ⁻¹' Iic (a : K) = Iic a := + castOrderEmbedding.preimage_Iic a #align rat.preimage_cast_Iic Rat.preimage_cast_Iic @[simp] -theorem preimage_cast_Ioi (a : ℚ) : (↑) ⁻¹' Ioi (a : K) = Ioi a := by - ext x - simp +theorem preimage_cast_Ioi (a : ℚ) : (↑) ⁻¹' Ioi (a : K) = Ioi a := + castOrderEmbedding.preimage_Ioi a #align rat.preimage_cast_Ioi Rat.preimage_cast_Ioi @[simp] -theorem preimage_cast_Iio (a : ℚ) : (↑) ⁻¹' Iio (a : K) = Iio a := by - ext x - simp +theorem preimage_cast_Iio (a : ℚ) : (↑) ⁻¹' Iio (a : K) = Iio a := + castOrderEmbedding.preimage_Iio a #align rat.preimage_cast_Iio Rat.preimage_cast_Iio +@[simp] +theorem preimage_cast_uIcc (a b : ℚ) : (↑) ⁻¹' uIcc (a : K) b = uIcc a b := + (castOrderEmbedding (K := K)).preimage_uIcc a b + +@[simp] +theorem preimage_cast_uIoc (a b : ℚ) : (↑) ⁻¹' uIoc (a : K) b = uIoc a b := + (castOrderEmbedding (K := K)).preimage_uIoc a b + end LinearOrderedField diff --git a/Mathlib/Data/Rat/Defs.lean b/Mathlib/Data/Rat/Defs.lean index 654b9dbe6abfe..b38070378e086 100644 --- a/Mathlib/Data/Rat/Defs.lean +++ b/Mathlib/Data/Rat/Defs.lean @@ -147,8 +147,8 @@ theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; rw [num_den'] at ha generalize hc : c /. d = x; cases' x with n₂ d₂ h₂ c₂; rw [num_den'] at hc rw [fv] - have d₁0 := ne_of_gt (Int.ofNat_lt.2 $ Nat.pos_of_ne_zero h₁) - have d₂0 := ne_of_gt (Int.ofNat_lt.2 $ Nat.pos_of_ne_zero h₂) + have d₁0 := ne_of_gt (Int.ofNat_lt.2 <| Nat.pos_of_ne_zero h₁) + have d₂0 := ne_of_gt (Int.ofNat_lt.2 <| Nat.pos_of_ne_zero h₂) exact (divInt_eq_iff (f0 d₁0 d₂0) (f0 b0 d0)).2 (H ((divInt_eq_iff b0 d₁0).1 ha) ((divInt_eq_iff d0 d₂0).1 hc)) #align rat.lift_binop_eq Rat.lift_binop_eq diff --git a/Mathlib/Data/Rat/NNRat.lean b/Mathlib/Data/Rat/NNRat.lean index 4bd8ad292500d..f6a7c4b1e29bf 100644 --- a/Mathlib/Data/Rat/NNRat.lean +++ b/Mathlib/Data/Rat/NNRat.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Bhavik Mehta -/ import Mathlib.Algebra.Algebra.Basic -import Mathlib.Algebra.BigOperators.Order import Mathlib.Algebra.Order.Nonneg.Field import Mathlib.Algebra.Order.Nonneg.Floor @@ -248,49 +247,6 @@ theorem coe_indicator (s : Set α) (f : α → ℚ≥0) (a : α) : theorem coe_pow (q : ℚ≥0) (n : ℕ) : (↑(q ^ n) : ℚ) = (q : ℚ) ^ n := coeHom.map_pow _ _ #align nnrat.coe_pow NNRat.coe_pow - -@[norm_cast] -theorem coe_list_sum (l : List ℚ≥0) : (l.sum : ℚ) = (l.map (↑)).sum := - coeHom.map_list_sum _ -#align nnrat.coe_list_sum NNRat.coe_list_sum - -@[norm_cast] -theorem coe_list_prod (l : List ℚ≥0) : (l.prod : ℚ) = (l.map (↑)).prod := - coeHom.map_list_prod _ -#align nnrat.coe_list_prod NNRat.coe_list_prod - -@[norm_cast] -theorem coe_multiset_sum (s : Multiset ℚ≥0) : (s.sum : ℚ) = (s.map (↑)).sum := - coeHom.map_multiset_sum _ -#align nnrat.coe_multiset_sum NNRat.coe_multiset_sum - -@[norm_cast] -theorem coe_multiset_prod (s : Multiset ℚ≥0) : (s.prod : ℚ) = (s.map (↑)).prod := - coeHom.map_multiset_prod _ -#align nnrat.coe_multiset_prod NNRat.coe_multiset_prod - -@[norm_cast] -theorem coe_sum {s : Finset α} {f : α → ℚ≥0} : ↑(∑ a in s, f a) = ∑ a in s, (f a : ℚ) := - coeHom.map_sum _ _ -#align nnrat.coe_sum NNRat.coe_sum - -theorem toNNRat_sum_of_nonneg {s : Finset α} {f : α → ℚ} (hf : ∀ a, a ∈ s → 0 ≤ f a) : - (∑ a in s, f a).toNNRat = ∑ a in s, (f a).toNNRat := by - rw [← coe_inj, coe_sum, Rat.coe_toNNRat _ (Finset.sum_nonneg hf)] - exact Finset.sum_congr rfl fun x hxs ↦ by rw [Rat.coe_toNNRat _ (hf x hxs)] -#align nnrat.to_nnrat_sum_of_nonneg NNRat.toNNRat_sum_of_nonneg - -@[norm_cast] -theorem coe_prod {s : Finset α} {f : α → ℚ≥0} : ↑(∏ a in s, f a) = ∏ a in s, (f a : ℚ) := - coeHom.map_prod _ _ -#align nnrat.coe_prod NNRat.coe_prod - -theorem toNNRat_prod_of_nonneg {s : Finset α} {f : α → ℚ} (hf : ∀ a ∈ s, 0 ≤ f a) : - (∏ a in s, f a).toNNRat = ∏ a in s, (f a).toNNRat := by - rw [← coe_inj, coe_prod, Rat.coe_toNNRat _ (Finset.prod_nonneg hf)] - exact Finset.prod_congr rfl fun x hxs ↦ by rw [Rat.coe_toNNRat _ (hf x hxs)] -#align nnrat.to_nnrat_prod_of_nonneg NNRat.toNNRat_prod_of_nonneg - @[norm_cast] theorem nsmul_coe (q : ℚ≥0) (n : ℕ) : ↑(n • q) = n • (q : ℚ) := coeHom.toAddMonoidHom.map_nsmul _ _ diff --git a/Mathlib/Data/Rat/NNRat/BigOperators.lean b/Mathlib/Data/Rat/NNRat/BigOperators.lean new file mode 100644 index 0000000000000..137204555a1d7 --- /dev/null +++ b/Mathlib/Data/Rat/NNRat/BigOperators.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2022 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 Mathlib.Algebra.BigOperators.Order +import Mathlib.Data.Rat.BigOperators +import Mathlib.Data.Rat.NNRat + +/-! # Casting lemmas for non-negative rational numbers involving sums and products +-/ + +open BigOperators + +variable {ι α : Type*} + +namespace NNRat + +@[norm_cast] +theorem coe_list_sum (l : List ℚ≥0) : (l.sum : ℚ) = (l.map (↑)).sum := + coeHom.map_list_sum _ +#align nnrat.coe_list_sum NNRat.coe_list_sum + +@[norm_cast] +theorem coe_list_prod (l : List ℚ≥0) : (l.prod : ℚ) = (l.map (↑)).prod := + coeHom.map_list_prod _ +#align nnrat.coe_list_prod NNRat.coe_list_prod + +@[norm_cast] +theorem coe_multiset_sum (s : Multiset ℚ≥0) : (s.sum : ℚ) = (s.map (↑)).sum := + coeHom.map_multiset_sum _ +#align nnrat.coe_multiset_sum NNRat.coe_multiset_sum + +@[norm_cast] +theorem coe_multiset_prod (s : Multiset ℚ≥0) : (s.prod : ℚ) = (s.map (↑)).prod := + coeHom.map_multiset_prod _ +#align nnrat.coe_multiset_prod NNRat.coe_multiset_prod + +@[norm_cast] +theorem coe_sum {s : Finset α} {f : α → ℚ≥0} : ↑(∑ a in s, f a) = ∑ a in s, (f a : ℚ) := + coeHom.map_sum _ _ +#align nnrat.coe_sum NNRat.coe_sum + +theorem toNNRat_sum_of_nonneg {s : Finset α} {f : α → ℚ} (hf : ∀ a, a ∈ s → 0 ≤ f a) : + (∑ a in s, f a).toNNRat = ∑ a in s, (f a).toNNRat := by + rw [← coe_inj, coe_sum, Rat.coe_toNNRat _ (Finset.sum_nonneg hf)] + exact Finset.sum_congr rfl fun x hxs ↦ by rw [Rat.coe_toNNRat _ (hf x hxs)] +#align nnrat.to_nnrat_sum_of_nonneg NNRat.toNNRat_sum_of_nonneg + +@[norm_cast] +theorem coe_prod {s : Finset α} {f : α → ℚ≥0} : ↑(∏ a in s, f a) = ∏ a in s, (f a : ℚ) := + coeHom.map_prod _ _ +#align nnrat.coe_prod NNRat.coe_prod + +theorem toNNRat_prod_of_nonneg {s : Finset α} {f : α → ℚ} (hf : ∀ a ∈ s, 0 ≤ f a) : + (∏ a in s, f a).toNNRat = ∏ a in s, (f a).toNNRat := by + rw [← coe_inj, coe_prod, Rat.coe_toNNRat _ (Finset.prod_nonneg hf)] + exact Finset.prod_congr rfl fun x hxs ↦ by rw [Rat.coe_toNNRat _ (hf x hxs)] +#align nnrat.to_nnrat_prod_of_nonneg NNRat.toNNRat_prod_of_nonneg + +end NNRat diff --git a/Mathlib/Data/Rat/Order.lean b/Mathlib/Data/Rat/Order.lean index e3444fa75338f..806d830ae53fc 100644 --- a/Mathlib/Data/Rat/Order.lean +++ b/Mathlib/Data/Rat/Order.lean @@ -3,6 +3,7 @@ Copyright (c) 2019 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ +import Mathlib.Init.Data.Bool.Lemmas import Mathlib.Algebra.Order.Field.Defs import Mathlib.Data.Rat.Basic import Mathlib.Data.Int.Cast.Lemmas diff --git a/Mathlib/Data/Rbtree/Init.lean b/Mathlib/Data/Rbtree/Init.lean index cb7d08c5c0dbf..051288a9aeb37 100644 --- a/Mathlib/Data/Rbtree/Init.lean +++ b/Mathlib/Data/Rbtree/Init.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ import Mathlib.Init.Align -import Std.Data.RBMap.Basic +import Std.Data.RBMap.Lemmas #align_import data.rbtree.init from "leanprover-community/mathlib"@"fcc158e986d4896605e97fb3ad17d5cfed49a242" diff --git a/Mathlib/Data/Real/Archimedean.lean b/Mathlib/Data/Real/Archimedean.lean index 664f2cdda534f..5308eb9d13d32 100644 --- a/Mathlib/Data/Real/Archimedean.lean +++ b/Mathlib/Data/Real/Archimedean.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Floris van Doorn -/ import Mathlib.Data.Real.Basic +import Mathlib.Data.Set.Image import Mathlib.Algebra.Order.Archimedean +import Mathlib.Algebra.Bounds #align_import data.real.basic from "leanprover-community/mathlib"@"cb42593171ba005beaaf4549fcfe0dece9ada4c9" diff --git a/Mathlib/Data/Real/Basic.lean b/Mathlib/Data/Real/Basic.lean index d7596200f07df..c0637100b8a04 100644 --- a/Mathlib/Data/Real/Basic.lean +++ b/Mathlib/Data/Real/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Floris van Doorn -/ -import Mathlib.Algebra.Bounds import Mathlib.Algebra.Star.Basic import Mathlib.Data.Real.CauSeqCompletion @@ -28,8 +27,6 @@ assert_not_exists Module assert_not_exists Submonoid assert_not_exists FloorRing -open Pointwise - /-- The type `ℝ` of real numbers constructed as equivalence classes of Cauchy sequences of rational numbers. -/ structure Real where ofCauchy :: diff --git a/Mathlib/Data/Real/CauSeq.lean b/Mathlib/Data/Real/CauSeq.lean index 956f052341e18..da1924bc15e09 100644 --- a/Mathlib/Data/Real/CauSeq.lean +++ b/Mathlib/Data/Real/CauSeq.lean @@ -3,10 +3,8 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Algebra.Order.AbsoluteValue import Mathlib.Algebra.Order.Group.MinMax -import Mathlib.Algebra.Order.Field.Basic import Mathlib.Algebra.Ring.Pi import Mathlib.GroupTheory.GroupAction.Pi import Mathlib.GroupTheory.GroupAction.Ring diff --git a/Mathlib/Data/Real/ConjugateExponents.lean b/Mathlib/Data/Real/ConjugateExponents.lean index 4aa43be1bbc1e..385f42fa3d3a0 100644 --- a/Mathlib/Data/Real/ConjugateExponents.lean +++ b/Mathlib/Data/Real/ConjugateExponents.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Yury Kudryashov -/ -import Mathlib.Data.Real.ENNReal +import Mathlib.Data.ENNReal.Basic #align_import data.real.conjugate_exponents from "leanprover-community/mathlib"@"2196ab363eb097c008d4497125e0dde23fb36db2" diff --git a/Mathlib/Data/Real/ENatENNReal.lean b/Mathlib/Data/Real/ENatENNReal.lean index 65f8754e5ee75..71244b365b5aa 100644 --- a/Mathlib/Data/Real/ENatENNReal.lean +++ b/Mathlib/Data/Real/ENatENNReal.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Data.ENat.Basic -import Mathlib.Data.Real.ENNReal +import Mathlib.Data.ENNReal.Basic #align_import data.real.enat_ennreal from "leanprover-community/mathlib"@"53b216bcc1146df1c4a0a86877890ea9f1f01589" diff --git a/Mathlib/Data/Real/EReal.lean b/Mathlib/Data/Real/EReal.lean index 64763dcbec277..9402eab2171a3 100644 --- a/Mathlib/Data/Real/EReal.lean +++ b/Mathlib/Data/Real/EReal.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Buzzard -/ import Mathlib.Data.Real.Basic -import Mathlib.Data.Real.ENNReal +import Mathlib.Data.ENNReal.Basic import Mathlib.Data.Sign #align_import data.real.ereal from "leanprover-community/mathlib"@"2196ab363eb097c008d4497125e0dde23fb36db2" @@ -445,6 +445,144 @@ theorem eq_bot_iff_forall_lt (x : EReal) : x = ⊥ ↔ ∀ y : ℝ, x < (y : ERe exact ⟨x.toReal, coe_toReal_le h⟩ #align ereal.eq_bot_iff_forall_lt EReal.eq_bot_iff_forall_lt +/-! ### Intervals and coercion from reals -/ + +lemma exists_between_coe_real {x z : EReal} (h : x < z) : ∃ y : ℝ, x < y ∧ y < z := by + obtain ⟨a, ha₁, ha₂⟩ := exists_between h + induction' a using EReal.rec with a₀ + · exact (not_lt_bot ha₁).elim + · exact ⟨a₀, by exact_mod_cast ha₁, by exact_mod_cast ha₂⟩ + · exact (not_top_lt ha₂).elim + +@[simp] +lemma image_coe_Icc (x y : ℝ) : Real.toEReal '' Icc x y = Icc ↑x ↑y := by + refine (image_comp WithBot.some WithTop.some _).trans ?_ + rw [WithTop.image_coe_Icc, WithBot.image_coe_Icc] + rfl + +@[simp] +lemma image_coe_Ico (x y : ℝ) : Real.toEReal '' Ico x y = Ico ↑x ↑y := by + refine (image_comp WithBot.some WithTop.some _).trans ?_ + rw [WithTop.image_coe_Ico, WithBot.image_coe_Ico] + rfl + +@[simp] +lemma image_coe_Ici (x : ℝ) : Real.toEReal '' Ici x = Ico ↑x ⊤ := by + refine (image_comp WithBot.some WithTop.some _).trans ?_ + rw [WithTop.image_coe_Ici, WithBot.image_coe_Ico] + rfl + +@[simp] +lemma image_coe_Ioc (x y : ℝ) : Real.toEReal '' Ioc x y = Ioc ↑x ↑y := by + refine (image_comp WithBot.some WithTop.some _).trans ?_ + rw [WithTop.image_coe_Ioc, WithBot.image_coe_Ioc] + rfl + +@[simp] +lemma image_coe_Ioo (x y : ℝ) : Real.toEReal '' Ioo x y = Ioo ↑x ↑y := by + refine (image_comp WithBot.some WithTop.some _).trans ?_ + rw [WithTop.image_coe_Ioo, WithBot.image_coe_Ioo] + rfl + +@[simp] +lemma image_coe_Ioi (x : ℝ) : Real.toEReal '' Ioi x = Ioo ↑x ⊤ := by + refine (image_comp WithBot.some WithTop.some _).trans ?_ + rw [WithTop.image_coe_Ioi, WithBot.image_coe_Ioo] + rfl + +@[simp] +lemma image_coe_Iic (x : ℝ) : Real.toEReal '' Iic x = Ioc ⊥ ↑x := by + refine (image_comp WithBot.some WithTop.some _).trans ?_ + rw [WithTop.image_coe_Iic, WithBot.image_coe_Iic] + rfl + +@[simp] +lemma image_coe_Iio (x : ℝ) : Real.toEReal '' Iio x = Ioo ⊥ ↑x := by + refine (image_comp WithBot.some WithTop.some _).trans ?_ + rw [WithTop.image_coe_Iio, WithBot.image_coe_Iio] + rfl + +@[simp] +lemma preimage_coe_Ici (x : ℝ) : Real.toEReal ⁻¹' Ici x = Ici x := by + change (WithBot.some ∘ WithTop.some) ⁻¹' (Ici (WithBot.some (WithTop.some x))) = _ + refine preimage_comp.trans ?_ + simp only [WithBot.preimage_coe_Ici, WithTop.preimage_coe_Ici] + +@[simp] +lemma preimage_coe_Ioi (x : ℝ) : Real.toEReal ⁻¹' Ioi x = Ioi x := by + change (WithBot.some ∘ WithTop.some) ⁻¹' (Ioi (WithBot.some (WithTop.some x))) = _ + refine preimage_comp.trans ?_ + simp only [WithBot.preimage_coe_Ioi, WithTop.preimage_coe_Ioi] + +@[simp] +lemma preimage_coe_Ioi_bot : Real.toEReal ⁻¹' Ioi ⊥ = univ := by + change (WithBot.some ∘ WithTop.some) ⁻¹' (Ioi ⊥) = _ + refine preimage_comp.trans ?_ + simp only [WithBot.preimage_coe_Ioi_bot, preimage_univ] + +@[simp] +lemma preimage_coe_Iic (y : ℝ) : Real.toEReal ⁻¹' Iic y = Iic y := by + change (WithBot.some ∘ WithTop.some) ⁻¹' (Iic (WithBot.some (WithTop.some y))) = _ + refine preimage_comp.trans ?_ + simp only [WithBot.preimage_coe_Iic, WithTop.preimage_coe_Iic] + +@[simp] +lemma preimage_coe_Iio (y : ℝ) : Real.toEReal ⁻¹' Iio y = Iio y := by + change (WithBot.some ∘ WithTop.some) ⁻¹' (Iio (WithBot.some (WithTop.some y))) = _ + refine preimage_comp.trans ?_ + simp only [WithBot.preimage_coe_Iio, WithTop.preimage_coe_Iio] + +@[simp] +lemma preimage_coe_Iio_top : Real.toEReal ⁻¹' Iio ⊤ = univ := by + change (WithBot.some ∘ WithTop.some) ⁻¹' (Iio (WithBot.some ⊤)) = _ + refine preimage_comp.trans ?_ + simp only [WithBot.preimage_coe_Iio, WithTop.preimage_coe_Iio_top] + +@[simp] +lemma preimage_coe_Icc (x y : ℝ) : Real.toEReal ⁻¹' Icc x y = Icc x y := by + simp_rw [← Ici_inter_Iic] + simp + +@[simp] +lemma preimage_coe_Ico (x y : ℝ) : Real.toEReal ⁻¹' Ico x y = Ico x y := by + simp_rw [← Ici_inter_Iio] + simp + +@[simp] +lemma preimage_coe_Ioc (x y : ℝ) : Real.toEReal ⁻¹' Ioc x y = Ioc x y := by + simp_rw [← Ioi_inter_Iic] + simp + +@[simp] +lemma preimage_coe_Ioo (x y : ℝ) : Real.toEReal ⁻¹' Ioo x y = Ioo x y := by + simp_rw [← Ioi_inter_Iio] + simp + +@[simp] +lemma preimage_coe_Ico_top (x : ℝ) : Real.toEReal ⁻¹' Ico x ⊤ = Ici x := by + rw [← Ici_inter_Iio] + simp + +@[simp] +lemma preimage_coe_Ioo_top (x : ℝ) : Real.toEReal ⁻¹' Ioo x ⊤ = Ioi x := by + rw [← Ioi_inter_Iio] + simp + +@[simp] +lemma preimage_coe_Ioc_bot (y : ℝ) : Real.toEReal ⁻¹' Ioc ⊥ y = Iic y := by + rw [← Ioi_inter_Iic] + simp + +@[simp] +lemma preimage_coe_Ioo_bot (y : ℝ) : Real.toEReal ⁻¹' Ioo ⊥ y = Iio y := by + rw [← Ioi_inter_Iio] + simp + +@[simp] +lemma preimage_coe_Ioo_bot_top : Real.toEReal ⁻¹' Ioo ⊥ ⊤ = univ := by + rw [← Ioi_inter_Iio] + simp + /-! ### ennreal coercion -/ @[simp] diff --git a/Mathlib/Data/Real/GoldenRatio.lean b/Mathlib/Data/Real/GoldenRatio.lean index d1b7e21d0f2cf..561fafca6dc53 100644 --- a/Mathlib/Data/Real/GoldenRatio.lean +++ b/Mathlib/Data/Real/GoldenRatio.lean @@ -1,14 +1,14 @@ /- Copyright (c) 2020 Anatole Dedecker. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Anatole Dedecker, Alexey Soloyev, Junyan Xu +Authors: Anatole Dedecker, Alexey Soloyev, Junyan Xu, Kamila Szewczyk -/ import Mathlib.Data.Real.Irrational import Mathlib.Data.Nat.Fib.Basic -import Mathlib.Data.Nat.PrimeNormNum import Mathlib.Data.Fin.VecNotation import Mathlib.Algebra.LinearRecurrence import Mathlib.Tactic.NormNum.NatFib +import Mathlib.Tactic.NormNum.Prime #align_import data.real.golden_ratio from "leanprover-community/mathlib"@"2196ab363eb097c008d4497125e0dde23fb36db2" @@ -90,6 +90,9 @@ theorem gold_sub_goldConj : φ - ψ = Real.sqrt 5 := by ring #align gold_sub_gold_conj gold_sub_goldConj +theorem gold_pow_sub_gold_pow (n : ℕ) : φ ^ (n + 2) - φ ^ (n + 1) = φ ^ n := by + rw [goldenRatio]; ring_nf; norm_num; ring + @[simp 1200] theorem gold_sq : φ ^ 2 = φ + 1 := by rw [goldenRatio, ← sub_eq_zero] @@ -117,6 +120,10 @@ theorem one_lt_gold : 1 < φ := by simp [← sq, gold_pos, zero_lt_one, - div_pow] -- Porting note: Added `- div_pow` #align one_lt_gold one_lt_gold +theorem gold_lt_two : φ < 2 := by calc + (1 + sqrt 5) / 2 < (1 + 3) / 2 := by gcongr; rw [sqrt_lt'] <;> norm_num + _ = 2 := by norm_num + theorem goldConj_neg : ψ < 0 := by linarith [one_sub_goldConj, one_lt_gold] #align gold_conj_neg goldConj_neg @@ -159,7 +166,6 @@ theorem goldConj_irrational : Irrational ψ := by ## Links with Fibonacci sequence -/ - section Fibrec variable {α : Type*} [CommSemiring α] @@ -233,3 +239,23 @@ theorem Real.coe_fib_eq' : theorem Real.coe_fib_eq : ∀ n, (Nat.fib n : ℝ) = (φ ^ n - ψ ^ n) / Real.sqrt 5 := by rw [← Function.funext_iff, Real.coe_fib_eq'] #align real.coe_fib_eq Real.coe_fib_eq + +/-- Relationship between the Fibonacci Sequence, Golden Ratio and its conjugate's exponents --/ +theorem fib_golden_conj_exp (n : ℕ) : Nat.fib (n + 1) - φ * Nat.fib n = ψ ^ n := by + repeat rw [coe_fib_eq] + rw [mul_div, div_sub_div_same, mul_sub, ← pow_succ] + ring_nf + have nz : sqrt 5 ≠ 0 := by norm_num + rw [← (mul_inv_cancel nz).symm, one_mul] + +/-- Relationship between the Fibonacci Sequence, Golden Ratio and its exponents --/ +theorem fib_golden_exp' (n : ℕ) : φ * Nat.fib (n + 1) + Nat.fib n = φ ^ (n + 1) := by + induction n with + | zero => norm_num + | succ n ih => + calc + _ = φ * (Nat.fib n) + φ ^ 2 * (Nat.fib (n + 1)) := + by simp only [Nat.fib_add_one (Nat.succ_ne_zero n), Nat.succ_sub_succ_eq_sub, tsub_zero, + Nat.cast_add, gold_sq]; ring + _ = φ * ((Nat.fib n) + φ * (Nat.fib (n + 1))) := by ring + _ = φ ^ (n + 2) := by rw [add_comm, ih]; ring diff --git a/Mathlib/Data/Real/NNReal.lean b/Mathlib/Data/Real/NNReal.lean index 2d1bcf775a878..e5d9c96b7632a 100644 --- a/Mathlib/Data/Real/NNReal.lean +++ b/Mathlib/Data/Real/NNReal.lean @@ -6,12 +6,12 @@ Authors: Johan Commelin import Mathlib.Algebra.Algebra.Basic import Mathlib.Algebra.BigOperators.Order import Mathlib.Algebra.BigOperators.Ring +import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Algebra.Order.Field.Canonical.Basic import Mathlib.Algebra.Order.Nonneg.Field import Mathlib.Algebra.Order.Nonneg.Floor import Mathlib.Data.Real.Pointwise import Mathlib.Order.ConditionallyCompleteLattice.Group -import Mathlib.Tactic.Positivity import Mathlib.Tactic.GCongr.Core #align_import data.real.nnreal from "leanprover-community/mathlib"@"de29c328903507bb7aff506af9135f4bdaf1849c" @@ -877,10 +877,7 @@ end Sub section Inv -theorem sum_div {ι} (s : Finset ι) (f : ι → ℝ≥0) (b : ℝ≥0) : - (∑ i in s, f i) / b = ∑ i in s, f i / b := - Finset.sum_div -#align nnreal.sum_div NNReal.sum_div +#align nnreal.sum_div Finset.sum_div @[simp] theorem inv_le {r p : ℝ≥0} (h : r ≠ 0) : r⁻¹ ≤ p ↔ 1 ≤ r * p := by diff --git a/Mathlib/Data/Real/Pi/Leibniz.lean b/Mathlib/Data/Real/Pi/Leibniz.lean index a54c6ceb80ada..af15a356b3019 100644 --- a/Mathlib/Data/Real/Pi/Leibniz.lean +++ b/Mathlib/Data/Real/Pi/Leibniz.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Benjamin Davidson -/ import Mathlib.Analysis.SpecialFunctions.Trigonometric.ArctanDeriv +import Mathlib.Analysis.SpecialFunctions.Pow.Asymptotics #align_import data.real.pi.leibniz from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Data/Real/Sqrt.lean b/Mathlib/Data/Real/Sqrt.lean index d4db77e39a29c..728ffa6eb92c6 100644 --- a/Mathlib/Data/Real/Sqrt.lean +++ b/Mathlib/Data/Real/Sqrt.lean @@ -6,7 +6,6 @@ Authors: Mario Carneiro, Floris van Doorn, Yury Kudryashov import Mathlib.Algebra.Star.Order import Mathlib.Topology.Algebra.Order.MonotoneContinuity import Mathlib.Topology.Instances.NNReal -import Mathlib.Tactic.Positivity #align_import data.real.sqrt from "leanprover-community/mathlib"@"31c24aa72e7b3e5ed97a8412470e904f82b81004" diff --git a/Mathlib/Data/Rel.lean b/Mathlib/Data/Rel.lean index e78b93764ed42..d08e156756fd2 100644 --- a/Mathlib/Data/Rel.lean +++ b/Mathlib/Data/Rel.lean @@ -5,7 +5,7 @@ Authors: Jeremy Avigad -/ import Mathlib.Order.CompleteLattice import Mathlib.Order.GaloisConnection -import Mathlib.Order.Hom.CompleteLattice +import Mathlib.Data.Set.Lattice #align_import data.rel from "leanprover-community/mathlib"@"706d88f2b8fdfeb0b22796433d7a6c1a010af9f2" diff --git a/Mathlib/Data/Seq/Seq.lean b/Mathlib/Data/Seq/Seq.lean index 5b0d9113fe12a..287c747dfa34b 100644 --- a/Mathlib/Data/Seq/Seq.lean +++ b/Mathlib/Data/Seq/Seq.lean @@ -3,10 +3,7 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.List.Basic import Mathlib.Data.LazyList -import Mathlib.Data.Nat.Basic -import Mathlib.Data.Stream.Init import Mathlib.Data.Seq.Computation #align_import data.seq.seq from "leanprover-community/mathlib"@"a7e36e48519ab281320c4d192da6a7b348ce40ad" diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index 50a80707f9e09..de779712c72f4 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -3,8 +3,10 @@ Copyright (c) 2014 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ +import Mathlib.Init.ZeroOne +import Mathlib.Data.Set.Defs +import Mathlib.Order.Basic import Mathlib.Order.SymmDiff -import Mathlib.Logic.Function.Iterate import Mathlib.Tactic.Tauto import Mathlib.Tactic.ByContra import Mathlib.Util.Delaborators @@ -65,15 +67,6 @@ set, sets, subset, subsets, union, intersection, insert, singleton, complement, -/ --- https://github.com/leanprover/lean4/issues/2096 -compile_def% Union.union -compile_def% Inter.inter -compile_def% SDiff.sdiff -compile_def% HasCompl.compl -compile_def% EmptyCollection.emptyCollection -compile_def% Insert.insert -compile_def% Singleton.singleton - /-! ### Set coercion to a type -/ open Function @@ -91,9 +84,9 @@ instance instBooleanAlgebraSet : BooleanAlgebra (Set α) := lt := fun s t => s ⊆ t ∧ ¬t ⊆ s, inf := (· ∩ ·), bot := ∅, - compl := fun s => { x | x ∉ s }, + compl := (·ᶜ), top := univ, - sdiff := fun s t => { x | x ∈ s ∧ x ∉ t } } + sdiff := (· \ ·) } instance : HasSSubset (Set α) := ⟨(· < ·)⟩ @@ -142,19 +135,6 @@ alias ⟨_root_.LE.le.subset, _root_.HasSubset.Subset.le⟩ := le_iff_subset alias ⟨_root_.LT.lt.ssubset, _root_.HasSSubset.SSubset.lt⟩ := lt_iff_ssubset #align has_ssubset.ssubset.lt HasSSubset.SSubset.lt --- Porting note: I've introduced this abbreviation, with the `@[coe]` attribute, --- so that `norm_cast` has something to index on. --- It is currently an abbreviation so that instance coming from `Subtype` are available. --- If you're interested in making it a `def`, as it probably should be, --- you'll then need to create additional instances (and possibly prove lemmas about them). --- The first error should appear below at `monotoneOn_iff_monotone`. -/-- Given the set `s`, `Elem s` is the `Type` of element of `s`. -/ -@[coe, reducible] def Elem (s : Set α) : Type u := { x // x ∈ s } - -/-- Coercion from a set to the corresponding subtype. -/ -instance {α : Type u} : CoeSort (Set α) (Type u) := - ⟨Elem⟩ - instance PiSetCoe.canLift (ι : Type u) (α : ι → Type v) [∀ i, Nonempty (α i)] (s : Set ι) : CanLift (∀ i : s, α i) (∀ i, α i) (fun f i => f i) fun _ => True := PiSubtype.canLift ι α s @@ -254,9 +234,6 @@ theorem forall_in_swap {p : α → β → Prop} : (∀ a ∈ s, ∀ (b), p a b) /-! ### Lemmas about `mem` and `setOf` -/ -@[simp, mfld_simps] theorem mem_setOf_eq {x : α} {p : α → Prop} : (x ∈ {y | p y}) = p x := rfl -#align set.mem_set_of_eq Set.mem_setOf_eq - theorem mem_setOf {a : α} {p : α → Prop} : a ∈ { x | p x } ↔ p a := Iff.rfl #align set.mem_set_of Set.mem_setOf @@ -666,11 +643,6 @@ theorem setOf_true : { _x : α | True } = univ := @[simp] theorem setOf_top : { _x : α | ⊤ } = univ := rfl -@[simp, mfld_simps] -theorem mem_univ (x : α) : x ∈ @univ α := - trivial -#align set.mem_univ Set.mem_univ - @[simp] theorem univ_eq_empty_iff : (univ : Set α) = ∅ ↔ IsEmpty α := eq_empty_iff_forall_not_mem.trans @@ -1559,7 +1531,7 @@ theorem disjoint_right : Disjoint s t ↔ ∀ ⦃a⦄, a ∈ t → a ∉ s := by #align set.disjoint_right Set.disjoint_right lemma not_disjoint_iff : ¬Disjoint s t ↔ ∃ x, x ∈ s ∧ x ∈ t := - Set.disjoint_iff.not.trans $ not_forall.trans $ exists_congr fun _ ↦ not_not + Set.disjoint_iff.not.trans <| not_forall.trans <| exists_congr fun _ ↦ not_not #align set.not_disjoint_iff Set.not_disjoint_iff lemma not_disjoint_iff_nonempty_inter : ¬ Disjoint s t ↔ (s ∩ t).Nonempty := not_disjoint_iff @@ -1648,7 +1620,6 @@ theorem inter_diff_distrib_right (s t u : Set α) : s \ t ∩ u = (s ∩ u) \ (t /-! ### Lemmas about complement -/ - theorem compl_def (s : Set α) : sᶜ = { x | x ∉ s } := rfl #align set.compl_def Set.compl_def @@ -1665,11 +1636,6 @@ theorem not_mem_of_mem_compl {s : Set α} {x : α} (h : x ∈ sᶜ) : x ∉ s := h #align set.not_mem_of_mem_compl Set.not_mem_of_mem_compl -@[simp] -theorem mem_compl_iff (s : Set α) (x : α) : x ∈ sᶜ ↔ x ∉ s := - Iff.rfl -#align set.mem_compl_iff Set.mem_compl_iff - theorem not_mem_compl_iff {x : α} : x ∉ sᶜ ↔ x ∈ s := not_not #align set.not_mem_compl_iff Set.not_mem_compl_iff @@ -1821,20 +1787,6 @@ theorem inter_compl_nonempty_iff {s t : Set α} : (s ∩ tᶜ).Nonempty ↔ ¬s /-! ### Lemmas about set difference -/ - -theorem diff_eq (s t : Set α) : s \ t = s ∩ tᶜ := - rfl -#align set.diff_eq Set.diff_eq - -@[simp] -theorem mem_diff {s t : Set α} (x : α) : x ∈ s \ t ↔ x ∈ s ∧ x ∉ t := - Iff.rfl -#align set.mem_diff Set.mem_diff - -theorem mem_diff_of_mem {s t : Set α} {x : α} (h1 : x ∈ s) (h2 : x ∉ t) : x ∈ s \ t := - ⟨h1, h2⟩ -#align set.mem_diff_of_mem Set.mem_diff_of_mem - theorem not_mem_diff_of_mem {s t : Set α} {x : α} (hx : x ∈ t) : x ∉ s \ t := fun h => h.2 hx #align set.not_mem_diff_of_mem Set.not_mem_diff_of_mem @@ -2077,7 +2029,7 @@ theorem diff_self_inter {s t : Set α} : s \ (s ∩ t) = s \ t := @[simp] theorem diff_singleton_eq_self {a : α} {s : Set α} (h : a ∉ s) : s \ {a} = s := - sdiff_eq_self_iff_disjoint.2 $ by simp [h] + sdiff_eq_self_iff_disjoint.2 <| by simp [h] #align set.diff_singleton_eq_self Set.diff_singleton_eq_self @[simp] @@ -2123,6 +2075,9 @@ theorem union_eq_diff_union_diff_union_inter (s t : Set α) : s ∪ t = s \ t /-! ### Symmetric difference -/ +section + +open scoped symmDiff theorem mem_symmDiff : a ∈ s ∆ t ↔ a ∈ s ∧ a ∉ t ∨ a ∈ t ∧ a ∉ s := Iff.rfl @@ -2162,6 +2117,8 @@ theorem subset_symmDiff_union_symmDiff_right (h : Disjoint t u) : s ⊆ s ∆ t h.le_symmDiff_sup_symmDiff_right #align set.subset_symm_diff_union_symm_diff_right Set.subset_symmDiff_union_symmDiff_right +end + /-! ### Powerset -/ #align set.powerset Set.powerset @@ -2670,7 +2627,7 @@ lemma nontrivial_iff_ne_singleton (ha : a ∈ s) : s.Nontrivial ↔ s ≠ {a} := #align set.nontrivial_iff_ne_singleton Set.nontrivial_iff_ne_singleton lemma Nonempty.exists_eq_singleton_or_nontrivial : s.Nonempty → (∃ a, s = {a}) ∨ s.Nontrivial := - fun ⟨a, ha⟩ ↦ (eq_singleton_or_nontrivial ha).imp_left $ Exists.intro a + fun ⟨a, ha⟩ ↦ (eq_singleton_or_nontrivial ha).imp_left <| Exists.intro a #align set.nonempty.exists_eq_singleton_or_nontrivial Set.Nonempty.exists_eq_singleton_or_nontrivial theorem univ_eq_true_false : univ = ({True, False} : Set Prop) := diff --git a/Mathlib/Data/Set/BoolIndicator.lean b/Mathlib/Data/Set/BoolIndicator.lean index 316fdbb9a390d..73f47177e632b 100644 --- a/Mathlib/Data/Set/BoolIndicator.lean +++ b/Mathlib/Data/Set/BoolIndicator.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Dagur Tómas Ásgeirsson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Dagur Tómas Ásgeirsson, Leonardo de Moura -/ -import Mathlib.Data.Set.Image +import Mathlib.Data.Set.Basic #align_import data.set.bool_indicator from "leanprover-community/mathlib"@"fc2ed6f838ce7c9b7c7171e58d78eaf7b438fb0e" diff --git a/Mathlib/Data/Set/Card.lean b/Mathlib/Data/Set/Card.lean index 85b2b3652dab4..d835ff6505c0b 100644 --- a/Mathlib/Data/Set/Card.lean +++ b/Mathlib/Data/Set/Card.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Peter Nelson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Peter Nelson -/ -import Mathlib.Data.Finite.Card +import Mathlib.SetTheory.Cardinal.Finite #align_import data.set.ncard from "leanprover-community/mathlib"@"74c2af38a828107941029b03839882c5c6f87a04" @@ -437,7 +437,7 @@ theorem Finite.exists_injOn_of_encard_le [Nonempty β] {s : Set α} {t : Set β} refine ⟨?_, ?_, fun x hxs hxa ↦ ⟨hxa, (hf₀s x hxs hxa).2⟩⟩ · rintro x hx; split_ifs with h; assumption; exact (hf₀s x hx h).1 exact InjOn.congr hinj (fun x ⟨_, hxa⟩ ↦ by rwa [Function.update_noteq]) -termination_by _ => encard s +termination_by encard s theorem Finite.exists_bijOn_of_encard_eq [Nonempty β] (hs : s.Finite) (h : s.encard = t.encard) : ∃ (f : α → β), BijOn f s t := by @@ -1055,7 +1055,7 @@ theorem one_lt_ncard (hs : s.Finite := by toFinite_tac) : #align set.one_lt_ncard Set.one_lt_ncard theorem one_lt_ncard_iff (hs : s.Finite := by toFinite_tac) : - 1 < s.ncard ↔ ∃ a b, a ∈ s ∧ b ∈ s ∧ a ≠ b := by + 1 < s.ncard ↔ ∃ a b, a ∈ s ∧ b ∈ s ∧ a ≠ b := by rw [one_lt_ncard hs] simp only [exists_prop, exists_and_left] #align set.one_lt_ncard_iff Set.one_lt_ncard_iff diff --git a/Mathlib/Data/Set/Defs.lean b/Mathlib/Data/Set/Defs.lean new file mode 100644 index 0000000000000..607436237e558 --- /dev/null +++ b/Mathlib/Data/Set/Defs.lean @@ -0,0 +1,346 @@ +/- +Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad, Johannes Hölzl, Reid Barton, Scott Morrison, Patrick Massot, Kyle Miller, +Minchao Wu, Yury Kudryashov, Floris van Doorn +-/ +import Std.Classes.SetNotation +import Mathlib.Data.SProd +import Mathlib.Data.Subtype +import Mathlib.Order.Notation +import Mathlib.Util.CompileInductive + +/-! +# Basic definitions about sets + +In this file we define various operations on sets. +We also provide basic lemmas needed to unfold the definitions. +More advanced theorems about these definitions are located in other files in `Mathlib/Data/Set`. + +## Main definitions + +- complement of a set and set difference; +- `Set.Elem`: coercion of a set to a type; it is reducibly equal to `{x // x ∈ s}`; +- `Set.preimage f s`, a.k.a. `f ⁻¹' s`: preimage of a set; +- `Set.range f`: the range of a function; + it is more general than `f '' univ` because it allows functions from `Sort*`; +- `s ×ˢ t`: product of `s : Set α` and `t : Set β` as a set in `α × β`; +- `Set.diagonal`: the diagonal in `α × α`; +- `Set.offDiag s`: the part of `s ×ˢ s` that is off the diagonal; +- `Set.pi`: indexed product of a family of sets `∀ i, Set (α i)`, + as a set in `∀ i, α i`; +- `Set.EqOn f g s`: the predicate saying that two functions are equal on a set; +- `Set.MapsTo f s t`: the predicate syaing that `f` sends all points of `s` to `t; +- `Set.MapsTo.restrict`: restrict `f : α → β` to `f' : s → t` provided that `Set.MapsTo f s t`; +- `Set.restrictPreimage`: restrict `f : α → β` to `f' : (f ⁻¹' t) → t`; +- `Set.InjOn`: the predicate saying that `f` is injective on a set; +- `Set.SurjOn f s t`: the prediate saying that `t ⊆ f '' s`; +- `Set.BijOn f s t`: the predicate saying that `f` is injective on `s` and `f '' s = t`; +- `Set.graphOn`: the graph of a function on a set; +- `Set.LeftInvOn`, `Set.RightInvOn`, `Set.InvOn`: + the predicates saying that `f'` is a left, right or two-sided inverse of `f` on `s`, `t`, or both; +- `Set.image2`: the image of a pair of sets under a binary operation, + mostly useful to define pointwise algebraic operations on sets; +- `Set.seq`: monadic `seq` operation on sets; + we don't use monadic notation to ensure support for maps between different universes; + +## Notations + +- `f '' s`: image of a set; +- `f ⁻¹' s`: preimage of a set; +- `s ×ˢ t`: the product of sets; +- `s ∪ t`: the union of two sets; +- `s ∩ t`: the intersection of two sets; +- `sᶜ`: the complement of a set; +- `s \ t`: the difference of two sets. + +## Keywords + +set, image, preimage +-/ + +-- https://github.com/leanprover/lean4/issues/2096 +compile_def% Union.union +compile_def% Inter.inter +compile_def% SDiff.sdiff +compile_def% HasCompl.compl +compile_def% EmptyCollection.emptyCollection +compile_def% Insert.insert +compile_def% Singleton.singleton + +universe u v w + +namespace Set + +variable {α : Type u} {β : Type v} {γ : Type w} + +@[simp, mfld_simps] theorem mem_setOf_eq {x : α} {p : α → Prop} : (x ∈ {y | p y}) = p x := rfl +#align set.mem_set_of_eq Set.mem_setOf_eq + +@[simp, mfld_simps] theorem mem_univ (x : α) : x ∈ @univ α := trivial +#align set.mem_univ Set.mem_univ + +instance : HasCompl (Set α) := ⟨fun s ↦ {x | x ∉ s}⟩ + +@[simp] theorem mem_compl_iff (s : Set α) (x : α) : x ∈ sᶜ ↔ x ∉ s := Iff.rfl +#align set.mem_compl_iff Set.mem_compl_iff + +theorem diff_eq (s t : Set α) : s \ t = s ∩ tᶜ := rfl +#align set.diff_eq Set.diff_eq + +@[simp] theorem mem_diff {s t : Set α} (x : α) : x ∈ s \ t ↔ x ∈ s ∧ x ∉ t := Iff.rfl +#align set.mem_diff Set.mem_diff + +theorem mem_diff_of_mem {s t : Set α} {x : α} (h1 : x ∈ s) (h2 : x ∉ t) : x ∈ s \ t := ⟨h1, h2⟩ +#align set.mem_diff_of_mem Set.mem_diff_of_mem + +-- Porting note: I've introduced this abbreviation, with the `@[coe]` attribute, +-- so that `norm_cast` has something to index on. +-- It is currently an abbreviation so that instance coming from `Subtype` are available. +-- If you're interested in making it a `def`, as it probably should be, +-- you'll then need to create additional instances (and possibly prove lemmas about them). +-- The first error should appear below at `monotoneOn_iff_monotone`. +/-- Given the set `s`, `Elem s` is the `Type` of element of `s`. -/ +@[coe, reducible] def Elem (s : Set α) : Type u := {x // x ∈ s} + +/-- Coercion from a set to the corresponding subtype. -/ +instance : CoeSort (Set α) (Type u) := ⟨Elem⟩ + +/-- The preimage of `s : Set β` by `f : α → β`, written `f ⁻¹' s`, + is the set of `x : α` such that `f x ∈ s`. -/ +def preimage (f : α → β) (s : Set β) : Set α := {x | f x ∈ s} +#align set.preimage Set.preimage + +/-- `f ⁻¹' t` denotes the preimage of `t : Set β` under the function `f : α → β`. -/ +infixl:80 " ⁻¹' " => preimage + +@[simp, mfld_simps] +theorem mem_preimage {f : α → β} {s : Set β} {a : α} : a ∈ f ⁻¹' s ↔ f a ∈ s := Iff.rfl +#align set.mem_preimage Set.mem_preimage + +/-- `f '' s` denotes the image of `s : Set α` under the function `f : α → β`. -/ +infixl:80 " '' " => image + +@[simp] +theorem mem_image (f : α → β) (s : Set α) (y : β) : y ∈ f '' s ↔ ∃ x ∈ s, f x = y := + Iff.rfl +#align set.mem_image Set.mem_image + +@[mfld_simps] +theorem mem_image_of_mem (f : α → β) {x : α} {a : Set α} (h : x ∈ a) : f x ∈ f '' a := + ⟨_, h, rfl⟩ +#align set.mem_image_of_mem Set.mem_image_of_mem + +/-- Restriction of `f` to `s` factors through `s.imageFactorization f : s → f '' s`. -/ +def imageFactorization (f : α → β) (s : Set α) : s → f '' s := fun p => + ⟨f p.1, mem_image_of_mem f p.2⟩ +#align set.image_factorization Set.imageFactorization + +/-- `kernImage f s` is the set of `y` such that `f ⁻¹ y ⊆ s`. -/ +def kernImage (f : α → β) (s : Set α) : Set β := {y | ∀ ⦃x⦄, f x = y → x ∈ s} +#align set.kern_image Set.kernImage + +lemma subset_kernImage_iff {s : Set β} {t : Set α} {f : α → β} : s ⊆ kernImage f t ↔ f ⁻¹' s ⊆ t := + ⟨fun h _ hx ↦ h hx rfl, + fun h _ hx y hy ↦ h (show f y ∈ s from hy.symm ▸ hx)⟩ + +section Range + +variable {ι : Sort*} {f : ι → α} + +/-- Range of a function. + +This function is more flexible than `f '' univ`, as the image requires that the domain is in Type +and not an arbitrary Sort. -/ +def range (f : ι → α) : Set α := {x | ∃ y, f y = x} +#align set.range Set.range + +@[simp] theorem mem_range {x : α} : x ∈ range f ↔ ∃ y, f y = x := Iff.rfl +#align set.mem_range Set.mem_range + +@[mfld_simps] theorem mem_range_self (i : ι) : f i ∈ range f := ⟨i, rfl⟩ +#align set.mem_range_self Set.mem_range_self + +/-- Any map `f : ι → α` factors through a map `rangeFactorization f : ι → range f`. -/ +def rangeFactorization (f : ι → α) : ι → range f := fun i => ⟨f i, mem_range_self i⟩ +#align set.range_factorization Set.rangeFactorization + +end Range + +/-- We can use the axiom of choice to pick a preimage for every element of `range f`. -/ +noncomputable def rangeSplitting (f : α → β) : range f → α := fun x => x.2.choose +#align set.range_splitting Set.rangeSplitting + +-- This can not be a `@[simp]` lemma because the head of the left hand side is a variable. +theorem apply_rangeSplitting (f : α → β) (x : range f) : f (rangeSplitting f x) = x := + x.2.choose_spec +#align set.apply_range_splitting Set.apply_rangeSplitting + +@[simp] +theorem comp_rangeSplitting (f : α → β) : f ∘ rangeSplitting f = Subtype.val := by + ext + simp only [Function.comp_apply] + apply apply_rangeSplitting +#align set.comp_range_splitting Set.comp_rangeSplitting + +section Prod + +/-- The cartesian product `Set.prod s t` is the set of `(a, b)` such that `a ∈ s` and `b ∈ t`. -/ +def prod (s : Set α) (t : Set β) : Set (α × β) := {p | p.1 ∈ s ∧ p.2 ∈ t} +#align set.prod Set.prod + +@[default_instance] +instance instSProd : SProd (Set α) (Set β) (Set (α × β)) where + sprod := Set.prod + +theorem prod_eq (s : Set α) (t : Set β) : s ×ˢ t = Prod.fst ⁻¹' s ∩ Prod.snd ⁻¹' t := rfl +#align set.prod_eq Set.prod_eq + +variable {a : α} {b : β} {s : Set α} {t : Set β} {p : α × β} + +theorem mem_prod_eq : (p ∈ s ×ˢ t) = (p.1 ∈ s ∧ p.2 ∈ t) := rfl +#align set.mem_prod_eq Set.mem_prod_eq + +@[simp, mfld_simps] +theorem mem_prod : p ∈ s ×ˢ t ↔ p.1 ∈ s ∧ p.2 ∈ t := .rfl +#align set.mem_prod Set.mem_prod + +@[mfld_simps] +theorem prod_mk_mem_set_prod_eq : ((a, b) ∈ s ×ˢ t) = (a ∈ s ∧ b ∈ t) := rfl +#align set.prod_mk_mem_set_prod_eq Set.prod_mk_mem_set_prod_eq + +theorem mk_mem_prod (ha : a ∈ s) (hb : b ∈ t) : (a, b) ∈ s ×ˢ t := ⟨ha, hb⟩ +#align set.mk_mem_prod Set.mk_mem_prod + +end Prod + +section Diagonal + +/-- `diagonal α` is the set of `α × α` consisting of all pairs of the form `(a, a)`. -/ +def diagonal (α : Type*) : Set (α × α) := {p | p.1 = p.2} +#align set.diagonal Set.diagonal + +theorem mem_diagonal (x : α) : (x, x) ∈ diagonal α := rfl +#align set.mem_diagonal Set.mem_diagonal + +@[simp] theorem mem_diagonal_iff {x : α × α} : x ∈ diagonal α ↔ x.1 = x.2 := .rfl +#align set.mem_diagonal_iff Set.mem_diagonal_iff + +/-- The off-diagonal of a set `s` is the set of pairs `(a, b)` with `a, b ∈ s` and `a ≠ b`. -/ +def offDiag (s : Set α) : Set (α × α) := {x | x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2} +#align set.off_diag Set.offDiag + +@[simp] +theorem mem_offDiag {x : α × α} {s : Set α} : x ∈ s.offDiag ↔ x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2 := + Iff.rfl +#align set.mem_off_diag Set.mem_offDiag + +end Diagonal + +section Pi + +variable {ι : Type*} {α : ι → Type*} + +/-- Given an index set `ι` and a family of sets `t : Π i, Set (α i)`, `pi s t` +is the set of dependent functions `f : Πa, π a` such that `f a` belongs to `t a` +whenever `a ∈ s`. -/ +def pi (s : Set ι) (t : ∀ i, Set (α i)) : Set (∀ i, α i) := {f | ∀ i ∈ s, f i ∈ t i} +#align set.pi Set.pi + +variable {s : Set ι} {t : ∀ i, Set (α i)} {f : ∀ i, α i} + +@[simp] theorem mem_pi : f ∈ s.pi t ↔ ∀ i ∈ s, f i ∈ t i := .rfl +#align set.mem_pi Set.mem_pi + +theorem mem_univ_pi : f ∈ pi univ t ↔ ∀ i, f i ∈ t i := by simp +#align set.mem_univ_pi Set.mem_univ_pi + +end Pi + +/-- Two functions `f₁ f₂ : α → β` are equal on `s` if `f₁ x = f₂ x` for all `x ∈ s`. -/ +def EqOn (f₁ f₂ : α → β) (s : Set α) : Prop := ∀ ⦃x⦄, x ∈ s → f₁ x = f₂ x +#align set.eq_on Set.EqOn + +/-- `MapsTo f a b` means that the image of `a` is contained in `b`. -/ +def MapsTo (f : α → β) (s : Set α) (t : Set β) : Prop := ∀ ⦃x⦄, x ∈ s → f x ∈ t +#align set.maps_to Set.MapsTo + +theorem mapsTo_image (f : α → β) (s : Set α) : MapsTo f s (f '' s) := fun _ ↦ mem_image_of_mem f +#align set.maps_to_image Set.mapsTo_image + +theorem mapsTo_preimage (f : α → β) (t : Set β) : MapsTo f (f ⁻¹' t) t := fun _ ↦ id +#align set.maps_to_preimage Set.mapsTo_preimage + +/-- Given a map `f` sending `s : Set α` into `t : Set β`, restrict domain of `f` to `s` +and the codomain to `t`. Same as `Subtype.map`. -/ +def MapsTo.restrict (f : α → β) (s : Set α) (t : Set β) (h : MapsTo f s t) : s → t := + Subtype.map f h +#align set.maps_to.restrict Set.MapsTo.restrict + +/-- The restriction of a function onto the preimage of a set. -/ +@[simps!] +def restrictPreimage (t : Set β) (f : α → β) : f ⁻¹' t → t := + (Set.mapsTo_preimage f t).restrict _ _ _ +#align set.restrict_preimage Set.restrictPreimage +#align set.restrict_preimage_coe Set.restrictPreimage_coe + +/-- `f` is injective on `a` if the restriction of `f` to `a` is injective. -/ +def InjOn (f : α → β) (s : Set α) : Prop := + ∀ ⦃x₁ : α⦄, x₁ ∈ s → ∀ ⦃x₂ : α⦄, x₂ ∈ s → f x₁ = f x₂ → x₁ = x₂ +#align set.inj_on Set.InjOn + +/-- The graph of a function `f : α → β` on a set `s`. -/ +def graphOn (f : α → β) (s : Set α) : Set (α × β) := (fun x ↦ (x, f x)) '' s + +/-- `f` is surjective from `a` to `b` if `b` is contained in the image of `a`. -/ +def SurjOn (f : α → β) (s : Set α) (t : Set β) : Prop := t ⊆ f '' s +#align set.surj_on Set.SurjOn + +/-- `f` is bijective from `s` to `t` if `f` is injective on `s` and `f '' s = t`. -/ +def BijOn (f : α → β) (s : Set α) (t : Set β) : Prop := MapsTo f s t ∧ InjOn f s ∧ SurjOn f s t +#align set.bij_on Set.BijOn + +/-- `g` is a left inverse to `f` on `a` means that `g (f x) = x` for all `x ∈ a`. -/ +def LeftInvOn (f' : β → α) (f : α → β) (s : Set α) : Prop := ∀ ⦃x⦄, x ∈ s → f' (f x) = x +#align set.left_inv_on Set.LeftInvOn + +/-- `g` is a right inverse to `f` on `b` if `f (g x) = x` for all `x ∈ b`. -/ +@[reducible] +def RightInvOn (f' : β → α) (f : α → β) (t : Set β) : Prop := LeftInvOn f f' t +#align set.right_inv_on Set.RightInvOn + +/-- `g` is an inverse to `f` viewed as a map from `a` to `b` -/ +def InvOn (g : β → α) (f : α → β) (s : Set α) (t : Set β) : Prop := + LeftInvOn g f s ∧ RightInvOn g f t +#align set.inv_on Set.InvOn + +section image2 + +/-- The image of a binary function `f : α → β → γ` as a function `Set α → Set β → Set γ`. +Mathematically this should be thought of as the image of the corresponding function `α × β → γ`.-/ +def image2 (f : α → β → γ) (s : Set α) (t : Set β) : Set γ := {c | ∃ a ∈ s, ∃ b ∈ t, f a b = c} +#align set.image2 Set.image2 + +variable {f : α → β → γ} {s : Set α} {t : Set β} {a : α} {b : β} {c : γ} + +@[simp] theorem mem_image2 : c ∈ image2 f s t ↔ ∃ a ∈ s, ∃ b ∈ t, f a b = c := .rfl +#align set.mem_image2 Set.mem_image2 + +theorem mem_image2_of_mem (ha : a ∈ s) (hb : b ∈ t) : f a b ∈ image2 f s t := + ⟨a, ha, b, hb, rfl⟩ +#align set.mem_image2_of_mem Set.mem_image2_of_mem + +end image2 + +/-- Given a set `s` of functions `α → β` and `t : Set α`, `seq s t` is the union of `f '' t` over +all `f ∈ s`. -/ +def seq (s : Set (α → β)) (t : Set α) : Set β := image2 (fun f ↦ f) s t +#align set.seq Set.seq + +@[simp] +theorem mem_seq_iff {s : Set (α → β)} {t : Set α} {b : β} : + b ∈ seq s t ↔ ∃ f ∈ s, ∃ a ∈ t, (f : α → β) a = b := + Iff.rfl +#align set.mem_seq_iff Set.mem_seq_iff + +lemma seq_eq_image2 (s : Set (α → β)) (t : Set α) : seq s t = image2 (fun f a ↦ f a) s t := rfl diff --git a/Mathlib/Data/Set/Finite.lean b/Mathlib/Data/Set/Finite.lean index a56f7b928f687..09b2182221dac 100644 --- a/Mathlib/Data/Set/Finite.lean +++ b/Mathlib/Data/Set/Finite.lean @@ -71,7 +71,7 @@ theorem finite_def {s : Set α} : s.Finite ↔ Nonempty (Fintype s) := ⟨fun ⟨h⟩ => ⟨h⟩, fun ⟨h⟩ => ⟨h⟩⟩ #align set.finite_def Set.finite_def -alias ⟨Finite.nonempty_fintype, _⟩ := finite_def +protected alias ⟨Finite.nonempty_fintype, _⟩ := finite_def #align set.finite.nonempty_fintype Set.Finite.nonempty_fintype theorem finite_coe_iff {s : Set α} : Finite s ↔ s.Finite := by @@ -274,6 +274,7 @@ protected theorem toFinset_diff [DecidableEq α] (hs : s.Finite) (ht : t.Finite) simp #align set.finite.to_finset_diff Set.Finite.toFinset_diff +open scoped symmDiff in protected theorem toFinset_symmDiff [DecidableEq α] (hs : s.Finite) (ht : t.Finite) (h : (s ∆ t).Finite) : h.toFinset = hs.toFinset ∆ ht.toFinset := by ext @@ -859,7 +860,7 @@ theorem finite_empty : (∅ : Set α).Finite := #align set.finite_empty Set.finite_empty protected theorem Infinite.nonempty {s : Set α} (h : s.Infinite) : s.Nonempty := - nonempty_iff_ne_empty.2 $ by + nonempty_iff_ne_empty.2 <| by rintro rfl exact h finite_empty #align set.infinite.nonempty Set.Infinite.nonempty @@ -926,10 +927,10 @@ theorem Finite.preimage (I : Set.InjOn f (f ⁻¹' s)) (h : s.Finite) : (f ⁻¹ #align set.finite.preimage Set.Finite.preimage protected lemma Infinite.preimage (hs : s.Infinite) (hf : s ⊆ range f) : (f ⁻¹' s).Infinite := - fun h ↦ hs $ finite_of_finite_preimage h hf + fun h ↦ hs <| finite_of_finite_preimage h hf lemma Infinite.preimage' (hs : (s ∩ range f).Infinite) : (f ⁻¹' s).Infinite := - (hs.preimage $ inter_subset_right _ _).mono $ preimage_mono $ inter_subset_left _ _ + (hs.preimage <| inter_subset_right _ _).mono <| preimage_mono <| inter_subset_left _ _ theorem Finite.preimage_embedding {s : Set β} (f : α ↪ β) (h : s.Finite) : (f ⁻¹' s).Finite := h.preimage fun _ _ _ _ h' => f.injective h' @@ -992,7 +993,7 @@ protected theorem infinite_prod : refine' ⟨fun h => _, _⟩ · simp_rw [Set.Infinite, @and_comm ¬_, ← not_imp] by_contra! - exact h ((this.1 h.nonempty.snd).prod $ this.2 h.nonempty.fst) + exact h ((this.1 h.nonempty.snd).prod <| this.2 h.nonempty.fst) · rintro (h | h) · exact h.1.prod_left h.2 · exact h.1.prod_right h.2 @@ -1057,16 +1058,25 @@ theorem Finite.finite_subsets {α : Type u} {a : Set α} (h : a.Finite) : { b | and_assoc, Finset.coeEmb] using h.subset⟩ #align set.finite.finite_subsets Set.Finite.finite_subsets +section Pi +variable {ι : Type*} [Finite ι] {κ : ι → Type*} {t : ∀ i, Set (κ i)} + /-- Finite product of finite sets is finite -/ -theorem Finite.pi {δ : Type*} [Finite δ] {κ : δ → Type*} {t : ∀ d, Set (κ d)} - (ht : ∀ d, (t d).Finite) : (pi univ t).Finite := by - cases _root_.nonempty_fintype δ +theorem Finite.pi (ht : ∀ i, (t i).Finite) : (pi univ t).Finite := by + cases nonempty_fintype ι lift t to ∀ d, Finset (κ d) using ht classical rw [← Fintype.coe_piFinset] apply Finset.finite_toSet #align set.finite.pi Set.Finite.pi +/-- Finite product of finite sets is finite. Note this is a variant of `Set.Finite.pi` without the +extra `i ∈ univ` binder. -/ +lemma Finite.pi' (ht : ∀ i, (t i).Finite) : {f : ∀ i, κ i | ∀ i, f i ∈ t i}.Finite := by + simpa [Set.pi] using Finite.pi ht + +end Pi + /-- A finite union of finsets is finite. -/ theorem union_finset_finite_of_range_finite (f : α → Finset β) (h : (range f).Finite) : (⋃ a, (f a : Set β)).Finite := by @@ -1218,6 +1228,23 @@ theorem Finite.dinduction_on {C : ∀ s : Set α, s.Finite → Prop} (s : Set α this h #align set.finite.dinduction_on Set.Finite.dinduction_on +/-- Induction up to a finite set `S`. -/ +theorem Finite.induction_to {C : Set α → Prop} {S : Set α} (h : S.Finite) + (S0 : Set α) (hS0 : S0 ⊆ S) (H0 : C S0) (H1 : ∀ s ⊂ S, C s → ∃ a ∈ S \ s, C (insert a s)) : + C S := by + have : Finite S := Finite.to_subtype h + have : Finite {T : Set α // T ⊆ S} := Finite.of_equiv (Set S) (Equiv.Set.powerset S).symm + rw [← Subtype.coe_mk (p := (· ⊆ S)) _ le_rfl] + rw [← Subtype.coe_mk (p := (· ⊆ S)) _ hS0] at H0 + refine Finite.to_wellFoundedGT.wf.induction_bot' (fun s hs hs' ↦ ?_) H0 + obtain ⟨a, ⟨ha1, ha2⟩, ha'⟩ := H1 s (ssubset_of_ne_of_subset hs s.2) hs' + exact ⟨⟨insert a s.1, insert_subset ha1 s.2⟩, Set.ssubset_insert ha2, ha'⟩ + +/-- Induction up to `univ`. -/ +theorem Finite.induction_to_univ [Finite α] {C : Set α → Prop} (S0 : Set α) + (H0 : C S0) (H1 : ∀ S ≠ univ, C S → ∃ a ∉ S, C (insert a S)) : C univ := + finite_univ.induction_to S0 (subset_univ S0) H0 (by simpa [ssubset_univ_iff]) + section attribute [local instance] Nat.fintypeIio @@ -1248,8 +1275,8 @@ theorem empty_card : Fintype.card (∅ : Set α) = 0 := rfl #align set.empty_card Set.empty_card -theorem empty_card' {h : Fintype.{u} (∅ : Set α)} : @Fintype.card (∅ : Set α) h = 0 := - by simp +theorem empty_card' {h : Fintype.{u} (∅ : Set α)} : @Fintype.card (∅ : Set α) h = 0 := by + simp #align set.empty_card' Set.empty_card' theorem card_fintypeInsertOfNotMem {a : α} (s : Set α) [Fintype s] (h : a ∉ s) : @@ -1338,7 +1365,7 @@ alias ⟨_, Infinite.to_subtype⟩ := infinite_coe_iff #align set.infinite.to_subtype Set.Infinite.to_subtype lemma Infinite.exists_not_mem_finite (hs : s.Infinite) (ht : t.Finite) : ∃ a, a ∈ s ∧ a ∉ t := by - by_contra! h; exact hs $ ht.subset h + by_contra! h; exact hs <| ht.subset h lemma Infinite.exists_not_mem_finset (hs : s.Infinite) (t : Finset α) : ∃ a ∈ s, a ∉ t := hs.exists_not_mem_finite t.finite_toSet @@ -1746,7 +1773,7 @@ lemma Finite.of_forall_not_lt_lt (h : ∀ ⦃x y z : α⦄, x < y → y < z → /-- If a set `s` does not contain any triple of elements `x < y < z`, then `s` is finite. -/ lemma Set.finite_of_forall_not_lt_lt (h : ∀ x ∈ s, ∀ y ∈ s, ∀ z ∈ s, x < y → y < z → False) : Set.Finite s := - @Set.toFinite _ s <| Finite.of_forall_not_lt_lt $ by simpa only [SetCoe.forall'] using h + @Set.toFinite _ s <| Finite.of_forall_not_lt_lt <| by simpa only [SetCoe.forall'] using h #align set.finite_of_forall_not_lt_lt Set.finite_of_forall_not_lt_lt lemma Set.finite_diff_iUnion_Ioo (s : Set α) : (s \ ⋃ (x ∈ s) (y ∈ s), Ioo x y).Finite := diff --git a/Mathlib/Data/Set/Function.lean b/Mathlib/Data/Set/Function.lean index 399ba0a3a5445..28cbef76aede1 100644 --- a/Mathlib/Data/Set/Function.lean +++ b/Mathlib/Data/Set/Function.lean @@ -174,13 +174,6 @@ variable {s s₁ s₂ : Set α} {t t₁ t₂ : Set β} {p : Set γ} {f f₁ f₂ /-! ### Equality on a set -/ - -/-- Two functions `f₁ f₂ : α → β` are equal on `s` - if `f₁ x = f₂ x` for all `x ∈ s`. -/ -def EqOn (f₁ f₂ : α → β) (s : Set α) : Prop := - ∀ ⦃x⦄, x ∈ s → f₁ x = f₂ x -#align set.eq_on Set.EqOn - @[simp] theorem eqOn_empty (f₁ f₂ : α → β) : EqOn f₁ f₂ ∅ := fun _ => False.elim #align set.eq_on_empty Set.eqOn_empty @@ -351,18 +344,6 @@ end Mono /-! ### maps to -/ - -/-- `MapsTo f a b` means that the image of `a` is contained in `b`. -/ -def MapsTo (f : α → β) (s : Set α) (t : Set β) : Prop := - ∀ ⦃x⦄, x ∈ s → f x ∈ t -#align set.maps_to Set.MapsTo - -/-- Given a map `f` sending `s : Set α` into `t : Set β`, restrict domain of `f` to `s` -and the codomain to `t`. Same as `Subtype.map`. -/ -def MapsTo.restrict (f : α → β) (s : Set α) (t : Set β) (h : MapsTo f s t) : s → t := - Subtype.map f h -#align set.maps_to.restrict Set.MapsTo.restrict - theorem MapsTo.restrict_commutes (f : α → β) (s : Set α) (t : Set β) (h : MapsTo f s t) : Subtype.val ∘ h.restrict f s t = f ∘ Subtype.val := rfl @@ -471,7 +452,7 @@ theorem MapsTo.iterate_restrict {f : α → α} {s : Set α} (h : MapsTo f s s) lemma mapsTo_of_subsingleton' [Subsingleton β] (f : α → β) (h : s.Nonempty → t.Nonempty) : MapsTo f s t := - fun a ha ↦ Subsingleton.mem_iff_nonempty.2 $ h ⟨a, ha⟩ + fun a ha ↦ Subsingleton.mem_iff_nonempty.2 <| h ⟨a, ha⟩ #align set.maps_to_of_subsingleton' Set.mapsTo_of_subsingleton' lemma mapsTo_of_subsingleton [Subsingleton α] (f : α → α) (s : Set α) : MapsTo f s s := @@ -526,13 +507,6 @@ theorem mapsTo_inter : MapsTo f s (t₁ ∩ t₂) ↔ MapsTo f s t₁ ∧ MapsTo theorem mapsTo_univ (f : α → β) (s : Set α) : MapsTo f s univ := fun _ _ => trivial #align set.maps_to_univ Set.mapsTo_univ -theorem mapsTo_image (f : α → β) (s : Set α) : MapsTo f s (f '' s) := by rw [mapsTo'] -#align set.maps_to_image Set.mapsTo_image - -theorem mapsTo_preimage (f : α → β) (t : Set β) : MapsTo f (f ⁻¹' t) t := - Subset.refl _ -#align set.maps_to_preimage Set.mapsTo_preimage - theorem mapsTo_range (f : α → β) (s : Set α) : MapsTo f s (range f) := (mapsTo_image f s).mono (Subset.refl s) (image_subset_range _ _) #align set.maps_to_range Set.mapsTo_range @@ -590,13 +564,6 @@ section variable (t f) -/-- The restriction of a function onto the preimage of a set. -/ -@[simps!] -def restrictPreimage : f ⁻¹' t → t := - (Set.mapsTo_preimage f t).restrict _ _ _ -#align set.restrict_preimage Set.restrictPreimage -#align set.restrict_preimage_coe Set.restrictPreimage_coe - theorem range_restrictPreimage : range (t.restrictPreimage f) = Subtype.val ⁻¹' range f := by delta Set.restrictPreimage rw [MapsTo.range_restrict, Set.image_preimage_eq_inter_range, Set.preimage_inter, @@ -628,12 +595,6 @@ end /-! ### Injectivity on a set -/ - -/-- `f` is injective on `a` if the restriction of `f` to `a` is injective. -/ -def InjOn (f : α → β) (s : Set α) : Prop := - ∀ ⦃x₁ : α⦄, x₁ ∈ s → ∀ ⦃x₂ : α⦄, x₂ ∈ s → f x₁ = f x₂ → x₁ = x₂ -#align set.inj_on Set.InjOn - theorem Subsingleton.injOn (hs : s.Subsingleton) (f : α → β) : InjOn f s := fun _ hx _ hy _ => hs hx hy #align set.subsingleton.inj_on Set.Subsingleton.injOn @@ -683,8 +644,7 @@ theorem injOn_union (h : Disjoint s₁ s₂) : theorem injOn_insert {f : α → β} {s : Set α} {a : α} (has : a ∉ s) : Set.InjOn f (insert a s) ↔ Set.InjOn f s ∧ f a ∉ f '' s := by - have : Disjoint s {a} := disjoint_iff_inf_le.mpr fun x ⟨hxs, (hxa : x = a)⟩ => has (hxa ▸ hxs) - rw [← union_singleton, injOn_union this] + rw [← union_singleton, injOn_union (disjoint_singleton_right.2 has)] simp #align set.inj_on_insert Set.injOn_insert @@ -709,6 +669,9 @@ theorem InjOn.comp (hg : InjOn g t) (hf : InjOn f s) (h : MapsTo f s t) : InjOn fun _ hx _ hy heq => hf hx hy <| hg (h hx) (h hy) heq #align set.inj_on.comp Set.InjOn.comp +lemma InjOn.image_of_comp (h : InjOn (g ∘ f) s) : InjOn g (f '' s) := + ball_image_iff.2 fun _x hx ↦ ball_image_iff.2 fun _y hy heq ↦ congr_arg f <| h hx hy heq + lemma InjOn.iterate {f : α → α} {s : Set α} (h : InjOn f s) (hf : MapsTo f s s) : ∀ n, InjOn f^[n] s | 0 => injOn_id _ @@ -790,13 +753,44 @@ theorem _root_.Disjoint.image {s t u : Set α} {f : α → β} (h : Disjoint s t rw [← hf.image_inter hs ht, h, image_empty] #align disjoint.image Disjoint.image -/-! ### Surjectivity on a set -/ +@[simp] lemma graphOn_empty (f : α → β) : graphOn f ∅ = ∅ := image_empty _ + +@[simp] +lemma graphOn_union (f : α → β) (s t : Set α) : graphOn f (s ∪ t) = graphOn f s ∪ graphOn f t := + image_union .. +@[simp] +lemma graphOn_singleton (f : α → β) (x : α) : graphOn f {x} = {(x, f x)} := + image_singleton .. + +@[simp] +lemma graphOn_insert (f : α → β) (x : α) (s : Set α) : + graphOn f (insert x s) = insert (x, f x) (graphOn f s) := + image_insert_eq .. -/-- `f` is surjective from `a` to `b` if `b` is contained in the image of `a`. -/ -def SurjOn (f : α → β) (s : Set α) (t : Set β) : Prop := - t ⊆ f '' s -#align set.surj_on Set.SurjOn +@[simp] +lemma image_fst_graphOn (f : α → β) (s : Set α) : Prod.fst '' graphOn f s = s := by + simp [graphOn, image_image] + +lemma exists_eq_graphOn_image_fst [Nonempty β] {s : Set (α × β)} : + (∃ f : α → β, s = graphOn f (Prod.fst '' s)) ↔ InjOn Prod.fst s := by + refine ⟨?_, fun h ↦ ?_⟩ + · rintro ⟨f, hf⟩ + rw [hf] + exact InjOn.image_of_comp <| injOn_id _ + · have : ∀ x ∈ Prod.fst '' s, ∃ y, (x, y) ∈ s := ball_image_iff.2 fun (x, y) h ↦ ⟨y, h⟩ + choose! f hf using this + rw [ball_image_iff] at hf + use f + rw [graphOn, image_image, EqOn.image_eq_self] + exact fun x hx ↦ h (hf x hx) hx rfl + +lemma exists_eq_graphOn [Nonempty β] {s : Set (α × β)} : + (∃ f t, s = graphOn f t) ↔ InjOn Prod.fst s := + .trans ⟨fun ⟨f, t, hs⟩ ↦ ⟨f, by rw [hs, image_fst_graphOn]⟩, fun ⟨f, hf⟩ ↦ ⟨f, _, hf⟩⟩ + exists_eq_graphOn_image_fst + +/-! ### Surjectivity on a set -/ theorem SurjOn.subset_range (h : SurjOn f s t) : t ⊆ range f := Subset.trans h <| image_subset_range f s @@ -886,7 +880,7 @@ lemma SurjOn.comp_right {s : Set β} {t : Set γ} (hf : Surjective f) (hg : Surj lemma surjOn_of_subsingleton' [Subsingleton β] (f : α → β) (h : t.Nonempty → s.Nonempty) : SurjOn f s t := - fun _ ha ↦ Subsingleton.mem_iff_nonempty.2 $ (h ⟨_, ha⟩).image _ + fun _ ha ↦ Subsingleton.mem_iff_nonempty.2 <| (h ⟨_, ha⟩).image _ #align set.surj_on_of_subsingleton' Set.surjOn_of_subsingleton' lemma surjOn_of_subsingleton [Subsingleton α] (f : α → α) (s : Set α) : SurjOn f s s := @@ -954,12 +948,6 @@ theorem eqOn_comp_right_iff : s.EqOn (g₁ ∘ f) (g₂ ∘ f) ↔ (f '' s).EqOn /-! ### Bijectivity -/ - -/-- `f` is bijective from `s` to `t` if `f` is injective on `s` and `f '' s = t`. -/ -def BijOn (f : α → β) (s : Set α) (t : Set β) : Prop := - MapsTo f s t ∧ InjOn f s ∧ SurjOn f s t -#align set.bij_on Set.BijOn - theorem BijOn.mapsTo (h : BijOn f s t) : MapsTo f s t := h.left #align set.bij_on.maps_to Set.BijOn.mapsTo @@ -1076,12 +1064,6 @@ theorem BijOn.compl (hst : BijOn f s t) (hf : Bijective f) : BijOn f sᶜ tᶜ : /-! ### left inverse -/ - -/-- `g` is a left inverse to `f` on `a` means that `g (f x) = x` for all `x ∈ a`. -/ -def LeftInvOn (f' : β → α) (f : α → β) (s : Set α) : Prop := - ∀ ⦃x⦄, x ∈ s → f' (f x) = x -#align set.left_inv_on Set.LeftInvOn - theorem LeftInvOn.eqOn (h : LeftInvOn f' f s) : EqOn (f' ∘ f) id s := h #align set.left_inv_on.eq_on Set.LeftInvOn.eqOn @@ -1154,13 +1136,6 @@ theorem LeftInvOn.image_image' (hf : LeftInvOn f' f s) (hs : s₁ ⊆ s) : f' '' /-! ### Right inverse -/ - -/-- `g` is a right inverse to `f` on `b` if `f (g x) = x` for all `x ∈ b`. -/ -@[reducible] -def RightInvOn (f' : β → α) (f : α → β) (t : Set β) : Prop := - LeftInvOn f f' t -#align set.right_inv_on Set.RightInvOn - theorem RightInvOn.eqOn (h : RightInvOn f' f t) : EqOn (f ∘ f') id t := h #align set.right_inv_on.eq_on Set.RightInvOn.eqOn @@ -1223,12 +1198,6 @@ theorem SurjOn.leftInvOn_of_rightInvOn (hf : SurjOn f s t) (hf' : RightInvOn f f /-! ### Two-side inverses -/ - -/-- `g` is an inverse to `f` viewed as a map from `a` to `b` -/ -def InvOn (g : β → α) (f : α → β) (s : Set α) (t : Set β) : Prop := - LeftInvOn g f s ∧ RightInvOn g f t -#align set.inv_on Set.InvOn - lemma invOn_id (s : Set α) : InvOn id id s s := ⟨s.leftInvOn_id, s.rightInvOn_id⟩ #align set.inv_on_id Set.invOn_id @@ -1266,7 +1235,7 @@ variable [Nonempty α] {s : Set α} {f : α → β} {a : α} {b : β} attribute [local instance] Classical.propDecidable /-- Construct the inverse for a function `f` on domain `s`. This function is a right inverse of `f` -on `f '' s`. For a computable version, see `Function.Injective.inv_of_mem_range`. -/ +on `f '' s`. For a computable version, see `Function.Embedding.invOfMemRange`. -/ noncomputable def invFunOn (f : α → β) (s : Set α) (b : β) : α := if h : ∃ a, a ∈ s ∧ f a = b then Classical.choose h else Classical.choice ‹Nonempty α› #align function.inv_fun_on Function.invFunOn @@ -1773,15 +1742,15 @@ theorem injOn_preimage (h : Semiconj f fa fb) {s : Set β} (hb : InjOn fb s) end Semiconj -theorem update_comp_eq_of_not_mem_range' {α β : Sort _} {γ : β → Sort*} [DecidableEq β] +theorem update_comp_eq_of_not_mem_range' {α : Sort*} {β : Type*} {γ : β → Sort*} [DecidableEq β] (g : ∀ b, γ b) {f : α → β} {i : β} (a : γ i) (h : i ∉ Set.range f) : - (fun j => (Function.update g i a) (f j)) = fun j => g (f j) := + (fun j => update g i a (f j)) = fun j => g (f j) := (update_comp_eq_of_forall_ne' _ _) fun x hx => h ⟨x, hx⟩ #align function.update_comp_eq_of_not_mem_range' Function.update_comp_eq_of_not_mem_range' /-- Non-dependent version of `Function.update_comp_eq_of_not_mem_range'` -/ -theorem update_comp_eq_of_not_mem_range {α β γ : Sort _} [DecidableEq β] (g : β → γ) {f : α → β} - {i : β} (a : γ) (h : i ∉ Set.range f) : Function.update g i a ∘ f = g ∘ f := +theorem update_comp_eq_of_not_mem_range {α : Sort*} {β : Type*} {γ : Sort*} [DecidableEq β] + (g : β → γ) {f : α → β} {i : β} (a : γ) (h : i ∉ Set.range f) : update g i a ∘ f = g ∘ f := update_comp_eq_of_not_mem_range' g a h #align function.update_comp_eq_of_not_mem_range Function.update_comp_eq_of_not_mem_range @@ -1789,7 +1758,7 @@ theorem insert_injOn (s : Set α) : sᶜ.InjOn fun a => insert a s := fun _a ha (insert_inj ha).1 #align function.insert_inj_on Function.insert_injOn -theorem monotoneOn_of_rightInvOn_of_mapsTo {α β : Sort _} [PartialOrder α] [LinearOrder β] +theorem monotoneOn_of_rightInvOn_of_mapsTo {α β : Type*} [PartialOrder α] [LinearOrder β] {φ : β → α} {ψ : α → β} {t : Set β} {s : Set α} (hφ : MonotoneOn φ t) (φψs : Set.RightInvOn ψ φ s) (ψts : Set.MapsTo ψ s t) : MonotoneOn ψ s := by rintro x xs y ys l @@ -1801,7 +1770,7 @@ theorem monotoneOn_of_rightInvOn_of_mapsTo {α β : Sort _} [PartialOrder α] [L exact le_refl _ #align function.monotone_on_of_right_inv_on_of_maps_to Function.monotoneOn_of_rightInvOn_of_mapsTo -theorem antitoneOn_of_rightInvOn_of_mapsTo {α β : Sort _} [PartialOrder α] [LinearOrder β] +theorem antitoneOn_of_rightInvOn_of_mapsTo [PartialOrder α] [LinearOrder β] {φ : β → α} {ψ : α → β} {t : Set β} {s : Set α} (hφ : AntitoneOn φ t) (φψs : Set.RightInvOn ψ φ s) (ψts : Set.MapsTo ψ s t) : AntitoneOn ψ s := (monotoneOn_of_rightInvOn_of_mapsTo hφ.dual_left φψs ψts).dual_right @@ -1856,7 +1825,7 @@ lemma bijOn' (h₁ : MapsTo e s t) (h₂ : MapsTo e.symm t s) : BijOn e s t := #align equiv.bij_on' Equiv.bijOn' protected lemma bijOn (h : ∀ a, e a ∈ t ↔ a ∈ s) : BijOn e s t := - e.bijOn' (fun a ↦ (h _).2) fun b hb ↦ (h _).1 $ by rwa [apply_symm_apply] + e.bijOn' (fun a ↦ (h _).2) fun b hb ↦ (h _).1 <| by rwa [apply_symm_apply] #align equiv.bij_on Equiv.bijOn lemma invOn : InvOn e e.symm t s := diff --git a/Mathlib/Data/Set/Image.lean b/Mathlib/Data/Set/Image.lean index 7c08f48308b2f..30b9e3c7da44a 100644 --- a/Mathlib/Data/Set/Image.lean +++ b/Mathlib/Data/Set/Image.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ import Mathlib.Data.Set.Basic +import Mathlib.Order.WithBot #align_import data.set.image from "leanprover-community/mathlib"@"001ffdc42920050657fd45bd2b8bfbec8eaaeb29" @@ -42,15 +43,6 @@ variable {α β γ : Type*} {ι ι' : Sort*} /-! ### Inverse image -/ -/-- The preimage of `s : Set β` by `f : α → β`, written `f ⁻¹' s`, - is the set of `x : α` such that `f x ∈ s`. -/ -def preimage {α : Type u} {β : Type v} (f : α → β) (s : Set β) : Set α := - { x | f x ∈ s } -#align set.preimage Set.preimage - -/-- `f ⁻¹' t` denotes the preimage of `t : Set β` under the function `f : α → β`. -/ -infixl:80 " ⁻¹' " => preimage - section Preimage variable {f : α → β} {g : β → γ} @@ -60,11 +52,6 @@ theorem preimage_empty : f ⁻¹' ∅ = ∅ := rfl #align set.preimage_empty Set.preimage_empty -@[simp, mfld_simps] -theorem mem_preimage {s : Set β} {a : α} : a ∈ f ⁻¹' s ↔ f a ∈ s := - Iff.rfl -#align set.mem_preimage Set.mem_preimage - theorem preimage_congr {f g : α → β} {s : Set β} (h : ∀ x : α, f x = g x) : f ⁻¹' s = g ⁻¹' s := by congr with x simp [h] @@ -103,6 +90,7 @@ theorem preimage_diff (f : α → β) (s t : Set β) : f ⁻¹' (s \ t) = f ⁻ rfl #align set.preimage_diff Set.preimage_diff +open scoped symmDiff in @[simp] lemma preimage_symmDiff {f : α → β} (s t : Set β) : f ⁻¹' (s ∆ t) = (f ⁻¹' s) ∆ (f ⁻¹' t) := rfl @@ -219,28 +207,15 @@ variable {f : α → β} {s t : Set α} -- Porting note: `Set.image` is already defined in `Init.Set` #align set.image Set.image -/-- `f '' s` denotes the image of `s : Set α` under the function `f : α → β`. -/ -infixl:80 " '' " => image - theorem mem_image_iff_bex {f : α → β} {s : Set α} {y : β} : y ∈ f '' s ↔ ∃ (x : _) (_ : x ∈ s), f x = y := bex_def.symm #align set.mem_image_iff_bex Set.mem_image_iff_bex -@[simp] -theorem mem_image (f : α → β) (s : Set α) (y : β) : y ∈ f '' s ↔ ∃ x ∈ s, f x = y := - Iff.rfl -#align set.mem_image Set.mem_image - theorem image_eta (f : α → β) : f '' s = (fun x => f x) '' s := rfl #align set.image_eta Set.image_eta -@[mfld_simps] -theorem mem_image_of_mem (f : α → β) {x : α} {a : Set α} (h : x ∈ a) : f x ∈ f '' a := - ⟨_, h, rfl⟩ -#align set.mem_image_of_mem Set.mem_image_of_mem - theorem _root_.Function.Injective.mem_set_image {f : α → β} (hf : Injective f) {s : Set α} {a : α} : f a ∈ f '' s ↔ a ∈ s := ⟨fun ⟨_, hb, Eq⟩ => hf Eq ▸ hb, mem_image_of_mem f⟩ @@ -467,6 +442,7 @@ theorem subset_image_diff (f : α → β) (s t : Set α) : f '' s \ f '' t ⊆ f exact image_subset f (subset_union_right t s) #align set.subset_image_diff Set.subset_image_diff +open scoped symmDiff in theorem subset_image_symmDiff : (f '' s) ∆ (f '' t) ⊆ f '' s ∆ t := (union_subset_union (subset_image_diff _ _ _) <| subset_image_diff _ _ _).trans (superset_of_eq (image_union _ _ _)) @@ -478,6 +454,7 @@ theorem image_diff {f : α → β} (hf : Injective f) (s t : Set α) : f '' (s \ (subset_image_diff f s t) #align set.image_diff Set.image_diff +open scoped symmDiff in theorem image_symmDiff (hf : Injective f) (s t : Set α) : f '' s ∆ t = (f '' s) ∆ (f '' t) := by simp_rw [Set.symmDiff_def, image_union, image_diff hf] #align set.image_symm_diff Set.image_symmDiff @@ -491,9 +468,11 @@ theorem Nonempty.of_image {f : α → β} {s : Set α} : (f '' s).Nonempty → s #align set.nonempty.of_image Set.Nonempty.of_image @[simp] -theorem nonempty_image_iff {f : α → β} {s : Set α} : (f '' s).Nonempty ↔ s.Nonempty := +theorem image_nonempty {f : α → β} {s : Set α} : (f '' s).Nonempty ↔ s.Nonempty := ⟨Nonempty.of_image, fun h => h.image f⟩ -#align set.nonempty_image_iff Set.nonempty_image_iff +#align set.nonempty_image_iff Set.image_nonempty + +@[deprecated] alias nonempty_image_iff := image_nonempty theorem Nonempty.preimage {s : Set β} (hs : s.Nonempty) {f : α → β} (hf : Surjective f) : (f ⁻¹' s).Nonempty := @@ -555,7 +534,7 @@ theorem image_preimage_inter (f : α → β) (s : Set α) (t : Set β) : @[simp] theorem image_inter_nonempty_iff {f : α → β} {s : Set α} {t : Set β} : (f '' s ∩ t).Nonempty ↔ (s ∩ f ⁻¹' t).Nonempty := by - rw [← image_inter_preimage, nonempty_image_iff] + rw [← image_inter_preimage, image_nonempty] #align set.image_inter_nonempty_iff Set.image_inter_nonempty_iff theorem image_diff_preimage {f : α → β} {s : Set α} {t : Set β} : f '' (s \ f ⁻¹' t) = f '' s \ t := @@ -594,6 +573,12 @@ theorem image_eq_image {f : α → β} (hf : Injective f) : f '' s = f '' t ↔ rw [← preimage_image_eq s hf, ← preimage_image_eq t hf, eq] #align set.image_eq_image Set.image_eq_image +theorem subset_image_iff {t : Set β} : + t ⊆ f '' s ↔ ∃ u, u ⊆ s ∧ f '' u = t := by + refine ⟨fun h ↦ ⟨f ⁻¹' t ∩ s, inter_subset_right _ _, ?_⟩, + fun ⟨u, hu, hu'⟩ ↦ hu'.symm ▸ image_mono hu⟩ + rwa [image_preimage_inter, inter_eq_left] + theorem image_subset_image_iff {f : α → β} (hf : Injective f) : f '' s ⊆ f '' t ↔ s ⊆ t := by refine' Iff.symm <| (Iff.intro (image_subset f)) fun h => _ rw [← preimage_image_eq s hf, ← preimage_image_eq t hf] @@ -618,11 +603,6 @@ theorem exists_image_iff (f : α → β) (x : Set α) (P : β → Prop) : ⟨⟨_, _, a.prop, rfl⟩, h⟩⟩ #align set.exists_image_iff Set.exists_image_iff -/-- Restriction of `f` to `s` factors through `s.imageFactorization f : s → f '' s`. -/ -def imageFactorization (f : α → β) (s : Set α) : s → f '' s := fun p => - ⟨f p.1, mem_image_of_mem f p.2⟩ -#align set.image_factorization Set.imageFactorization - theorem imageFactorization_eq {f : α → β} {s : Set α} : Subtype.val ∘ imageFactorization f s = f ∘ Subtype.val := funext fun _ => rfl @@ -674,26 +654,6 @@ section Range variable {f : ι → α} {s t : Set α} -/-- Range of a function. - -This function is more flexible than `f '' univ`, as the image requires that the domain is in Type -and not an arbitrary Sort. -/ -def range (f : ι → α) : Set α := - { x | ∃ y, f y = x } -#align set.range Set.range - -@[simp] -theorem mem_range {x : α} : x ∈ range f ↔ ∃ y, f y = x := - Iff.rfl -#align set.mem_range Set.mem_range - --- Porting note --- @[simp] `simp` can prove this -@[mfld_simps] -theorem mem_range_self (i : ι) : f i ∈ range f := - ⟨i, rfl⟩ -#align set.mem_range_self Set.mem_range_self - theorem forall_range_iff {p : α → Prop} : (∀ a ∈ range f, p a) ↔ ∀ i, p (f i) := by simp #align set.forall_range_iff Set.forall_range_iff @@ -1070,10 +1030,6 @@ theorem image_compl_preimage {f : α → β} {s : Set β} : f '' (f ⁻¹' s)ᶜ rw [compl_eq_univ_diff, image_diff_preimage, image_univ] #align set.image_compl_preimage Set.image_compl_preimage -/-- Any map `f : ι → β` factors through a map `rangeFactorization f : ι → range f`. -/ -def rangeFactorization (f : ι → β) : ι → range f := fun i => ⟨f i, mem_range_self i⟩ -#align set.range_factorization Set.rangeFactorization - theorem rangeFactorization_eq {f : ι → β} : Subtype.val ∘ rangeFactorization f = f := funext fun _ => rfl #align set.range_factorization_eq Set.rangeFactorization_eq @@ -1169,22 +1125,6 @@ theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) -- rw [SetCoe.exists, Subtype.coe_mk, exists_prop, exists_eq_right, mem_set_of, Subtype.coe_mk] #align set.range_inclusion Set.range_inclusion -/-- We can use the axiom of choice to pick a preimage for every element of `range f`. -/ -noncomputable def rangeSplitting (f : α → β) : range f → α := fun x => x.2.choose -#align set.range_splitting Set.rangeSplitting - --- This can not be a `@[simp]` lemma because the head of the left hand side is a variable. -theorem apply_rangeSplitting (f : α → β) (x : range f) : f (rangeSplitting f x) = x := - x.2.choose_spec -#align set.apply_range_splitting Set.apply_rangeSplitting - -@[simp] -theorem comp_rangeSplitting (f : α → β) : f ∘ rangeSplitting f = (↑) := by - ext - simp only [Function.comp_apply] - apply apply_rangeSplitting -#align set.comp_range_splitting Set.comp_rangeSplitting - -- When `f` is injective, see also `Equiv.ofInjective`. theorem leftInverse_rangeSplitting (f : α → β) : LeftInverse (rangeFactorization f) (rangeSplitting f) := fun x => by @@ -1337,7 +1277,7 @@ theorem Surjective.image_surjective (hf : Surjective f) : Surjective (image f) : @[simp] theorem Surjective.nonempty_preimage (hf : Surjective f) {s : Set β} : - (f ⁻¹' s).Nonempty ↔ s.Nonempty := by rw [← nonempty_image_iff, hf.image_preimage] + (f ⁻¹' s).Nonempty ↔ s.Nonempty := by rw [← image_nonempty, hf.image_preimage] #align function.surjective.nonempty_preimage Function.Surjective.nonempty_preimage theorem Injective.image_injective (hf : Injective f) : Injective (image f) := by @@ -1494,7 +1434,7 @@ theorem forall_set_subtype {t : Set α} (p : Set α → Prop) : theorem preimage_coe_nonempty {s t : Set α} : (((↑) : s → α) ⁻¹' t).Nonempty ↔ (s ∩ t).Nonempty := by - rw [inter_comm, ← image_preimage_coe, nonempty_image_iff] + rw [inter_comm, ← image_preimage_coe, image_nonempty] #align subtype.preimage_coe_nonempty Subtype.preimage_coe_nonempty theorem preimage_coe_eq_empty {s t : Set α} : ((↑) : s → α) ⁻¹' t = ∅ ↔ s ∩ t = ∅ := by diff --git a/Mathlib/Data/Set/Intervals/Basic.lean b/Mathlib/Data/Set/Intervals/Basic.lean index de1cb4a9fb2ca..235bda91b08e8 100644 --- a/Mathlib/Data/Set/Intervals/Basic.lean +++ b/Mathlib/Data/Set/Intervals/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Patrick Massot, Yury Kudryashov, Rémy Degenne -/ import Mathlib.Order.MinMax -import Mathlib.Data.Set.Prod +import Mathlib.Data.Set.Basic import Mathlib.Tactic.Says #align_import data.set.intervals.basic from "leanprover-community/mathlib"@"3ba15165bd6927679be7c22d6091a87337e3cd0c" diff --git a/Mathlib/Data/Set/Intervals/Group.lean b/Mathlib/Data/Set/Intervals/Group.lean index 021b799751759..94effcf4d014f 100644 --- a/Mathlib/Data/Set/Intervals/Group.lean +++ b/Mathlib/Data/Set/Intervals/Group.lean @@ -3,10 +3,10 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Patrick Massot, Yury Kudryashov, Rémy Degenne -/ +import Mathlib.Algebra.GroupPower.Order +import Mathlib.Data.Int.Cast.Lemmas import Mathlib.Data.Set.Intervals.Basic -import Mathlib.Data.Set.Pairwise.Basic -import Mathlib.Algebra.Order.Group.Abs -import Mathlib.Algebra.GroupPower.Lemmas +import Mathlib.Logic.Pairwise #align_import data.set.intervals.group from "leanprover-community/mathlib"@"c227d107bbada5d0d9d20287e3282c0a7f1651a0" diff --git a/Mathlib/Data/Set/Intervals/Instances.lean b/Mathlib/Data/Set/Intervals/Instances.lean index d90f415e063f3..d312fe55443f7 100644 --- a/Mathlib/Data/Set/Intervals/Instances.lean +++ b/Mathlib/Data/Set/Intervals/Instances.lean @@ -5,6 +5,7 @@ Authors: Stuart Presnell, Eric Wieser, Yaël Dillies, Patrick Massot, Scott Morr -/ import Mathlib.Algebra.GroupPower.Order import Mathlib.Algebra.Ring.Regular +import Mathlib.Data.Set.Intervals.Basic #align_import data.set.intervals.instances from "leanprover-community/mathlib"@"d012cd09a9b256d870751284dd6a29882b0be105" diff --git a/Mathlib/Data/Set/Intervals/OrdConnected.lean b/Mathlib/Data/Set/Intervals/OrdConnected.lean index aa9a7196c9cd4..afa19047837a2 100644 --- a/Mathlib/Data/Set/Intervals/OrdConnected.lean +++ b/Mathlib/Data/Set/Intervals/OrdConnected.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Yury G. Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury G. Kudryashov -/ -import Mathlib.Data.Set.Intervals.UnorderedInterval +import Mathlib.Data.Set.Intervals.OrderEmbedding import Mathlib.Data.Set.Lattice import Mathlib.Order.Antichain @@ -21,8 +21,8 @@ In this file we prove that intersection of a family of `OrdConnected` sets is `O that all standard intervals are `OrdConnected`. -/ -open Interval - +open scoped Interval +open Set open OrderDual (toDual ofDual) namespace Set @@ -78,28 +78,60 @@ protected theorem Icc_subset (s : Set α) [hs : OrdConnected s] {x y} (hx : x hs.out hx hy #align set.Icc_subset Set.Icc_subset +end Preorder + +end Set + +namespace OrderEmbedding + +variable {α β : Type*} [Preorder α] [Preorder β] + +theorem image_Icc (e : α ↪o β) (he : OrdConnected (range e)) (x y : α) : + e '' Icc x y = Icc (e x) (e y) := by + rw [← e.preimage_Icc, image_preimage_eq_inter_range, inter_eq_left.2 (he.out ⟨_, rfl⟩ ⟨_, rfl⟩)] + +theorem image_Ico (e : α ↪o β) (he : OrdConnected (range e)) (x y : α) : + e '' Ico x y = Ico (e x) (e y) := by + rw [← e.preimage_Ico, image_preimage_eq_inter_range, + inter_eq_left.2 <| Ico_subset_Icc_self.trans <| he.out ⟨_, rfl⟩ ⟨_, rfl⟩] + +theorem image_Ioc (e : α ↪o β) (he : OrdConnected (range e)) (x y : α) : + e '' Ioc x y = Ioc (e x) (e y) := by + rw [← e.preimage_Ioc, image_preimage_eq_inter_range, + inter_eq_left.2 <| Ioc_subset_Icc_self.trans <| he.out ⟨_, rfl⟩ ⟨_, rfl⟩] + +theorem image_Ioo (e : α ↪o β) (he : OrdConnected (range e)) (x y : α) : + e '' Ioo x y = Ioo (e x) (e y) := by + rw [← e.preimage_Ioo, image_preimage_eq_inter_range, + inter_eq_left.2 <| Ioo_subset_Icc_self.trans <| he.out ⟨_, rfl⟩ ⟨_, rfl⟩] + +end OrderEmbedding + +namespace Set + +section Preorder + +variable {α β : Type*} [Preorder α] [Preorder β] {s t : Set α} + @[simp] lemma image_subtype_val_Icc {s : Set α} [OrdConnected s] (x y : s) : Subtype.val '' Icc x y = Icc x.1 y := - (Subtype.image_preimage_val s (Icc x.1 y)).trans <| inter_eq_left.2 <| s.Icc_subset x.2 y.2 + (OrderEmbedding.subtype (· ∈ s)).image_Icc (by simpa) x y @[simp] lemma image_subtype_val_Ico {s : Set α} [OrdConnected s] (x y : s) : Subtype.val '' Ico x y = Ico x.1 y := - (Subtype.image_preimage_val s (Ico x.1 y)).trans <| inter_eq_left.2 <| - Ico_subset_Icc_self.trans <| s.Icc_subset x.2 y.2 + (OrderEmbedding.subtype (· ∈ s)).image_Ico (by simpa) x y @[simp] lemma image_subtype_val_Ioc {s : Set α} [OrdConnected s] (x y : s) : Subtype.val '' Ioc x y = Ioc x.1 y := - (Subtype.image_preimage_val s (Ioc x.1 y)).trans <| inter_eq_left.2 <| - Ioc_subset_Icc_self.trans <| s.Icc_subset x.2 y.2 + (OrderEmbedding.subtype (· ∈ s)).image_Ioc (by simpa) x y @[simp] lemma image_subtype_val_Ioo {s : Set α} [OrdConnected s] (x y : s) : Subtype.val '' Ioo x y = Ioo x.1 y := - (Subtype.image_preimage_val s (Ioo x.1 y)).trans <| inter_eq_left.2 <| - Ioo_subset_Icc_self.trans <| s.Icc_subset x.2 y.2 + (OrderEmbedding.subtype (· ∈ s)).image_Ioo (by simpa) x y theorem OrdConnected.inter {s t : Set α} (hs : OrdConnected s) (ht : OrdConnected t) : OrdConnected (s ∩ t) := diff --git a/Mathlib/Data/Set/Intervals/OrderEmbedding.lean b/Mathlib/Data/Set/Intervals/OrderEmbedding.lean new file mode 100644 index 0000000000000..11df3b15c67dd --- /dev/null +++ b/Mathlib/Data/Set/Intervals/OrderEmbedding.lean @@ -0,0 +1,50 @@ +/- +Copyright (c) 2024 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Data.Set.Intervals.UnorderedInterval +import Mathlib.Order.Hom.Basic + +/-! +# Preimages of intervals under order embeddings + +In this file we prove that the preimage of an interval in the codomain under an `OrderEmbedding` +is an interval in the domain. + +Note that similar statements about images require the range to be order-connected. +-/ + +open Set + +namespace OrderEmbedding + +variable {α β : Type*} + +section Preorder + +variable [Preorder α] [Preorder β] (e : α ↪o β) (x y : α) + +@[simp] theorem preimage_Ici : e ⁻¹' Ici (e x) = Ici x := ext fun _ ↦ e.le_iff_le +@[simp] theorem preimage_Iic : e ⁻¹' Iic (e x) = Iic x := ext fun _ ↦ e.le_iff_le +@[simp] theorem preimage_Ioi : e ⁻¹' Ioi (e x) = Ioi x := ext fun _ ↦ e.lt_iff_lt +@[simp] theorem preimage_Iio : e ⁻¹' Iio (e x) = Iio x := ext fun _ ↦ e.lt_iff_lt + +@[simp] theorem preimage_Icc : e ⁻¹' Icc (e x) (e y) = Icc x y := by ext; simp +@[simp] theorem preimage_Ico : e ⁻¹' Ico (e x) (e y) = Ico x y := by ext; simp +@[simp] theorem preimage_Ioc : e ⁻¹' Ioc (e x) (e y) = Ioc x y := by ext; simp +@[simp] theorem preimage_Ioo : e ⁻¹' Ioo (e x) (e y) = Ioo x y := by ext; simp + +end Preorder + +variable [LinearOrder α] + +@[simp] theorem preimage_uIcc [Lattice β] (e : α ↪o β) (x y : α) : + e ⁻¹' (uIcc (e x) (e y)) = uIcc x y := by + cases le_total x y <;> simp [*] + +@[simp] theorem preimage_uIoc [LinearOrder β] (e : α ↪o β) (x y : α) : + e ⁻¹' (uIoc (e x) (e y)) = uIoc x y := by + cases le_or_lt x y <;> simp [*] + +end OrderEmbedding diff --git a/Mathlib/Data/Set/Intervals/ProjIcc.lean b/Mathlib/Data/Set/Intervals/ProjIcc.lean index aac89cb9582cd..45a7ad0252e05 100644 --- a/Mathlib/Data/Set/Intervals/ProjIcc.lean +++ b/Mathlib/Data/Set/Intervals/ProjIcc.lean @@ -63,10 +63,10 @@ theorem coe_projIic (b x : α) : (projIic b x : α) = min b x := rfl theorem coe_projIcc (a b : α) (h : a ≤ b) (x : α) : (projIcc a b h x : α) = max a (min b x) := rfl #align set.coe_proj_Icc Set.coe_projIcc -theorem projIci_of_le (hx : x ≤ a) : projIci a x = ⟨a, le_rfl⟩ := Subtype.ext $ max_eq_left hx +theorem projIci_of_le (hx : x ≤ a) : projIci a x = ⟨a, le_rfl⟩ := Subtype.ext <| max_eq_left hx #align set.proj_Ici_of_le Set.projIci_of_le -theorem projIic_of_le (hx : b ≤ x) : projIic b x = ⟨b, le_rfl⟩ := Subtype.ext $ min_eq_left hx +theorem projIic_of_le (hx : b ≤ x) : projIic b x = ⟨b, le_rfl⟩ := Subtype.ext <| min_eq_left hx #align set.proj_Iic_of_le Set.projIic_of_le theorem projIcc_of_le_left (hx : x ≤ a) : projIcc a b h x = ⟨a, left_mem_Icc.2 h⟩ := by @@ -231,11 +231,11 @@ theorem IccExtend_range (f : Icc a b → β) : range (IccExtend h f) = range f : #align set.Icc_extend_range Set.IccExtend_range theorem IciExtend_of_le (f : Ici a → β) (hx : x ≤ a) : IciExtend f x = f ⟨a, le_rfl⟩ := - congr_arg f $ projIci_of_le hx + congr_arg f <| projIci_of_le hx #align set.Ici_extend_of_le Set.IciExtend_of_le theorem IicExtend_of_le (f : Iic b → β) (hx : b ≤ x) : IicExtend f x = f ⟨b, le_rfl⟩ := - congr_arg f $ projIic_of_le hx + congr_arg f <| projIic_of_le hx #align set.Iic_extend_of_le Set.IicExtend_of_le theorem IccExtend_of_le_left (f : Icc a b → β) (hx : x ≤ a) : @@ -245,7 +245,7 @@ theorem IccExtend_of_le_left (f : Icc a b → β) (hx : x ≤ a) : theorem IccExtend_of_right_le (f : Icc a b → β) (hx : b ≤ x) : IccExtend h f x = f ⟨b, right_mem_Icc.2 h⟩ := - congr_arg f $ projIcc_of_right_le h hx + congr_arg f <| projIcc_of_right_le h hx #align set.Icc_extend_of_right_le Set.IccExtend_of_right_le @[simp] @@ -269,11 +269,11 @@ theorem IccExtend_right (f : Icc a b → β) : IccExtend h f b = f ⟨b, right_m #align set.Icc_extend_right Set.IccExtend_right theorem IciExtend_of_mem (f : Ici a → β) (hx : x ∈ Ici a) : IciExtend f x = f ⟨x, hx⟩ := - congr_arg f $ projIci_of_mem hx + congr_arg f <| projIci_of_mem hx #align set.Ici_extend_of_mem Set.IciExtend_of_mem theorem IicExtend_of_mem (f : Iic b → β) (hx : x ∈ Iic b) : IicExtend f x = f ⟨x, hx⟩ := - congr_arg f $ projIic_of_mem hx + congr_arg f <| projIic_of_mem hx #align set.Iic_extend_of_mem Set.IicExtend_of_mem theorem IccExtend_of_mem (f : Icc a b → β) (hx : x ∈ Icc a b) : IccExtend h f x = f ⟨x, hx⟩ := @@ -282,12 +282,12 @@ theorem IccExtend_of_mem (f : Icc a b → β) (hx : x ∈ Icc a b) : IccExtend h @[simp] theorem IciExtend_coe (f : Ici a → β) (x : Ici a) : IciExtend f x = f x := - congr_arg f $ projIci_coe x + congr_arg f <| projIci_coe x #align set.Ici_extend_coe Set.IciExtend_coe @[simp] theorem IicExtend_coe (f : Iic b → β) (x : Iic b) : IicExtend f x = f x := - congr_arg f $ projIic_coe x + congr_arg f <| projIic_coe x #align set.Iic_extend_coe Set.IicExtend_coe @[simp] diff --git a/Mathlib/Data/Set/Intervals/UnorderedInterval.lean b/Mathlib/Data/Set/Intervals/UnorderedInterval.lean index 4d8710095008e..6551cc2a95a30 100644 --- a/Mathlib/Data/Set/Intervals/UnorderedInterval.lean +++ b/Mathlib/Data/Set/Intervals/UnorderedInterval.lean @@ -221,9 +221,9 @@ theorem Icc_min_max : Icc (min a b) (max a b) = [[a, b]] := rfl #align set.Icc_min_max Set.Icc_min_max -lemma uIcc_of_not_le (h : ¬a ≤ b) : [[a, b]] = Icc b a := uIcc_of_gt $ lt_of_not_ge h +lemma uIcc_of_not_le (h : ¬a ≤ b) : [[a, b]] = Icc b a := uIcc_of_gt <| lt_of_not_ge h #align set.uIcc_of_not_le Set.uIcc_of_not_le -lemma uIcc_of_not_ge (h : ¬b ≤ a) : [[a, b]] = Icc a b := uIcc_of_lt $ lt_of_not_ge h +lemma uIcc_of_not_ge (h : ¬b ≤ a) : [[a, b]] = Icc a b := uIcc_of_lt <| lt_of_not_ge h #align set.uIcc_of_not_ge Set.uIcc_of_not_ge lemma uIcc_eq_union : [[a, b]] = Icc a b ∪ Icc b a := by rw [Icc_union_Icc', max_comm] <;> rfl diff --git a/Mathlib/Data/Set/Intervals/WithBotTop.lean b/Mathlib/Data/Set/Intervals/WithBotTop.lean index dfede85678eee..63eb443079b77 100644 --- a/Mathlib/Data/Set/Intervals/WithBotTop.lean +++ b/Mathlib/Data/Set/Intervals/WithBotTop.lean @@ -3,6 +3,7 @@ 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 -/ +import Mathlib.Data.Set.Image import Mathlib.Data.Set.Intervals.Basic #align_import data.set.intervals.with_bot_top from "leanprover-community/mathlib"@"d012cd09a9b256d870751284dd6a29882b0be105" @@ -27,12 +28,11 @@ theorem preimage_coe_top : (some : α → WithTop α) ⁻¹' {⊤} = (∅ : Set eq_empty_of_subset_empty fun _ => coe_ne_top #align with_top.preimage_coe_top WithTop.preimage_coe_top -variable [PartialOrder α] {a b : α} +variable [Preorder α] {a b : α} theorem range_coe : range (some : α → WithTop α) = Iio ⊤ := by ext x - rw [mem_Iio, lt_top_iff_ne_top, mem_range, ← none_eq_top, Option.ne_none_iff_exists] - rfl + rw [mem_Iio, WithTop.lt_top_iff_ne_top, mem_range, ne_top_iff_exists] #align with_top.range_coe WithTop.range_coe @[simp] @@ -137,7 +137,7 @@ theorem preimage_coe_bot : (some : α → WithBot α) ⁻¹' {⊥} = (∅ : Set @WithTop.preimage_coe_top αᵒᵈ #align with_bot.preimage_coe_bot WithBot.preimage_coe_bot -variable [PartialOrder α] {a b : α} +variable [Preorder α] {a b : α} theorem range_coe : range (some : α → WithBot α) = Ioi ⊥ := @WithTop.range_coe αᵒᵈ _ diff --git a/Mathlib/Data/Set/Lattice.lean b/Mathlib/Data/Set/Lattice.lean index 81b6dc6dab274..aefaa1c698564 100644 --- a/Mathlib/Data/Set/Lattice.lean +++ b/Mathlib/Data/Set/Lattice.lean @@ -247,14 +247,6 @@ instance Set.completeAtomicBooleanAlgebra : CompleteAtomicBooleanAlgebra (Set α sInf_le := fun s t t_in a h => h _ t_in iInf_iSup_eq := by intros; ext; simp [Classical.skolem] } -/-- `kernImage f s` is the set of `y` such that `f ⁻¹ y ⊆ s`. -/ -def kernImage (f : α → β) (s : Set α) : Set β := - { y | ∀ ⦃x⦄, f x = y → x ∈ s } -#align set.kern_image Set.kernImage - -lemma subset_kernImage_iff {f : α → β} : s ⊆ kernImage f t ↔ f ⁻¹' s ⊆ t := - ⟨fun h _ hx ↦ h hx rfl, - fun h _ hx y hy ↦ h (show f y ∈ s from hy.symm ▸ hx)⟩ section GaloisConnection variable {f : α → β} @@ -374,7 +366,7 @@ theorem nonempty_of_union_eq_top_of_nonempty {ι : Type*} (t : Set ι) (s : ι theorem nonempty_of_nonempty_iUnion {s : ι → Set α} (h_Union : (⋃ i, s i).Nonempty) : Nonempty ι := by obtain ⟨x, hx⟩ := h_Union - exact ⟨Classical.choose $ mem_iUnion.mp hx⟩ + exact ⟨Classical.choose <| mem_iUnion.mp hx⟩ theorem nonempty_of_nonempty_iUnion_eq_univ {s : ι → Set α} [Nonempty α] (h_Union : ⋃ i, s i = univ) : Nonempty ι := @@ -592,11 +584,11 @@ lemma iInter_const (s : Set β) : ⋂ _ : ι, s = s := iInf_const #align set.Inter_const Set.iInter_const lemma iUnion_eq_const (hf : ∀ i, f i = s) : ⋃ i, f i = s := - (iUnion_congr hf).trans $ iUnion_const _ + (iUnion_congr hf).trans <| iUnion_const _ #align set.Union_eq_const Set.iUnion_eq_const lemma iInter_eq_const (hf : ∀ i, f i = s) : ⋂ i, f i = s := - (iInter_congr hf).trans $ iInter_const _ + (iInter_congr hf).trans <| iInter_const _ #align set.Inter_eq_const Set.iInter_eq_const end Nonempty @@ -1435,7 +1427,7 @@ alias sUnion_mono := sUnion_subset_sUnion #align set.sUnion_mono Set.sUnion_mono theorem iUnion_subset_iUnion_const {s : Set α} (h : ι → ι₂) : ⋃ _ : ι, s ⊆ ⋃ _ : ι₂, s := - @iSup_const_mono (Set α) ι ι₂ _ s h + iSup_const_mono (α := Set α) h #align set.Union_subset_Union_const Set.iUnion_subset_iUnion_const @[simp] @@ -2079,19 +2071,6 @@ end Image2 section Seq -/-- Given a set `s` of functions `α → β` and `t : Set α`, `seq s t` is the union of `f '' t` over -all `f ∈ s`. -/ -def seq (s : Set (α → β)) (t : Set α) : Set β := image2 (fun f ↦ f) s t -#align set.seq Set.seq - -@[simp] -theorem mem_seq_iff {s : Set (α → β)} {t : Set α} {b : β} : - b ∈ seq s t ↔ ∃ f ∈ s, ∃ a ∈ t, (f : α → β) a = b := - Iff.rfl -#align set.mem_seq_iff Set.mem_seq_iff - -lemma seq_eq_image2 (s : Set (α → β)) (t : Set α) : seq s t = image2 (fun f a ↦ f a) s t := rfl - theorem seq_def {s : Set (α → β)} {t : Set α} : seq s t = ⋃ f ∈ s, f '' t := by rw [seq_eq_image2, iUnion_image_left] #align set.seq_def Set.seq_def @@ -2378,15 +2357,18 @@ theorem iSup_iUnion (s : ι → Set α) (f : α → β) : ⨆ a ∈ ⋃ i, s i, #align supr_Union iSup_iUnion theorem iInf_iUnion (s : ι → Set α) (f : α → β) : ⨅ a ∈ ⋃ i, s i, f a = ⨅ (i) (a ∈ s i), f a := - @iSup_iUnion α βᵒᵈ _ _ s f + iSup_iUnion (β := βᵒᵈ) s f #align infi_Union iInf_iUnion +theorem sSup_iUnion (t : ι → Set β) : sSup (⋃ i, t i) = ⨆ i, sSup (t i) := by + simp_rw [sSup_eq_iSup, iSup_iUnion] + theorem sSup_sUnion (s : Set (Set β)) : sSup (⋃₀ s) = ⨆ t ∈ s, sSup t := by simp only [sUnion_eq_biUnion, sSup_eq_iSup, iSup_iUnion] #align Sup_sUnion sSup_sUnion theorem sInf_sUnion (s : Set (Set β)) : sInf (⋃₀ s) = ⨅ t ∈ s, sInf t := - @sSup_sUnion βᵒᵈ _ _ + sSup_sUnion (β := βᵒᵈ) s #align Inf_sUnion sInf_sUnion lemma iSup_sUnion (S : Set (Set α)) (f : α → β) : diff --git a/Mathlib/Data/Set/List.lean b/Mathlib/Data/Set/List.lean index 8d4e8a8e52161..47405136cb16d 100644 --- a/Mathlib/Data/Set/List.lean +++ b/Mathlib/Data/Set/List.lean @@ -5,7 +5,6 @@ Authors: Yury Kudryashov -/ import Mathlib.Data.Set.Image import Mathlib.Data.List.Basic -import Mathlib.Data.Fin.Basic #align_import data.set.list from "leanprover-community/mathlib"@"2ec920d35348cb2d13ac0e1a2ad9df0fdf1a76b4" diff --git a/Mathlib/Data/Set/MulAntidiagonal.lean b/Mathlib/Data/Set/MulAntidiagonal.lean index 99d6c7ecda33a..c1f6f5409a73c 100644 --- a/Mathlib/Data/Set/MulAntidiagonal.lean +++ b/Mathlib/Data/Set/MulAntidiagonal.lean @@ -115,8 +115,8 @@ theorem eq_of_fst_le_fst_of_snd_le_snd (h₁ : (x : α × α).1 ≤ (y : α × variable {s t} -@[to_additive Set.AddAntidiagonal.finite_of_isPwo] -theorem finite_of_isPwo (hs : s.IsPwo) (ht : t.IsPwo) (a) : (mulAntidiagonal s t a).Finite := by +@[to_additive Set.AddAntidiagonal.finite_of_isPWO] +theorem finite_of_isPWO (hs : s.IsPWO) (ht : t.IsPWO) (a) : (mulAntidiagonal s t a).Finite := by refine' not_infinite.1 fun h => _ have h1 : (mulAntidiagonal s t a).PartiallyWellOrderedOn (Prod.fst ⁻¹'o (· ≤ ·)) := fun f hf => hs (Prod.fst ∘ f) fun n => (mem_mulAntidiagonal.1 (hf n)).1 @@ -127,17 +127,17 @@ theorem finite_of_isPwo (hs : s.IsPwo) (ht : t.IsPwo) (a) : (mulAntidiagonal s t obtain ⟨m, n, mn, h2'⟩ := h2 (fun x => (h.natEmbedding _) (g x)) fun n => (h.natEmbedding _ _).2 refine' mn.ne (g.injective <| (h.natEmbedding _).injective _) exact eq_of_fst_le_fst_of_snd_le_snd _ _ _ (hg _ _ mn.le) h2' -#align set.mul_antidiagonal.finite_of_is_pwo Set.MulAntidiagonal.finite_of_isPwo -#align set.add_antidiagonal.finite_of_is_pwo Set.AddAntidiagonal.finite_of_isPwo +#align set.mul_antidiagonal.finite_of_is_pwo Set.MulAntidiagonal.finite_of_isPWO +#align set.add_antidiagonal.finite_of_is_pwo Set.AddAntidiagonal.finite_of_isPWO end OrderedCancelCommMonoid -@[to_additive Set.AddAntidiagonal.finite_of_isWf] -theorem finite_of_isWf [LinearOrderedCancelCommMonoid α] {s t : Set α} (hs : s.IsWf) (ht : t.IsWf) +@[to_additive Set.AddAntidiagonal.finite_of_isWF] +theorem finite_of_isWF [LinearOrderedCancelCommMonoid α] {s t : Set α} (hs : s.IsWF) (ht : t.IsWF) (a) : (mulAntidiagonal s t a).Finite := - finite_of_isPwo hs.isPwo ht.isPwo a -#align set.mul_antidiagonal.finite_of_is_wf Set.MulAntidiagonal.finite_of_isWf -#align set.add_antidiagonal.finite_of_is_wf Set.AddAntidiagonal.finite_of_isWf + finite_of_isPWO hs.isPWO ht.isPWO a +#align set.mul_antidiagonal.finite_of_is_wf Set.MulAntidiagonal.finite_of_isWF +#align set.add_antidiagonal.finite_of_is_wf Set.AddAntidiagonal.finite_of_isWF end MulAntidiagonal diff --git a/Mathlib/Data/Set/NAry.lean b/Mathlib/Data/Set/NAry.lean index 78db75413ff78..c49b3d693029c 100644 --- a/Mathlib/Data/Set/NAry.lean +++ b/Mathlib/Data/Set/NAry.lean @@ -26,21 +26,6 @@ variable {α α' β β' γ γ' δ δ' ε ε' ζ ζ' ν : Type*} {f f' : α → variable {s s' : Set α} {t t' : Set β} {u u' : Set γ} {v : Set δ} {a a' : α} {b b' : β} {c c' : γ} {d d' : δ} -/-- The image of a binary function `f : α → β → γ` as a function `Set α → Set β → Set γ`. -Mathematically this should be thought of as the image of the corresponding function `α × β → γ`.-/ -def image2 (f : α → β → γ) (s : Set α) (t : Set β) : Set γ := - { c | ∃ a ∈ s, ∃ b ∈ t, f a b = c } -#align set.image2 Set.image2 - -@[simp] -theorem mem_image2 : c ∈ image2 f s t ↔ ∃ a ∈ s, ∃ b ∈ t, f a b = c := - Iff.rfl -#align set.mem_image2 Set.mem_image2 - -theorem mem_image2_of_mem (ha : a ∈ s) (hb : b ∈ t) : f a b ∈ image2 f s t := - ⟨a, ha, b, hb, rfl⟩ -#align set.mem_image2_of_mem Set.mem_image2_of_mem - theorem mem_image2_iff (hf : Injective2 f) : f a b ∈ image2 f s t ↔ a ∈ s ∧ b ∈ t := ⟨by rintro ⟨a', ha', b', hb', h⟩ diff --git a/Mathlib/Data/Set/Opposite.lean b/Mathlib/Data/Set/Opposite.lean index f076979ac34c9..fb026cb4da3ee 100644 --- a/Mathlib/Data/Set/Opposite.lean +++ b/Mathlib/Data/Set/Opposite.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel -/ import Mathlib.Data.Opposite -import Mathlib.Data.Set.Image +import Mathlib.Data.Set.Basic #align_import data.set.opposite from "leanprover-community/mathlib"@"fc2ed6f838ce7c9b7c7171e58d78eaf7b438fb0e" diff --git a/Mathlib/Data/Set/Pairwise/Basic.lean b/Mathlib/Data/Set/Pairwise/Basic.lean index 4a8b83f99d44b..c69caad74ba1a 100644 --- a/Mathlib/Data/Set/Pairwise/Basic.lean +++ b/Mathlib/Data/Set/Pairwise/Basic.lean @@ -209,6 +209,16 @@ theorem pairwise_bot_iff : s.Pairwise (⊥ : α → α → Prop) ↔ (s : Set α alias ⟨Pairwise.subsingleton, _⟩ := pairwise_bot_iff #align set.pairwise.subsingleton Set.Pairwise.subsingleton +/-- See also `Function.injective_iff_pairwise_ne` -/ +lemma injOn_iff_pairwise_ne {s : Set ι} : InjOn f s ↔ s.Pairwise (f · ≠ f ·) := by + simp only [InjOn, Set.Pairwise, not_imp_not] + +alias ⟨InjOn.pairwise_ne, _⟩ := injOn_iff_pairwise_ne + +protected theorem Pairwise.image {s : Set ι} (h : s.Pairwise (r on f)) : (f '' s).Pairwise r := + ball_image_iff.2 fun _x hx ↦ ball_image_iff.2 fun _y hy hne ↦ h hx hy <| ne_of_apply_ne _ hne + +/-- See also `Set.Pairwise.image`. -/ theorem InjOn.pairwise_image {s : Set ι} (h : s.InjOn f) : (f '' s).Pairwise r ↔ s.Pairwise (r on f) := by simp (config := { contextual := true }) [h.eq_iff, Set.Pairwise] diff --git a/Mathlib/Data/Set/Pointwise/Basic.lean b/Mathlib/Data/Set/Pointwise/Basic.lean index a75a47092fb93..f9314e7f82943 100644 --- a/Mathlib/Data/Set/Pointwise/Basic.lean +++ b/Mathlib/Data/Set/Pointwise/Basic.lean @@ -1301,7 +1301,7 @@ theorem image_mul : m '' (s * t) = m '' s * m '' t := @[to_additive] lemma mul_subset_range {s t : Set β} (hs : s ⊆ range m) (ht : t ⊆ range m) : s * t ⊆ range m := by - rintro _ ⟨a, ha, b, hb, rfl⟩; + rintro _ ⟨a, ha, b, hb, rfl⟩ obtain ⟨a, rfl⟩ := hs ha obtain ⟨b, rfl⟩ := ht hb exact ⟨a * b, map_mul _ _ _⟩ @@ -1334,7 +1334,7 @@ theorem image_div : m '' (s / t) = m '' s / m '' t := @[to_additive] lemma div_subset_range {s t : Set β} (hs : s ⊆ range m) (ht : t ⊆ range m) : s / t ⊆ range m := by - rintro _ ⟨a, ha, b, hb, rfl⟩; + rintro _ ⟨a, ha, b, hb, rfl⟩ obtain ⟨a, rfl⟩ := hs ha obtain ⟨b, rfl⟩ := ht hb exact ⟨a / b, map_div _ _ _⟩ diff --git a/Mathlib/Data/Set/Pointwise/SMul.lean b/Mathlib/Data/Set/Pointwise/SMul.lean index 5d80f6acff855..9356644574732 100644 --- a/Mathlib/Data/Set/Pointwise/SMul.lean +++ b/Mathlib/Data/Set/Pointwise/SMul.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Floris van Doorn -/ import Mathlib.Algebra.Module.Basic -import Mathlib.Data.Set.Pairwise.Lattice +import Mathlib.Data.Set.Image import Mathlib.Data.Set.Pointwise.Basic #align_import data.set.pointwise.smul from "leanprover-community/mathlib"@"5e526d18cea33550268dcbbddcb822d5cde40654" @@ -337,7 +337,7 @@ theorem smul_set_eq_empty : a • s = ∅ ↔ s = ∅ := @[to_additive (attr := simp)] theorem smul_set_nonempty : (a • s).Nonempty ↔ s.Nonempty := - nonempty_image_iff + image_nonempty #align set.smul_set_nonempty Set.smul_set_nonempty #align set.vadd_set_nonempty Set.vadd_set_nonempty @@ -951,6 +951,7 @@ theorem smul_set_sdiff : a • (s \ t) = a • s \ a • t := #align set.smul_set_sdiff Set.smul_set_sdiff #align set.vadd_set_sdiff Set.vadd_set_sdiff +open scoped symmDiff in @[to_additive] theorem smul_set_symmDiff : a • s ∆ t = (a • s) ∆ (a • t) := image_symmDiff (MulAction.injective a) _ _ @@ -1072,6 +1073,7 @@ theorem smul_set_sdiff₀ (ha : a ≠ 0) : a • (s \ t) = a • s \ a • t := image_diff (MulAction.injective₀ ha) _ _ #align set.smul_set_sdiff₀ Set.smul_set_sdiff₀ +open scoped symmDiff in theorem smul_set_symmDiff₀ (ha : a ≠ 0) : a • s ∆ t = (a • s) ∆ (a • t) := image_symmDiff (MulAction.injective₀ ha) _ _ #align set.smul_set_symm_diff₀ Set.smul_set_symmDiff₀ diff --git a/Mathlib/Data/Set/Prod.lean b/Mathlib/Data/Set/Prod.lean index 60d433696efe4..69e909d725786 100644 --- a/Mathlib/Data/Set/Prod.lean +++ b/Mathlib/Data/Set/Prod.lean @@ -35,38 +35,6 @@ section Prod variable {α β γ δ : Type*} {s s₁ s₂ : Set α} {t t₁ t₂ : Set β} {a : α} {b : β} -/-- The cartesian product `Set.prod s t` is the set of `(a, b)` such that `a ∈ s` and `b ∈ t`. -/ -def prod (s : Set α) (t : Set β) : Set (α × β) := - { p | p.1 ∈ s ∧ p.2 ∈ t } -#align set.prod Set.prod - -@[default_instance] -instance instSProd : SProd (Set α) (Set β) (Set (α × β)) where - sprod := Set.prod - -theorem prod_eq (s : Set α) (t : Set β) : s ×ˢ t = Prod.fst ⁻¹' s ∩ Prod.snd ⁻¹' t := - rfl -#align set.prod_eq Set.prod_eq - -theorem mem_prod_eq {p : α × β} : (p ∈ s ×ˢ t) = (p.1 ∈ s ∧ p.2 ∈ t) := - rfl -#align set.mem_prod_eq Set.mem_prod_eq - -@[simp, mfld_simps] -theorem mem_prod {p : α × β} : p ∈ s ×ˢ t ↔ p.1 ∈ s ∧ p.2 ∈ t := - Iff.rfl -#align set.mem_prod Set.mem_prod - --- Porting note: Removing `simp` as `simp` can prove it -@[mfld_simps] -theorem prod_mk_mem_set_prod_eq : ((a, b) ∈ s ×ˢ t) = (a ∈ s ∧ b ∈ t) := - rfl -#align set.prod_mk_mem_set_prod_eq Set.prod_mk_mem_set_prod_eq - -theorem mk_mem_prod (ha : a ∈ s) (hb : b ∈ t) : (a, b) ∈ s ×ˢ t := - ⟨ha, hb⟩ -#align set.mk_mem_prod Set.mk_mem_prod - theorem Subsingleton.prod (hs : s.Subsingleton) (ht : t.Subsingleton) : (s ×ˢ t).Subsingleton := fun _x hx _y hy ↦ Prod.ext (hs hx.1 hy.1) (ht hx.2 hy.2) @@ -494,19 +462,6 @@ section Diagonal variable {α : Type*} {s t : Set α} -/-- `diagonal α` is the set of `α × α` consisting of all pairs of the form `(a, a)`. -/ -def diagonal (α : Type*) : Set (α × α) := - { p | p.1 = p.2 } -#align set.diagonal Set.diagonal - -theorem mem_diagonal (x : α) : (x, x) ∈ diagonal α := by simp [diagonal] -#align set.mem_diagonal Set.mem_diagonal - -@[simp] -theorem mem_diagonal_iff {x : α × α} : x ∈ diagonal α ↔ x.1 = x.2 := - Iff.rfl -#align set.mem_diagonal_iff Set.mem_diagonal_iff - lemma diagonal_nonempty [Nonempty α] : (diagonal α).Nonempty := Nonempty.elim ‹_› fun x => ⟨_, mem_diagonal x⟩ #align set.diagonal_nonempty Set.diagonal_nonempty @@ -644,16 +599,6 @@ section OffDiag variable {α : Type*} {s t : Set α} {x : α × α} {a : α} -/-- The off-diagonal of a set `s` is the set of pairs `(a, b)` with `a, b ∈ s` and `a ≠ b`. -/ -def offDiag (s : Set α) : Set (α × α) := - { x | x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2 } -#align set.off_diag Set.offDiag - -@[simp] -theorem mem_offDiag : x ∈ s.offDiag ↔ x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2 := - Iff.rfl -#align set.mem_off_diag Set.mem_offDiag - theorem offDiag_mono : Monotone (offDiag : Set α → Set (α × α)) := fun _ _ h _ => And.imp (@h _) <| And.imp_left <| @h _ #align set.off_diag_mono Set.offDiag_mono @@ -745,22 +690,6 @@ section Pi variable {ι : Type*} {α β : ι → Type*} {s s₁ s₂ : Set ι} {t t₁ t₂ : ∀ i, Set (α i)} {i : ι} -/-- Given an index set `ι` and a family of sets `t : Π i, Set (α i)`, `pi s t` -is the set of dependent functions `f : Πa, π a` such that `f a` belongs to `t a` -whenever `a ∈ s`. -/ -def pi (s : Set ι) (t : ∀ i, Set (α i)) : Set (∀ i, α i) := - { f | ∀ i ∈ s, f i ∈ t i } -#align set.pi Set.pi - -@[simp] -theorem mem_pi {f : ∀ i, α i} : f ∈ s.pi t ↔ ∀ i ∈ s, f i ∈ t i := - Iff.rfl -#align set.mem_pi Set.mem_pi - --- Porting note: Removing `simp` as `simp` can prove it -theorem mem_univ_pi {f : ∀ i, α i} : f ∈ pi univ t ↔ ∀ i, f i ∈ t i := by simp -#align set.mem_univ_pi Set.mem_univ_pi - @[simp] theorem empty_pi (s : ∀ i, Set (α i)) : pi ∅ s = univ := by ext @@ -946,7 +875,7 @@ theorem pi_update_of_mem [DecidableEq ι] (hi : i ∈ s) (f : ∀ j, α j) (a : by rw [union_pi, singleton_pi', update_same, pi_update_of_not_mem]; simp #align set.pi_update_of_mem Set.pi_update_of_mem -theorem univ_pi_update [DecidableEq ι] {β : ∀ _, Type*} (i : ι) (f : ∀ j, α j) (a : α i) +theorem univ_pi_update [DecidableEq ι] {β : ι → Type*} (i : ι) (f : ∀ j, α j) (a : α i) (t : ∀ j, α j → Set (β j)) : (pi univ fun j => t j (update f i a j)) = { x | x i ∈ t i a } ∩ pi {i}ᶜ fun j => t j (f j) := by rw [compl_eq_univ_diff, ← pi_update_of_mem (mem_univ _)] diff --git a/Mathlib/Data/Set/Semiring.lean b/Mathlib/Data/Set/Semiring.lean index 323b1b8449b07..2676fa1745394 100644 --- a/Mathlib/Data/Set/Semiring.lean +++ b/Mathlib/Data/Set/Semiring.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ import Mathlib.Algebra.Order.Kleene -import Mathlib.Data.Set.Pointwise.SMul +import Mathlib.Data.Set.Pointwise.Basic #align_import data.set.semiring from "leanprover-community/mathlib"@"62e8311c791f02c47451bf14aa2501048e7c2f33" diff --git a/Mathlib/Data/Set/Sups.lean b/Mathlib/Data/Set/Sups.lean index 327574a2989bd..d12c008c6b587 100644 --- a/Mathlib/Data/Set/Sups.lean +++ b/Mathlib/Data/Set/Sups.lean @@ -170,7 +170,7 @@ theorem sups_inter_subset_right : s ⊻ (t₁ ∩ t₂) ⊆ s ⊻ t₁ ∩ s ⊻ #align set.sups_inter_subset_right Set.sups_inter_subset_right lemma image_sups (f : F) (s t : Set α) : f '' (s ⊻ t) = f '' s ⊻ f '' t := - image_image2_distrib $ map_sup f + image_image2_distrib <| map_sup f lemma subset_sups_self : s ⊆ s ⊻ s := λ _a ha ↦ mem_sups.2 ⟨_, ha, _, ha, sup_idem⟩ lemma sups_subset_self : s ⊻ s ⊆ s ↔ SupClosed s := sups_subset_iff @@ -337,7 +337,7 @@ theorem infs_inter_subset_right : s ⊼ (t₁ ∩ t₂) ⊆ s ⊼ t₁ ∩ s ⊼ #align set.infs_inter_subset_right Set.infs_inter_subset_right lemma image_infs (f : F) (s t : Set α) : f '' (s ⊼ t) = f '' s ⊼ f '' t := - image_image2_distrib $ map_inf f + image_image2_distrib <| map_inf f lemma subset_infs_self : s ⊆ s ⊼ s := λ _a ha ↦ mem_infs.2 ⟨_, ha, _, ha, inf_idem⟩ lemma infs_self_subset : s ⊼ s ⊆ s ↔ InfClosed s := infs_subset_iff diff --git a/Mathlib/Data/SetLike/Basic.lean b/Mathlib/Data/SetLike/Basic.lean index 5370a3d11c39a..e040497d25099 100644 --- a/Mathlib/Data/SetLike/Basic.lean +++ b/Mathlib/Data/SetLike/Basic.lean @@ -62,7 +62,7 @@ end MySubobject An alternative to `SetLike` could have been an extensional `Membership` typeclass: ``` -class ExtMembership (α : out_param $ Type u) (β : Type v) extends Membership α β := +class ExtMembership (α : out_param <| Type u) (β : Type v) extends Membership α β := (ext_iff : ∀ {s t : β}, s = t ↔ ∀ (x : α), x ∈ s ↔ x ∈ t) ``` While this is equivalent, `SetLike` conveniently uses a carrier set projection directly. diff --git a/Mathlib/Data/Sigma/Lex.lean b/Mathlib/Data/Sigma/Lex.lean index 92bf4ac304216..0b08167394da2 100644 --- a/Mathlib/Data/Sigma/Lex.lean +++ b/Mathlib/Data/Sigma/Lex.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Data.Sigma.Basic import Mathlib.Order.RelClasses #align_import data.sigma.lex from "leanprover-community/mathlib"@"41cf0cc2f528dd40a8f2db167ea4fb37b8fde7f3" @@ -85,7 +84,7 @@ theorem lex_swap : Lex (Function.swap r) s a b ↔ Lex r (fun i => Function.swap #align sigma.lex_swap Sigma.lex_swap instance [∀ i, IsRefl (α i) (s i)] : IsRefl _ (Lex r s) := - ⟨fun ⟨_, _⟩ => Lex.right _ _ $ refl _⟩ + ⟨fun ⟨_, _⟩ => Lex.right _ _ <| refl _⟩ instance [IsIrrefl ι r] [∀ i, IsIrrefl (α i) (s i)] : IsIrrefl _ (Lex r s) := ⟨by @@ -117,7 +116,7 @@ instance [IsAsymm ι r] [∀ i, IsAntisymm (α i) (s i)] : IsAntisymm _ (Lex r s · exact (asymm hij hji).elim · exact (irrefl _ hij).elim · exact (irrefl _ hji).elim - · exact ext rfl (heq_of_eq $ antisymm hab hba)⟩ + · exact ext rfl (heq_of_eq <| antisymm hab hba)⟩ instance [IsTrichotomous ι r] [∀ i, IsTotal (α i) (s i)] : IsTotal _ (Lex r s) := ⟨by @@ -137,8 +136,8 @@ instance [IsTrichotomous ι r] [∀ i, IsTrichotomous (α i) (s i)] : IsTrichoto · obtain hab | rfl | hba := trichotomous_of (s i) a b · exact Or.inl (Lex.right _ _ hab) · exact Or.inr (Or.inl rfl) - · exact Or.inr (Or.inr $ Lex.right _ _ hba) - · exact Or.inr (Or.inr $ Lex.left _ _ hji)⟩ + · exact Or.inr (Or.inr <| Lex.right _ _ hba) + · exact Or.inr (Or.inr <| Lex.left _ _ hji)⟩ end Sigma diff --git a/Mathlib/Data/Sigma/Order.lean b/Mathlib/Data/Sigma/Order.lean index 7dbc7ab139220..c43a27f73c081 100644 --- a/Mathlib/Data/Sigma/Order.lean +++ b/Mathlib/Data/Sigma/Order.lean @@ -6,6 +6,7 @@ Authors: Yaël Dillies import Mathlib.Data.Sigma.Lex import Mathlib.Order.BoundedOrder import Mathlib.Mathport.Notation +import Mathlib.Data.Sigma.Basic #align_import data.sigma.order from "leanprover-community/mathlib"@"1fc36cc9c8264e6e81253f88be7fb2cb6c92d76a" diff --git a/Mathlib/Data/Sign.lean b/Mathlib/Data/Sign.lean index 34aff1961e3ce..79be25a2d7539 100644 --- a/Mathlib/Data/Sign.lean +++ b/Mathlib/Data/Sign.lean @@ -5,7 +5,6 @@ Authors: Eric Rodriguez -/ import Mathlib.Algebra.BigOperators.Order import Mathlib.Data.Fintype.BigOperators -import Mathlib.Data.Int.Lemmas #align_import data.sign from "leanprover-community/mathlib"@"2445c98ae4b87eabebdde552593519b9b6dc350c" /-! diff --git a/Mathlib/Data/String/Lemmas.lean b/Mathlib/Data/String/Lemmas.lean index 0d7675265df56..64304b7006aad 100644 --- a/Mathlib/Data/String/Lemmas.lean +++ b/Mathlib/Data/String/Lemmas.lean @@ -3,8 +3,9 @@ Copyright (c) 2021 Chris Bailey. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Bailey -/ -import Mathlib.Data.List.Basic +import Mathlib.Init.Data.Nat.Notation import Mathlib.Data.String.Defs +import Mathlib.Tactic.Basic namespace String diff --git a/Mathlib/Data/Subtype.lean b/Mathlib/Data/Subtype.lean index 797709ad8335b..11157b4d8b18e 100644 --- a/Mathlib/Data/Subtype.lean +++ b/Mathlib/Data/Subtype.lean @@ -73,7 +73,7 @@ theorem ext_iff {a1 a2 : { x // p x }} : a1 = a2 ↔ (a1 : α) = (a2 : α) := theorem heq_iff_coe_eq (h : ∀ x, p x ↔ q x) {a1 : { x // p x }} {a2 : { x // q x }} : HEq a1 a2 ↔ (a1 : α) = (a2 : α) := Eq.rec (motive := λ (pp: (α → Prop)) _ => ∀ a2' : {x // pp x}, HEq a1 a2' ↔ (a1 : α) = (a2' : α)) - (λ _ => heq_iff_eq.trans ext_iff) (funext $ λ x => propext (h x)) a2 + (λ _ => heq_iff_eq.trans ext_iff) (funext <| λ x => propext (h x)) a2 #align subtype.heq_iff_coe_eq Subtype.heq_iff_coe_eq lemma heq_iff_coe_heq {α β : Sort _} {p : α → Prop} {q : β → Prop} {a : {x // p x}} diff --git a/Mathlib/Data/Sum/Interval.lean b/Mathlib/Data/Sum/Interval.lean index a1186898ec78f..36a7d123ec087 100644 --- a/Mathlib/Data/Sum/Interval.lean +++ b/Mathlib/Data/Sum/Interval.lean @@ -147,7 +147,7 @@ lemma mem_sumLexLift : (∃ a₁ b₂ c₂, a = inl a₁ ∧ b = inr b₂ ∧ c = inr c₂ ∧ c₂ ∈ g₂ a₁ b₂) ∨ ∃ a₂ b₂ c₂, a = inr a₂ ∧ b = inr b₂ ∧ c = inr c₂ ∧ c₂ ∈ f₂ a₂ b₂ := by constructor - · obtain a | a := a <;> obtain b | b := b + · obtain a | a := a <;> obtain b | b := b · rw [sumLexLift, mem_map] rintro ⟨c, hc, rfl⟩ exact Or.inl ⟨a, b, c, rfl, rfl, rfl, hc⟩ @@ -155,11 +155,11 @@ lemma mem_sumLexLift : · rintro ⟨c, hc, rfl⟩ exact Or.inr (Or.inl ⟨a, b, c, rfl, rfl, rfl, hc⟩) · rintro ⟨c, hc, rfl⟩ - exact Or.inr (Or.inr $ Or.inl ⟨a, b, c, rfl, rfl, rfl, hc⟩) + exact Or.inr (Or.inr <| Or.inl ⟨a, b, c, rfl, rfl, rfl, hc⟩) · exact fun h ↦ (not_mem_empty _ h).elim · rw [sumLexLift, mem_map] rintro ⟨c, hc, rfl⟩ - exact Or.inr (Or.inr $ Or.inr $ ⟨a, b, c, rfl, rfl, rfl, hc⟩) + exact Or.inr (Or.inr <| Or.inr <| ⟨a, b, c, rfl, rfl, rfl, hc⟩) · rintro (⟨a, b, c, rfl, rfl, rfl, hc⟩ | ⟨a, b, c, rfl, rfl, rfl, hc⟩ | ⟨a, b, c, rfl, rfl, rfl, hc⟩ | ⟨a, b, c, rfl, rfl, rfl, hc⟩) · exact mem_map_of_mem _ hc diff --git a/Mathlib/Data/Sum/Lattice.lean b/Mathlib/Data/Sum/Lattice.lean index 316e8b67f10a4..dfe6a3a4db472 100644 --- a/Mathlib/Data/Sum/Lattice.lean +++ b/Mathlib/Data/Sum/Lattice.lean @@ -40,11 +40,11 @@ instance instSemilatticeSup : SemilatticeSup (α ⊕ₗ β) where | inrₗ b₁, inlₗ a₂ => inl_le_inr _ _ | inrₗ b₁, inrₗ b₂ => inr_le_inr_iff.2 le_sup_right sup_le x y z hxz hyz := match x, y, z, hxz, hyz with - | inlₗ a₁, inlₗ a₂, inlₗ a₃, Lex.inl h₁₃, Lex.inl h₂₃ => inl_le_inl_iff.2 $ sup_le h₁₃ h₂₃ + | inlₗ a₁, inlₗ a₂, inlₗ a₃, Lex.inl h₁₃, Lex.inl h₂₃ => inl_le_inl_iff.2 <| sup_le h₁₃ h₂₃ | inlₗ a₁, inlₗ a₂, inrₗ b₃, Lex.sep _ _, Lex.sep _ _ => Lex.sep _ _ | inlₗ a₁, inrₗ b₂, inrₗ b₃, Lex.sep _ _, Lex.inr h₂₃ => inr_le_inr_iff.2 h₂₃ | inrₗ b₁, inlₗ a₂, inrₗ b₃, Lex.inr h₁₃, Lex.sep _ _ => inr_le_inr_iff.2 h₁₃ - | inrₗ b₁, inrₗ b₂, inrₗ b₃, Lex.inr h₁₃, Lex.inr h₂₃ => inr_le_inr_iff.2 $ sup_le h₁₃ h₂₃ + | inrₗ b₁, inrₗ b₂, inrₗ b₃, Lex.inr h₁₃, Lex.inr h₂₃ => inr_le_inr_iff.2 <| sup_le h₁₃ h₂₃ @[simp] lemma inl_sup (a₁ a₂ : α) : (inlₗ (a₁ ⊔ a₂) : α ⊕ β) = inlₗ a₁ ⊔ inlₗ a₂ := rfl @[simp] lemma inr_sup (b₁ b₂ : β) : (inrₗ (b₁ ⊔ b₂) : α ⊕ β) = inrₗ b₁ ⊔ inrₗ b₂ := rfl @@ -73,11 +73,11 @@ instance instSemilatticeInf : SemilatticeInf (α ⊕ₗ β) where | inrₗ b₁, inlₗ a₂ => le_rfl | inrₗ b₁, inrₗ b₂ => inr_le_inr_iff.2 inf_le_right le_inf x y z hzx hzy := match x, y, z, hzx, hzy with - | inlₗ a₁, inlₗ a₂, inlₗ a₃, Lex.inl h₁₃, Lex.inl h₂₃ => inl_le_inl_iff.2 $ le_inf h₁₃ h₂₃ + | inlₗ a₁, inlₗ a₂, inlₗ a₃, Lex.inl h₁₃, Lex.inl h₂₃ => inl_le_inl_iff.2 <| le_inf h₁₃ h₂₃ | inlₗ a₁, inlₗ a₂, inrₗ b₃, Lex.inl h₁₃, Lex.sep _ _ => inl_le_inl_iff.2 h₁₃ | inlₗ a₁, inrₗ b₂, inlₗ a₃, Lex.sep _ _, Lex.inl h₂₃ => inl_le_inl_iff.2 h₂₃ | inlₗ a₁, inrₗ b₂, inrₗ b₃, Lex.sep _ _, Lex.sep _ _ => Lex.sep _ _ - | inrₗ b₁, inrₗ b₂, inrₗ b₃, Lex.inr h₁₃, Lex.inr h₂₃ => inr_le_inr_iff.2 $ le_inf h₁₃ h₂₃ + | inrₗ b₁, inrₗ b₂, inrₗ b₃, Lex.inr h₁₃, Lex.inr h₂₃ => inr_le_inr_iff.2 <| le_inf h₁₃ h₂₃ @[simp] lemma inl_inf (a₁ a₂ : α) : (inlₗ (a₁ ⊓ a₂) : α ⊕ β) = inlₗ a₁ ⊓ inlₗ a₂ := rfl @[simp] lemma inr_inf (b₁ b₂ : β) : (inrₗ (b₁ ⊓ b₂) : α ⊕ β) = inrₗ b₁ ⊓ inrₗ b₂ := rfl diff --git a/Mathlib/Data/Sym/Card.lean b/Mathlib/Data/Sym/Card.lean index 14f61935dc771..456d582a27580 100644 --- a/Mathlib/Data/Sym/Card.lean +++ b/Mathlib/Data/Sym/Card.lean @@ -6,6 +6,7 @@ Authors: Yaël Dillies, Bhavik Mehta, Huỳnh Trần Khanh, Stuart Presnell import Mathlib.Algebra.BigOperators.Basic import Mathlib.Data.Finset.Sym import Mathlib.Data.Fintype.Sum +import Mathlib.Data.Fintype.Prod #align_import data.sym.card from "leanprover-community/mathlib"@"0bd2ea37bcba5769e14866170f251c9bc64e35d7" @@ -103,7 +104,7 @@ theorem card_sym_fin_eq_multichoose : ∀ n k : ℕ, card (Sym (Fin n) k) = mult refine Fintype.card_congr (Equiv.symm ?_) apply (Sym.e1.symm.sumCongr Sym.e2.symm).trans apply Equiv.sumCompl - termination_by card_sym_fin_eq_multichoose n k => n + k + termination_by n k => n + k #align sym.card_sym_fin_eq_multichoose Sym.card_sym_fin_eq_multichoose /-- For any fintype `α` of cardinality `n`, `card (Sym α k) = multichoose (card α) k`. -/ diff --git a/Mathlib/Data/TwoPointing.lean b/Mathlib/Data/TwoPointing.lean index a0009fedc13f4..b6dc8ddc7bc7d 100644 --- a/Mathlib/Data/TwoPointing.lean +++ b/Mathlib/Data/TwoPointing.lean @@ -3,8 +3,8 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Data.Sum.Basic import Mathlib.Logic.Nontrivial.Defs +import Mathlib.Logic.Nonempty #align_import data.two_pointing from "leanprover-community/mathlib"@"fc2ed6f838ce7c9b7c7171e58d78eaf7b438fb0e" diff --git a/Mathlib/Data/UInt.lean b/Mathlib/Data/UInt.lean index bc17670d8751f..4d3f820b63c4c 100644 --- a/Mathlib/Data/UInt.lean +++ b/Mathlib/Data/UInt.lean @@ -125,8 +125,8 @@ def isAlphanum (c : UInt8) : Bool := theorem toChar_aux (n : Nat) (h : n < size) : Nat.isValidChar (UInt32.ofNat n).1 := by rw [UInt32.val_eq_of_lt] - exact Or.inl $ Nat.lt_trans h $ by decide - exact Nat.lt_trans h $ by decide + exact Or.inl <| Nat.lt_trans h <| by decide + exact Nat.lt_trans h <| by decide /-- The numbers from 0 to 256 are all valid UTF-8 characters, so we can embed one in the other. -/ def toChar (n : UInt8) : Char := ⟨n.toUInt32, toChar_aux n.1 n.1.2⟩ diff --git a/Mathlib/Data/ULift.lean b/Mathlib/Data/ULift.lean index edab755a00fbf..55ee3490322e2 100644 --- a/Mathlib/Data/ULift.lean +++ b/Mathlib/Data/ULift.lean @@ -75,13 +75,13 @@ theorem «exists» {p : PLift α → Prop} : (∃ x, p x) ↔ ∃ x : α, p (PLi #align plift.exists PLift.exists @[simp] lemma map_injective : Injective (PLift.map f) ↔ Injective f := - (Injective.of_comp_iff' _ down_bijective).trans $ up_injective.of_comp_iff _ + (Injective.of_comp_iff' _ down_bijective).trans <| up_injective.of_comp_iff _ @[simp] lemma map_surjective : Surjective (PLift.map f) ↔ Surjective f := - (down_surjective.of_comp_iff _).trans $ Surjective.of_comp_iff' up_bijective _ + (down_surjective.of_comp_iff _).trans <| Surjective.of_comp_iff' up_bijective _ @[simp] lemma map_bijective : Bijective (PLift.map f) ↔ Bijective f := - (down_bijective.of_comp_iff _).trans $ Bijective.of_comp_iff' up_bijective _ + (down_bijective.of_comp_iff _).trans <| Bijective.of_comp_iff' up_bijective _ end PLift @@ -140,14 +140,14 @@ theorem «exists» {p : ULift α → Prop} : (∃ x, p x) ↔ ∃ x : α, p (ULi #align ulift.exists ULift.exists @[simp] lemma map_injective : Injective (ULift.map f : ULift.{u'} α → ULift.{v'} β) ↔ Injective f := - (Injective.of_comp_iff' _ down_bijective).trans $ up_injective.of_comp_iff _ + (Injective.of_comp_iff' _ down_bijective).trans <| up_injective.of_comp_iff _ @[simp] lemma map_surjective : Surjective (ULift.map f : ULift.{u'} α → ULift.{v'} β) ↔ Surjective f := - (down_surjective.of_comp_iff _).trans $ Surjective.of_comp_iff' up_bijective _ + (down_surjective.of_comp_iff _).trans <| Surjective.of_comp_iff' up_bijective _ @[simp] lemma map_bijective : Bijective (ULift.map f : ULift.{u'} α → ULift.{v'} β) ↔ Bijective f := - (down_bijective.of_comp_iff _).trans $ Bijective.of_comp_iff' up_bijective _ + (down_bijective.of_comp_iff _).trans <| Bijective.of_comp_iff' up_bijective _ @[ext] theorem ext (x y : ULift α) (h : x.down = y.down) : x = y := diff --git a/Mathlib/Data/UnionFind.lean b/Mathlib/Data/UnionFind.lean index a598cc0794698..b12a769d01177 100644 --- a/Mathlib/Data/UnionFind.lean +++ b/Mathlib/Data/UnionFind.lean @@ -3,9 +3,8 @@ Copyright (c) 2021 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Tactic.Basic -import Std.Tactic.Simpa -import Mathlib.Data.Array.Basic +import Mathlib.Init.Data.Nat.Lemmas +import Mathlib.Init.Order.LinearOrder set_option autoImplicit true @@ -149,7 +148,7 @@ theorem setParent {arr : Array (UFNode α)} {n} {m : UFModel n} (hm : m.Models a ⟨hm.1.set (fun k (h : (k:ℕ) ≠ i) ↦ by simp [UFModel.setParent, h.symm]) (fun _ ↦ by simp [UFModel.setParent, hp]), - hm.2.set (fun _ _ ↦ rfl) (fun _ ↦ hrk.trans $ hm.2.get_eq ..)⟩ + hm.2.set (fun _ _ ↦ rfl) (fun _ ↦ hrk.trans <| hm.2.get_eq ..)⟩ end UFModel.Models @@ -189,7 +188,7 @@ def rankMax (self : UnionFind α) := (rankMaxAux self self.size).1 + 1 theorem lt_rankMax' (self : UnionFind α) (i : Fin self.size) : (self.arr.get i).rank < self.rankMax := - Nat.lt_succ.2 $ (rankMaxAux self self.size).2 _ i.2 _ + Nat.lt_succ.2 <| (rankMaxAux self self.size).2 _ i.2 _ theorem lt_rankMax (self : UnionFind α) (i : Nat) : self.rank i < self.rankMax := by simp [rank]; split; {apply lt_rankMax'}; apply Nat.succ_pos @@ -241,7 +240,7 @@ def findAux (self : UnionFind α) (x : Fin self.size) : ⟨root.2, ?_⟩, le_of_lt this⟩ have : x.1 ≠ root := mt (congrArg _) (ne_of_lt this); dsimp only at this simp [UFModel.setParent, this, hr] -termination_by _ α self x => self.rankMax - self.rank x +termination_by self.rankMax - self.rank x def find (self : UnionFind α) (x : Fin self.size) : (s : UnionFind α) × (root : Fin s.size) ×' diff --git a/Mathlib/Data/Vector.lean b/Mathlib/Data/Vector.lean index 8d63a0cb71f4d..e3c75fc0833a6 100644 --- a/Mathlib/Data/Vector.lean +++ b/Mathlib/Data/Vector.lean @@ -9,7 +9,6 @@ import Std.Data.List.Lemmas import Mathlib.Init.Data.List.Basic import Mathlib.Init.Data.List.Lemmas import Mathlib.Data.Nat.Order.Basic -import Mathlib.Algebra.Order.Monoid.OrderDual #align_import data.vector from "leanprover-community/lean"@"855e5b74e3a52a40552e8f067169d747d48743fd" diff --git a/Mathlib/Data/Vector/Snoc.lean b/Mathlib/Data/Vector/Snoc.lean index e619a76d802ba..4d403a83db863 100644 --- a/Mathlib/Data/Vector/Snoc.lean +++ b/Mathlib/Data/Vector/Snoc.lean @@ -49,8 +49,7 @@ theorem reverse_snoc : reverse (xs.snoc x) = x ::ᵥ (reverse xs) := by cases xs simp only [reverse, snoc, cons, toList_mk] congr - simp [toList, (·++·), Vector.append, Append.append] - rfl + simp [toList, Vector.append, Append.append] theorem replicate_succ_to_snoc (val : α) : replicate (n+1) val = (replicate n val).snoc val := by diff --git a/Mathlib/Data/Vector3.lean b/Mathlib/Data/Vector3.lean index c7b1c0fbb2f1f..2142d24e114fa 100644 --- a/Mathlib/Data/Vector3.lean +++ b/Mathlib/Data/Vector3.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.Fin.Fin2 -import Mathlib.Init.Align +import Mathlib.Init.Logic import Mathlib.Mathport.Notation +import Mathlib.Tactic.TypeStar #align_import data.vector3 from "leanprover-community/mathlib"@"3d7987cda72abc473c7cdbbb075170e9ac620042" diff --git a/Mathlib/Data/ZMod/Algebra.lean b/Mathlib/Data/ZMod/Algebra.lean index bf54b768b20c9..ff3c05c6c2d91 100644 --- a/Mathlib/Data/ZMod/Algebra.lean +++ b/Mathlib/Data/ZMod/Algebra.lean @@ -34,8 +34,7 @@ def algebra' (h : m ∣ n) : Algebra (ZMod n) R := show (a * r : R) = r * a by rcases ZMod.int_cast_surjective a with ⟨k, rfl⟩ show ZMod.castHom h R k * r = r * ZMod.castHom h R k - rw [map_intCast] - exact Commute.cast_int_left r k + rw [map_intCast, Int.cast_comm] smul_def' := fun a r => rfl } #align zmod.algebra' ZMod.algebra' diff --git a/Mathlib/Data/ZMod/Basic.lean b/Mathlib/Data/ZMod/Basic.lean index 0f5fa03ee8070..6e32452d2f1f6 100644 --- a/Mathlib/Data/ZMod/Basic.lean +++ b/Mathlib/Data/ZMod/Basic.lean @@ -320,9 +320,9 @@ theorem cast_mul (h : m ∣ n) (a b : ZMod n) : ((a * b : ZMod n) : R) = a * b : exact h.trans (Nat.dvd_sub_mod _) #align zmod.cast_mul ZMod.cast_mul -/-- The canonical ring homomorphism from `ZMod n` to a ring of characteristic `n`. +/-- The canonical ring homomorphism from `ZMod n` to a ring of characteristic dividing `n`. -See also `ZMod.lift` (in `Data.ZMod.Quotient`) for a generalized version working in `AddGroup`s. +See also `ZMod.lift` for a generalized version working in `AddGroup`s. -/ def castHom (h : m ∣ n) (R : Type*) [Ring R] [CharP R m] : ZMod n →+* R where toFun := (↑) @@ -819,7 +819,7 @@ def chineseRemainder {m n : ℕ} (h : m.Coprime n) : ZMod (m * n) ≃+* ZMod m haveI : NeZero n := ⟨right_ne_zero_of_mul hmn0⟩ have left_inv : Function.LeftInverse inv_fun to_fun := by intro x - dsimp only [dvd_mul_left, dvd_mul_right, ZMod.castHom_apply] + dsimp only [ZMod.castHom_apply] conv_rhs => rw [← ZMod.nat_cast_zmod_val x] rw [if_neg hmn0, ZMod.eq_iff_modEq_nat, ← Nat.modEq_and_modEq_iff_modEq_mul h, Prod.fst_zmod_cast, Prod.snd_zmod_cast] @@ -1161,7 +1161,7 @@ theorem natAbs_min_of_le_div_two (n : ℕ) (x y : ℤ) (he : (x : ZMod n) = y) ( rw [← add_le_add_iff_right x.natAbs] refine' le_trans (le_trans ((add_le_add_iff_left _).2 hl) _) (Int.natAbs_sub_le _ _) rw [add_sub_cancel, Int.natAbs_mul, Int.natAbs_ofNat] - refine' le_trans _ (Nat.le_mul_of_pos_right <| Int.natAbs_pos.2 hm) + refine' le_trans _ (Nat.le_mul_of_pos_right _ <| Int.natAbs_pos.2 hm) rw [← mul_two]; apply Nat.div_mul_le_self #align zmod.nat_abs_min_of_le_div_two ZMod.natAbs_min_of_le_div_two diff --git a/Mathlib/Data/ZMod/Defs.lean b/Mathlib/Data/ZMod/Defs.lean index 426ee3f15d3f2..20caf4bb821e6 100644 --- a/Mathlib/Data/ZMod/Defs.lean +++ b/Mathlib/Data/ZMod/Defs.lean @@ -5,7 +5,7 @@ Authors: Eric Rodriguez -/ import Mathlib.Algebra.NeZero import Mathlib.Data.Nat.ModEq -import Mathlib.Data.Fintype.Lattice +import Mathlib.Data.Fintype.Card #align_import data.zmod.defs from "leanprover-community/mathlib"@"3a2b5524a138b5d0b818b858b516d4ac8a484b03" diff --git a/Mathlib/Data/ZMod/IntUnitsPower.lean b/Mathlib/Data/ZMod/IntUnitsPower.lean index 0e39556b0dedf..3ff0f55e78dc7 100644 --- a/Mathlib/Data/ZMod/IntUnitsPower.lean +++ b/Mathlib/Data/ZMod/IntUnitsPower.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.CharP.Two import Mathlib.Algebra.GroupPower.Ring import Mathlib.Data.Int.Order.Units import Mathlib.Data.ZMod.Basic diff --git a/Mathlib/Data/ZMod/Quotient.lean b/Mathlib/Data/ZMod/Quotient.lean index d7122d20761d5..8a53edb36018f 100644 --- a/Mathlib/Data/ZMod/Quotient.lean +++ b/Mathlib/Data/ZMod/Quotient.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ import Mathlib.Algebra.Group.Equiv.TypeTags +import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.Data.ZMod.Basic import Mathlib.GroupTheory.GroupAction.Quotient import Mathlib.RingTheory.Ideal.QuotientOperations diff --git a/Mathlib/Deprecated/Submonoid.lean b/Mathlib/Deprecated/Submonoid.lean index e1fa90237a3b4..53a39a5a428c1 100644 --- a/Mathlib/Deprecated/Submonoid.lean +++ b/Mathlib/Deprecated/Submonoid.lean @@ -59,7 +59,7 @@ structure IsSubmonoid (s : Set M) : Prop where #align is_submonoid IsSubmonoid theorem Additive.isAddSubmonoid {s : Set M} : - ∀ _ : IsSubmonoid s, @IsAddSubmonoid (Additive M) _ s + IsSubmonoid s → @IsAddSubmonoid (Additive M) _ s | ⟨h₁, h₂⟩ => ⟨h₁, @h₂⟩ #align additive.is_add_submonoid Additive.isAddSubmonoid @@ -69,7 +69,7 @@ theorem Additive.isAddSubmonoid_iff {s : Set M} : #align additive.is_add_submonoid_iff Additive.isAddSubmonoid_iff theorem Multiplicative.isSubmonoid {s : Set A} : - ∀ _ : IsAddSubmonoid s, @IsSubmonoid (Multiplicative A) _ s + IsAddSubmonoid s → @IsSubmonoid (Multiplicative A) _ s | ⟨h₁, h₂⟩ => ⟨h₁, @h₂⟩ #align multiplicative.is_submonoid Multiplicative.isSubmonoid diff --git a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean index e9169f0f59ed5..f4e51b04f73fd 100644 --- a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean +++ b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean @@ -164,15 +164,15 @@ theorem map_add_one : ∀ x, f (x + 1) = f x + 1 := theorem map_one_add (x : ℝ) : f (1 + x) = 1 + f x := by rw [add_comm, map_add_one, add_comm 1] #align circle_deg1_lift.map_one_add CircleDeg1Lift.map_one_add -#noalign circle_deg1_lift.coe_inj -- Use `FunLike.coe_inj` +#noalign circle_deg1_lift.coe_inj -- Use `DFunLike.coe_inj` @[ext] theorem ext ⦃f g : CircleDeg1Lift⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align circle_deg1_lift.ext CircleDeg1Lift.ext theorem ext_iff {f g : CircleDeg1Lift} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align circle_deg1_lift.ext_iff CircleDeg1Lift.ext_iff instance : Monoid CircleDeg1Lift where @@ -182,7 +182,7 @@ instance : Monoid CircleDeg1Lift where one := ⟨.id, fun _ => rfl⟩ mul_one f := rfl one_mul f := rfl - mul_assoc f₁ f₂ f₃ := FunLike.coe_injective rfl + mul_assoc f₁ f₂ f₃ := DFunLike.coe_injective rfl instance : Inhabited CircleDeg1Lift := ⟨1⟩ diff --git a/Mathlib/Dynamics/Ergodic/Ergodic.lean b/Mathlib/Dynamics/Ergodic/Ergodic.lean index 3707a8e93c524..78936a9bd380b 100644 --- a/Mathlib/Dynamics/Ergodic/Ergodic.lean +++ b/Mathlib/Dynamics/Ergodic/Ergodic.lean @@ -101,9 +101,9 @@ theorem preErgodic_conjugate_iff {e : α ≃ᵐ β} (h : MeasurePreserving e μ refine' ⟨fun hf => preErgodic_of_preErgodic_conjugate (h.symm e) hf _, fun hf => preErgodic_of_preErgodic_conjugate h hf _⟩ · change (e.symm ∘ e) ∘ f ∘ e.symm = f ∘ e.symm - rw [MeasurableEquiv.symm_comp_self, comp.left_id] + rw [MeasurableEquiv.symm_comp_self, id_comp] · change e ∘ f = e ∘ f ∘ e.symm ∘ e - rw [MeasurableEquiv.symm_comp_self, comp.right_id] + rw [MeasurableEquiv.symm_comp_self, comp_id] #align measure_theory.measure_preserving.pre_ergodic_conjugate_iff MeasureTheory.MeasurePreserving.preErgodic_conjugate_iff theorem ergodic_conjugate_iff {e : α ≃ᵐ β} (h : MeasurePreserving e μ μ') : diff --git a/Mathlib/Dynamics/Ergodic/MeasurePreserving.lean b/Mathlib/Dynamics/Ergodic/MeasurePreserving.lean index 0067365ee87f1..f0edd36dd8900 100644 --- a/Mathlib/Dynamics/Ergodic/MeasurePreserving.lean +++ b/Mathlib/Dynamics/Ergodic/MeasurePreserving.lean @@ -149,13 +149,14 @@ protected theorem iterate {f : α → α} (hf : MeasurePreserving f μa μa) : variable {μ : Measure α} {f : α → α} {s : Set α} +open scoped symmDiff in lemma measure_symmDiff_preimage_iterate_le (hf : MeasurePreserving f μ μ) (hs : MeasurableSet s) (n : ℕ) : μ (s ∆ (f^[n] ⁻¹' s)) ≤ n • μ (s ∆ (f ⁻¹' s)) := by induction' n with n ih; simp simp only [add_smul, one_smul, ← n.add_one] refine' le_trans (measure_symmDiff_le s (f^[n] ⁻¹' s) (f^[n+1] ⁻¹' s)) (add_le_add ih _) - replace hs : MeasurableSet (s ∆ (f ⁻¹' s)) := hs.symmDiff $ hf.measurable hs + replace hs : MeasurableSet (s ∆ (f ⁻¹' s)) := hs.symmDiff <| hf.measurable hs rw [iterate_succ', preimage_comp, ← preimage_symmDiff, (hf.iterate n).measure_preimage hs] /-- If `μ univ < n * μ s` and `f` is a map preserving measure `μ`, diff --git a/Mathlib/Dynamics/PeriodicPts.lean b/Mathlib/Dynamics/PeriodicPts.lean index 169b40878b7b4..f372cbf5b4241 100644 --- a/Mathlib/Dynamics/PeriodicPts.lean +++ b/Mathlib/Dynamics/PeriodicPts.lean @@ -353,7 +353,7 @@ theorem le_of_lt_minimalPeriod_of_iterate_eq {m n : ℕ} (hm : m < minimalPeriod hm #align function.le_of_lt_minimal_period_of_iterate_eq Function.le_of_lt_minimalPeriod_of_iterate_eq -theorem iterate_injOn_Iio_minimalPeriod : (Iio $ minimalPeriod f x).InjOn (f^[·] x) := +theorem iterate_injOn_Iio_minimalPeriod : (Iio <| minimalPeriod f x).InjOn (f^[·] x) := fun _m hm _n hn hmn ↦ (le_of_lt_minimalPeriod_of_iterate_eq hm hmn).antisymm (le_of_lt_minimalPeriod_of_iterate_eq hn hmn.symm) #align function.eq_of_lt_minimal_period_of_iterate_eq Function.iterate_injOn_Iio_minimalPeriod diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/Adjoin.lean index ada78d06a3dfd..20a17cbc9bce5 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/Adjoin.lean @@ -315,6 +315,24 @@ theorem _root_.AlgEquiv.fieldRange_eq_top (f : E ≃ₐ[F] K) : end Lattice +section equivMap + +variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] + {K : Type*} [Field K] [Algebra F K] (L : IntermediateField F E) (f : E →ₐ[F] K) + +theorem fieldRange_comp_val : (f.comp L.val).fieldRange = L.map f := toSubalgebra_injective <| by + rw [toSubalgebra_map, AlgHom.fieldRange_toSubalgebra, AlgHom.range_comp, range_val] + +/-- An intermediate field is isomorphic to its image under an `AlgHom` +(which is automatically injective) -/ +noncomputable def equivMap : L ≃ₐ[F] L.map f := + (AlgEquiv.ofInjective _ (f.comp L.val).injective).trans (equivOfEq (fieldRange_comp_val L f)) + +@[simp] +theorem coe_equivMap_apply (x : L) : ↑(equivMap L f x) = f x := rfl + +end equivMap + section AdjoinDef variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] (S : Set E) @@ -466,6 +484,31 @@ theorem restrictScalars_adjoin (K : IntermediateField F E) (S : Set E) : restrictScalars F (adjoin K S) = adjoin F (K ∪ S) := by rw [← adjoin_self _ K, adjoin_adjoin_left, adjoin_self _ K] +variable {F} in +theorem extendScalars_adjoin {K : IntermediateField F E} {S : Set E} (h : K ≤ adjoin F S) : + extendScalars h = adjoin K S := restrictScalars_injective F <| by + rw [extendScalars_restrictScalars, restrictScalars_adjoin] + exact le_antisymm (adjoin.mono F S _ <| Set.subset_union_right _ S) <| adjoin_le_iff.2 <| + Set.union_subset h (subset_adjoin F S) + +variable {F} in +/-- If `E / L / F` and `E / L' / F` are two field extension towers, `L ≃ₐ[F] L'` is an isomorphism +compatible with `E / L` and `E / L'`, then for any subset `S` of `E`, `L(S)` and `L'(S)` are +equal as intermediate fields of `E / F`. -/ +theorem restrictScalars_adjoin_of_algEquiv + {L L' : Type*} [Field L] [Field L'] + [Algebra F L] [Algebra L E] [Algebra F L'] [Algebra L' E] + [IsScalarTower F L E] [IsScalarTower F L' E] (i : L ≃ₐ[F] L') + (hi : algebraMap L E = (algebraMap L' E) ∘ i) (S : Set E) : + (adjoin L S).restrictScalars F = (adjoin L' S).restrictScalars F := by + apply_fun toSubfield using (fun K K' h ↦ by + ext x; change x ∈ K.toSubfield ↔ x ∈ K'.toSubfield; rw [h]) + change Subfield.closure _ = Subfield.closure _ + congr + ext x + exact ⟨fun ⟨y, h⟩ ↦ ⟨i y, by rw [← h, hi]; rfl⟩, + fun ⟨y, h⟩ ↦ ⟨i.symm y, by rw [← h, hi, Function.comp_apply, AlgEquiv.apply_symm_apply]⟩⟩ + theorem algebra_adjoin_le_adjoin : Algebra.adjoin F S ≤ (adjoin F S).toSubalgebra := Algebra.adjoin_le (subset_adjoin _ _) #align intermediate_field.algebra_adjoin_le_adjoin IntermediateField.algebra_adjoin_le_adjoin @@ -558,6 +601,9 @@ def AdjoinSimple.gen : F⟮α⟯ := #align intermediate_field.adjoin_simple.gen IntermediateField.AdjoinSimple.gen @[simp] +theorem AdjoinSimple.coe_gen : (AdjoinSimple.gen F α : E) = α := + rfl + theorem AdjoinSimple.algebraMap_gen : algebraMap F⟮α⟯ E (AdjoinSimple.gen F α) = α := rfl #align intermediate_field.adjoin_simple.algebra_map_gen IntermediateField.AdjoinSimple.algebraMap_gen @@ -627,37 +673,47 @@ theorem le_sup_toSubalgebra : E1.toSubalgebra ⊔ E2.toSubalgebra ≤ (E1 ⊔ E2 sup_le (show E1 ≤ E1 ⊔ E2 from le_sup_left) (show E2 ≤ E1 ⊔ E2 from le_sup_right) #align intermediate_field.le_sup_to_subalgebra IntermediateField.le_sup_toSubalgebra -theorem sup_toSubalgebra [h1 : FiniteDimensional K E1] [h2 : FiniteDimensional K E2] : +theorem sup_toSubalgebra_of_isAlgebraic_right (halg : Algebra.IsAlgebraic K E2) : (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := by - let S1 := E1.toSubalgebra - let S2 := E2.toSubalgebra - refine' - le_antisymm - (show _ ≤ (S1 ⊔ S2).toIntermediateField _ from - sup_le (show S1 ≤ _ from le_sup_left) (show S2 ≤ _ from le_sup_right)) - (le_sup_toSubalgebra E1 E2) - suffices IsField (S1 ⊔ S2 : Subalgebra K L) by - intro x hx - by_cases hx' : (⟨x, hx⟩ : (S1 ⊔ S2 : Subalgebra K L)) = 0 - · rw [← Subtype.coe_mk x, hx', Subalgebra.coe_zero, inv_zero] - exact (S1 ⊔ S2).zero_mem - · obtain ⟨y, h⟩ := this.mul_inv_cancel hx' - exact (congr_arg (· ∈ S1 ⊔ S2) <| eq_inv_of_mul_eq_one_right <| Subtype.ext_iff.mp h).mp y.2 - exact - isField_of_isIntegral_of_isField' - (Algebra.isIntegral_sup.mpr - ⟨Algebra.IsIntegral.of_finite K E1, Algebra.IsIntegral.of_finite K E2⟩) - (Field.toIsField K) -#align intermediate_field.sup_to_subalgebra IntermediateField.sup_toSubalgebra - -instance finiteDimensional_sup [h1 : FiniteDimensional K E1] [h2 : FiniteDimensional K E2] : + have : (adjoin E1 (E2 : Set L)).toSubalgebra = _ := adjoin_algebraic_toSubalgebra fun x h ↦ + IsAlgebraic.tower_top E1 (isAlgebraic_iff.1 (halg ⟨x, h⟩)) + apply_fun Subalgebra.restrictScalars K at this + erw [← restrictScalars_toSubalgebra, restrictScalars_adjoin, + Algebra.restrictScalars_adjoin] at this + exact this + +theorem sup_toSubalgebra_of_isAlgebraic_left (halg : Algebra.IsAlgebraic K E1) : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := by + have := sup_toSubalgebra_of_isAlgebraic_right E2 E1 halg + rwa [sup_comm (a := E1), sup_comm (a := E1.toSubalgebra)] + +/-- The compositum of two intermediate fields is equal to the compositum of them +as subalgebras, if one of them is algebraic over the base field. -/ +theorem sup_toSubalgebra_of_isAlgebraic + (halg : Algebra.IsAlgebraic K E1 ∨ Algebra.IsAlgebraic K E2) : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := + halg.elim (sup_toSubalgebra_of_isAlgebraic_left E1 E2) + (sup_toSubalgebra_of_isAlgebraic_right E1 E2) + +theorem sup_toSubalgebra_of_left [FiniteDimensional K E1] : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := + sup_toSubalgebra_of_isAlgebraic_left E1 E2 (Algebra.IsAlgebraic.of_finite K _) +#align intermediate_field.sup_to_subalgebra IntermediateField.sup_toSubalgebra_of_left + +@[deprecated] alias sup_toSubalgebra := sup_toSubalgebra_of_left + +theorem sup_toSubalgebra_of_right [FiniteDimensional K E2] : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := + sup_toSubalgebra_of_isAlgebraic_right E1 E2 (Algebra.IsAlgebraic.of_finite K _) + +instance finiteDimensional_sup [FiniteDimensional K E1] [FiniteDimensional K E2] : FiniteDimensional K (E1 ⊔ E2 : IntermediateField K L) := by let g := Algebra.TensorProduct.productMap E1.val E2.val suffices g.range = (E1 ⊔ E2).toSubalgebra by have h : FiniteDimensional K (Subalgebra.toSubmodule g.range) := g.toLinearMap.finiteDimensional_range rwa [this] at h - rw [Algebra.TensorProduct.productMap_range, E1.range_val, E2.range_val, sup_toSubalgebra] + rw [Algebra.TensorProduct.productMap_range, E1.range_val, E2.range_val, sup_toSubalgebra_of_left] #align intermediate_field.finite_dimensional_sup IntermediateField.finiteDimensional_sup variable {ι : Type*} {t : ι → IntermediateField K L} @@ -728,6 +784,61 @@ theorem isSplittingField_iSup {p : ι → K[X]} end Supremum +section Tower + +variable (E) + +variable {K : Type*} [Field K] [Algebra F K] [Algebra E K] [IsScalarTower F E K] + +/-- If `K / E / F` is a field extension tower, `L` is an intermediate field of `K / F`, such that +either `E / F` or `L / F` is algebraic, then `E(L) = E[L]`. -/ +theorem adjoin_toSubalgebra_of_isAlgebraic (L : IntermediateField F K) + (halg : Algebra.IsAlgebraic F E ∨ Algebra.IsAlgebraic F L) : + (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := by + let i := IsScalarTower.toAlgHom F E K + let E' := i.fieldRange + let i' : E ≃ₐ[F] E' := AlgEquiv.ofInjectiveField i + have hi : algebraMap E K = (algebraMap E' K) ∘ i' := by ext x; rfl + apply_fun _ using Subalgebra.restrictScalars_injective F + erw [← restrictScalars_toSubalgebra, restrictScalars_adjoin_of_algEquiv i' hi, + Algebra.restrictScalars_adjoin_of_algEquiv i' hi, restrictScalars_adjoin, + Algebra.restrictScalars_adjoin] + exact E'.sup_toSubalgebra_of_isAlgebraic L (halg.imp i'.isAlgebraic id) + +theorem adjoin_toSubalgebra_of_isAlgebraic_left (L : IntermediateField F K) + (halg : Algebra.IsAlgebraic F E) : + (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := + adjoin_toSubalgebra_of_isAlgebraic E L (Or.inl halg) + +theorem adjoin_toSubalgebra_of_isAlgebraic_right (L : IntermediateField F K) + (halg : Algebra.IsAlgebraic F L) : + (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := + adjoin_toSubalgebra_of_isAlgebraic E L (Or.inr halg) + +/-- If `K / E / F` is a field extension tower, `L` is an intermediate field of `K / F`, such that +either `E / F` or `L / F` is algebraic, then `[E(L) : E] ≤ [L : F]`. A corollary of +`Subalgebra.adjoin_rank_le` since in this case `E(L) = E[L]`. -/ +theorem adjoin_rank_le_of_isAlgebraic (L : IntermediateField F K) + (halg : Algebra.IsAlgebraic F E ∨ Algebra.IsAlgebraic F L) : + Module.rank E (adjoin E (L : Set K)) ≤ Module.rank F L := by + have h : (adjoin E (L.toSubalgebra : Set K)).toSubalgebra = + Algebra.adjoin E (L.toSubalgebra : Set K) := + L.adjoin_toSubalgebra_of_isAlgebraic E halg + have := L.toSubalgebra.adjoin_rank_le E + rwa [(Subalgebra.equivOfEq _ _ h).symm.toLinearEquiv.rank_eq] at this + +theorem adjoin_rank_le_of_isAlgebraic_left (L : IntermediateField F K) + (halg : Algebra.IsAlgebraic F E) : + Module.rank E (adjoin E (L : Set K)) ≤ Module.rank F L := + adjoin_rank_le_of_isAlgebraic E L (Or.inl halg) + +theorem adjoin_rank_le_of_isAlgebraic_right (L : IntermediateField F K) + (halg : Algebra.IsAlgebraic F L) : + Module.rank E (adjoin E (L : Set K)) ≤ Module.rank F L := + adjoin_rank_le_of_isAlgebraic E L (Or.inr halg) + +end Tower + open Set CompleteLattice /- Porting note: this was tagged `simp`, but the LHS can be simplified now that the notation @@ -796,6 +907,15 @@ theorem exists_finset_of_mem_supr'' {ι : Type*} {f : ι → IntermediateField F exact minpoly.ne_zero (isIntegral_iff.mp (h i ⟨x1, hx1⟩).isIntegral) #align intermediate_field.exists_finset_of_mem_supr'' IntermediateField.exists_finset_of_mem_supr'' +theorem exists_finset_of_mem_adjoin {S : Set E} {x : E} (hx : x ∈ adjoin F S) : + ∃ T : Finset E, (T : Set E) ⊆ S ∧ x ∈ adjoin F (T : Set E) := by + simp_rw [← biSup_adjoin_simple S, ← iSup_subtype''] at hx + obtain ⟨s, hx'⟩ := exists_finset_of_mem_iSup hx + refine ⟨s.image Subtype.val, by simp, SetLike.le_def.mp ?_ hx'⟩ + simp_rw [Finset.coe_image, iSup_le_iff, adjoin_le_iff] + rintro _ h _ rfl + exact subset_adjoin F _ ⟨_, h, rfl⟩ + end AdjoinSimple end AdjoinDef @@ -866,6 +986,12 @@ theorem finrank_bot : finrank F (⊥ : IntermediateField F E) = 1 := by rw [finr @[simp] protected theorem finrank_top : finrank (⊤ : IntermediateField F E) E = 1 := rank_eq_one_iff_finrank_eq_one.mp IntermediateField.rank_top +@[simp] theorem rank_top' : Module.rank F (⊤ : IntermediateField F E) = Module.rank F E := + rank_top F E + +@[simp] theorem finrank_top' : finrank F (⊤ : IntermediateField F E) = finrank F E := + finrank_top F E + theorem rank_adjoin_eq_one_iff : Module.rank F (adjoin F S) = 1 ↔ S ⊆ (⊥ : IntermediateField F E) := Iff.trans rank_eq_one_iff adjoin_eq_bot_iff #align intermediate_field.rank_adjoin_eq_one_iff IntermediateField.rank_adjoin_eq_one_iff @@ -926,9 +1052,11 @@ end AdjoinIntermediateFieldLattice section AdjoinIntegralElement +universe u + variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] {α : E} -variable {K : Type*} [Field K] [Algebra F K] +variable {K : Type u} [Field K] [Algebra F K] theorem minpoly_gen (α : E) : minpoly F (AdjoinSimple.gen F α) = minpoly F α := by @@ -974,6 +1102,9 @@ theorem adjoinRootEquivAdjoin_apply_root (h : IsIntegral F α) : AdjoinRoot.lift_root (aeval_gen_minpoly F α) #align intermediate_field.adjoin_root_equiv_adjoin_apply_root IntermediateField.adjoinRootEquivAdjoin_apply_root +theorem adjoin_root_eq_top (p : K[X]) [Fact (Irreducible p)] : K⟮AdjoinRoot.root p⟯ = ⊤ := + (eq_adjoin_of_eq_algebra_adjoin K _ ⊤ (AdjoinRoot.adjoinRoot_eq_top (f := p)).symm).symm + section PowerBasis variable {L : Type*} [Field L] [Algebra K L] @@ -1133,6 +1264,56 @@ theorem card_algHom_adjoin_integral (h : IsIntegral F α) (h_sep : (minpoly F α simp only [adjoin.powerBasis_dim, adjoin.powerBasis_gen, minpoly_gen, h_sep, h_splits] #align intermediate_field.card_alg_hom_adjoin_integral IntermediateField.card_algHom_adjoin_integral +open FiniteDimensional AdjoinRoot in +/-- Let `f, g` be monic polynomials over `K`. If `f` is irreducible, and `g(x) - α` is irreducible +in `K⟮α⟯` with `α` a root of `f`, then `f(g(x))` is irreducible. -/ +theorem _root_.Polynomial.irreducible_comp {f g : K[X]} (hfm : f.Monic) (hgm : g.Monic) + (hf : Irreducible f) + (hg : ∀ (E : Type u) [Field E] [Algebra K E] (x : E) (hx : minpoly K x = f), + Irreducible (g.map (algebraMap _ _) - C (AdjoinSimple.gen K x))) : + Irreducible (f.comp g) := by + have hf' : natDegree f ≠ 0 := + fun e ↦ not_irreducible_C (f.coeff 0) (eq_C_of_natDegree_eq_zero e ▸ hf) + have hg' : natDegree g ≠ 0 + · have := Fact.mk hf + intro e + apply not_irreducible_C ((g.map (algebraMap _ _)).coeff 0 - AdjoinSimple.gen K (root f)) + rw [map_sub, coeff_map, ← map_C, ← eq_C_of_natDegree_eq_zero e] + apply hg (AdjoinRoot f) + rw [AdjoinRoot.minpoly_root hf.ne_zero, hfm, inv_one, map_one, mul_one] + have H₁ : f.comp g ≠ 0 := fun h ↦ by simpa [hf', hg', natDegree_comp] using congr_arg natDegree h + have H₂ : ¬ IsUnit (f.comp g) := fun h ↦ + by simpa [hf', hg', natDegree_comp] using natDegree_eq_zero_of_isUnit h + have ⟨p, hp₁, hp₂⟩ := WfDvdMonoid.exists_irreducible_factor H₂ H₁ + suffices natDegree p = natDegree f * natDegree g from (associated_of_dvd_of_natDegree_le hp₂ H₁ + (this.trans natDegree_comp.symm).ge).irreducible hp₁ + have := Fact.mk hp₁ + let Kx := AdjoinRoot p + letI := (AdjoinRoot.powerBasis hp₁.ne_zero).finiteDimensional + have key₁ : f = minpoly K (aeval (root p) g) + · refine minpoly.eq_of_irreducible_of_monic hf ?_ hfm + rw [← aeval_comp] + exact aeval_eq_zero_of_dvd_aeval_eq_zero hp₂ (AdjoinRoot.eval₂_root p) + have key₁' : finrank K K⟮aeval (root p) g⟯ = natDegree f + · rw [adjoin.finrank, ← key₁] + exact IsIntegral.of_finite _ _ + have key₂ : g.map (algebraMap _ _) - C (AdjoinSimple.gen K (aeval (root p) g)) = + minpoly K⟮aeval (root p) g⟯ (root p) + · exact minpoly.eq_of_irreducible_of_monic (hg _ _ key₁.symm) (by simp [AdjoinSimple.gen]) + (Monic.sub_of_left (hgm.map _) (degree_lt_degree (by simpa [Nat.pos_iff_ne_zero] using hg'))) + have key₂' : finrank K⟮aeval (root p) g⟯ Kx = natDegree g + · trans natDegree (minpoly K⟮aeval (root p) g⟯ (root p)) + · have : K⟮aeval (root p) g⟯⟮root p⟯ = ⊤ + · apply restrictScalars_injective K + rw [restrictScalars_top, adjoin_adjoin_left, Set.union_comm, ← adjoin_adjoin_left, + adjoin_root_eq_top p, restrictScalars_adjoin] + simp + rw [← finrank_top', ← this, adjoin.finrank] + exact IsIntegral.of_finite _ _ + · simp [← key₂] + have := FiniteDimensional.finrank_mul_finrank K K⟮aeval (root p) g⟯ Kx + rwa [key₁', key₂', (AdjoinRoot.powerBasis hp₁.ne_zero).finrank, powerBasis_dim, eq_comm] at this + end AdjoinIntegralElement section Induction @@ -1192,165 +1373,12 @@ theorem induction_on_adjoin [FiniteDimensional F E] (P : IntermediateField F E end Induction -section AlgHomMkAdjoinSplits - -variable (F E K : Type*) [Field F] [Field E] [Field K] [Algebra F E] [Algebra F K] {S : Set E} - -/-- Lifts `L → K` of `F → K` -/ -structure Lifts where - /-- The domain of a lift. -/ - carrier : IntermediateField F E - /-- The lifted RingHom, expressed as an AlgHom. -/ - emb : carrier →ₐ[F] K -#align intermediate_field.lifts IntermediateField.Lifts - -variable {F E K} - -instance : PartialOrder (Lifts F E K) where - le L₁ L₂ := ∃ h : L₁.carrier ≤ L₂.carrier, ∀ x, L₂.emb (inclusion h x) = L₁.emb x - le_refl L := ⟨le_rfl, by simp⟩ - le_trans L₁ L₂ L₃ := by - rintro ⟨h₁₂, h₁₂'⟩ ⟨h₂₃, h₂₃'⟩ - refine ⟨h₁₂.trans h₂₃, fun _ ↦ ?_⟩ - rw [← inclusion_inclusion h₁₂ h₂₃, h₂₃', h₁₂'] - le_antisymm := by - rintro ⟨L₁, e₁⟩ ⟨L₂, e₂⟩ ⟨h₁₂, h₁₂'⟩ ⟨h₂₁, h₂₁'⟩ - obtain rfl : L₁ = L₂ := h₁₂.antisymm h₂₁ - congr - exact AlgHom.ext h₂₁' - -noncomputable instance : OrderBot (Lifts F E K) where - bot := ⟨⊥, (Algebra.ofId F K).comp (botEquiv F E)⟩ - bot_le L := ⟨bot_le, fun x ↦ by - obtain ⟨x, rfl⟩ := (botEquiv F E).symm.surjective x - simp_rw [AlgHom.comp_apply, AlgHom.coe_coe, AlgEquiv.apply_symm_apply] - exact L.emb.commutes x⟩ - -noncomputable instance : Inhabited (Lifts F E K) := - ⟨⊥⟩ - -/-- A chain of lifts has an upper bound. -/ -theorem Lifts.exists_upper_bound (c : Set (Lifts F E K)) (hc : IsChain (· ≤ ·) c) : - ∃ ub, ∀ a ∈ c, a ≤ ub := by - let t (i : ↑(insert ⊥ c)) := i.val.carrier - let t' (i) := (t i).toSubalgebra - have hc := hc.insert fun _ _ _ ↦ .inl bot_le - have dir : Directed (· ≤ ·) t := hc.directedOn.directed_val.mono_comp _ fun _ _ h ↦ h.1 - refine ⟨⟨iSup t, (Subalgebra.iSupLift t' dir (fun i ↦ i.val.emb) (fun i j h ↦ ?_) _ rfl).comp - (Subalgebra.equivOfEq _ _ <| toSubalgebra_iSup_of_directed dir)⟩, - fun L hL ↦ have hL := Set.mem_insert_of_mem ⊥ hL; ⟨le_iSup t ⟨L, hL⟩, fun x ↦ ?_⟩⟩ - · refine AlgHom.ext fun x ↦ (hc.total i.2 j.2).elim (fun hij ↦ (hij.snd x).symm) fun hji ↦ ?_ - erw [AlgHom.comp_apply, ← hji.snd (Subalgebra.inclusion h x), - inclusion_inclusion, inclusion_self, AlgHom.id_apply x] - · dsimp only [AlgHom.comp_apply] - exact Subalgebra.iSupLift_inclusion (K := t') (i := ⟨L, hL⟩) x (le_iSup t' ⟨L, hL⟩) -#align intermediate_field.lifts.exists_upper_bound IntermediateField.Lifts.exists_upper_bound - -/-- Given an element `s : E` whose conjugates are all in `K`, any lift can be extended to one - whose carrier contains `s`. -/ -theorem Lifts.exists_lift_of_splits (x : Lifts F E K) {s : E} (h1 : IsIntegral F s) - (h2 : (minpoly F s).Splits (algebraMap F K)) : ∃ y, x ≤ y ∧ s ∈ y.carrier := - have I1 : IsIntegral x.carrier s := h1.tower_top - have I2 := (minpoly.degree_pos I1).ne' - have key : (minpoly x.carrier s).Splits x.emb.toRingHom := - splits_of_splits_of_dvd _ (map_ne_zero (minpoly.ne_zero h1)) - ((splits_map_iff _ _).2 (x.emb.comp_algebraMap ▸ h2)) (minpoly.dvd_map_of_isScalarTower _ _ _) - letI : Algebra x.carrier K := x.emb.toRingHom.toAlgebra - let carrier := x.carrier⟮s⟯.restrictScalars F - letI : Algebra x.carrier carrier := x.carrier⟮s⟯.toSubalgebra.algebra - let φ : carrier →ₐ[x.carrier] K := ((algHomAdjoinIntegralEquiv x.carrier I1).symm - ⟨rootOfSplits x.emb.toRingHom key I2, by - rw [mem_aroots, and_iff_right (minpoly.ne_zero I1)] - exact map_rootOfSplits x.emb.toRingHom key I2⟩) - ⟨⟨carrier, (@algHomEquivSigma F x.carrier carrier K _ _ _ _ _ _ _ _ - (IsScalarTower.of_algebraMap_eq fun _ ↦ rfl)).symm ⟨x.emb, φ⟩⟩, - ⟨fun z hz ↦ algebraMap_mem x.carrier⟮s⟯ ⟨z, hz⟩, φ.commutes⟩, - mem_adjoin_simple_self x.carrier s⟩ -#align intermediate_field.lifts.exists_lift_of_splits IntermediateField.Lifts.exists_lift_of_splits - -variable (hK : ∀ s ∈ S, IsIntegral F s ∧ (minpoly F s).Splits (algebraMap F K)) - (hK' : ∀ s : E, IsIntegral F s ∧ (minpoly F s).Splits (algebraMap F K)) - {L : IntermediateField F E} (f : L →ₐ[F] K) (hL : L ≤ adjoin F S) - --- The following uses the hypothesis `hK`. - -theorem exists_algHom_adjoin_of_splits : ∃ φ : adjoin F S →ₐ[F] K, φ.comp (inclusion hL) = f := by - obtain ⟨φ, hfφ, hφ⟩ := zorn_nonempty_Ici₀ _ - (fun c _ hc _ _ ↦ Lifts.exists_upper_bound c hc) ⟨L, f⟩ le_rfl - refine ⟨φ.emb.comp (inclusion <| adjoin_le_iff.mpr fun s hs ↦ ?_), ?_⟩ - · rcases φ.exists_lift_of_splits (hK s hs).1 (hK s hs).2 with ⟨y, h1, h2⟩ - exact (hφ y h1).1 h2 - · ext; apply hfφ.2 - -theorem nonempty_algHom_adjoin_of_splits : Nonempty (adjoin F S →ₐ[F] K) := - have ⟨φ, _⟩ := exists_algHom_adjoin_of_splits hK (⊥ : Lifts F E K).emb bot_le; ⟨φ⟩ -#align intermediate_field.alg_hom_mk_adjoin_splits IntermediateField.nonempty_algHom_adjoin_of_splits - -variable (hS : adjoin F S = ⊤) - -theorem exists_algHom_of_adjoin_splits : ∃ φ : E →ₐ[F] K, φ.comp L.val = f := - have ⟨φ, hφ⟩ := exists_algHom_adjoin_of_splits hK f (hS.symm ▸ le_top) - ⟨φ.comp ((equivOfEq hS).trans topEquiv).symm.toAlgHom, hφ⟩ - -theorem nonempty_algHom_of_adjoin_splits : Nonempty (E →ₐ[F] K) := - have ⟨φ, _⟩ := exists_algHom_of_adjoin_splits hK (⊥ : Lifts F E K).emb hS; ⟨φ⟩ -#align intermediate_field.alg_hom_mk_adjoin_splits' IntermediateField.nonempty_algHom_of_adjoin_splits - -variable {x : E} (hx : x ∈ adjoin F S) {y : K} (hy : aeval y (minpoly F x) = 0) - -theorem exists_algHom_adjoin_of_splits_of_aeval : ∃ φ : adjoin F S →ₐ[F] K, φ ⟨x, hx⟩ = y := by - have ix := isAlgebraic_adjoin (fun s hs ↦ (hK s hs).1) ⟨x, hx⟩ - rw [isAlgebraic_iff_isIntegral, isIntegral_iff] at ix - obtain ⟨φ, hφ⟩ := exists_algHom_adjoin_of_splits hK ((algHomAdjoinIntegralEquiv F ix).symm - ⟨y, mem_aroots.mpr ⟨minpoly.ne_zero ix, hy⟩⟩) (adjoin_simple_le_iff.mpr hx) - exact ⟨φ, (FunLike.congr_fun hφ <| AdjoinSimple.gen F x).trans <| - algHomAdjoinIntegralEquiv_symm_apply_gen F ix _⟩ - -theorem exists_algHom_of_adjoin_splits_of_aeval : ∃ φ : E →ₐ[F] K, φ x = y := - have ⟨φ, hφ⟩ := exists_algHom_adjoin_of_splits_of_aeval hK (hS ▸ mem_top) hy - ⟨φ.comp ((equivOfEq hS).trans topEquiv).symm.toAlgHom, hφ⟩ - -/- The following uses the hypothesis - (hK' : ∀ s : E, IsIntegral F s ∧ (minpoly F s).Splits (algebraMap F K)) -/ - -theorem exists_algHom_of_splits : ∃ φ : E →ₐ[F] K, φ.comp L.val = f := - exists_algHom_of_adjoin_splits (fun x _ ↦ hK' x) f (adjoin_univ F E) - -theorem nonempty_algHom_of_splits : Nonempty (E →ₐ[F] K) := - nonempty_algHom_of_adjoin_splits (fun x _ ↦ hK' x) (adjoin_univ F E) - -theorem exists_algHom_of_splits_of_aeval : ∃ φ : E →ₐ[F] K, φ x = y := - exists_algHom_of_adjoin_splits_of_aeval (fun x _ ↦ hK' x) (adjoin_univ F E) hy - -end AlgHomMkAdjoinSplits - end IntermediateField -section Algebra.IsAlgebraic - -/-- Let `K/F` be an algebraic extension of fields and `L` a field in which all the minimal -polynomial over `F` of elements of `K` splits. Then, for `x ∈ K`, the images of `x` by the -`F`-algebra morphisms from `K` to `L` are exactly the roots in `L` of the minimal polynomial -of `x` over `F`. -/ -theorem Algebra.IsAlgebraic.range_eval_eq_rootSet_minpoly_of_splits {F K : Type*} (L : Type*) - [Field F] [Field K] [Field L] [Algebra F L] [Algebra F K] - (hA : ∀ x : K, (minpoly F x).Splits (algebraMap F L)) - (hK : Algebra.IsAlgebraic F K) (x : K) : - (Set.range fun (ψ : K →ₐ[F] L) => ψ x) = (minpoly F x).rootSet L := by - ext a - rw [mem_rootSet_of_ne (minpoly.ne_zero (hK.isIntegral x))] - refine ⟨fun ⟨ψ, hψ⟩ ↦ ?_, fun ha ↦ IntermediateField.exists_algHom_of_splits_of_aeval - (fun x ↦ ⟨hK.isIntegral x, hA x⟩) ha⟩ - rw [← hψ, Polynomial.aeval_algHom_apply ψ x, minpoly.aeval, map_zero] - -end Algebra.IsAlgebraic - -section PowerBasis +namespace PowerBasis variable {K L : Type*} [Field K] [Field L] [Algebra K L] -namespace PowerBasis - open IntermediateField /-- `pb.equivAdjoinSimple` is the equivalence between `K⟮pb.gen⟯` and `L` itself. -/ @@ -1384,5 +1412,3 @@ theorem equivAdjoinSimple_symm_gen (pb : PowerBasis K L) : #align power_basis.equiv_adjoin_simple_symm_gen PowerBasis.equivAdjoinSimple_symm_gen end PowerBasis - -end PowerBasis diff --git a/Mathlib/FieldTheory/ChevalleyWarning.lean b/Mathlib/FieldTheory/ChevalleyWarning.lean index 85d1acce37ab7..edc9b4ba2437d 100644 --- a/Mathlib/FieldTheory/ChevalleyWarning.lean +++ b/Mathlib/FieldTheory/ChevalleyWarning.lean @@ -64,7 +64,7 @@ theorem MvPolynomial.sum_eval_eq_zero (f : MvPolynomial σ K) obtain ⟨i, hi⟩ : ∃ i, d i < q - 1; exact f.exists_degree_lt (q - 1) h hd calc (∑ x : σ → K, f.coeff d * ∏ i, x i ^ d i) = f.coeff d * ∑ x : σ → K, ∏ i, x i ^ d i := - mul_sum.symm + (mul_sum ..).symm _ = 0 := (mul_eq_zero.mpr ∘ Or.inr) ?_ calc (∑ x : σ → K, ∏ i, x i ^ d i) = @@ -151,7 +151,7 @@ theorem char_dvd_card_solutions_of_sum_lt {s : Finset ι} {f : ι → MvPolynomi F.totalDegree ≤ ∑ i in s, (1 - f i ^ (q - 1)).totalDegree := totalDegree_finset_prod s _ _ ≤ ∑ i in s, (q - 1) * (f i).totalDegree := (sum_le_sum fun i _ => ?_) -- see ↓ - _ = (q - 1) * ∑ i in s, (f i).totalDegree := mul_sum.symm + _ = (q - 1) * ∑ i in s, (f i).totalDegree := (mul_sum ..).symm _ < (q - 1) * Fintype.card σ := by rwa [mul_lt_mul_left hq] -- Now we prove the remaining step from the preceding calculation show (1 - f i ^ (q - 1)).totalDegree ≤ (q - 1) * (f i).totalDegree diff --git a/Mathlib/FieldTheory/Extension.lean b/Mathlib/FieldTheory/Extension.lean new file mode 100644 index 0000000000000..0629116b75c28 --- /dev/null +++ b/Mathlib/FieldTheory/Extension.lean @@ -0,0 +1,216 @@ +/- +Copyright (c) 2020 Thomas Browning. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Thomas Browning +-/ +import Mathlib.FieldTheory.Adjoin + +/-! +# Extension of field embeddings + +`IntermediateField.exists_algHom_of_adjoin_splits'` is the main result: if E/L/F is a tower of +field extensions, K is another extension of F, and `f` is an embedding of L/F into K/F, such +that the minimal polynomials of a set of generators of E/L splits in K (via `f`), then `f` +extends to an embedding of E/F into K/F. +-/ + +open Polynomial + +namespace IntermediateField + +variable (F E K : Type*) [Field F] [Field E] [Field K] [Algebra F E] [Algebra F K] {S : Set E} + +/-- Lifts `L → K` of `F → K` -/ +structure Lifts where + /-- The domain of a lift. -/ + carrier : IntermediateField F E + /-- The lifted RingHom, expressed as an AlgHom. -/ + emb : carrier →ₐ[F] K +#align intermediate_field.lifts IntermediateField.Lifts + +variable {F E K} + +instance : PartialOrder (Lifts F E K) where + le L₁ L₂ := ∃ h : L₁.carrier ≤ L₂.carrier, ∀ x, L₂.emb (inclusion h x) = L₁.emb x + le_refl L := ⟨le_rfl, by simp⟩ + le_trans L₁ L₂ L₃ := by + rintro ⟨h₁₂, h₁₂'⟩ ⟨h₂₃, h₂₃'⟩ + refine ⟨h₁₂.trans h₂₃, fun _ ↦ ?_⟩ + rw [← inclusion_inclusion h₁₂ h₂₃, h₂₃', h₁₂'] + le_antisymm := by + rintro ⟨L₁, e₁⟩ ⟨L₂, e₂⟩ ⟨h₁₂, h₁₂'⟩ ⟨h₂₁, h₂₁'⟩ + obtain rfl : L₁ = L₂ := h₁₂.antisymm h₂₁ + congr + exact AlgHom.ext h₂₁' + +noncomputable instance : OrderBot (Lifts F E K) where + bot := ⟨⊥, (Algebra.ofId F K).comp (botEquiv F E)⟩ + bot_le L := ⟨bot_le, fun x ↦ by + obtain ⟨x, rfl⟩ := (botEquiv F E).symm.surjective x + simp_rw [AlgHom.comp_apply, AlgHom.coe_coe, AlgEquiv.apply_symm_apply] + exact L.emb.commutes x⟩ + +noncomputable instance : Inhabited (Lifts F E K) := + ⟨⊥⟩ + +/-- A chain of lifts has an upper bound. -/ +theorem Lifts.exists_upper_bound (c : Set (Lifts F E K)) (hc : IsChain (· ≤ ·) c) : + ∃ ub, ∀ a ∈ c, a ≤ ub := by + let t (i : ↑(insert ⊥ c)) := i.val.carrier + let t' (i) := (t i).toSubalgebra + have hc := hc.insert fun _ _ _ ↦ .inl bot_le + have dir : Directed (· ≤ ·) t := hc.directedOn.directed_val.mono_comp _ fun _ _ h ↦ h.1 + refine ⟨⟨iSup t, (Subalgebra.iSupLift t' dir (fun i ↦ i.val.emb) (fun i j h ↦ ?_) _ rfl).comp + (Subalgebra.equivOfEq _ _ <| toSubalgebra_iSup_of_directed dir)⟩, + fun L hL ↦ have hL := Set.mem_insert_of_mem ⊥ hL; ⟨le_iSup t ⟨L, hL⟩, fun x ↦ ?_⟩⟩ + · refine AlgHom.ext fun x ↦ (hc.total i.2 j.2).elim (fun hij ↦ (hij.snd x).symm) fun hji ↦ ?_ + erw [AlgHom.comp_apply, ← hji.snd (Subalgebra.inclusion h x), + inclusion_inclusion, inclusion_self, AlgHom.id_apply x] + · dsimp only [AlgHom.comp_apply] + exact Subalgebra.iSupLift_inclusion (K := t') (i := ⟨L, hL⟩) x (le_iSup t' ⟨L, hL⟩) +#align intermediate_field.lifts.exists_upper_bound IntermediateField.Lifts.exists_upper_bound + +/-- Given a lift `x` and an integral element `s : E` over `x.carrier` whose conjugates over +`x.carrier` are all in `K`, we can extend the lift to a lift whose carrier contains `s`. -/ +theorem Lifts.exists_lift_of_splits' (x : Lifts F E K) {s : E} (h1 : IsIntegral x.carrier s) + (h2 : (minpoly x.carrier s).Splits x.emb.toRingHom) : ∃ y, x ≤ y ∧ s ∈ y.carrier := + have I2 := (minpoly.degree_pos h1).ne' + letI : Algebra x.carrier K := x.emb.toRingHom.toAlgebra + let carrier := x.carrier⟮s⟯.restrictScalars F + letI : Algebra x.carrier carrier := x.carrier⟮s⟯.toSubalgebra.algebra + let φ : carrier →ₐ[x.carrier] K := ((algHomAdjoinIntegralEquiv x.carrier h1).symm + ⟨rootOfSplits x.emb.toRingHom h2 I2, by + rw [mem_aroots, and_iff_right (minpoly.ne_zero h1)] + exact map_rootOfSplits x.emb.toRingHom h2 I2⟩) + ⟨⟨carrier, (@algHomEquivSigma F x.carrier carrier K _ _ _ _ _ _ _ _ + (IsScalarTower.of_algebraMap_eq fun _ ↦ rfl)).symm ⟨x.emb, φ⟩⟩, + ⟨fun z hz ↦ algebraMap_mem x.carrier⟮s⟯ ⟨z, hz⟩, φ.commutes⟩, + mem_adjoin_simple_self x.carrier s⟩ + +/-- Given an integral element `s : E` over `F` whose `F`-conjugates are all in `K`, +any lift can be extended to one whose carrier contains `s`. -/ +theorem Lifts.exists_lift_of_splits (x : Lifts F E K) {s : E} (h1 : IsIntegral F s) + (h2 : (minpoly F s).Splits (algebraMap F K)) : ∃ y, x ≤ y ∧ s ∈ y.carrier := + Lifts.exists_lift_of_splits' x h1.tower_top <| h1.minpoly_splits_tower_top' <| by + rwa [← x.emb.comp_algebraMap] at h2 +#align intermediate_field.lifts.exists_lift_of_splits IntermediateField.Lifts.exists_lift_of_splits + +section + +private theorem exists_algHom_adjoin_of_splits'' {L : IntermediateField F E} + (f : L →ₐ[F] K) (hK : ∀ s ∈ S, IsIntegral L s ∧ (minpoly L s).Splits f.toRingHom) : + ∃ φ : adjoin L S →ₐ[F] K, φ.comp (IsScalarTower.toAlgHom F L _) = f := by + obtain ⟨φ, hfφ, hφ⟩ := zorn_nonempty_Ici₀ _ + (fun c _ hc _ _ ↦ Lifts.exists_upper_bound c hc) ⟨L, f⟩ le_rfl + refine ⟨φ.emb.comp (inclusion <| (le_extendScalars_iff hfφ.1 <| adjoin L S).mp <| + adjoin_le_iff.mpr fun s h ↦ ?_), AlgHom.ext hfφ.2⟩ + letI := (inclusion hfφ.1).toAlgebra + letI : SMul L φ.carrier := Algebra.toSMul + have : IsScalarTower L φ.carrier E := ⟨(smul_assoc · (· : E))⟩ + have := φ.exists_lift_of_splits' (hK s h).1.tower_top ((hK s h).1.minpoly_splits_tower_top' ?_) + · obtain ⟨y, h1, h2⟩ := this; exact (hφ y h1).1 h2 + · convert (hK s h).2; ext; apply hfφ.2 + +variable {L : Type*} [Field L] [Algebra F L] [Algebra L E] [IsScalarTower F L E] + (f : L →ₐ[F] K) (hK : ∀ s ∈ S, IsIntegral L s ∧ (minpoly L s).Splits f.toRingHom) + +theorem exists_algHom_adjoin_of_splits' : + ∃ φ : adjoin L S →ₐ[F] K, φ.comp (IsScalarTower.toAlgHom F L _) = f := by + let L' := (IsScalarTower.toAlgHom F L E).fieldRange + let f' : L' →ₐ[F] K := f.comp (AlgEquiv.ofInjectiveField _).symm.toAlgHom + have := exists_algHom_adjoin_of_splits'' f' (S := S) fun s hs ↦ ?_ + · obtain ⟨φ, hφ⟩ := this; refine ⟨φ.comp <| + inclusion (?_ : (adjoin L S).restrictScalars F ≤ (adjoin L' S).restrictScalars F), ?_⟩ + · simp_rw [← SetLike.coe_subset_coe, coe_restrictScalars, adjoin_subset_adjoin_iff] + refine ⟨subset_adjoin_of_subset_left S (F := L'.toSubfield) le_rfl, subset_adjoin _ _⟩ + · ext x; exact congr($hφ _).trans (congr_arg f <| AlgEquiv.symm_apply_apply _ _) + letI : Algebra L L' := (AlgEquiv.ofInjectiveField _).toRingEquiv.toRingHom.toAlgebra + have : IsScalarTower L L' E := IsScalarTower.of_algebraMap_eq' rfl + refine ⟨(hK s hs).1.tower_top, (hK s hs).1.minpoly_splits_tower_top' ?_⟩ + convert (hK s hs).2; ext; exact congr_arg f (AlgEquiv.symm_apply_apply _ _) + +theorem exists_algHom_of_adjoin_splits' (hS : adjoin L S = ⊤) : + ∃ φ : E →ₐ[F] K, φ.comp (IsScalarTower.toAlgHom F L E) = f := + have ⟨φ, hφ⟩ := exists_algHom_adjoin_of_splits' f hK + ⟨φ.comp (((equivOfEq hS).trans topEquiv).symm.toAlgHom.restrictScalars F), hφ⟩ + +theorem exists_algHom_of_splits' (hK : ∀ s : E, IsIntegral L s ∧ (minpoly L s).Splits f.toRingHom) : + ∃ φ : E →ₐ[F] K, φ.comp (IsScalarTower.toAlgHom F L E) = f := + exists_algHom_of_adjoin_splits' f (fun x _ ↦ hK x) (adjoin_univ L E) + +end + +variable (hK : ∀ s ∈ S, IsIntegral F s ∧ (minpoly F s).Splits (algebraMap F K)) + (hK' : ∀ s : E, IsIntegral F s ∧ (minpoly F s).Splits (algebraMap F K)) + {L : IntermediateField F E} (f : L →ₐ[F] K) (hL : L ≤ adjoin F S) + +-- The following uses the hypothesis `hK`. + +theorem exists_algHom_adjoin_of_splits : ∃ φ : adjoin F S →ₐ[F] K, φ.comp (inclusion hL) = f := by + obtain ⟨φ, hfφ, hφ⟩ := zorn_nonempty_Ici₀ _ + (fun c _ hc _ _ ↦ Lifts.exists_upper_bound c hc) ⟨L, f⟩ le_rfl + refine ⟨φ.emb.comp (inclusion <| adjoin_le_iff.mpr fun s hs ↦ ?_), ?_⟩ + · rcases φ.exists_lift_of_splits (hK s hs).1 (hK s hs).2 with ⟨y, h1, h2⟩ + exact (hφ y h1).1 h2 + · ext; apply hfφ.2 + +theorem nonempty_algHom_adjoin_of_splits : Nonempty (adjoin F S →ₐ[F] K) := + have ⟨φ, _⟩ := exists_algHom_adjoin_of_splits hK (⊥ : Lifts F E K).emb bot_le; ⟨φ⟩ +#align intermediate_field.alg_hom_mk_adjoin_splits IntermediateField.nonempty_algHom_adjoin_of_splits + +variable (hS : adjoin F S = ⊤) + +theorem exists_algHom_of_adjoin_splits : ∃ φ : E →ₐ[F] K, φ.comp L.val = f := + have ⟨φ, hφ⟩ := exists_algHom_adjoin_of_splits hK f (hS.symm ▸ le_top) + ⟨φ.comp ((equivOfEq hS).trans topEquiv).symm.toAlgHom, hφ⟩ + +theorem nonempty_algHom_of_adjoin_splits : Nonempty (E →ₐ[F] K) := + have ⟨φ, _⟩ := exists_algHom_of_adjoin_splits hK (⊥ : Lifts F E K).emb hS; ⟨φ⟩ +#align intermediate_field.alg_hom_mk_adjoin_splits' IntermediateField.nonempty_algHom_of_adjoin_splits + +variable {x : E} (hx : x ∈ adjoin F S) {y : K} (hy : aeval y (minpoly F x) = 0) + +theorem exists_algHom_adjoin_of_splits_of_aeval : ∃ φ : adjoin F S →ₐ[F] K, φ ⟨x, hx⟩ = y := by + have ix := isAlgebraic_adjoin (fun s hs ↦ (hK s hs).1) ⟨x, hx⟩ + rw [isAlgebraic_iff_isIntegral, isIntegral_iff] at ix + obtain ⟨φ, hφ⟩ := exists_algHom_adjoin_of_splits hK ((algHomAdjoinIntegralEquiv F ix).symm + ⟨y, mem_aroots.mpr ⟨minpoly.ne_zero ix, hy⟩⟩) (adjoin_simple_le_iff.mpr hx) + exact ⟨φ, (DFunLike.congr_fun hφ <| AdjoinSimple.gen F x).trans <| + algHomAdjoinIntegralEquiv_symm_apply_gen F ix _⟩ + +theorem exists_algHom_of_adjoin_splits_of_aeval : ∃ φ : E →ₐ[F] K, φ x = y := + have ⟨φ, hφ⟩ := exists_algHom_adjoin_of_splits_of_aeval hK (hS ▸ mem_top) hy + ⟨φ.comp ((equivOfEq hS).trans topEquiv).symm.toAlgHom, hφ⟩ + +/- The following uses the hypothesis + (hK' : ∀ s : E, IsIntegral F s ∧ (minpoly F s).Splits (algebraMap F K)) -/ + +theorem exists_algHom_of_splits : ∃ φ : E →ₐ[F] K, φ.comp L.val = f := + exists_algHom_of_adjoin_splits (fun x _ ↦ hK' x) f (adjoin_univ F E) + +theorem nonempty_algHom_of_splits : Nonempty (E →ₐ[F] K) := + nonempty_algHom_of_adjoin_splits (fun x _ ↦ hK' x) (adjoin_univ F E) + +theorem exists_algHom_of_splits_of_aeval : ∃ φ : E →ₐ[F] K, φ x = y := + exists_algHom_of_adjoin_splits_of_aeval (fun x _ ↦ hK' x) (adjoin_univ F E) hy + +end IntermediateField + +section Algebra.IsAlgebraic + +/-- Let `K/F` be an algebraic extension of fields and `L` a field in which all the minimal +polynomial over `F` of elements of `K` splits. Then, for `x ∈ K`, the images of `x` by the +`F`-algebra morphisms from `K` to `L` are exactly the roots in `L` of the minimal polynomial +of `x` over `F`. -/ +theorem Algebra.IsAlgebraic.range_eval_eq_rootSet_minpoly_of_splits {F K : Type*} (L : Type*) + [Field F] [Field K] [Field L] [Algebra F L] [Algebra F K] + (hA : ∀ x : K, (minpoly F x).Splits (algebraMap F L)) + (hK : Algebra.IsAlgebraic F K) (x : K) : + (Set.range fun (ψ : K →ₐ[F] L) => ψ x) = (minpoly F x).rootSet L := by + ext a + rw [mem_rootSet_of_ne (minpoly.ne_zero (hK.isIntegral x))] + refine ⟨fun ⟨ψ, hψ⟩ ↦ ?_, fun ha ↦ IntermediateField.exists_algHom_of_splits_of_aeval + (fun x ↦ ⟨hK.isIntegral x, hA x⟩) ha⟩ + rw [← hψ, Polynomial.aeval_algHom_apply ψ x, minpoly.aeval, map_zero] + +end Algebra.IsAlgebraic diff --git a/Mathlib/FieldTheory/Finite/Basic.lean b/Mathlib/FieldTheory/Finite/Basic.lean index e7f3b3f42fee4..7bd8089818f55 100644 --- a/Mathlib/FieldTheory/Finite/Basic.lean +++ b/Mathlib/FieldTheory/Finite/Basic.lean @@ -299,7 +299,7 @@ theorem sum_pow_units [DecidableEq K] (i : ℕ) : · rw [Fintype.card_units, Nat.cast_sub, cast_card_eq_zero, Nat.cast_one, zero_sub] show 1 ≤ q; exact Fintype.card_pos_iff.mpr ⟨0⟩ - rw [← forall_pow_eq_one_iff, FunLike.ext_iff] + rw [← forall_pow_eq_one_iff, DFunLike.ext_iff] apply forall_congr'; intro x; simp [Units.ext_iff] #align finite_field.sum_pow_units FiniteField.sum_pow_units @@ -586,17 +586,9 @@ theorem isSquare_of_char_two (hF : ringChar F = 2) (a : F) : IsSquare a := /-- In a finite field of odd characteristic, not every element is a square. -/ theorem exists_nonsquare (hF : ringChar F ≠ 2) : ∃ a : F, ¬IsSquare a := by -- Idea: the squaring map on `F` is not injective, hence not surjective - let sq : F → F := fun x => x ^ 2 - have h : ¬Function.Injective sq := by - simp only [Function.Injective, not_forall, exists_prop] - refine' ⟨-1, 1, _, Ring.neg_one_ne_one_of_char_ne_two hF⟩ - simp only [one_pow, neg_one_sq] - rw [Finite.injective_iff_surjective] at h - -- sq not surjective - simp_rw [IsSquare, ← pow_two, @eq_comm _ _ (_ ^ 2)] - unfold Function.Surjective at h - push_neg at h ⊢ - exact h + have h : ¬Function.Injective fun x : F ↦ x * x := fun h ↦ + h.ne (Ring.neg_one_ne_one_of_char_ne_two hF) <| by simp + simpa [Finite.injective_iff_surjective, Function.Surjective, IsSquare, eq_comm] using h #align finite_field.exists_nonsquare FiniteField.exists_nonsquare end Finite @@ -606,14 +598,8 @@ variable [Fintype F] /-- The finite field `F` has even cardinality iff it has characteristic `2`. -/ theorem even_card_iff_char_two : ringChar F = 2 ↔ Fintype.card F % 2 = 0 := by rcases FiniteField.card F (ringChar F) with ⟨n, hp, h⟩ - rw [h, Nat.pow_mod] - constructor - · intro hF - simp [hF] - · rw [← Nat.even_iff, Nat.even_pow] - rintro ⟨hev, hnz⟩ - rw [Nat.even_iff, Nat.mod_mod] at hev - exact (Nat.Prime.eq_two_or_odd hp).resolve_right (ne_of_eq_of_ne hev zero_ne_one) + rw [h, ← Nat.even_iff, Nat.even_pow, hp.even_iff] + simp #align finite_field.even_card_iff_char_two FiniteField.even_card_iff_char_two theorem even_card_of_char_two (hF : ringChar F = 2) : Fintype.card F % 2 = 0 := diff --git a/Mathlib/FieldTheory/Finiteness.lean b/Mathlib/FieldTheory/Finiteness.lean index 7d6b1bae0c928..f43ac616eac9f 100644 --- a/Mathlib/FieldTheory/Finiteness.lean +++ b/Mathlib/FieldTheory/Finiteness.lean @@ -3,7 +3,9 @@ Copyright (c) 2019 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.LinearAlgebra.Dimension.DivisionRing +import Mathlib.LinearAlgebra.Basis.VectorSpace +import Mathlib.LinearAlgebra.Dimension.Constructions +import Mathlib.LinearAlgebra.Dimension.Finite #align_import field_theory.finiteness from "leanprover-community/mathlib"@"039a089d2a4b93c761b234f3e5f5aeb752bac60f" diff --git a/Mathlib/FieldTheory/Fixed.lean b/Mathlib/FieldTheory/Fixed.lean index 5507a68d14dfd..06927f9ddfe71 100644 --- a/Mathlib/FieldTheory/Fixed.lean +++ b/Mathlib/FieldTheory/Fixed.lean @@ -314,13 +314,13 @@ theorem linearIndependent_toLinearMap (R : Type u) (A : Type v) (B : Type w) [Co LinearIndependent B (AlgHom.toLinearMap : (A →ₐ[R] B) → A →ₗ[R] B) := have : LinearIndependent B (LinearMap.ltoFun R A B ∘ AlgHom.toLinearMap) := ((linearIndependent_monoidHom A B).comp ((↑) : (A →ₐ[R] B) → A →* B) fun _ _ hfg => - AlgHom.ext fun _ => FunLike.ext_iff.1 hfg _ : + AlgHom.ext fun _ => DFunLike.ext_iff.1 hfg _ : _) this.of_comp _ #align linear_independent_to_linear_map linearIndependent_toLinearMap theorem cardinal_mk_algHom (K : Type u) (V : Type v) (W : Type w) [Field K] [Field V] [Algebra K V] - [FiniteDimensional K V] [Field W] [Algebra K W] [FiniteDimensional K W] : + [FiniteDimensional K V] [Field W] [Algebra K W] : Cardinal.mk (V →ₐ[K] W) ≤ finrank W (V →ₗ[K] W) := (linearIndependent_toLinearMap K V W).cardinal_mk_le_finrank #align cardinal_mk_alg_hom cardinal_mk_algHom @@ -345,7 +345,7 @@ theorem finrank_eq_card (G : Type u) (F : Type v) [Group G] [Field F] [Fintype G Fintype.card G ≤ Fintype.card (F →ₐ[FixedPoints.subfield G F] F) := Fintype.card_le_of_injective _ (MulSemiringAction.toAlgHom_injective _ F) _ ≤ finrank F (F →ₗ[FixedPoints.subfield G F] F) := (finrank_algHom (subfield G F) F) - _ = finrank (FixedPoints.subfield G F) F := finrank_linear_map' _ _ _ + _ = finrank (FixedPoints.subfield G F) F := finrank_linearMap_self _ _ _ #align fixed_points.finrank_eq_card FixedPoints.finrank_eq_card /-- `MulSemiringAction.toAlgHom` is bijective. -/ @@ -359,7 +359,7 @@ theorem toAlgHom_bijective (G : Type u) (F : Type v) [Group G] [Field F] [Finite · apply le_antisymm · exact Fintype.card_le_of_injective _ (MulSemiringAction.toAlgHom_injective _ F) · rw [← finrank_eq_card G F] - exact LE.le.trans_eq (finrank_algHom _ F) (finrank_linear_map' _ _ _) + exact LE.le.trans_eq (finrank_algHom _ F) (finrank_linearMap_self _ _ _) #align fixed_points.to_alg_hom_bijective FixedPoints.toAlgHom_bijective /-- Bijection between G and algebra homomorphisms that fix the fixed points -/ diff --git a/Mathlib/FieldTheory/Galois.lean b/Mathlib/FieldTheory/Galois.lean index 082bac86a9fda..9317d006c7743 100644 --- a/Mathlib/FieldTheory/Galois.lean +++ b/Mathlib/FieldTheory/Galois.lean @@ -420,8 +420,9 @@ theorem of_separable_splitting_field [sp : p.IsSplittingField F E] (hp : p.Separ intro K x hx hK simp only at * -- Porting note: need to specify two implicit arguments of `finrank_mul_finrank` - rw [of_separable_splitting_field_aux hp K (Multiset.mem_toFinset.mp hx), hK, - @finrank_mul_finrank _ _ _ _ _ _ _ K⟮x⟯.module _ K⟮x⟯.isScalarTower _] + letI := K⟮x⟯.module + letI := K⟮x⟯.isScalarTower (R := F) + rw [of_separable_splitting_field_aux hp K (Multiset.mem_toFinset.mp hx), hK, finrank_mul_finrank] symm refine' LinearEquiv.finrank_eq _ rfl diff --git a/Mathlib/FieldTheory/IntermediateField.lean b/Mathlib/FieldTheory/IntermediateField.lean index c4a918cdb8fae..ff300c72dfc1b 100644 --- a/Mathlib/FieldTheory/IntermediateField.lean +++ b/Mathlib/FieldTheory/IntermediateField.lean @@ -387,6 +387,10 @@ instance toAlgebra {R : Type*} [Semiring R] [Algebra L R] : Algebra S R := S.toSubalgebra.toAlgebra #align intermediate_field.to_algebra IntermediateField.toAlgebra +@[simp] lemma algebraMap_apply (x : S) : algebraMap S L x = x := rfl + +@[simp] lemma coe_algebraMap_apply (x : K) : ↑(algebraMap K S x) = algebraMap K L x := rfl + instance isScalarTower_bot {R : Type*} [Semiring R] [Algebra L R] : IsScalarTower S L R := IsScalarTower.subalgebra _ _ _ S.toSubalgebra #align intermediate_field.is_scalar_tower_bot IntermediateField.isScalarTower_bot @@ -456,7 +460,7 @@ theorem gc_map_comap (f :L →ₐ[K] L') : GaloisConnection (map f) (comap f) := fun _ _ ↦ map_le_iff_le_comap /-- Given an equivalence `e : L ≃ₐ[K] L'` of `K`-field extensions and an intermediate -field `E` of `L/K`, `intermediate_field_equiv_map e E` is the induced equivalence +field `E` of `L/K`, `intermediateFieldMap e E` is the induced equivalence between `E` and `E.map e` -/ def intermediateFieldMap (e : L ≃ₐ[K] L') (E : IntermediateField K L) : E ≃ₐ[K] E.map e.toAlgHom := e.subalgebraMap E.toSubalgebra diff --git a/Mathlib/FieldTheory/IsAlgClosed/Basic.lean b/Mathlib/FieldTheory/IsAlgClosed/Basic.lean index 5aa7f231ec507..53ba5e7b2fa37 100644 --- a/Mathlib/FieldTheory/IsAlgClosed/Basic.lean +++ b/Mathlib/FieldTheory/IsAlgClosed/Basic.lean @@ -34,6 +34,13 @@ polynomial in `k` splits. algebraic closure, algebraically closed +## TODO + +- Prove that if `K / k` is algebraic, and any monic irreducible polynomial over `k` has a root + in `K`, then `K` is algebraically closed (in fact an algebraic closure of `k`). + + Reference: , Theorem 2 + -/ @@ -218,8 +225,19 @@ instance (priority := 100) IsAlgClosure.separable (R K : Type*) [Field R] [Field namespace IsAlgClosed -variable (K : Type u) [Field K] (L : Type v) (M : Type w) [Field L] [Algebra K L] [Field M] - [Algebra K M] [IsAlgClosed M] (hL : Algebra.IsAlgebraic K L) +variable {K : Type u} [Field K] {L : Type v} {M : Type w} [Field L] [Algebra K L] [Field M] + [Algebra K M] [IsAlgClosed M] + +/-- If E/L/K is a tower of field extensions with E/L algebraic, and if M is an algebraically + closed extension of K, then any embedding of L/K into M/K extends to an embedding of E/K. + Known as the extension lemma in https://math.stackexchange.com/a/687914. -/ +theorem surjective_comp_algebraMap_of_isAlgebraic {E : Type*} + [Field E] [Algebra K E] [Algebra L E] [IsScalarTower K L E] (hE : Algebra.IsAlgebraic L E) : + Function.Surjective fun φ : E →ₐ[K] M ↦ φ.comp (IsScalarTower.toAlgHom K L E) := + fun f ↦ IntermediateField.exists_algHom_of_splits' + (E := E) f fun s ↦ ⟨(hE s).isIntegral, IsAlgClosed.splits_codomain _⟩ + +variable (hL : Algebra.IsAlgebraic K L) (K L M) /-- Less general version of `lift`. -/ private noncomputable irreducible_def lift_aux : L →ₐ[K] M := @@ -265,6 +283,10 @@ noncomputable instance (priority := 100) perfectRing (p : ℕ) [Fact p.Prime] [C PerfectRing.ofSurjective k p fun _ => IsAlgClosed.exists_pow_nat_eq _ <| NeZero.pos p #align is_alg_closed.perfect_ring IsAlgClosed.perfectRing +noncomputable instance (priority := 100) perfectField [IsAlgClosed k] : PerfectField k := by + obtain _ | ⟨p, _, _⟩ := CharP.exists' k + exacts [.ofCharZero k, PerfectRing.toPerfectField k p] + /-- Algebraically closed fields are infinite since `Xⁿ⁺¹ - 1` is separable when `#K = n` -/ instance (priority := 500) {K : Type*} [Field K] [IsAlgClosed K] : Infinite K := by apply Infinite.of_not_fintype diff --git a/Mathlib/FieldTheory/IsSepClosed.lean b/Mathlib/FieldTheory/IsSepClosed.lean index 76070f0d8a24d..49d592bebd781 100644 --- a/Mathlib/FieldTheory/IsSepClosed.lean +++ b/Mathlib/FieldTheory/IsSepClosed.lean @@ -26,6 +26,9 @@ and prove some of their properties. - `IsSepClosure.equiv` is a proof that any two separable closures of the same field are isomorphic. +- `IsSepClosure.isAlgClosure_of_perfectField`, `IsSepClosure.of_isAlgClosure_of_perfectField`: + if `k` is a perfect field, then its separable closure coincides with its algebraic closure. + ## Tags separable closure, separably closed @@ -40,11 +43,8 @@ separable closure, separably closed - In particular, a separable closure (`SeparableClosure`) exists. -## TODO - -- If `k` is a perfect field, then its separable closure coincides with its algebraic closure. - -- An algebraic extension of a separably closed field is purely inseparable. +- `Algebra.IsAlgebraic.isPurelyInseparable_of_isSepClosed`: an algebraic extension of a separably + closed field is purely inseparable. -/ @@ -94,6 +94,13 @@ theorem exists_root [IsSepClosed k] (p : k[X]) (hp : p.degree ≠ 0) (hsep : p.S ∃ x, IsRoot p x := exists_root_of_splits _ (IsSepClosed.splits_of_separable p hsep) hp +variable (k) in +/-- A separably closed perfect field is also algebraically closed. -/ +instance (priority := 100) isAlgClosed_of_perfectField [IsSepClosed k] [PerfectField k] : + IsAlgClosed k := + IsAlgClosed.of_exists_root k fun p _ h ↦ exists_root p ((degree_pos_of_irreducible h).ne') + (PerfectField.separable_of_irreducible h) + theorem exists_pow_nat_eq [IsSepClosed k] (x : k) (n : ℕ) [hn : NeZero (n : k)] : ∃ z, z ^ n = x := by have hn' : 0 < n := Nat.pos_of_ne_zero fun h => by @@ -191,6 +198,27 @@ class IsSepClosure [Algebra k K] : Prop where instance IsSepClosure.self_of_isSepClosed [IsSepClosed k] : IsSepClosure k k := ⟨by assumption, isSeparable_self k⟩ +/-- If `K` is perfect and is a separable closure of `k`, +then it is also an algebraic closure of `k`. -/ +instance (priority := 100) IsSepClosure.isAlgClosure_of_perfectField_top + [Algebra k K] [IsSepClosure k K] [PerfectField K] : IsAlgClosure k K := + haveI : IsSepClosed K := IsSepClosure.sep_closed k + ⟨inferInstance, IsSepClosure.separable.isAlgebraic⟩ + +/-- If `k` is perfect, `K` is a separable closure of `k`, +then it is also an algebraic closure of `k`. -/ +instance (priority := 100) IsSepClosure.isAlgClosure_of_perfectField + [Algebra k K] [IsSepClosure k K] [PerfectField k] : IsAlgClosure k K := + have halg : Algebra.IsAlgebraic k K := IsSepClosure.separable.isAlgebraic + haveI := halg.perfectField; inferInstance + +/-- If `k` is perfect, `K` is an algebraic closure of `k`, +then it is also a separable closure of `k`. -/ +instance (priority := 100) IsSepClosure.of_isAlgClosure_of_perfectField + [Algebra k K] [IsAlgClosure k K] [PerfectField k] : IsSepClosure k K := + ⟨haveI := IsAlgClosure.alg_closed (R := k) (K := K); inferInstance, + (IsAlgClosure.algebraic (R := k) (K := K)).isSeparable_of_perfectField⟩ + variable {k} {K} theorem isSepClosure_iff [Algebra k K] : @@ -211,8 +239,16 @@ end IsSepClosure namespace IsSepClosed -variable {K : Type u} {L : Type v} {M : Type w} [Field K] [Field L] [Algebra K L] [Field M] - [Algebra K M] [IsSepClosed M] [IsSeparable K L] +variable {K : Type u} (L : Type v) {M : Type w} [Field K] [Field L] [Algebra K L] [Field M] + [Algebra K M] [IsSepClosed M] + +theorem surjective_comp_algebraMap_of_isSeparable {E : Type*} + [Field E] [Algebra K E] [Algebra L E] [IsScalarTower K L E] [IsSeparable L E] : + Function.Surjective fun φ : E →ₐ[K] M ↦ φ.comp (IsScalarTower.toAlgHom K L E) := + fun f ↦ IntermediateField.exists_algHom_of_splits' (E := E) f + fun s ↦ ⟨IsSeparable.isIntegral L s, IsSepClosed.splits_codomain _ <| IsSeparable.separable L s⟩ + +variable [IsSeparable K L] {L} /-- A (random) homomorphism from a separable extension L of K into a separably closed extension M of K. -/ diff --git a/Mathlib/FieldTheory/KrullTopology.lean b/Mathlib/FieldTheory/KrullTopology.lean index 5e48cc47f304a..ebca4adc56ca2 100644 --- a/Mathlib/FieldTheory/KrullTopology.lean +++ b/Mathlib/FieldTheory/KrullTopology.lean @@ -222,7 +222,7 @@ theorem krullTopology_t2 {K L : Type*} [Field K] [Field L] [Algebra K L] (h_int : Algebra.IsIntegral K L) : T2Space (L ≃ₐ[K] L) := { t2 := fun f g hfg => by let φ := f⁻¹ * g - cases' FunLike.exists_ne hfg with x hx + cases' DFunLike.exists_ne hfg with x hx have hφx : φ x ≠ x := by apply ne_of_apply_ne f change f (f.symm (g x)) ≠ f x @@ -263,7 +263,7 @@ theorem krullTopology_totallyDisconnected {K L : Type*} [Field K] [Field L] [Alg apply isTotallyDisconnected_of_isClopen_set intro σ τ h_diff have hστ : σ⁻¹ * τ ≠ 1 := by rwa [Ne.def, inv_mul_eq_one] - rcases FunLike.exists_ne hστ with ⟨x, hx : (σ⁻¹ * τ) x ≠ x⟩ + rcases DFunLike.exists_ne hστ with ⟨x, hx : (σ⁻¹ * τ) x ≠ x⟩ let E := IntermediateField.adjoin K ({x} : Set L) haveI := IntermediateField.adjoin.finiteDimensional (h_int x) refine' ⟨σ • E.fixingSubgroup, diff --git a/Mathlib/FieldTheory/KummerExtension.lean b/Mathlib/FieldTheory/KummerExtension.lean index db15cae26a4c4..117432070b14e 100644 --- a/Mathlib/FieldTheory/KummerExtension.lean +++ b/Mathlib/FieldTheory/KummerExtension.lean @@ -8,6 +8,7 @@ import Mathlib.RingTheory.AdjoinRoot import Mathlib.LinearAlgebra.Charpoly.Basic import Mathlib.FieldTheory.Galois import Mathlib.LinearAlgebra.Eigenspace.Minpoly +import Mathlib.RingTheory.Norm /-! # Kummer Extensions @@ -31,12 +32,21 @@ then isomorphic to `Multiplicative (ZMod n)` whose inverse is given by ## Other results Criteria for `X ^ n - C a` to be irreducible is given: -- `X_pow_sub_C_irreducible_iff_of_prime`: `X ^ n - C a` is irreducible iff `a` is not a `p`-power. +- `X_pow_sub_C_irreducible_iff_of_prime`: + For `n = p` a prime, `X ^ n - C a` is irreducible iff `a` is not a `p`-power. +- `X_pow_sub_C_irreducible_iff_of_prime_pow`: + For `n = p ^ k` an odd prime power, `X ^ n - C a` is irreducible iff `a` is not a `p`-power. +- `X_pow_sub_C_irreducible_iff_forall_prime_of_odd`: + For `n` odd, `X ^ n - C a` is irreducible iff `a` is not a `p`-power for all prime `p ∣ n`. +- `X_pow_sub_C_irreducible_iff_of_odd`: + For `n` odd, `X ^ n - C a` is irreducible iff `a` is not a `d`-power for `d ∣ n` and `d ≠ 1`. -TODO: criteria for general `n`. See [serge_lang_algebra] VI,§9. +TODO: criteria for even `n`. See [serge_lang_algebra] VI,§9. -/ -variable {K : Type*} [Field K] +universe u + +variable {K : Type u} [Field K] open Polynomial IntermediateField AdjoinRoot @@ -109,6 +119,115 @@ lemma root_X_pow_sub_C_ne_zero_iff {n : ℕ} {a : K} (H : Irreducible (X ^ n - C (AdjoinRoot.root (X ^ n - C a)) ≠ 0 ↔ a ≠ 0 := (root_X_pow_sub_C_eq_zero_iff H).not +theorem pow_ne_of_irreducible_X_pow_sub_C {n : ℕ} {a : K} + (H : Irreducible (X ^ n - C a)) {m : ℕ} (hm : m ∣ n) (hm' : m ≠ 1) (b : K) : b ^ m ≠ a := by + have hn : n ≠ 0 := fun e ↦ not_irreducible_C + (1 - a) (by simpa only [e, pow_zero, ← C.map_one, ← map_sub] using H) + obtain ⟨k, rfl⟩ := hm + rintro rfl + obtain ⟨q, hq⟩ := sub_dvd_pow_sub_pow (X ^ k) (C b) m + rw [mul_comm, pow_mul, map_pow, hq] at H + have : degree q = 0 + · simpa [isUnit_iff_degree_eq_zero, degree_X_pow_sub_C, + Nat.pos_iff_ne_zero, (mul_ne_zero_iff.mp hn).2] using H.2 _ q rfl + apply_fun degree at hq + simp only [this, ← pow_mul, mul_comm k m, degree_X_pow_sub_C, Nat.pos_iff_ne_zero.mpr hn, + Nat.pos_iff_ne_zero.mpr (mul_ne_zero_iff.mp hn).2, degree_mul, ← map_pow, add_zero, + Nat.cast_injective.eq_iff] at hq + exact hm' ((mul_eq_right₀ (mul_ne_zero_iff.mp hn).2).mp hq) + +theorem X_pow_sub_C_irreducible_of_prime {p : ℕ} (hp : p.Prime) {a : K} (ha : ∀ b : K, b ^ p ≠ a) : + Irreducible (X ^ p - C a) := by + -- First of all, We may find an irreducible factor `g` of `X ^ p - C a`. + have : ¬ IsUnit (X ^ p - C a) + · rw [Polynomial.isUnit_iff_degree_eq_zero, degree_X_pow_sub_C hp.pos, Nat.cast_eq_zero] + exact hp.ne_zero + have ⟨g, hg, hg'⟩ := WfDvdMonoid.exists_irreducible_factor this (X_pow_sub_C_ne_zero hp.pos a) + -- It suffices to show that `deg g = p`. + suffices natDegree g = p from (associated_of_dvd_of_natDegree_le hg' + (X_pow_sub_C_ne_zero hp.pos a) (this.trans natDegree_X_pow_sub_C.symm).ge).irreducible hg + -- Suppose `deg g ≠ p`. + by_contra h + have : Fact (Irreducible g) := ⟨hg⟩ + -- Let `r` be a root of `g`, then `N_K(r) ^ p = N_K(r ^ p) = N_K(a) = a ^ (deg g)`. + have key : (Algebra.norm K (AdjoinRoot.root g)) ^ p = a ^ g.natDegree + · have := eval₂_eq_zero_of_dvd_of_eval₂_eq_zero _ _ hg' (AdjoinRoot.eval₂_root g) + rw [eval₂_sub, eval₂_pow, eval₂_C, eval₂_X, sub_eq_zero] at this + rw [← map_pow, this, ← AdjoinRoot.algebraMap_eq, Algebra.norm_algebraMap, + ← finrank_top', ← IntermediateField.adjoin_root_eq_top g, + IntermediateField.adjoin.finrank, + AdjoinRoot.minpoly_root hg.ne_zero, natDegree_mul_C] + · simpa using hg.ne_zero + · exact AdjoinRoot.isIntegral_root hg.ne_zero + -- Since `a ^ (deg g)` is a `p`-power, and `p` is coprime to `deg g`, we conclude that `a` is + -- also a `p`-power, contradicting the hypothesis + have : p.Coprime (natDegree g) := hp.coprime_iff_not_dvd.mpr (fun e ↦ h (((natDegree_le_of_dvd hg' + (X_pow_sub_C_ne_zero hp.pos a)).trans_eq natDegree_X_pow_sub_C).antisymm (Nat.le_of_dvd + (natDegree_pos_iff_degree_pos.mpr <| Polynomial.degree_pos_of_irreducible hg) e))) + exact ha _ ((pow_mem_range_pow_of_coprime this.symm a).mp ⟨_, key⟩).choose_spec + +theorem X_pow_sub_C_irreducible_iff_of_prime {p : ℕ} (hp : p.Prime) {a : K} : + Irreducible (X ^ p - C a) ↔ ∀ b, b ^ p ≠ a := + ⟨(pow_ne_of_irreducible_X_pow_sub_C · dvd_rfl hp.ne_one), X_pow_sub_C_irreducible_of_prime hp⟩ + +theorem X_pow_mul_sub_C_irreducible + {n m : ℕ} {a : K} (hm : Irreducible (X ^ m - C a)) + (hn : ∀ (E : Type u) [Field E] [Algebra K E] (x : E) (hx : minpoly K x = X ^ m - C a), + Irreducible (X ^ n - C (AdjoinSimple.gen K x))) : + Irreducible (X ^ (n * m) - C a) := by + have hm' : m ≠ 0 + · rintro rfl + rw [pow_zero, ← C.map_one, ← map_sub] at hm + exact not_irreducible_C _ hm + simpa [pow_mul] using irreducible_comp (monic_X_pow_sub_C a hm') (monic_X_pow n) hm + (by simpa only [Polynomial.map_pow, map_X] using hn) + +-- TODO: generalize to even `n` +theorem X_pow_sub_C_irreducible_of_odd + {n : ℕ} (hn : Odd n) {a : K} (ha : ∀ p : ℕ, p.Prime → p ∣ n → ∀ b : K, b ^ p ≠ a) : + Irreducible (X ^ n - C a) := by + induction n using induction_on_primes generalizing K a with + | h₀ => simp at hn + | h₁ => simpa using irreducible_X_sub_C a + | h p n hp IH => + rw [mul_comm] + apply X_pow_mul_sub_C_irreducible + (X_pow_sub_C_irreducible_of_prime hp (ha p hp (dvd_mul_right _ _))) + intro E _ _ x hx + have : IsIntegral K x := not_not.mp fun h ↦ by + simpa only [degree_zero, degree_X_pow_sub_C hp.pos, + WithBot.nat_ne_bot] using congr_arg degree (hx.symm.trans (dif_neg h)) + apply IH (Nat.odd_mul.mp hn).2 + intros q hq hqn b hb + apply ha q hq (dvd_mul_of_dvd_right hqn p) (Algebra.norm _ b) + rw [← map_pow, hb, ← adjoin.powerBasis_gen this, + Algebra.PowerBasis.norm_gen_eq_coeff_zero_minpoly] + simp [minpoly_gen, hx, hp.ne_zero.symm, (Nat.odd_mul.mp hn).1.neg_pow] + +theorem X_pow_sub_C_irreducible_iff_forall_prime_of_odd {n : ℕ} (hn : Odd n) {a : K} : + Irreducible (X ^ n - C a) ↔ (∀ p : ℕ, p.Prime → p ∣ n → ∀ b : K, b ^ p ≠ a) := + ⟨fun e _ hp hpn ↦ pow_ne_of_irreducible_X_pow_sub_C e hpn hp.ne_one, + X_pow_sub_C_irreducible_of_odd hn⟩ + +theorem X_pow_sub_C_irreducible_iff_of_odd {n : ℕ} (hn : Odd n) {a : K} : + Irreducible (X ^ n - C a) ↔ (∀ d, d ∣ n → d ≠ 1 → ∀ b : K, b ^ d ≠ a) := + ⟨fun e _ ↦ pow_ne_of_irreducible_X_pow_sub_C e, + fun H ↦ X_pow_sub_C_irreducible_of_odd hn fun p hp hpn ↦ (H p hpn hp.ne_one)⟩ + +-- TODO: generalize to `p = 2` +theorem X_pow_sub_C_irreducible_of_prime_pow + {p : ℕ} (hp : p.Prime) (hp' : p ≠ 2) (n : ℕ) {a : K} (ha : ∀ b : K, b ^ p ≠ a) : + Irreducible (X ^ (p ^ n) - C a) := by + apply X_pow_sub_C_irreducible_of_odd (hp.odd_of_ne_two hp').pow + intros q hq hq' + simpa [(Nat.prime_dvd_prime_iff_eq hq hp).mp (hq.dvd_of_dvd_pow hq')] using ha + +theorem X_pow_sub_C_irreducible_iff_of_prime_pow + {p : ℕ} (hp : p.Prime) (hp' : p ≠ 2) {n} (hn : n ≠ 0) {a : K} : + Irreducible (X ^ p ^ n - C a) ↔ ∀ b, b ^ p ≠ a := + ⟨(pow_ne_of_irreducible_X_pow_sub_C · (dvd_pow dvd_rfl hn) hp.ne_one), + X_pow_sub_C_irreducible_of_prime_pow hp hp' n⟩ + end Irreducible /-! @@ -396,3 +515,111 @@ lemma finrank_of_isSplittingField_X_pow_sub_C : FiniteDimensional.finrank K L = (mem_primitiveRoots hn).mp hζ.choose_spec).toEquiv.trans Multiplicative.toAdd), ZMod.card] end IsSplittingField + +/-! ### Cyclic extensions of order `n` when `K` has all `n`-th roots of unity. -/ + +section IsCyclic + +variable {L} [Field L] [Algebra K L] [IsGalois K L] [FiniteDimensional K L] [IsCyclic (L ≃ₐ[K] L)] +variable (hK : (primitiveRoots (FiniteDimensional.finrank K L) K).Nonempty) + +open BigOperators FiniteDimensional +variable (K L) + +/-- If `L/K` is a cyclic extension of degree `n`, and `K` contains all `n`-th roots of unity, +then `L = K[α]` for some `α ^ n ∈ K`. -/ +lemma exists_root_adjoin_eq_top_of_isCyclic : + ∃ (α : L), α ^ (finrank K L) ∈ Set.range (algebraMap K L) ∧ K⟮α⟯ = ⊤ := by + -- Let `ζ` be an `n`-th root of unity, and `σ` be a generator of `L ≃ₐ[K] L`. + have ⟨ζ, hζ⟩ := hK + rw [mem_primitiveRoots finrank_pos] at hζ + obtain ⟨σ, hσ⟩ := ‹IsCyclic (L ≃ₐ[K] L)› + have hσ' := orderOf_eq_card_of_forall_mem_zpowers hσ + -- Since the minimal polynomial of `σ` over `K` is `Xⁿ - 1`, + -- `σ` has an eigenvector `v` with eigenvalue `ζ`. + have : IsRoot (minpoly K σ.toLinearMap) ζ := by + simpa [minpoly_algEquiv_toLinearMap σ (isOfFinOrder_of_finite σ), hσ', + sub_eq_zero, IsGalois.card_aut_eq_finrank] using hζ.pow_eq_one + obtain ⟨v, hv⟩ := (Module.End.hasEigenvalue_of_isRoot this).exists_hasEigenvector + have hv' := hv.pow_apply + simp_rw [← AlgEquiv.pow_toLinearMap, AlgEquiv.toLinearMap_apply] at hv' + -- We claim that `v` is the desired root. + refine ⟨v, ?_, ?_⟩ + · -- Since `v ^ n` is fixed by `σ` (`σ (v ^ n) = ζ ^ n • v ^ n = v ^ n`), it is in `K`. + rw [← IntermediateField.mem_bot, + ← OrderIso.map_bot IsGalois.intermediateFieldEquivSubgroup.symm] + intro ⟨σ', hσ'⟩ + obtain ⟨n, rfl : σ ^ n = σ'⟩ := mem_powers_iff_mem_zpowers.mpr (hσ σ') + rw [smul_pow', Submonoid.smul_def, AlgEquiv.smul_def, hv', smul_pow, ← pow_mul, + mul_comm, pow_mul, hζ.pow_eq_one, one_pow, one_smul] + · -- Since `σ` does not fix `K⟮α⟯`, `K⟮α⟯` is `L`. + apply IsGalois.intermediateFieldEquivSubgroup.injective + rw [map_top, eq_top_iff] + intros σ' hσ' + obtain ⟨n, rfl : σ ^ n = σ'⟩ := mem_powers_iff_mem_zpowers.mpr (hσ σ') + have := hσ' ⟨v, IntermediateField.mem_adjoin_simple_self K v⟩ + simp only [AlgEquiv.smul_def, hv'] at this + conv_rhs at this => rw [← one_smul K v] + obtain ⟨k, rfl⟩ := hζ.dvd_of_pow_eq_one n (smul_left_injective K hv.2 this) + rw [pow_mul, ← IsGalois.card_aut_eq_finrank, pow_card_eq_one, one_pow] + exact one_mem _ + +variable {K L} + +lemma irreducible_X_pow_sub_C_of_root_adjoin_eq_top + {a : K} {α : L} (ha : α ^ (finrank K L) = algebraMap K L a) (hα : K⟮α⟯ = ⊤) : + Irreducible (X ^ (finrank K L) - C a) := by + have : X ^ (finrank K L) - C a = minpoly K α + · refine minpoly.unique _ _ (monic_X_pow_sub_C _ finrank_pos.ne.symm) ?_ ?_ + · simp only [aeval_def, eval₂_sub, eval₂_X_pow, ha, eval₂_C, sub_self] + · intros q hq hq' + refine le_trans ?_ (degree_le_of_dvd (minpoly.dvd _ _ hq') hq.ne_zero) + rw [degree_X_pow_sub_C finrank_pos, + degree_eq_natDegree (minpoly.ne_zero (IsIntegral.of_finite K α)), + ← IntermediateField.adjoin.finrank (IsIntegral.of_finite K α), hα, Nat.cast_le] + exact (finrank_top K L).ge + exact this ▸ minpoly.irreducible (IsIntegral.of_finite K α) + +lemma isSplittingField_X_pow_sub_C_of_root_adjoin_eq_top + {a : K} {α : L} (ha : α ^ (finrank K L) = algebraMap K L a) (hα : K⟮α⟯ = ⊤) : + IsSplittingField K L (X ^ (finrank K L) - C a) := by + constructor + · rw [← splits_id_iff_splits, Polynomial.map_sub, Polynomial.map_pow, Polynomial.map_C, + Polynomial.map_X] + have ⟨_, hζ⟩ := hK + rw [mem_primitiveRoots finrank_pos] at hζ + exact X_pow_sub_C_splits_of_isPrimitiveRoot (hζ.map_of_injective (algebraMap K _).injective) ha + · rw [eq_top_iff, ← IntermediateField.top_toSubalgebra, ← hα, + IntermediateField.adjoin_simple_toSubalgebra_of_integral (IsIntegral.of_finite K α)] + apply Algebra.adjoin_mono + rw [Set.singleton_subset_iff, mem_rootSet_of_ne (X_pow_sub_C_ne_zero finrank_pos a), + aeval_def, eval₂_sub, eval₂_X_pow, eval₂_C, ha, sub_self] + +end IsCyclic + +open FiniteDimensional in +/-- +Suppose `L/K` is a finite extension of dimension `n`, and `K` contains all `n`-th roots of unity. +Then `L/K` is cyclic iff +`L` is a splitting field of some irreducible polynomial of the form `Xⁿ - a : K[X]` iff +`L = K[α]` for some `αⁿ ∈ K`. +-/ +lemma isCyclic_tfae (K L) [Field K] [Field L] [Algebra K L] [FiniteDimensional K L] + (hK : (primitiveRoots (FiniteDimensional.finrank K L) K).Nonempty) : + List.TFAE [ + IsGalois K L ∧ IsCyclic (L ≃ₐ[K] L), + ∃ a : K, Irreducible (X ^ (finrank K L) - C a) ∧ + IsSplittingField K L (X ^ (finrank K L) - C a), + ∃ (α : L), α ^ (finrank K L) ∈ Set.range (algebraMap K L) ∧ K⟮α⟯ = ⊤] := by + tfae_have 1 → 3 + · intro ⟨inst₁, inst₂⟩ + exact exists_root_adjoin_eq_top_of_isCyclic K L hK + tfae_have 3 → 2 + · intro ⟨α, ⟨a, ha⟩, hα⟩ + exact ⟨a, irreducible_X_pow_sub_C_of_root_adjoin_eq_top ha.symm hα, + isSplittingField_X_pow_sub_C_of_root_adjoin_eq_top hK ha.symm hα⟩ + tfae_have 2 → 1 + · intro ⟨a, H, inst⟩ + exact ⟨isGalois_of_isSplittingField_X_pow_sub_C hK H L, + isCyclic_of_isSplittingField_X_pow_sub_C hK H L⟩ + tfae_finish diff --git a/Mathlib/FieldTheory/Minpoly/Basic.lean b/Mathlib/FieldTheory/Minpoly/Basic.lean index 3059999be3d97..d4a93c93d935d 100644 --- a/Mathlib/FieldTheory/Minpoly/Basic.lean +++ b/Mathlib/FieldTheory/Minpoly/Basic.lean @@ -200,6 +200,34 @@ theorem degree_pos [Nontrivial B] (hx : IsIntegral A x) : 0 < degree (minpoly A natDegree_pos_iff_degree_pos.mp (natDegree_pos hx) #align minpoly.degree_pos minpoly.degree_pos +section +variable [Nontrivial B] + +open Polynomial in +theorem degree_eq_one_iff : (minpoly A x).degree = 1 ↔ x ∈ (algebraMap A B).range := by + refine ⟨minpoly.mem_range_of_degree_eq_one _ _, ?_⟩ + rintro ⟨x, rfl⟩ + haveI := Module.nontrivial A B + exact (degree_X_sub_C x ▸ minpoly.min A (algebraMap A B x) (monic_X_sub_C x) (by simp)).antisymm + (Nat.WithBot.add_one_le_of_lt <| minpoly.degree_pos isIntegral_algebraMap) + +theorem natDegree_eq_one_iff : + (minpoly A x).natDegree = 1 ↔ x ∈ (algebraMap A B).range := by + rw [← Polynomial.degree_eq_iff_natDegree_eq_of_pos zero_lt_one] + exact degree_eq_one_iff + +theorem two_le_natDegree_iff (int : IsIntegral A x) : + 2 ≤ (minpoly A x).natDegree ↔ x ∉ (algebraMap A B).range := by + rw [iff_not_comm, ← natDegree_eq_one_iff, not_le] + exact ⟨fun h ↦ h.trans_lt one_lt_two, fun h ↦ by linarith only [minpoly.natDegree_pos int, h]⟩ + +theorem two_le_natDegree_subalgebra {B} [CommRing B] [Algebra A B] [Nontrivial B] + {S : Subalgebra A B} {x : B} (int : IsIntegral S x) : 2 ≤ (minpoly S x).natDegree ↔ x ∉ S := by + rw [two_le_natDegree_iff int, Iff.not] + apply Set.ext_iff.mp Subtype.range_val_subtype + +end + /-- If `B/A` is an injective ring extension, and `a` is an element of `A`, then the minimal polynomial of `algebraMap A B a` is `X - C a`. -/ theorem eq_X_sub_C_of_algebraMap_inj (a : A) (hf : Function.Injective (algebraMap A B)) : diff --git a/Mathlib/FieldTheory/Minpoly/Field.lean b/Mathlib/FieldTheory/Minpoly/Field.lean index bb73fc2cf143a..72be5d603622e 100644 --- a/Mathlib/FieldTheory/Minpoly/Field.lean +++ b/Mathlib/FieldTheory/Minpoly/Field.lean @@ -167,7 +167,7 @@ def rootsOfMinPolyPiType (φ : E →ₐ[F] K) theorem aux_inj_roots_of_min_poly : Injective (rootsOfMinPolyPiType F E K) := by intro f g h - suffices (f : E →ₗ[F] K) = g by rwa [FunLike.ext'_iff] at this ⊢ + suffices (f : E →ₗ[F] K) = g by rwa [DFunLike.ext'_iff] at this ⊢ rw [funext_iff] at h exact LinearMap.ext_on (FiniteDimensional.finBasis F E).span_eq fun e he => Subtype.ext_iff.mp (h ⟨e, he⟩) @@ -261,3 +261,37 @@ theorem coeff_zero_ne_zero (hx : IsIntegral A x) (h : x ≠ 0) : coeff (minpoly end IsDomain end minpoly + +section AlgHom + +variable {K L} [Field K] [CommRing L] [IsDomain L] [Algebra K L] + +/-- The minimal polynomial (over `K`) of `σ : Gal(L/K)` is `X ^ (orderOf σ) - 1`. -/ +lemma minpoly_algEquiv_toLinearMap (σ : L ≃ₐ[K] L) (hσ : IsOfFinOrder σ) : + minpoly K σ.toLinearMap = X ^ (orderOf σ) - C 1 := by + refine (minpoly.unique _ _ (monic_X_pow_sub_C _ hσ.orderOf_pos.ne.symm) ?_ ?_).symm + · rw [(aeval σ.toLinearMap).map_sub (X ^ orderOf σ) (C (1 : K))] + simp [← AlgEquiv.pow_toLinearMap, pow_orderOf_eq_one] + · intros q hq hs + rw [degree_eq_natDegree hq.ne_zero, degree_X_pow_sub_C hσ.orderOf_pos, Nat.cast_le, ← not_lt] + intro H + rw [aeval_eq_sum_range' H, ← Fin.sum_univ_eq_sum_range] at hs + simp_rw [← AlgEquiv.pow_toLinearMap] at hs + apply hq.ne_zero + simpa using Fintype.linearIndependent_iff.mp + (((linearIndependent_algHom_toLinearMap' K L L).comp _ AlgEquiv.coe_algHom_injective).comp _ + (Subtype.val_injective.comp ((finEquivPowers σ hσ).injective))) + (q.coeff ∘ (↑)) hs ⟨_, H⟩ + +/-- The minimal polynomial (over `K`) of `σ : Gal(L/K)` is `X ^ (orderOf σ) - 1`. -/ +lemma minpoly_algHom_toLinearMap (σ : L →ₐ[K] L) (hσ : IsOfFinOrder σ) : + minpoly K σ.toLinearMap = X ^ (orderOf σ) - C 1 := by + have : orderOf σ = orderOf (AlgEquiv.algHomUnitsEquiv _ _ hσ.unit) + · erw [orderOf_injective (AlgEquiv.algHomUnitsEquiv K L) + (AlgEquiv.algHomUnitsEquiv K L).injective] + rw [← orderOf_units] + rfl + rw [this, ← minpoly_algEquiv_toLinearMap]; rfl + rwa [← orderOf_pos_iff, ← this, orderOf_pos_iff] + +end AlgHom diff --git a/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean b/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean index acdd23f680982..1eba68f18f939 100644 --- a/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean +++ b/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean @@ -86,8 +86,8 @@ lemma eval₂_minpolyDiv_self {T} [CommRing T] [Algebra R T] [IsDomain T] [Decid lemma eval_minpolyDiv_of_aeval_eq_zero [IsDomain S] [DecidableEq S] {y} (hy : aeval y (minpoly R x) = 0) : (minpolyDiv R x).eval y = if x = y then aeval x (derivative <| minpoly R x) else 0 := by - rw [eval, eval₂_minpolyDiv_of_eval₂_eq_zero]; rfl - exact hy + rw [eval, eval₂_minpolyDiv_of_eval₂_eq_zero, RingHom.id_apply, RingHom.id_apply] + simpa [aeval_def] using hy lemma natDegree_minpolyDiv_succ [Nontrivial S] : natDegree (minpolyDiv R x) + 1 = natDegree (minpoly R x) := by @@ -105,7 +105,7 @@ lemma natDegree_minpolyDiv : lemma natDegree_minpolyDiv_lt [Nontrivial S] : natDegree (minpolyDiv R x) < natDegree (minpoly R x) := by rw [← natDegree_minpolyDiv_succ hx] - exact Nat.lt.base _ + exact Nat.lt_succ_self _ lemma coeff_minpolyDiv_mem_adjoin (x : S) (i) : coeff (minpolyDiv R x) i ∈ Algebra.adjoin R {x} := by @@ -123,7 +123,7 @@ lemma coeff_minpolyDiv_mem_adjoin (x : S) (i) : · exact zero_mem _ · refine (Nat.le_add_left _ i).trans_lt ?_ rw [← add_assoc] - exact Nat.lt.base _ + exact Nat.lt_succ_self _ lemma minpolyDiv_eq_of_isIntegrallyClosed [IsDomain R] [IsIntegrallyClosed R] [IsDomain S] [Algebra R K] [Algebra K S] [IsScalarTower R K S] [IsFractionRing R K] : @@ -150,7 +150,8 @@ lemma coeff_minpolyDiv_sub_pow_mem_span {i} (hi : i ≤ natDegree (minpolyDiv R (Submodule.mem_span_singleton_self x)) rw [Submodule.span_mul_span, Set.mul_singleton, Set.image_image] apply Submodule.span_mono - rintro _ ⟨j, hj : j < i, rfl⟩ + rintro _ ⟨j, hj, rfl⟩ + rw [Set.mem_Iio] at hj exact ⟨j + 1, Nat.add_lt_of_lt_sub hj, pow_succ' x j⟩ lemma span_coeff_minpolyDiv : diff --git a/Mathlib/FieldTheory/MvPolynomial.lean b/Mathlib/FieldTheory/MvPolynomial.lean index 26cc54021d74d..6266e728237ef 100644 --- a/Mathlib/FieldTheory/MvPolynomial.lean +++ b/Mathlib/FieldTheory/MvPolynomial.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl -/ import Mathlib.LinearAlgebra.Dimension.StrongRankCondition import Mathlib.RingTheory.MvPolynomial.Basic +import Mathlib.Data.MvPolynomial.CommRing #align_import field_theory.mv_polynomial from "leanprover-community/mathlib"@"039a089d2a4b93c761b234f3e5f5aeb752bac60f" diff --git a/Mathlib/FieldTheory/Normal.lean b/Mathlib/FieldTheory/Normal.lean index 2a4daefc64200..f5565b010e43b 100644 --- a/Mathlib/FieldTheory/Normal.lean +++ b/Mathlib/FieldTheory/Normal.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Thomas Browning, Patrick Lutz -/ -import Mathlib.FieldTheory.Adjoin +import Mathlib.FieldTheory.Extension import Mathlib.FieldTheory.SplittingField.Construction import Mathlib.GroupTheory.Solvable @@ -273,7 +273,7 @@ theorem AlgHom.fieldRange_of_normal [Algebra F K] {E : IntermediateField F K} [N -- Porting note: this was `IsScalarTower F E E := by infer_instance`. letI : Algebra E E := Algebra.id E let g := f.restrictNormal' E - rw [← show E.val.comp ↑g = f from FunLike.ext_iff.mpr (f.restrictNormal_commutes E), + rw [← show E.val.comp ↑g = f from DFunLike.ext_iff.mpr (f.restrictNormal_commutes E), ← AlgHom.map_fieldRange, AlgEquiv.fieldRange_eq_top g, ← AlgHom.fieldRange_eq_map, IntermediateField.fieldRange_val] #align alg_hom.field_range_of_normal AlgHom.fieldRange_of_normal diff --git a/Mathlib/FieldTheory/NormalClosure.lean b/Mathlib/FieldTheory/NormalClosure.lean index dc91328b88fa5..4b2af8bae8482 100644 --- a/Mathlib/FieldTheory/NormalClosure.lean +++ b/Mathlib/FieldTheory/NormalClosure.lean @@ -216,7 +216,7 @@ noncomputable def Algebra.IsAlgebraic.algHomEmbeddingOfSplits (alg : IsAlgebraic { toFun := (φ.comp <| inclusion <| normalClosure_le_iSup_adjoin alg).comp ∘ (normalClosure.algHomEquiv F K L').symm inj' := fun _ _ h ↦ (normalClosure.algHomEquiv F K L').symm.injective <| by - rw [FunLike.ext'_iff] at h ⊢ + rw [DFunLike.ext'_iff] at h ⊢ exact (φ.comp _).injective.comp_left h } namespace IntermediateField diff --git a/Mathlib/FieldTheory/Perfect.lean b/Mathlib/FieldTheory/Perfect.lean index 926294a0eaaf9..860f9930a1e5f 100644 --- a/Mathlib/FieldTheory/Perfect.lean +++ b/Mathlib/FieldTheory/Perfect.lean @@ -24,6 +24,9 @@ prime characteristic. sense of Serre. * `PerfectField.ofCharZero`: all fields of characteristic zero are perfect. * `PerfectField.ofFinite`: all finite fields are perfect. + * `Algebra.IsAlgebraic.isSeparable_of_perfectField`, `Algebra.IsAlgebraic.perfectField`: + if `L / K` is an algebraic extension, `K` is a perfect field, then `L / K` is separable, + and `L` is also a perfect field. -/ @@ -35,7 +38,7 @@ NB: This is not related to the concept with the same name introduced by Bass (re covers of modules). -/ class PerfectRing (R : Type*) (p : ℕ) [CommSemiring R] [Fact p.Prime] [CharP R p] : Prop where /-- A ring is perfect if the Frobenius map is bijective. -/ - bijective_frobenius : Bijective $ frobenius R p + bijective_frobenius : Bijective <| frobenius R p section PerfectRing @@ -44,13 +47,13 @@ variable (R : Type*) (p : ℕ) [CommSemiring R] [Fact p.Prime] [CharP R p] /-- For a reduced ring, surjectivity of the Frobenius map is a sufficient condition for perfection. -/ lemma PerfectRing.ofSurjective (R : Type*) (p : ℕ) [CommRing R] [Fact p.Prime] [CharP R p] - [IsReduced R] (h : Surjective $ frobenius R p) : PerfectRing R p := + [IsReduced R] (h : Surjective <| frobenius R p) : PerfectRing R p := ⟨frobenius_inj R p, h⟩ #align perfect_ring.of_surjective PerfectRing.ofSurjective instance PerfectRing.ofFiniteOfIsReduced (R : Type*) [CommRing R] [CharP R p] [Finite R] [IsReduced R] : PerfectRing R p := - ofSurjective _ _ $ Finite.surjective_of_injective (frobenius_inj R p) + ofSurjective _ _ <| Finite.surjective_of_injective (frobenius_inj R p) variable [PerfectRing R p] @@ -211,10 +214,21 @@ instance toPerfectRing (p : ℕ) [hp : Fact p.Prime] [CharP K p] : PerfectRing K obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd rw [eq_of_monic_of_associated ((minpoly.monic ha).map ι) ((monic_X_sub_C a).pow q) hq, natDegree_pow, natDegree_X_sub_C, mul_one] - have hg_sep : (g.map ι).Separable := (separable_of_irreducible $ minpoly.irreducible ha).map + have hg_sep : (g.map ι).Separable := (separable_of_irreducible <| minpoly.irreducible ha).map rw [hg_pow] at hg_sep refine' (Separable.of_pow (not_isUnit_X_sub_C a) _ hg_sep).2 rw [g.natDegree_map ι, ← Nat.pos_iff_ne_zero, natDegree_pos_iff_degree_pos] exact minpoly.degree_pos ha end PerfectField + +/-- If `L / K` is an algebraic extension, `K` is a perfect field, then `L / K` is separable. -/ +theorem Algebra.IsAlgebraic.isSeparable_of_perfectField {K L : Type*} [Field K] [Field L] + [Algebra K L] [PerfectField K] (halg : Algebra.IsAlgebraic K L) : IsSeparable K L := + ⟨fun x ↦ PerfectField.separable_of_irreducible <| minpoly.irreducible (halg x).isIntegral⟩ + +/-- If `L / K` is an algebraic extension, `K` is a perfect field, then so is `L`. -/ +theorem Algebra.IsAlgebraic.perfectField {K L : Type*} [Field K] [Field L] [Algebra K L] + [PerfectField K] (halg : Algebra.IsAlgebraic K L) : PerfectField L := ⟨fun {f} hf ↦ by + obtain ⟨_, _, hi, h⟩ := hf.exists_dvd_monic_irreducible_of_isIntegral halg.isIntegral + exact (PerfectField.separable_of_irreducible hi).map |>.of_dvd h⟩ diff --git a/Mathlib/FieldTheory/PerfectClosure.lean b/Mathlib/FieldTheory/PerfectClosure.lean index 0489e266fb725..d58c6d484c634 100644 --- a/Mathlib/FieldTheory/PerfectClosure.lean +++ b/Mathlib/FieldTheory/PerfectClosure.lean @@ -46,7 +46,7 @@ def mk (x : ℕ × K) : PerfectClosure K p := #align perfect_closure.mk PerfectClosure.mk @[simp] theorem mk_succ_pow (m : ℕ) (x : K) : mk K p ⟨m + 1, x ^ p⟩ = mk K p ⟨m, x⟩ := - Eq.symm $ Quot.sound (R.intro m x) + Eq.symm <| Quot.sound (R.intro m x) @[simp] theorem quot_mk_eq_mk (x : ℕ × K) : (Quot.mk (R K p) x : PerfectClosure K p) = mk K p x := diff --git a/Mathlib/FieldTheory/PolynomialGaloisGroup.lean b/Mathlib/FieldTheory/PolynomialGaloisGroup.lean index b32d789978e29..4b58ebf1d5508 100644 --- a/Mathlib/FieldTheory/PolynomialGaloisGroup.lean +++ b/Mathlib/FieldTheory/PolynomialGaloisGroup.lean @@ -422,6 +422,7 @@ theorem prime_degree_dvd_card [CharZero F] (p_irr : Irreducible p) (p_deg : p.na have hα : IsIntegral F α := .of_finite F α use FiniteDimensional.finrank F⟮α⟯ p.SplittingField suffices (minpoly F α).natDegree = p.natDegree by + letI _ : AddCommGroup F⟮α⟯ := Ring.toAddCommGroup rw [← FiniteDimensional.finrank_mul_finrank F F⟮α⟯ p.SplittingField, IntermediateField.adjoin.finrank hα, this] suffices minpoly F α ∣ p by diff --git a/Mathlib/FieldTheory/PrimitiveElement.lean b/Mathlib/FieldTheory/PrimitiveElement.lean index c0164c8f3f9f6..7a9359a368d8d 100644 --- a/Mathlib/FieldTheory/PrimitiveElement.lean +++ b/Mathlib/FieldTheory/PrimitiveElement.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning, Patrick Lutz -/ import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure -import Mathlib.FieldTheory.NormalClosure import Mathlib.RingTheory.IntegralDomain #align_import field_theory.primitive_element from "leanprover-community/mathlib"@"df76f43357840485b9d04ed5dee5ab115d420e87" diff --git a/Mathlib/FieldTheory/RatFunc.lean b/Mathlib/FieldTheory/RatFunc.lean index 52b7364155cc5..7eaca923b1381 100644 --- a/Mathlib/FieldTheory/RatFunc.lean +++ b/Mathlib/FieldTheory/RatFunc.lean @@ -146,7 +146,7 @@ we construct a value of `P` for such elements of `RatFunc K` by setting When `[IsDomain K]`, one can use `RatFunc.liftOn'`, which has the stronger requirement of `∀ {p q a : K[X]} (hq : q ≠ 0) (ha : a ≠ 0), f (a * p) (a * q) = f p q)`. -/ -protected irreducible_def liftOn {P : Sort v} (x : RatFunc K) (f : ∀ _p _q : K[X], P) +protected irreducible_def liftOn {P : Sort v} (x : RatFunc K) (f : K[X] → K[X] → P) (H : ∀ {p q p' q'} (_hq : q ∈ K[X]⁰) (_hq' : q' ∈ K[X]⁰), q' * p = q * p' → f p q = f p' q') : P := by refine Localization.liftOn (toFractionRing x) (fun p q => f p q) ?_ @@ -162,14 +162,14 @@ protected irreducible_def liftOn {P : Sort v} (x : RatFunc K) (f : ∀ _p _q : K -- mul_cancel_left_coe_nonZeroDivisors.mp mul_eq) #align ratfunc.lift_on RatFunc.liftOn -theorem liftOn_ofFractionRing_mk {P : Sort v} (n : K[X]) (d : K[X]⁰) (f : ∀ _p _q : K[X], P) +theorem liftOn_ofFractionRing_mk {P : Sort v} (n : K[X]) (d : K[X]⁰) (f : K[X] → K[X] → P) (H : ∀ {p q p' q'} (_hq : q ∈ K[X]⁰) (_hq' : q' ∈ K[X]⁰), q' * p = q * p' → f p q = f p' q') : RatFunc.liftOn (ofFractionRing (Localization.mk n d)) f @H = f n d := by rw [RatFunc.liftOn] exact Localization.liftOn_mk _ _ _ _ #align ratfunc.lift_on_of_fraction_ring_mk RatFunc.liftOn_ofFractionRing_mk -theorem liftOn_condition_of_liftOn'_condition {P : Sort v} {f : ∀ _p _q : K[X], P} +theorem liftOn_condition_of_liftOn'_condition {P : Sort v} {f : K[X] → K[X] → P} (H : ∀ {p q a} (hq : q ≠ 0) (_ha : a ≠ 0), f (a * p) (a * q) = f p q) ⦃p q p' q' : K[X]⦄ (hq : q ≠ 0) (hq' : q' ≠ 0) (h : q' * p = q * p') : f p q = f p' q' := calc @@ -241,7 +241,7 @@ theorem mk_eq_mk {p q p' q' : K[X]} (hq : q ≠ 0) (hq' : q' ≠ 0) : (IsFractionRing.injective K[X] (FractionRing K[X])).eq_iff] #align ratfunc.mk_eq_mk RatFunc.mk_eq_mk -theorem liftOn_mk {P : Sort v} (p q : K[X]) (f : ∀ _p _q : K[X], P) (f0 : ∀ p, f p 0 = f 0 1) +theorem liftOn_mk {P : Sort v} (p q : K[X]) (f : K[X] → K[X] → P) (f0 : ∀ p, f p 0 = f 0 1) (H' : ∀ {p q p' q'} (_hq : q ≠ 0) (_hq' : q' ≠ 0), q' * p = q * p' → f p q = f p' q') (H : ∀ {p q p' q'} (_hq : q ∈ K[X]⁰) (_hq' : q' ∈ K[X]⁰), q' * p = q * p' → f p q = f p' q' := fun {p q p' q'} hq hq' h => H' (nonZeroDivisors.ne_zero hq) (nonZeroDivisors.ne_zero hq') h) : @@ -260,14 +260,14 @@ for all elements of `RatFunc K` by setting `lift_on' (p / q) f _ = f p q`. The value of `f p 0` for any `p` is never used and in principle this may be anything, although many usages of `lift_on'` assume `f p 0 = f 0 1`. -/ -protected irreducible_def liftOn' {P : Sort v} (x : RatFunc K) (f : ∀ _p _q : K[X], P) +protected irreducible_def liftOn' {P : Sort v} (x : RatFunc K) (f : K[X] → K[X] → P) (H : ∀ {p q a} (_hq : q ≠ 0) (_ha : a ≠ 0), f (a * p) (a * q) = f p q) : P := x.liftOn f fun {_p _q _p' _q'} hq hq' => liftOn_condition_of_liftOn'_condition (@H) (nonZeroDivisors.ne_zero hq) (nonZeroDivisors.ne_zero hq') #align ratfunc.lift_on' RatFunc.liftOn' -theorem liftOn'_mk {P : Sort v} (p q : K[X]) (f : ∀ _p _q : K[X], P) (f0 : ∀ p, f p 0 = f 0 1) +theorem liftOn'_mk {P : Sort v} (p q : K[X]) (f : K[X] → K[X] → P) (f0 : ∀ p, f p 0 = f 0 1) (H : ∀ {p q a} (_hq : q ≠ 0) (_ha : a ≠ 0), f (a * p) (a * q) = f p q) : (RatFunc.mk p q).liftOn' f @H = f p q := by rw [RatFunc.liftOn', RatFunc.liftOn_mk _ _ _ f0] @@ -690,7 +690,7 @@ theorem coe_mapRingHom_eq_coe_map [RingHomClass F R[X] S[X]] (φ : F) (hφ : R[X #align ratfunc.coe_map_ring_hom_eq_coe_map RatFunc.coe_mapRingHom_eq_coe_map set_option maxHeartbeats 300000 in --- TODO: Generalize to `FunLike` classes, +-- TODO: Generalize to `DFunLike` classes, /-- Lift a monoid with zero homomorphism `R[X] →*₀ G₀` to a `RatFunc R →*₀ G₀` on the condition that `φ` maps non zero divisors to non zero divisors, by mapping both the numerator and denominator and quotienting them. -/ @@ -995,7 +995,7 @@ instance : IsFractionRing K[X] (RatFunc K) where variable {K} @[simp] -theorem liftOn_div {P : Sort v} (p q : K[X]) (f : ∀ _p _q : K[X], P) (f0 : ∀ p, f p 0 = f 0 1) +theorem liftOn_div {P : Sort v} (p q : K[X]) (f : K[X] → K[X] → P) (f0 : ∀ p, f p 0 = f 0 1) (H' : ∀ {p q p' q'} (_hq : q ≠ 0) (_hq' : q' ≠ 0), q' * p = q * p' → f p q = f p' q') (H : ∀ {p q p' q'} (_hq : q ∈ K[X]⁰) (_hq' : q' ∈ K[X]⁰), q' * p = q * p' → f p q = f p' q' := fun {p q p' q'} hq hq' h => H' (nonZeroDivisors.ne_zero hq) (nonZeroDivisors.ne_zero hq') h) : @@ -1004,7 +1004,7 @@ theorem liftOn_div {P : Sort v} (p q : K[X]) (f : ∀ _p _q : K[X], P) (f0 : ∀ #align ratfunc.lift_on_div RatFunc.liftOn_div @[simp] -theorem liftOn'_div {P : Sort v} (p q : K[X]) (f : ∀ _p _q : K[X], P) (f0 : ∀ p, f p 0 = f 0 1) +theorem liftOn'_div {P : Sort v} (p q : K[X]) (f : K[X] → K[X] → P) (f0 : ∀ p, f p 0 = f 0 1) (H) : (RatFunc.liftOn' (algebraMap _ (RatFunc K) p / algebraMap _ _ q)) f @H = f p q := by rw [RatFunc.liftOn', liftOn_div _ _ _ f0] diff --git a/Mathlib/FieldTheory/Separable.lean b/Mathlib/FieldTheory/Separable.lean index 8ae70dd7b20d9..fa854edc7f50b 100644 --- a/Mathlib/FieldTheory/Separable.lean +++ b/Mathlib/FieldTheory/Separable.lean @@ -635,8 +635,10 @@ lemma IsSeparable.of_equiv_equiv {A₁ B₁ A₂ B₂ : Type*} [Field A₁] [Fie letI := ((algebraMap A₁ B₁).comp e₁.symm.toRingHom).toAlgebra haveI : IsScalarTower A₁ A₂ B₁ := IsScalarTower.of_algebraMap_eq (fun x ↦ by simp [RingHom.algebraMap_toAlgebra]) - let e : B₁ ≃ₐ[A₂] B₂ := { e₂ with commutes' := fun r ↦ by simpa [RingHom.algebraMap_toAlgebra] - using FunLike.congr_fun he.symm (e₁.symm r) } + let e : B₁ ≃ₐ[A₂] B₂ := + { e₂ with + commutes' := fun r ↦ by + simpa [RingHom.algebraMap_toAlgebra] using DFunLike.congr_fun he.symm (e₁.symm r) } haveI := isSeparable_tower_top_of_isSeparable A₁ A₂ B₁ exact IsSeparable.of_algHom _ _ e.symm.toAlgHom diff --git a/Mathlib/FieldTheory/SeparableDegree.lean b/Mathlib/FieldTheory/SeparableDegree.lean index ff9f8f743c017..fd7a3235d957d 100644 --- a/Mathlib/FieldTheory/SeparableDegree.lean +++ b/Mathlib/FieldTheory/SeparableDegree.lean @@ -7,7 +7,6 @@ import Mathlib.FieldTheory.SplittingField.Construction import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure import Mathlib.FieldTheory.Separable import Mathlib.FieldTheory.NormalClosure -import Mathlib.RingTheory.IntegralDomain import Mathlib.RingTheory.Polynomial.SeparableDegree /-! @@ -25,10 +24,10 @@ This file contains basics about the separable degree of a field extension. **Remark:** if `E / F` is not algebraic, then this definition makes no mathematical sense, and if it is infinite, then its cardinality doesn't behave as expected (namely, not equal to the - field extension degree of `separableClosure F E / F`). For example, if $ F = \mathbb{Q} $ and - $ E = \mathbb{Q}( \mu_{p^\infty} ) $, then $ \operatorname{Emb}_F (E) $ is in bijection with + field extension degree of `separableClosure F E / F`). For example, if $F = \mathbb{Q}$ and + $E = \mathbb{Q}( \mu_{p^\infty} )$, then $\operatorname{Emb}_F (E)$ is in bijection with $\operatorname{Gal}(E/F)$, which is isomorphic to - $ \mathbb{Z}_p^\times $, which is uncountable, while $ [E:F] $ is countable. + $\mathbb{Z}_p^\times$, which is uncountable, while $[E:F]$ is countable. **TODO:** prove or disprove that if `E / F` is algebraic and `Emb F E` is infinite, then `Field.Emb F E` has cardinality `2 ^ Module.rank F (separableClosure F E)`. @@ -321,8 +320,13 @@ theorem natSepDegree_eq_natDegree_iff (hf : f ≠ 0) : /-- If a polynomial is separable, then its separable degree is equal to its degree. -/ theorem natSepDegree_eq_natDegree_of_separable (h : f.Separable) : - f.natSepDegree = f.natDegree := - (natSepDegree_eq_natDegree_iff f h.ne_zero).2 h + f.natSepDegree = f.natDegree := (natSepDegree_eq_natDegree_iff f h.ne_zero).2 h + +variable {f} in +/-- Same as `Polynomial.natSepDegree_eq_natDegree_of_separable`, but enables the use of +dot notation. -/ +theorem Separable.natSepDegree_eq_natDegree (h : f.Separable) : + f.natSepDegree = f.natDegree := natSepDegree_eq_natDegree_of_separable f h /-- If a polynomial splits over `E`, then its separable degree is equal to the number of distinct roots of it over `E`. -/ @@ -402,7 +406,7 @@ the degree of `g`. -/ theorem IsSeparableContraction.natSepDegree_eq {g : Polynomial F} {q : ℕ} [ExpChar F q] (h : IsSeparableContraction q f g) : f.natSepDegree = g.natDegree := by obtain ⟨h1, m, h2⟩ := h - rw [← h2, natSepDegree_expand, natSepDegree_eq_natDegree_of_separable g h1] + rw [← h2, natSepDegree_expand, h1.natSepDegree_eq_natDegree] variable {f} in /-- If a polynomial has separable contraction, then its separable degree is equal to the degree of @@ -436,7 +440,7 @@ theorem natSepDegree_eq_one_iff_of_monic' (q : ℕ) [ExpChar F q] (hm : f.Monic) refine ⟨fun h ↦ ?_, fun ⟨n, y, h⟩ ↦ ?_⟩ · obtain ⟨g, h1, n, rfl⟩ := hi.hasSeparableContraction q have h2 : g.natDegree = 1 := by - rwa [natSepDegree_expand _ q, natSepDegree_eq_natDegree_of_separable g h1] at h + rwa [natSepDegree_expand _ q, h1.natSepDegree_eq_natDegree] at h rw [((monic_expand_iff <| expChar_pow_pos F q n).mp hm).eq_X_add_C h2] exact ⟨n, -(g.coeff 0), by rw [map_neg, sub_neg_eq_add]⟩ rw [h, natSepDegree_expand _ q, natSepDegree_X_sub_C] @@ -583,7 +587,7 @@ theorem finSepDegree_eq_finrank_of_isSeparable [IsSeparable F E] : rw [H L h] at hd by_cases hd' : finSepDegree L E = 0 · rw [← hd, hd', mul_zero] - linarith only [h', hd, Nat.le_mul_of_pos_right (m := finrank F L) (Nat.pos_of_ne_zero hd')] + linarith only [h', hd, Nat.le_mul_of_pos_right (finrank F L) (Nat.pos_of_ne_zero hd')] rw [← finSepDegree_top F, ← finrank_top F E] refine induction_on_adjoin (fun K : IntermediateField F E ↦ finSepDegree F K = finrank F K) (by simp_rw [finSepDegree_bot, IntermediateField.finrank_bot]) (fun L x h ↦ ?_) ⊤ @@ -603,7 +607,7 @@ theorem finSepDegree_eq_finrank_iff [FiniteDimensional F E] : have halg := IsAlgebraic.of_finite F x refine (finSepDegree_adjoin_simple_eq_finrank_iff F E x halg).1 <| le_antisymm (finSepDegree_adjoin_simple_le_finrank F E x halg) <| le_of_not_lt fun h ↦ ?_ - have := Nat.mul_lt_mul h (finSepDegree_le_finrank F⟮x⟯ E) Fin.size_pos' + have := Nat.mul_lt_mul_of_lt_of_le' h (finSepDegree_le_finrank F⟮x⟯ E) Fin.size_pos' rw [finSepDegree_mul_finSepDegree_of_isAlgebraic F F⟮x⟯ E (Algebra.IsAlgebraic.of_finite _ E), FiniteDimensional.finrank_mul_finrank F F⟮x⟯ E] at this linarith only [heq, this]⟩, fun _ ↦ finSepDegree_eq_finrank_of_isSeparable F E⟩ diff --git a/Mathlib/FieldTheory/SplittingField/Construction.lean b/Mathlib/FieldTheory/SplittingField/Construction.lean index 4f6dc5c469054..967738a329eb2 100644 --- a/Mathlib/FieldTheory/SplittingField/Construction.lean +++ b/Mathlib/FieldTheory/SplittingField/Construction.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ import Mathlib.FieldTheory.SplittingField.IsSplittingField +import Mathlib.Algebra.CharP.Algebra #align_import field_theory.splitting_field.construction from "leanprover-community/mathlib"@"e3f4be1fcb5376c4948d7f095bec45350bfb9d1a" @@ -110,7 +111,7 @@ It constructs the type, proves that is a field and algebra over the base field. Uses recursion on the degree. -/ -def SplittingFieldAuxAux (n : ℕ) : ∀ {K : Type u} [Field K], ∀ _ : K[X], +def SplittingFieldAuxAux (n : ℕ) : ∀ {K : Type u} [Field K], K[X] → Σ (L : Type u) (_ : Field L), Algebra K L := -- Porting note: added motive Nat.recOn (motive := fun (_x : ℕ) => ∀ {K : Type u} [_inst_4 : Field K], K[X] → diff --git a/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean b/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean index 2ab079ec52db6..8cb90894c1570 100644 --- a/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean +++ b/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.CharP.Algebra import Mathlib.FieldTheory.IntermediateField import Mathlib.RingTheory.Adjoin.Field diff --git a/Mathlib/FieldTheory/Tower.lean b/Mathlib/FieldTheory/Tower.lean index a57679cb2c8d6..c1aae8b95083a 100644 --- a/Mathlib/FieldTheory/Tower.lean +++ b/Mathlib/FieldTheory/Tower.lean @@ -39,58 +39,11 @@ open BigOperators Cardinal Submodule variable (F : Type u) (K : Type v) (A : Type w) -section Ring - -variable [CommRing F] [Ring K] [AddCommGroup A] - -variable [Algebra F K] [Module K A] [Module F A] [IsScalarTower F K A] - -variable [StrongRankCondition F] [StrongRankCondition K] - [Module.Free F K] [Module.Free K A] - -/-- Tower law: if `A` is a `K`-module and `K` is an extension of `F` then -$\operatorname{rank}_F(A) = \operatorname{rank}_F(K) * \operatorname{rank}_K(A)$. -/ -theorem lift_rank_mul_lift_rank : - Cardinal.lift.{w} (Module.rank F K) * Cardinal.lift.{v} (Module.rank K A) = - Cardinal.lift.{v} (Module.rank F A) := by - -- porting note: `Module.Free.exists_basis` now has implicit arguments, but this is annoying - -- to fix as it is a projection. - obtain ⟨_, b⟩ := Module.Free.exists_basis (R := F) (M := K) - obtain ⟨_, c⟩ := Module.Free.exists_basis (R := K) (M := A) - rw [← (Module.rank F K).lift_id, ← b.mk_eq_rank, ← (Module.rank K A).lift_id, ← c.mk_eq_rank, ← - lift_umax.{w, v}, ← (b.smul c).mk_eq_rank, mk_prod, lift_mul, lift_lift, lift_lift, lift_lift, - lift_lift, lift_umax.{v, w}] -#align lift_rank_mul_lift_rank lift_rank_mul_lift_rank - -/-- Tower law: if `A` is a `K`-module and `K` is an extension of `F` then -$\operatorname{rank}_F(A) = \operatorname{rank}_F(K) * \operatorname{rank}_K(A)$. - -This is a simpler version of `lift_rank_mul_lift_rank` with `K` and `A` in the same universe. -/ -theorem rank_mul_rank (F : Type u) (K A : Type v) [CommRing F] [Ring K] [AddCommGroup A] - [Algebra F K] [Module K A] [Module F A] [IsScalarTower F K A] [StrongRankCondition F] - [StrongRankCondition K] [Module.Free F K] [Module.Free K A] : - Module.rank F K * Module.rank K A = Module.rank F A := by - convert lift_rank_mul_lift_rank F K A <;> rw [lift_id] -#align rank_mul_rank rank_mul_rank - -/-- Tower law: if `A` is a `K`-module and `K` is an extension of `F` then -$\operatorname{rank}_F(A) = \operatorname{rank}_F(K) * \operatorname{rank}_K(A)$. -/ -theorem FiniteDimensional.finrank_mul_finrank' [Module.Finite F K] - [Module.Finite K A] : finrank F K * finrank K A = finrank F A := by - letI := nontrivial_of_invariantBasisNumber F - let b := Module.Free.chooseBasis F K - let c := Module.Free.chooseBasis K A - rw [finrank_eq_card_basis b, finrank_eq_card_basis c, finrank_eq_card_basis (b.smul c), - Fintype.card_prod] -#align finite_dimensional.finrank_mul_finrank' FiniteDimensional.finrank_mul_finrank' - -end Ring - section Field -variable [Field F] [DivisionRing K] [AddCommGroup A] +variable [DivisionRing F] [DivisionRing K] [AddCommGroup A] -variable [Algebra F K] [Module K A] [Module F A] [IsScalarTower F K A] +variable [Module F K] [Module K A] [Module F A] [IsScalarTower F K A] namespace FiniteDimensional @@ -100,15 +53,16 @@ theorem trans [FiniteDimensional F K] [FiniteDimensional K A] : FiniteDimensiona Module.Finite.trans K A #align finite_dimensional.trans FiniteDimensional.trans -/-- In a tower of field extensions `L / K / F`, if `L / F` is finite, so is `K / F`. +/-- In a tower of field extensions `A / K / F`, if `A / F` is finite, so is `K / F`. -(In fact, it suffices that `L` is a nontrivial ring.) +(In fact, it suffices that `A` is a nontrivial ring.) -Note this cannot be an instance as Lean cannot infer `L`. +Note this cannot be an instance as Lean cannot infer `A`. -/ -theorem left (K L : Type*) [Field K] [Algebra F K] [Ring L] [Nontrivial L] [Algebra F L] - [Algebra K L] [IsScalarTower F K L] [FiniteDimensional F L] : FiniteDimensional F K := - FiniteDimensional.of_injective (IsScalarTower.toAlgHom F K L).toLinearMap (RingHom.injective _) +theorem left [Nontrivial A] [FiniteDimensional F A] : FiniteDimensional F K := + let ⟨x, hx⟩ := exists_ne (0 : A) + FiniteDimensional.of_injective + (LinearMap.ringLmapEquivSelf K ℕ A |>.symm x |>.restrictScalars F) (smul_left_injective K hx) #align finite_dimensional.left FiniteDimensional.left theorem right [hf : FiniteDimensional F A] : FiniteDimensional K A := @@ -118,20 +72,8 @@ theorem right [hf : FiniteDimensional F A] : FiniteDimensional K A := exact Submodule.subset_span⟩⟩ #align finite_dimensional.right FiniteDimensional.right -/-- Tower law: if `A` is a `K`-vector space and `K` is a field extension of `F` then -`dim_F(A) = dim_F(K) * dim_K(A)`. - -This is `FiniteDimensional.finrank_mul_finrank'` with one fewer finiteness assumption. -/ -theorem finrank_mul_finrank [FiniteDimensional F K] : finrank F K * finrank K A = finrank F A := by - by_cases hA : FiniteDimensional K A - · replace hA : FiniteDimensional K A := hA -- porting note: broken instance cache - rw [finrank_mul_finrank'] - · rw [finrank_of_infinite_dimensional hA, mul_zero, finrank_of_infinite_dimensional] - exact mt (@right F K A _ _ _ _ _ _ _) hA -#align finite_dimensional.finrank_mul_finrank FiniteDimensional.finrank_mul_finrank - -theorem Subalgebra.isSimpleOrder_of_finrank_prime (A) [Ring A] [IsDomain A] [Algebra F A] - (hp : (finrank F A).Prime) : IsSimpleOrder (Subalgebra F A) := +theorem Subalgebra.isSimpleOrder_of_finrank_prime (F A) [Field F] [Ring A] [IsDomain A] + [Algebra F A] (hp : (finrank F A).Prime) : IsSimpleOrder (Subalgebra F A) := { toNontrivial := ⟨⟨⊥, ⊤, fun he => Nat.not_prime_one ((Subalgebra.bot_eq_top_iff_finrank_eq_one.1 he).subst hp)⟩⟩ @@ -145,23 +87,7 @@ theorem Subalgebra.isSimpleOrder_of_finrank_prime (A) [Ring A] [IsDomain A] [Alg #align finite_dimensional.subalgebra.is_simple_order_of_finrank_prime FiniteDimensional.Subalgebra.isSimpleOrder_of_finrank_prime -- TODO: `IntermediateField` version --- TODO: generalize by removing [FiniteDimensional F K] --- V = ⊕F, --- (V →ₗ[F] K) = ((⊕F) →ₗ[F] K) = (⊕ (F →ₗ[F] K)) = ⊕K -instance _root_.LinearMap.finite_dimensional'' (F : Type u) (K : Type v) (V : Type w) [Field F] - [Field K] [Algebra F K] [FiniteDimensional F K] [AddCommGroup V] [Module F V] - [FiniteDimensional F V] : FiniteDimensional K (V →ₗ[F] K) := - right F _ _ -#align linear_map.finite_dimensional'' LinearMap.finite_dimensional'' - -theorem finrank_linear_map' (F : Type u) (K : Type v) (V : Type w) [Field F] [Field K] [Algebra F K] - [FiniteDimensional F K] [AddCommGroup V] [Module F V] [FiniteDimensional F V] : - finrank K (V →ₗ[F] K) = finrank F V := - mul_right_injective₀ finrank_pos.ne' <| - calc - finrank F K * finrank K (V →ₗ[F] K) = finrank F (V →ₗ[F] K) := finrank_mul_finrank _ _ _ - _ = finrank F V * finrank F K := (finrank_linearMap F V K) - _ = finrank F K * finrank F V := mul_comm _ _ +@[deprecated] alias finrank_linear_map' := FiniteDimensional.finrank_linearMap_self #align finite_dimensional.finrank_linear_map' FiniteDimensional.finrank_linear_map' end FiniteDimensional diff --git a/Mathlib/Geometry/Euclidean/Angle/Oriented/Rotation.lean b/Mathlib/Geometry/Euclidean/Angle/Oriented/Rotation.lean index 3bd4a85aa1a1f..152ddf78a51b8 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Oriented/Rotation.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Oriented/Rotation.lean @@ -128,7 +128,7 @@ theorem linearEquiv_det_rotation (θ : Real.Angle) : LinearEquiv.det (o.rotation θ).toLinearEquiv = 1 := Units.ext <| by -- porting note: Lean can't see through `LinearEquiv.coe_det` and needed the rewrite - -- in mathlib3 this was just `units.ext $ o.det_rotation θ` + -- in mathlib3 this was just `units.ext <| o.det_rotation θ` simpa only [LinearEquiv.coe_det, Units.val_one] using o.det_rotation θ #align orientation.linear_equiv_det_rotation Orientation.linearEquiv_det_rotation diff --git a/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean b/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean index 787f159577ec1..d5a7208a82ab9 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean @@ -5,6 +5,7 @@ Authors: Joseph Myers, Manuel Candales -/ import Mathlib.Analysis.Convex.Between import Mathlib.Geometry.Euclidean.Angle.Unoriented.Basic +import Mathlib.Analysis.NormedSpace.AffineIsometry #align_import geometry.euclidean.angle.unoriented.affine from "leanprover-community/mathlib"@"46b633fd842bef9469441c0209906f6dddd2b4f5" diff --git a/Mathlib/Geometry/Euclidean/Circumcenter.lean b/Mathlib/Geometry/Euclidean/Circumcenter.lean index 1bf8cf5108220..df34b4a1b8d62 100644 --- a/Mathlib/Geometry/Euclidean/Circumcenter.lean +++ b/Mathlib/Geometry/Euclidean/Circumcenter.lean @@ -135,7 +135,7 @@ theorem existsUnique_dist_eq_of_insert {s : AffineSubspace ℝ P} · rintro ⟨cc₃, cr₃⟩ ⟨hcc₃, hcr₃⟩ simp only at hcc₃ hcr₃ obtain ⟨t₃, cc₃', hcc₃', hcc₃''⟩ : - ∃ (r : ℝ)(p0 : P)(_ : p0 ∈ s), cc₃ = r • (p -ᵥ ↑((orthogonalProjection s) p)) +ᵥ p0 := by + ∃ r : ℝ, ∃ p0 ∈ s, cc₃ = r • (p -ᵥ ↑((orthogonalProjection s) p)) +ᵥ p0 := by rwa [mem_affineSpan_insert_iff (orthogonalProjection_mem p)] at hcc₃ have hcr₃' : ∃ r, ∀ p1 ∈ ps, dist p1 cc₃ = r := ⟨cr₃, fun p1 hp1 => dist_of_mem_subset_mk_sphere (Set.mem_insert_of_mem _ hp1) hcr₃⟩ @@ -681,7 +681,7 @@ theorem sum_reflectionCircumcenterWeightsWithCircumcenter {n : ℕ} {i₁ i₂ : simp_rw [sum_pointsWithCircumcenter, reflectionCircumcenterWeightsWithCircumcenter, sum_ite, sum_const, filter_or, filter_eq'] rw [card_union_eq] - · simp + · set_option simprocs false in simp · simpa only [if_true, mem_univ, disjoint_singleton] using h #align affine.simplex.sum_reflection_circumcenter_weights_with_circumcenter Affine.Simplex.sum_reflectionCircumcenterWeightsWithCircumcenter diff --git a/Mathlib/Geometry/Euclidean/Inversion/Basic.lean b/Mathlib/Geometry/Euclidean/Inversion/Basic.lean index 08ee55572da48..dd4e2ab6f1595 100644 --- a/Mathlib/Geometry/Euclidean/Inversion/Basic.lean +++ b/Mathlib/Geometry/Euclidean/Inversion/Basic.lean @@ -22,8 +22,6 @@ Currently, we prove only a few basic lemmas needed to prove Ptolemy's inequality `EuclideanGeometry.mul_dist_le_mul_dist_add_mul_dist`. -/ -set_option autoImplicit true - noncomputable section open Metric Function AffineMap Set AffineSubspace @@ -206,9 +204,9 @@ open EuclideanGeometry ### Continuity of inversion -/ -protected theorem Filter.Tendsto.inversion {l : Filter α} {fc fx : α → P} {fR : α → ℝ} - (hc : Tendsto fc l (𝓝 c)) (hR : Tendsto fR l (𝓝 R)) (hx : Tendsto fx l (𝓝 x)) - (hne : x ≠ c) : +protected theorem Filter.Tendsto.inversion {α : Type*} {x c : P} {R : ℝ} {l : Filter α} + {fc fx : α → P} {fR : α → ℝ} (hc : Tendsto fc l (𝓝 c)) (hR : Tendsto fR l (𝓝 R)) + (hx : Tendsto fx l (𝓝 x)) (hne : x ≠ c) : Tendsto (fun a ↦ inversion (fc a) (fR a) (fx a)) l (𝓝 (inversion c R x)) := (((hR.div (hx.dist hc) <| dist_ne_zero.2 hne).pow 2).smul (hx.vsub hc)).vadd hc diff --git a/Mathlib/Geometry/Euclidean/PerpBisector.lean b/Mathlib/Geometry/Euclidean/PerpBisector.lean index 55e73920e4349..a67219092a363 100644 --- a/Mathlib/Geometry/Euclidean/PerpBisector.lean +++ b/Mathlib/Geometry/Euclidean/PerpBisector.lean @@ -20,12 +20,10 @@ define this subspace. euclidean geometry, perpendicular, perpendicular bisector, line segment bisector, equidistant -/ -set_option autoImplicit true - open Set open scoped BigOperators RealInnerProductSpace -variable [NormedAddCommGroup V] [InnerProductSpace ℝ V] [MetricSpace P] +variable {V P : Type*} [NormedAddCommGroup V] [InnerProductSpace ℝ V] [MetricSpace P] variable [NormedAddTorsor V P] noncomputable section @@ -135,7 +133,7 @@ theorem inner_vsub_vsub_of_dist_eq_of_dist_eq {c₁ c₂ p₁ p₂ : P} (hc₁ : end EuclideanGeometry -variable [NormedAddCommGroup V'] [InnerProductSpace ℝ V'] [MetricSpace P'] +variable {V' P' : Type*} [NormedAddCommGroup V'] [InnerProductSpace ℝ V'] [MetricSpace P'] variable [NormedAddTorsor V' P'] theorem Isometry.preimage_perpBisector {f : P → P'} (h : Isometry f) (p₁ p₂ : P) : diff --git a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean index 7da09659c4592..5fefa8fc75c3b 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean @@ -62,12 +62,12 @@ theorem toDerivation_injective : instance : LinearMapClass (LeftInvariantDerivation I G) 𝕜 C^∞⟮I, G; 𝕜⟯ C^∞⟮I, G; 𝕜⟯ where coe f := f.toDerivation - coe_injective' _ _ h := toDerivation_injective <| FunLike.ext' h + coe_injective' _ _ h := toDerivation_injective <| DFunLike.ext' h map_add f := map_add f.1 map_smulₛₗ f := map_smul f.1.1 instance : CoeFun (LeftInvariantDerivation I G) fun _ => C^∞⟮I, G; 𝕜⟯ → C^∞⟮I, G; 𝕜⟯ := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ variable {M : Type*} [TopologicalSpace M] [ChartedSpace H M] {x : M} {r : 𝕜} {X Y : LeftInvariantDerivation I G} {f f' : C^∞⟮I, G; 𝕜⟯} @@ -82,12 +82,12 @@ theorem toFun_eq_coe : X.toFun = ⇑X := #noalign left_invariant_derivation.to_derivation_eq_coe theorem coe_injective : - @Function.Injective (LeftInvariantDerivation I G) (_ → C^∞⟮I, G; 𝕜⟯) FunLike.coe := - FunLike.coe_injective + @Function.Injective (LeftInvariantDerivation I G) (_ → C^∞⟮I, G; 𝕜⟯) DFunLike.coe := + DFunLike.coe_injective #align left_invariant_derivation.coe_injective LeftInvariantDerivation.coe_injective @[ext] -theorem ext (h : ∀ f, X f = Y f) : X = Y := FunLike.ext _ _ h +theorem ext (h : ∀ f, X f = Y f) : X = Y := DFunLike.ext _ _ h #align left_invariant_derivation.ext LeftInvariantDerivation.ext variable (X Y f) @@ -215,7 +215,7 @@ variable (I G) /-- The coercion to function is a monoid homomorphism. -/ @[simps] def coeFnAddMonoidHom : LeftInvariantDerivation I G →+ C^∞⟮I, G; 𝕜⟯ → C^∞⟮I, G; 𝕜⟯ := - ⟨⟨FunLike.coe, coe_zero⟩, coe_add⟩ + ⟨⟨DFunLike.coe, coe_zero⟩, coe_add⟩ #align left_invariant_derivation.coe_fn_add_monoid_hom LeftInvariantDerivation.coeFnAddMonoidHom variable {I G} diff --git a/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean b/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean index 35536fa87b174..79407a6f802ef 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean @@ -18,13 +18,25 @@ Note that, since a manifold here is not second-countable and Hausdorff a Lie gro guaranteed to be second-countable (even though it can be proved it is Hausdorff). Note also that Lie groups here are not necessarily finite dimensional. -## Main definitions and statements +## Main definitions * `LieAddGroup I G` : a Lie additive group where `G` is a manifold on the model with corners `I`. -* `LieGroup I G` : a Lie multiplicative group where `G` is a manifold on the model with - corners `I`. +* `LieGroup I G` : a Lie multiplicative group where `G` is a manifold on the model with corners `I`. +* `SmoothInv₀`: typeclass for smooth manifolds with `0` and `Inv` such that inversion is a smooth + map at each non-zero point. This includes complete normed fields and (multiplicative) Lie groups. + + +## Main results +* `ContMDiff.inv`, `ContMDiff.div` and variants: point-wise inversion and division of maps `M → G` + is smooth +* `ContMDiff.inv₀` and variants: if `SmoothInv₀ N`, point-wise inversion of smooth maps `f : M → N` + is smooth at all points at which `f` doesn't vanish. + ``ContMDiff.div₀` and variants: if also `SmoothMul N` (i.e., `N` is a Lie group except possibly + for smoothness of inversion at `0`), similar results hold for point-wise division. * `normedSpaceLieAddGroup` : a normed vector space over a nontrivially normed field - is an additive Lie group. + is an additive Lie group. +* `Instances/UnitsOfNormedAlgebra` shows that the group of units of a complete normed `𝕜`-algebra + is a multiplicative Lie group. ## Implementation notes @@ -37,15 +49,12 @@ so the definition does not apply. Hence the definition should be more general, a `I : ModelWithCorners 𝕜 E H`. -/ -set_option autoImplicit true - - noncomputable section open scoped Manifold -- See note [Design choices about smooth algebraic structures] -/-- A Lie (additive) group is a group and a smooth manifold at the same time in which +/-- An additive Lie group is a group and a smooth manifold at the same time in which the addition and negation operations are smooth. -/ class LieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) @@ -55,7 +64,7 @@ class LieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [Top #align lie_add_group LieAddGroup -- See note [Design choices about smooth algebraic structures] -/-- A Lie group is a group and a smooth manifold at the same time in which +/-- A (multiplicative) Lie group is a group and a smooth manifold at the same time in which the multiplication and inverse operations are smooth. -/ @[to_additive] class LieGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] @@ -65,7 +74,13 @@ class LieGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [Topolo smooth_inv : Smooth I I fun a : G => a⁻¹ #align lie_group LieGroup -section LieGroup +/-! + ### Smoothness of inversion, negation, division and subtraction + + Let `f : M → G` be a `C^n` or smooth functions into a Lie group, then `f` is point-wise + invertible with smooth inverse `f`. If `f` and `g` are two such functions, the quotient + `f / g` (i.e., the point-wise product of `f` and the point-wise inverse of `g`) is also smooth. -/ +section PointwiseDivision variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {F : Type*} @@ -81,7 +96,8 @@ section variable (I) -@[to_additive] +/-- In a Lie group, inversion is a smooth map. -/ +@[to_additive "In an additive Lie group, inversion is a smooth map."] theorem smooth_inv : Smooth I I fun x : G => x⁻¹ := LieGroup.smooth_inv #align smooth_inv smooth_inv @@ -208,9 +224,10 @@ nonrec theorem Smooth.div {f g : M → G} (hf : Smooth I' I f) (hg : Smooth I' I #align smooth.div Smooth.div #align smooth.sub Smooth.sub -end LieGroup +end PointwiseDivision -section ProdLieGroup +/-! Binary product of Lie groups -/ +section Product -- Instance of product group @[to_additive] @@ -222,7 +239,7 @@ instance {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalS [Group G'] [LieGroup I' G'] : LieGroup (I.prod I') (G × G') := { SmoothMul.prod _ _ _ _ with smooth_inv := smooth_fst.inv.prod_mk smooth_snd.inv } -end ProdLieGroup +end Product /-! ### Normed spaces are Lie groups -/ @@ -231,7 +248,12 @@ instance normedSpaceLieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E smooth_neg := contDiff_neg.contMDiff #align normed_space_lie_add_group normedSpaceLieAddGroup -section HasSmoothInv +/-! ## Smooth manifolds with smooth inversion away from zero + +Typeclass for smooth manifolds with `0` and `Inv` such that inversion is smooth at all non-zero +points. (This includes multiplicative Lie groups, but also complete normed semifields.) +Point-wise inversion is smooth when the function/denominator is non-zero. -/ +section SmoothInv₀ -- See note [Design choices about smooth algebraic structures] /-- A smooth manifold with `0` and `Inv` such that `fun x ↦ x⁻¹` is smooth at all nonzero points. @@ -268,7 +290,7 @@ theorem hasContinuousInv₀_of_hasSmoothInv₀ : HasContinuousInv₀ G := theorem SmoothOn_inv₀ : SmoothOn I I (Inv.inv : G → G) {0}ᶜ := fun _x hx => (smoothAt_inv₀ I hx).smoothWithinAt -variable {I} +variable {I} {s : Set M} {a : M} theorem ContMDiffWithinAt.inv₀ (hf : ContMDiffWithinAt I' I n f s a) (ha : f a ≠ 0) : ContMDiffWithinAt I' I n (fun x => (f x)⁻¹) s a := @@ -301,8 +323,13 @@ theorem SmoothOn.inv₀ (hf : SmoothOn I' I f s) (h0 : ∀ x ∈ s, f x ≠ 0) : SmoothOn I' I (fun x => (f x)⁻¹) s := ContMDiffOn.inv₀ hf h0 -end HasSmoothInv +end SmoothInv₀ +/-! ### Point-wise division of smooth functions + +If `[SmoothMul I N]` and `[SmoothInv₀ I N]`, point-wise division of smooth functions `f : M → N` +is smooth whenever the denominator is non-zero. (This includes `N` being a completely normed field.) +-/ section Div variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} @@ -310,7 +337,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalS [TopologicalSpace G] [ChartedSpace H G] [GroupWithZero G] [SmoothInv₀ I G] [SmoothMul I G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H' M] - {f g : M → G} + {f g : M → G} {s : Set M} {a : M} {n : ℕ∞} theorem ContMDiffWithinAt.div₀ (hf : ContMDiffWithinAt I' I n f s a) (hg : ContMDiffWithinAt I' I n g s a) (h₀ : g a ≠ 0) : diff --git a/Mathlib/Geometry/Manifold/Algebra/Monoid.lean b/Mathlib/Geometry/Manifold/Algebra/Monoid.lean index f5dd615d84571..8e319601d783c 100644 --- a/Mathlib/Geometry/Manifold/Algebra/Monoid.lean +++ b/Mathlib/Geometry/Manifold/Algebra/Monoid.lean @@ -289,7 +289,7 @@ instance : Inhabited (SmoothMonoidMorphism I I' G G') := @[to_additive] instance : MonoidHomClass (SmoothMonoidMorphism I I' G G') G G' where coe a := a.toFun - coe_injective' f g h := by cases f; cases g; congr; exact FunLike.ext' h + coe_injective' f g h := by cases f; cases g; congr; exact DFunLike.ext' h map_one f := f.map_one map_mul f := f.map_mul diff --git a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean index 2638e41ce7dfb..01ae340e99346 100644 --- a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean +++ b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean @@ -91,14 +91,14 @@ under pointwise multiplication. @[to_additive] instance semigroup {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] : Semigroup C^∞⟮I, N; I', G⟯ := - FunLike.coe_injective.semigroup _ coe_mul + DFunLike.coe_injective.semigroup _ coe_mul #align smooth_map.semigroup SmoothMap.semigroup #align smooth_map.add_semigroup SmoothMap.addSemigroup @[to_additive] instance monoid {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] : Monoid C^∞⟮I, N; I', G⟯ := - FunLike.coe_injective.monoid _ coe_one coe_mul coe_pow + DFunLike.coe_injective.monoid _ coe_one coe_mul coe_pow #align smooth_map.monoid SmoothMap.monoid #align smooth_map.add_monoid SmoothMap.addMonoid @@ -107,7 +107,7 @@ instance monoid {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] Similar to `AddMonoidHom.coeFn`."] def coeFnMonoidHom {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] : C^∞⟮I, N; I', G⟯ →* N → G where - toFun := FunLike.coe + toFun := DFunLike.coe map_one' := coe_one map_mul' := coe_mul #align smooth_map.coe_fn_monoid_hom SmoothMap.coeFnMonoidHom @@ -150,7 +150,7 @@ variable {I I'} @[to_additive] instance commMonoid {G : Type*} [CommMonoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] : CommMonoid C^∞⟮I, N; I', G⟯ := - FunLike.coe_injective.commMonoid _ coe_one coe_mul coe_pow + DFunLike.coe_injective.commMonoid _ coe_one coe_mul coe_pow #align smooth_map.comm_monoid SmoothMap.commMonoid #align smooth_map.add_comm_monoid SmoothMap.addCommMonoid diff --git a/Mathlib/Geometry/Manifold/BumpFunction.lean b/Mathlib/Geometry/Manifold/BumpFunction.lean index 8e9e820bbbea3..eef8da7fbff66 100644 --- a/Mathlib/Geometry/Manifold/BumpFunction.lean +++ b/Mathlib/Geometry/Manifold/BumpFunction.lean @@ -101,7 +101,7 @@ theorem eqOn_source : EqOn f (f.toContDiffBump ∘ extChartAt I c) (chartAt H c) theorem eventuallyEq_of_mem_source (hx : x ∈ (chartAt H c).source) : f =ᶠ[𝓝 x] f.toContDiffBump ∘ extChartAt I c := - f.eqOn_source.eventuallyEq_of_mem <| IsOpen.mem_nhds (chartAt H c).open_source hx + f.eqOn_source.eventuallyEq_of_mem <| (chartAt H c).open_source.mem_nhds hx #align smooth_bump_function.eventually_eq_of_mem_source SmoothBumpFunction.eventuallyEq_of_mem_source theorem one_of_dist_le (hs : x ∈ (chartAt H c).source) @@ -314,10 +314,10 @@ variable [SmoothManifoldWithCorners I M] {I} /-- A smooth bump function is infinitely smooth. -/ protected theorem smooth : Smooth I 𝓘(ℝ) f := by - refine' contMDiff_of_support fun x hx => _ + refine contMDiff_of_tsupport fun x hx => ?_ have : x ∈ (chartAt H c).source := f.tsupport_subset_chartAt_source hx - refine' ContMDiffAt.congr_of_eventuallyEq _ <| f.eqOn_source.eventuallyEq_of_mem <| - IsOpen.mem_nhds (chartAt H c).open_source this + refine ContMDiffAt.congr_of_eventuallyEq ?_ <| f.eqOn_source.eventuallyEq_of_mem <| + (chartAt H c).open_source.mem_nhds this exact f.contDiffAt.contMDiffAt.comp _ (contMDiffAt_extChartAt' this) #align smooth_bump_function.smooth SmoothBumpFunction.smooth @@ -333,7 +333,7 @@ protected theorem continuous : Continuous f := on the source of the chart at `c`, then `f • g` is smooth on the whole manifold. -/ theorem smooth_smul {G} [NormedAddCommGroup G] [NormedSpace ℝ G] {g : M → G} (hg : SmoothOn I 𝓘(ℝ, G) g (chartAt H c).source) : Smooth I 𝓘(ℝ, G) fun x => f x • g x := by - refine contMDiff_of_support fun x hx => ?_ + refine contMDiff_of_tsupport fun x hx => ?_ have : x ∈ (chartAt H c).source -- porting note: was a more readable `calc` -- calc @@ -341,7 +341,7 @@ theorem smooth_smul {G} [NormedAddCommGroup G] [NormedSpace ℝ G] {g : M → G} -- _ ⊆ tsupport f := (tsupport_smul_subset_left _ _) -- _ ⊆ (chart_at _ c).source := f.tsupport_subset_chartAt_source · exact f.tsupport_subset_chartAt_source <| tsupport_smul_subset_left _ _ hx - exact f.smoothAt.smul ((hg _ this).contMDiffAt <| IsOpen.mem_nhds (chartAt _ _).open_source this) + exact f.smoothAt.smul ((hg _ this).contMDiffAt <| (chartAt _ _).open_source.mem_nhds this) #align smooth_bump_function.smooth_smul SmoothBumpFunction.smooth_smul end SmoothBumpFunction diff --git a/Mathlib/Geometry/Manifold/ChartedSpace.lean b/Mathlib/Geometry/Manifold/ChartedSpace.lean index 2ad848a4620ec..caee3bc6596df 100644 --- a/Mathlib/Geometry/Manifold/ChartedSpace.lean +++ b/Mathlib/Geometry/Manifold/ChartedSpace.lean @@ -110,12 +110,9 @@ In the locale `Manifold`, we denote the composition of partial homeomorphisms wi composition of partial equivs with `≫`. -/ -set_option autoImplicit true - - noncomputable section -open Classical Topology Filter +open Topology universe u @@ -170,7 +167,7 @@ structure StructureGroupoid (H : Type u) [TopologicalSpace H] where id_mem' : PartialHomeomorph.refl H ∈ members locality' : ∀ e : PartialHomeomorph H H, (∀ x ∈ e.source, ∃ s, IsOpen s ∧ x ∈ s ∧ e.restr s ∈ members) → e ∈ members - eq_on_source' : ∀ e e' : PartialHomeomorph H H, e ∈ members → e' ≈ e → e' ∈ members + mem_of_eqOnSource' : ∀ e e' : PartialHomeomorph H H, e ∈ members → e' ≈ e → e' ∈ members #align structure_groupoid StructureGroupoid variable [TopologicalSpace H] @@ -201,8 +198,8 @@ instance : Inf (StructureGroupoid H) := refine And.intro hs.left (And.intro hs.right.left ?_) · exact hs.right.right.left · exact hs.right.right.right) - (eq_on_source' := fun e e' he hee' => - ⟨G.eq_on_source' e e' he.left hee', G'.eq_on_source' e e' he.right hee'⟩)⟩ + (mem_of_eqOnSource' := fun e e' he hee' => + ⟨G.mem_of_eqOnSource' e e' he.left hee', G'.mem_of_eqOnSource' e e' he.right hee'⟩)⟩ instance : InfSet (StructureGroupoid H) := ⟨fun S => StructureGroupoid.mk @@ -226,10 +223,10 @@ instance : InfSet (StructureGroupoid H) := intro x hex rcases he x hex with ⟨s, hs⟩ exact ⟨s, ⟨hs.left, ⟨hs.right.left, hs.right.right i hi⟩⟩⟩) - (eq_on_source' := by + (mem_of_eqOnSource' := by simp only [mem_iInter] intro e e' he he'e - exact fun i hi => i.eq_on_source' e e' (he i hi) he'e)⟩ + exact fun i hi => i.mem_of_eqOnSource' e e' (he i hi) he'e)⟩ theorem StructureGroupoid.trans (G : StructureGroupoid H) {e e' : PartialHomeomorph H H} (he : e ∈ G) (he' : e' ∈ G) : e ≫ₕ e' ∈ G := @@ -250,10 +247,10 @@ theorem StructureGroupoid.locality (G : StructureGroupoid H) {e : PartialHomeomo G.locality' e h #align structure_groupoid.locality StructureGroupoid.locality -theorem StructureGroupoid.eq_on_source (G : StructureGroupoid H) {e e' : PartialHomeomorph H H} +theorem StructureGroupoid.mem_of_eqOnSource (G : StructureGroupoid H) {e e' : PartialHomeomorph H H} (he : e ∈ G) (h : e' ≈ e) : e' ∈ G := - G.eq_on_source' e e' he h -#align structure_groupoid.eq_on_source StructureGroupoid.eq_on_source + G.mem_of_eqOnSource' e e' he h +#align structure_groupoid.eq_on_source StructureGroupoid.mem_of_eqOnSource /-- Partial order on the set of groupoids, given by inclusion of the members of the groupoid. -/ instance StructureGroupoid.partialOrder : PartialOrder (StructureGroupoid H) := @@ -311,7 +308,7 @@ def idGroupoid (H : Type u) [TopologicalSpace H] : StructureGroupoid H where · exfalso rw [mem_setOf_eq] at hs rwa [hs] at x's - eq_on_source' e e' he he'e := by + mem_of_eqOnSource' e e' he he'e := by cases' he with he he · left have : e = e' := by @@ -382,7 +379,7 @@ def Pregroupoid.groupoid (PG : Pregroupoid H) : StructureGroupoid H where convert hs.2 using 1 dsimp [PartialHomeomorph.restr] rw [s_open.interior_eq] - eq_on_source' e e' he ee' := by + mem_of_eqOnSource' e e' he ee' := by constructor · apply PG.congr e'.open_source ee'.2 simp only [ee'.1, he.1] @@ -408,11 +405,11 @@ theorem groupoid_of_pregroupoid_le (PG₁ PG₂ : Pregroupoid H) exact ⟨h _ _ he.1, h _ _ he.2⟩ #align groupoid_of_pregroupoid_le groupoid_of_pregroupoid_le -theorem mem_pregroupoid_of_eq_on_source (PG : Pregroupoid H) {e e' : PartialHomeomorph H H} +theorem mem_pregroupoid_of_eqOnSource (PG : Pregroupoid H) {e e' : PartialHomeomorph H H} (he' : e ≈ e') (he : PG.property e e.source) : PG.property e' e'.source := by rw [← he'.1] exact PG.congr e.open_source he'.eqOn.symm he -#align mem_pregroupoid_of_eq_on_source mem_pregroupoid_of_eq_on_source +#align mem_pregroupoid_of_eq_on_source mem_pregroupoid_of_eqOnSource /-- The pregroupoid of all partial maps on a topological space `H`. -/ @[reducible] @@ -472,7 +469,7 @@ def idRestrGroupoid : StructureGroupoid H where members := { e | ∃ (s : Set H) (h : IsOpen s), e ≈ PartialHomeomorph.ofSet s h } trans' := by rintro e e' ⟨s, hs, hse⟩ ⟨s', hs', hse'⟩ - refine' ⟨s ∩ s', IsOpen.inter hs hs', _⟩ + refine ⟨s ∩ s', hs.inter hs', ?_⟩ have := PartialHomeomorph.EqOnSource.trans' hse hse' rwa [PartialHomeomorph.ofSet_trans_ofSet] at this symm' := by @@ -492,7 +489,7 @@ def idRestrGroupoid : StructureGroupoid H where rw [hs.interior_eq] exact hxs simpa only [mfld_simps] using PartialHomeomorph.EqOnSource.eqOn hes' hes - eq_on_source' := by + mem_of_eqOnSource' := by rintro e e' ⟨s, hs, hse⟩ hee' exact ⟨s, hs, Setoid.trans hee' hse⟩ #align id_restr_groupoid idRestrGroupoid @@ -505,7 +502,7 @@ theorem idRestrGroupoid_mem {s : Set H} (hs : IsOpen s) : ofSet s hs ∈ @idRest instance closedUnderRestriction_idRestrGroupoid : ClosedUnderRestriction (@idRestrGroupoid H _) := ⟨by rintro e ⟨s', hs', he⟩ s hs - use s' ∩ s, IsOpen.inter hs' hs + use s' ∩ s, hs'.inter hs refine' Setoid.trans (PartialHomeomorph.EqOnSource.restr he s) _ exact ⟨by simp only [hs.interior_eq, mfld_simps], by simp only [mfld_simps, eqOn_refl]⟩⟩ #align closed_under_restriction_id_restr_groupoid closedUnderRestriction_idRestrGroupoid @@ -518,7 +515,7 @@ theorem closedUnderRestriction_iff_id_le (G : StructureGroupoid H) : · intro _i apply StructureGroupoid.le_iff.mpr rintro e ⟨s, hs, hes⟩ - refine' G.eq_on_source _ hes + refine' G.mem_of_eqOnSource _ hes convert closedUnderRestriction' G.id_mem hs -- Porting note: was -- change s = _ ∩ _ @@ -622,6 +619,16 @@ theorem chart_target_mem_nhds (x : M) : (chartAt H x).target ∈ 𝓝 (chartAt H (chartAt H x).open_target.mem_nhds <| mem_chart_target H x #align chart_target_mem_nhds chart_target_mem_nhds +variable (M) in +@[simp] +theorem iUnion_source_chartAt : (⋃ x : M, (chartAt H x).source) = (univ : Set M) := + eq_univ_iff_forall.mpr fun x ↦ mem_iUnion.mpr ⟨x, mem_chart_source H x⟩ + +theorem ChartedSpace.isOpen_iff (s : Set M) : + IsOpen s ↔ ∀ x : M, IsOpen <| chartAt H x '' ((chartAt H x).source ∩ s) := by + rw [isOpen_iff_of_cover (fun i ↦ (chartAt H i).open_source) (iUnion_source_chartAt H M)] + simp only [(chartAt H _).isOpen_image_iff_of_subset_source (inter_subset_left _ _)] + /-- `achart H x` is the chart at `x`, considered as an element of the atlas. Especially useful for working with `BasicSmoothVectorBundleCore`. -/ def achart (x : M) : atlas H M := @@ -676,7 +683,7 @@ theorem ChartedSpace.locallyCompactSpace [LocallyCompactSpace H] : LocallyCompac rw [← (chartAt H x).symm_map_nhds_eq (mem_chart_source H x)] exact ((compact_basis_nhds (chartAt H x x)).hasBasis_self_subset (chart_target_mem_nhds H x)).map _ - refine locallyCompactSpace_of_hasBasis this ?_ + refine .of_hasBasis this ?_ rintro x s ⟨_, h₂, h₃⟩ exact h₂.image_of_continuousOn ((chartAt H x).continuousOn_symm.mono h₃) #align charted_space.locally_compact ChartedSpace.locallyCompactSpace @@ -792,7 +799,7 @@ instance prodChartedSpace (H : Type*) [TopologicalSpace H] (M : Type*) [Topologi section prodChartedSpace @[ext] -theorem ModelProd.ext {x y : ModelProd α β} (h₁ : x.1 = y.1) (h₂ : x.2 = y.2) : x = y := +theorem ModelProd.ext {x y : ModelProd H H'} (h₁ : x.1 = y.1) (h₂ : x.2 = y.2) : x = y := Prod.ext h₁ h₂ variable [TopologicalSpace H] [TopologicalSpace M] [ChartedSpace H M] [TopologicalSpace H'] @@ -881,7 +888,7 @@ theorem open_target (he : e ∈ c.atlas) : IsOpen e.target := by /-- An element of the atlas in a charted space without topology becomes a partial homeomorphism for the topology constructed from this atlas. The `PartialHomeomorph` version is given in this definition. -/ -protected def localHomeomorph (e : PartialEquiv M H) (he : e ∈ c.atlas) : +protected def partialHomeomorph (e : PartialEquiv M H) (he : e ∈ c.atlas) : @PartialHomeomorph M H c.toTopologicalSpace _ := { c.toTopologicalSpace, e with open_source := by convert c.open_source' he @@ -911,14 +918,14 @@ protected def localHomeomorph (e : PartialEquiv M H) (he : e ∈ c.atlas) : congr 1 exact inter_comm _ _ simpa [PartialEquiv.trans_source, preimage_inter, preimage_comp.symm, A] using this } -#align charted_space_core.local_homeomorph ChartedSpaceCore.localHomeomorph +#align charted_space_core.local_homeomorph ChartedSpaceCore.partialHomeomorph /-- Given a charted space without topology, endow it with a genuine charted space structure with respect to the topology constructed from the atlas. -/ def toChartedSpace : @ChartedSpace H _ M c.toTopologicalSpace := { c.toTopologicalSpace with - atlas := ⋃ (e : PartialEquiv M H) (he : e ∈ c.atlas), {c.localHomeomorph e he} - chartAt := fun x ↦ c.localHomeomorph (c.chartAt x) (c.chart_mem_atlas x) + atlas := ⋃ (e : PartialEquiv M H) (he : e ∈ c.atlas), {c.partialHomeomorph e he} + chartAt := fun x ↦ c.partialHomeomorph (c.chartAt x) (c.chart_mem_atlas x) mem_chart_source := fun x ↦ c.mem_chart_source x chart_mem_atlas := fun x ↦ by simp only [mem_iUnion, mem_singleton_iff] @@ -1034,7 +1041,7 @@ theorem StructureGroupoid.compatible_of_mem_maximalAtlas {e e' : PartialHomeomor _ ≈ (e.symm ≫ₕ ofSet f.source f.open_source) ≫ₕ e' := by rw [trans_assoc] _ ≈ e.symm.restr s ≫ₕ e' := by rw [trans_of_set']; apply refl _ ≈ (e.symm ≫ₕ e').restr s := by rw [restr_trans] - exact G.eq_on_source C (Setoid.symm D) + exact G.mem_of_eqOnSource C (Setoid.symm D) #align structure_groupoid.compatible_of_mem_maximal_atlas StructureGroupoid.compatible_of_mem_maximalAtlas variable (G) @@ -1098,7 +1105,7 @@ theorem singleton_hasGroupoid (h : e.source = Set.univ) (G : StructureGroupoid H intro e' e'' he' he'' rw [e.singletonChartedSpace_mem_atlas_eq h e' he', e.singletonChartedSpace_mem_atlas_eq h e'' he''] - refine' G.eq_on_source _ e.symm_trans_self + refine' G.mem_of_eqOnSource _ e.symm_trans_self have hle : idRestrGroupoid ≤ G := (closedUnderRestriction_iff_id_le G).mp (by assumption) exact StructureGroupoid.le_iff.mp hle _ (idRestrGroupoid_mem _) } #align local_homeomorph.singleton_has_groupoid PartialHomeomorph.singleton_hasGroupoid @@ -1156,7 +1163,8 @@ protected instance instHasGroupoid [ClosedUnderRestriction G] : HasGroupoid s G rw [hc.symm, mem_singleton_iff] at he rw [hc'.symm, mem_singleton_iff] at he' rw [he, he'] - refine' G.eq_on_source _ (subtypeRestr_symm_trans_subtypeRestr s (chartAt H x) (chartAt H x')) + refine' G.mem_of_eqOnSource _ + (subtypeRestr_symm_trans_subtypeRestr s (chartAt H x) (chartAt H x')) apply closedUnderRestriction' · exact G.compatible (chart_mem_atlas _ _) (chart_mem_atlas _ _) · exact isOpen_inter_preimage_symm (chartAt _ _) s.2 @@ -1270,7 +1278,7 @@ def Structomorph.trans (e : Structomorph G M M') (e' : Structomorph G M' M'') : _ ≈ (c.symm ≫ₕ (f₁ ≫ₕ f₂) ≫ₕ c').restr s := by simp only [EqOnSource.restr, trans_assoc, _root_.refl] _ ≈ F₂ := by simp only [feq, _root_.refl] - have : F₂ ∈ G := G.eq_on_source A (Setoid.symm this) + have : F₂ ∈ G := G.mem_of_eqOnSource A (Setoid.symm this) exact this } #align structomorph.trans Structomorph.trans diff --git a/Mathlib/Geometry/Manifold/Complex.lean b/Mathlib/Geometry/Manifold/Complex.lean index a34ebf30f1158..303eb5348086d 100644 --- a/Mathlib/Geometry/Manifold/Complex.lean +++ b/Mathlib/Geometry/Manifold/Complex.lean @@ -5,7 +5,7 @@ Authors: Heather Macbeth -/ import Mathlib.Analysis.Complex.AbsMax import Mathlib.Analysis.LocallyConvex.WithSeminorms -import Mathlib.Geometry.Manifold.MFDeriv +import Mathlib.Geometry.Manifold.MFDeriv.Basic import Mathlib.Topology.LocallyConstant.Basic #align_import geometry.manifold.complex from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean index 8713c9c05f086..a29f49e212b84 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean @@ -20,7 +20,7 @@ embedding `e : M → H`, then `e` is smooth. chain rule, manifolds, higher derivative -/ -open Set Function Filter ChartedSpace SmoothManifoldWithCorners +open Set Filter Function open scoped Topology Manifold @@ -39,21 +39,6 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] {H'' : Type*} [TopologicalSpace H''] {I'' : ModelWithCorners 𝕜 E'' H''} {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H'' M''] - -- declare a smooth manifold `N` over the pair `(F, G)`. - {F : Type*} - [NormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type*} [TopologicalSpace G] - {J : ModelWithCorners 𝕜 F G} {N : Type*} [TopologicalSpace N] [ChartedSpace G N] - [SmoothManifoldWithCorners J N] - -- declare a smooth manifold `N'` over the pair `(F', G')`. - {F' : Type*} - [NormedAddCommGroup F'] [NormedSpace 𝕜 F'] {G' : Type*} [TopologicalSpace G'] - {J' : ModelWithCorners 𝕜 F' G'} {N' : Type*} [TopologicalSpace N'] [ChartedSpace G' N'] - [SmoothManifoldWithCorners J' N'] - -- F₁, F₂, F₃, F₄ are normed spaces - {F₁ : Type*} - [NormedAddCommGroup F₁] [NormedSpace 𝕜 F₁] {F₂ : Type*} [NormedAddCommGroup F₂] - [NormedSpace 𝕜 F₂] {F₃ : Type*} [NormedAddCommGroup F₃] [NormedSpace 𝕜 F₃] {F₄ : Type*} - [NormedAddCommGroup F₄] [NormedSpace 𝕜 F₄] -- declare functions, sets, points and smoothness indices {e : PartialHomeomorph M H} {e' : PartialHomeomorph M' H'} {f f₁ : M → M'} {s s₁ t : Set M} {x : M} {m n : ℕ∞} @@ -340,14 +325,35 @@ theorem smoothWithinAt_one [One M'] : SmoothWithinAt I I' (1 : M → M') s x := end id -theorem contMDiff_of_support {f : M → F} (hf : ∀ x ∈ tsupport f, ContMDiffAt I 𝓘(𝕜, F) n f x) : - ContMDiff I 𝓘(𝕜, F) n f := by +/-- `f` is continuously differentiable if it is cont. differentiable at +each `x ∈ mulTSupport f`. -/ +@[to_additive "`f` is continuously differentiable if it is continuously +differentiable at each `x ∈ tsupport f`."] +theorem contMDiff_of_mulTSupport [One M'] {f : M → M'} + (hf : ∀ x ∈ mulTSupport f, ContMDiffAt I I' n f x) : ContMDiff I I' n f := by intro x - by_cases hx : x ∈ tsupport f + by_cases hx : x ∈ mulTSupport f · exact hf x hx - · refine' ContMDiffAt.congr_of_eventuallyEq _ (eventuallyEq_zero_nhds.2 hx) - exact contMDiffAt_const -#align cont_mdiff_of_support contMDiff_of_support + · exact ContMDiffAt.congr_of_eventuallyEq contMDiffAt_const + (not_mem_mulTSupport_iff_eventuallyEq.1 hx) +#align cont_mdiff_of_support contMDiff_of_tsupport + +-- deprecated since 15 January 2024 +@[deprecated] alias contMDiff_of_support := contMDiff_of_tsupport + +@[to_additive contMDiffWithinAt_of_not_mem] +theorem contMDiffWithinAt_of_not_mem_mulTSupport {f : M → M'} [One M'] {x : M} + (hx : x ∉ mulTSupport f) (n : ℕ∞) (s : Set M) : ContMDiffWithinAt I I' n f s x := by + apply contMDiffWithinAt_const.congr_of_eventuallyEq + (eventually_nhdsWithin_of_eventually_nhds <| not_mem_mulTSupport_iff_eventuallyEq.mp hx) + (image_eq_one_of_nmem_mulTSupport hx) + +/-- `f` is continuously differentiable at each point outside of its `mulTSupport`. -/ +@[to_additive contMDiffAt_of_not_mem] +theorem contMDiffAt_of_not_mem_mulTSupport {f : M → M'} [One M'] {x : M} + (hx : x ∉ mulTSupport f) (n : ℕ∞) : ContMDiffAt I I' n f x := + contMDiffWithinAt_of_not_mem_mulTSupport hx n univ + /-! ### The inclusion map from one open set to another is smooth -/ @@ -366,23 +372,20 @@ theorem contMDiff_subtype_val {n : ℕ∞} {U : Opens M} : ContMDiff I I n (Subt theorem ContMDiff.extend_one [T2Space M] [One M'] {n : ℕ∞} {U : Opens M} {f : U → M'} (supp : HasCompactMulSupport f) (diff : ContMDiff I I' n f) : ContMDiff I I' n (Subtype.val.extend f 1) := fun x ↦ by - by_cases h : x ∈ mulTSupport (Subtype.val.extend f 1) - · rw [show x = ↑(⟨x, Subtype.coe_image_subset _ _ - (supp.mulTSupport_extend_one_subset continuous_subtype_val h)⟩ : U) by rfl, - ← contMdiffAt_subtype_iff, ← comp_def, extend_comp Subtype.val_injective] - exact diff.contMDiffAt - · exact contMDiffAt_const.congr_of_eventuallyEq (not_mem_mulTSupport_iff_eventuallyEq.mp h) + refine contMDiff_of_mulTSupport (fun x h ↦ ?_) _ + lift x to U using Subtype.coe_image_subset _ _ + (supp.mulTSupport_extend_one_subset continuous_subtype_val h) + rw [← contMdiffAt_subtype_iff, ← comp_def, extend_comp Subtype.val_injective] + exact diff.contMDiffAt theorem contMDiff_inclusion {n : ℕ∞} {U V : Opens M} (h : U ≤ V) : ContMDiff I I n (Set.inclusion h : U → V) := by rintro ⟨x, hx : x ∈ U⟩ apply (contDiffWithinAt_localInvariantProp I I n).liftProp_inclusion intro y - dsimp [ContDiffWithinAtProp] + dsimp only [ContDiffWithinAtProp, id_comp, preimage_univ] rw [Set.univ_inter] - refine' contDiffWithinAt_id.congr _ _ - · exact I.rightInvOn - · exact congr_arg I (I.left_inv y) + exact contDiffWithinAt_id.congr I.rightInvOn (congr_arg I (I.left_inv y)) #align cont_mdiff_inclusion contMDiff_inclusion theorem smooth_subtype_iff {U : Opens M} {f : M → M'} {x : U} : @@ -392,8 +395,8 @@ theorem smooth_subtype_val {U : Opens M} : Smooth I I (Subtype.val : U → M) := @[to_additive] theorem Smooth.extend_one [T2Space M] [One M'] {U : Opens M} {f : U → M'} - (supp : HasCompactMulSupport f) (diff : Smooth I I' f) : - Smooth I I' (Subtype.val.extend f 1) := ContMDiff.extend_one supp diff + (supp : HasCompactMulSupport f) (diff : Smooth I I' f) : Smooth I I' (Subtype.val.extend f 1) := + ContMDiff.extend_one supp diff theorem smooth_inclusion {U V : Opens M} (h : U ≤ V) : Smooth I I (Set.inclusion h : U → V) := contMDiff_inclusion h diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean index 392ed7dd07b2a..72a8d61596133 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean @@ -124,7 +124,8 @@ theorem contDiffWithinAt_localInvariantProp (n : ℕ∞) : symm apply contDiffWithinAt_inter have : u ∈ 𝓝 (I.symm (I x)) := by - rw [ModelWithCorners.left_inv]; exact IsOpen.mem_nhds u_open xu + rw [ModelWithCorners.left_inv] + exact u_open.mem_nhds xu apply ContinuousAt.preimage_mem_nhds I.continuous_symm.continuousAt this right_invariance' := by intro s x f e he hx h @@ -165,7 +166,7 @@ theorem contDiffWithinAtProp_mono_of_mem (n : ℕ∞) ⦃s x t⦄ ⦃f : H → H #align cont_diff_within_at_prop_mono_of_mem contDiffWithinAtProp_mono_of_mem theorem contDiffWithinAtProp_id (x : H) : ContDiffWithinAtProp I I n id univ x := by - simp only [ContDiffWithinAtProp._eq_1, comp.left_id, preimage_univ, univ_inter] + simp only [ContDiffWithinAtProp, id_comp, preimage_univ, univ_inter] have : ContDiffWithinAt 𝕜 n id (range I) (I x) := contDiff_id.contDiffAt.contDiffWithinAt refine this.congr (fun y hy => ?_) ?_ · simp only [ModelWithCorners.right_inv I hy, mfld_simps] @@ -361,7 +362,7 @@ theorem contMDiffWithinAt_iff_target : and_iff_left_of_imp <| (continuousAt_extChartAt _ _).comp_continuousWithinAt simp_rw [cont, ContDiffWithinAtProp, extChartAt, PartialHomeomorph.extend, PartialEquiv.coe_trans, ModelWithCorners.toPartialEquiv_coe, PartialHomeomorph.coe_coe, modelWithCornersSelf_coe, - chartAt_self_eq, PartialHomeomorph.refl_apply, comp.left_id] + chartAt_self_eq, PartialHomeomorph.refl_apply, id_comp] rfl #align cont_mdiff_within_at_iff_target contMDiffWithinAt_iff_target @@ -582,7 +583,7 @@ theorem contMDiffOn_iff_target : ∀ y : M', ContMDiffOn I 𝓘(𝕜, E') n (extChartAt I' y ∘ f) (s ∩ f ⁻¹' (extChartAt I' y).source) := by simp only [contMDiffOn_iff, ModelWithCorners.source_eq, chartAt_self_eq, - PartialHomeomorph.refl_localEquiv, PartialEquiv.refl_trans, extChartAt, + PartialHomeomorph.refl_partialEquiv, PartialEquiv.refl_trans, extChartAt, PartialHomeomorph.extend, Set.preimage_univ, Set.inter_univ, and_congr_right_iff] intro h constructor @@ -902,6 +903,10 @@ theorem contMDiffOn_congr (h₁ : ∀ y ∈ s, f₁ y = f y) : (contDiffWithinAt_localInvariantProp I I' n).liftPropOn_congr_iff h₁ #align cont_mdiff_on_congr contMDiffOn_congr +theorem ContMDiffOn.congr_mono (hf : ContMDiffOn I I' n f s) (h₁ : ∀ y ∈ s₁, f₁ y = f y) + (hs : s₁ ⊆ s) : ContMDiffOn I I' n f₁ s₁ := + (hf.mono hs).congr h₁ + /-! ### Locality -/ diff --git a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean index 29c91bfdbd422..299a9610cc6a5 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Floris van Doorn -/ -import Mathlib.Geometry.Manifold.MFDeriv +import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential import Mathlib.Geometry.Manifold.ContMDiffMap #align_import geometry.manifold.cont_mdiff_mfderiv from "leanprover-community/mathlib"@"e473c3198bb41f68560cab68a0529c854b618833" @@ -59,7 +59,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {s s₁ t : Set M} {x : M} {m n : ℕ∞} -- Porting note: section about deducing differentiability from smoothness moved to --- `Geometry.Manifold.MFDeriv` +-- `Geometry.Manifold.MFDeriv.Basic` /-! ### The derivative of a smooth function is smooth -/ @@ -381,7 +381,7 @@ theorem ContMDiffOn.contMDiffOn_tangentMapWithin (hf : ContMDiffOn I I' n f s) ( suffices h : ContMDiffOn I.tangent I'.tangent m (tangentMapWithin I I' f s) s'_lift · refine' ⟨π E (TangentSpace I) ⁻¹' (o ∩ l.source), _, _, _⟩ show IsOpen (π E (TangentSpace I) ⁻¹' (o ∩ l.source)); - exact (IsOpen.inter o_open l.open_source).preimage (FiberBundle.continuous_proj E _) + exact (o_open.inter l.open_source).preimage (FiberBundle.continuous_proj E _) show p ∈ π E (TangentSpace I) ⁻¹' (o ∩ l.source) · simp have : p.proj ∈ f ⁻¹' r.source ∩ s := by simp [hp] @@ -490,7 +490,8 @@ theorem ContMDiffOn.contMDiffOn_tangentMapWithin (hf : ContMDiffOn I I' n f s) ( tangentMapWithin I' I' r r.source (tangentMapWithin I I' f s' q) = tangentMap I' I' r (tangentMapWithin I I' f s' q) := by apply tangentMapWithin_eq_tangentMap - · apply IsOpen.uniqueMDiffWithinAt _ r.open_source; simp [hq] + · apply r.open_source.uniqueMDiffWithinAt _ + simp [hq] · exact mdifferentiableAt_atlas I' (chart_mem_atlas H' (f p.proj)) hq.1.1 have : f p.proj = (tangentMapWithin I I' f s p).1 := rfl rw [A] diff --git a/Mathlib/Geometry/Manifold/ContMDiffMap.lean b/Mathlib/Geometry/Manifold/ContMDiffMap.lean index a1c80476ad85f..7ade4189a204f 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMap.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMap.lean @@ -48,10 +48,10 @@ namespace ContMDiffMap variable {I} {I'} {M} {M'} {n} -instance funLike : FunLike C^n⟮I, M; I', M'⟯ M fun _ => M' where +instance instFunLike : FunLike C^n⟮I, M; I', M'⟯ M M' where coe := Subtype.val coe_injective' := Subtype.coe_injective -#align cont_mdiff_map.fun_like ContMDiffMap.funLike +#align cont_mdiff_map.fun_like ContMDiffMap.instFunLike protected theorem contMDiff (f : C^n⟮I, M; I', M'⟯) : ContMDiff I I' n f := f.prop @@ -65,22 +65,22 @@ protected theorem smooth (f : C^∞⟮I, M; I', M'⟯) : Smooth I I' f := -- instance : Coe C^n⟮I, M; I', M'⟯ C(M, M') := -- ⟨fun f => ⟨f, f.contMDiff.continuous⟩⟩ -attribute [to_additive_ignore_args 21] ContMDiffMap ContMDiffMap.funLike +attribute [to_additive_ignore_args 21] ContMDiffMap ContMDiffMap.instFunLike variable {f g : C^n⟮I, M; I', M'⟯} @[simp] theorem coeFn_mk (f : M → M') (hf : ContMDiff I I' n f) : - FunLike.coe (F := C^n⟮I, M; I', M'⟯) ⟨f, hf⟩ = f := + DFunLike.coe (F := C^n⟮I, M; I', M'⟯) ⟨f, hf⟩ = f := rfl #align cont_mdiff_map.coe_fn_mk ContMDiffMap.coeFn_mk theorem coe_injective ⦃f g : C^n⟮I, M; I', M'⟯⦄ (h : (f : M → M') = g) : f = g := - FunLike.ext' h + DFunLike.ext' h #align cont_mdiff_map.coe_inj ContMDiffMap.coe_injective @[ext] -theorem ext (h : ∀ x, f x = g x) : f = g := FunLike.ext _ _ h +theorem ext (h : ∀ x, f x = g x) : f = g := DFunLike.ext _ _ h #align cont_mdiff_map.ext ContMDiffMap.ext instance : ContinuousMapClass C^n⟮I, M; I', M'⟯ M M' where diff --git a/Mathlib/Geometry/Manifold/DerivationBundle.lean b/Mathlib/Geometry/Manifold/DerivationBundle.lean index d39f60907fb07..48fc3cb03afff 100644 --- a/Mathlib/Geometry/Manifold/DerivationBundle.lean +++ b/Mathlib/Geometry/Manifold/DerivationBundle.lean @@ -50,9 +50,9 @@ namespace PointedSmoothMap open scoped Derivation -instance funLike {x : M} : FunLike C^∞⟮I, M; 𝕜⟯⟨x⟩ M fun _ => 𝕜 := - ContMDiffMap.funLike -#align pointed_smooth_map.fun_like PointedSmoothMap.funLike +instance instFunLike {x : M} : FunLike C^∞⟮I, M; 𝕜⟯⟨x⟩ M 𝕜 := + ContMDiffMap.instFunLike +#align pointed_smooth_map.fun_like PointedSmoothMap.instFunLike instance {x : M} : CommRing C^∞⟮I, M; 𝕜⟯⟨x⟩ := SmoothMap.commRing diff --git a/Mathlib/Geometry/Manifold/Diffeomorph.lean b/Mathlib/Geometry/Manifold/Diffeomorph.lean index 995a04d616bf6..a8fa7c182e6e5 100644 --- a/Mathlib/Geometry/Manifold/Diffeomorph.lean +++ b/Mathlib/Geometry/Manifold/Diffeomorph.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Nicolò Cavalleri, Yury Kudryashov -/ import Mathlib.Geometry.Manifold.ContMDiffMap -import Mathlib.Geometry.Manifold.MFDeriv +import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential #align_import geometry.manifold.diffeomorph from "leanprover-community/mathlib"@"e354e865255654389cc46e6032160238df2e0f40" @@ -99,7 +99,7 @@ instance : EquivLike (M ≃ₘ^n⟮I, I'⟯ M') M M' where inv Φ := Φ.toEquiv.symm left_inv Φ := Φ.left_inv right_inv Φ := Φ.right_inv - coe_injective' _ _ h _ := toEquiv_injective <| FunLike.ext' h + coe_injective' _ _ h _ := toEquiv_injective <| DFunLike.ext' h /-- Interpret a diffeomorphism as a `ContMDiffMap`. -/ @[coe] @@ -160,7 +160,7 @@ theorem toEquiv_inj {h h' : M ≃ₘ^n⟮I, I'⟯ M'} : h.toEquiv = h'.toEquiv /-- Coercion to function `λ h : M ≃ₘ^n⟮I, I'⟯ M', (h : M → M')` is injective. -/ theorem coeFn_injective : Injective ((↑) : (M ≃ₘ^n⟮I, I'⟯ M') → (M → M')) := - FunLike.coe_injective + DFunLike.coe_injective #align diffeomorph.coe_fn_injective Diffeomorph.coeFn_injective @[ext] diff --git a/Mathlib/Geometry/Manifold/Instances/Sphere.lean b/Mathlib/Geometry/Manifold/Instances/Sphere.lean index c84328c8ea028..9f59ac591ff1a 100644 --- a/Mathlib/Geometry/Manifold/Instances/Sphere.lean +++ b/Mathlib/Geometry/Manifold/Instances/Sphere.lean @@ -10,7 +10,7 @@ import Mathlib.Analysis.InnerProductSpace.Calculus import Mathlib.Analysis.InnerProductSpace.PiL2 import Mathlib.Geometry.Manifold.Algebra.LieGroup import Mathlib.Geometry.Manifold.Instances.Real -import Mathlib.Geometry.Manifold.MFDeriv +import Mathlib.Geometry.Manifold.MFDeriv.Basic #align_import geometry.manifold.instances.sphere from "leanprover-community/mathlib"@"0dc4079202c28226b2841a51eb6d3cc2135bb80f" @@ -568,7 +568,7 @@ theorem mfderiv_coe_sphere_injective {n : ℕ} [Fact (finrank ℝ E = n + 1)] (v (ℝ ∙ (↑(-v) : E))ᗮ.subtypeL (U.symm 0) := by convert hasFDerivAt_stereoInvFunAux_comp_coe (-v : E) simp - have := congr_arg FunLike.coe <| (this.comp 0 U.symm.toContinuousLinearEquiv.hasFDerivAt).fderiv + have := congr_arg DFunLike.coe <| (this.comp 0 U.symm.toContinuousLinearEquiv.hasFDerivAt).fderiv refine Eq.subst this.symm ?_ rw [ContinuousLinearMap.coe_comp', ContinuousLinearEquiv.coe_coe] simpa using Subtype.coe_injective diff --git a/Mathlib/Geometry/Manifold/IntegralCurve.lean b/Mathlib/Geometry/Manifold/IntegralCurve.lean new file mode 100644 index 0000000000000..2cf8f42e28d23 --- /dev/null +++ b/Mathlib/Geometry/Manifold/IntegralCurve.lean @@ -0,0 +1,504 @@ +/- +Copyright (c) 2023 Winston Yin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Winston Yin +-/ +import Mathlib.Analysis.ODE.Gronwall +import Mathlib.Analysis.ODE.PicardLindelof +import Mathlib.Geometry.Manifold.InteriorBoundary +import Mathlib.Geometry.Manifold.MFDeriv.Atlas + +/-! +# Integral curves of vector fields on a manifold + +Let `M` be a manifold and `v : (x : M) → TangentSpace I x` be a vector field on `M`. An integral +curve of `v` is a function `γ : ℝ → M` such that the derivative of `γ` at `t` equals `v (γ t)`. The +integral curve may only be defined for all `t` within some subset of `ℝ`. + +## Main definitions + +Let `v : M → TM` be a vector field on `M`, and let `γ : ℝ → M`. +* `IsIntegralCurve γ v`: `γ t` is tangent to `v (γ t)` for all `t : ℝ`. That is, `γ` is a global +integral curve of `v`. +* `IsIntegralCurveOn γ v s`: `γ t` is tangent to `v (γ t)` for all `t ∈ s`, where `s : Set ℝ`. +* `IsIntegralCurveAt γ v t₀`: `γ t` is tangent to `v (γ t)` for all `t` in some open interval +around `t₀`. That is, `γ` is a local integral curve of `v`. + +For `IsIntegralCurveOn γ v s` and `IsIntegralCurveAt γ v t₀`, even though `γ` is defined for all +time, its value outside of the set `s` or a small interval around `t₀` is irrelevant and considered +junk. + +## Main results + +* `exists_isIntegralCurveAt_of_contMDiffAt_boundaryless`: Existence of local integral curves for a +$C^1$ vector field. This follows from the existence theorem for solutions to ODEs +(`exists_forall_hasDerivAt_Ioo_eq_of_contDiffAt`). +* `isIntegralCurveOn_Ioo_eqOn_of_contMDiff_boundaryless`: Uniqueness of local integral curves for a +$C^1$ vector field. This follows from the uniqueness theorem for solutions to ODEs +(`ODE_solution_unique_of_mem_set_Ioo`). This requires the manifold to be Hausdorff (`T2Space`). + +## Implementation notes + +For the existence and uniqueness theorems, we assume that the image of the integral curve lies in +the interior of the manifold. The case where the integral curve may lie on the boundary of the +manifold requires special treatment, and we leave it as a TODO. + +We state simpler versions of the theorem for boundaryless manifolds as corollaries. + +## TODO + +* The case where the integral curve may venture to the boundary of the manifold. See Theorem 9.34, +Lee. May require submanifolds. + +## Reference +* Lee, J. M. (2012). _Introduction to Smooth Manifolds_. Springer New York. + +## Tags + +integral curve, vector field, local existence, uniqueness +-/ + +open scoped Manifold Topology + +open Set + +variable + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + {H : Type*} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] + +/-- If `γ : ℝ → M` is $C^1$ on `s : Set ℝ` and `v` is a vector field on `M`, +`IsIntegralCurveOn γ v s` means `γ t` is tangent to `v (γ t)` for all `t ∈ s`. The value of `γ` +outside of `s` is irrelevant and considered junk. -/ +def IsIntegralCurveOn (γ : ℝ → M) (v : (x : M) → TangentSpace I x) (s : Set ℝ) : Prop := + ∀ t ∈ s, HasMFDerivAt 𝓘(ℝ, ℝ) I γ t ((1 : ℝ →L[ℝ] ℝ).smulRight <| v (γ t)) + +/-- If `v` is a vector field on `M` and `t₀ : ℝ`, `IsIntegralCurveAt γ v t₀` means `γ : ℝ → M` is a +local integral curve of `v` in a neighbourhood containing `t₀`. The value of `γ` outside of this +interval is irrelevant and considered junk. -/ +def IsIntegralCurveAt (γ : ℝ → M) (v : (x : M) → TangentSpace I x) (t₀ : ℝ) : Prop := + ∀ᶠ t in 𝓝 t₀, HasMFDerivAt 𝓘(ℝ, ℝ) I γ t ((1 : ℝ →L[ℝ] ℝ).smulRight <| v (γ t)) + +/-- If `v : M → TM` is a vector field on `M`, `IsIntegralCurve γ v` means `γ : ℝ → M` is a global +integral curve of `v`. That is, `γ t` is tangent to `v (γ t)` for all `t : ℝ`. -/ +def IsIntegralCurve (γ : ℝ → M) (v : (x : M) → TangentSpace I x) : Prop := + ∀ t : ℝ, HasMFDerivAt 𝓘(ℝ, ℝ) I γ t ((1 : ℝ →L[ℝ] ℝ).smulRight (v (γ t))) + +variable {γ γ' : ℝ → M} {v : (x : M) → TangentSpace I x} {s s' : Set ℝ} {t₀ : ℝ} + +lemma IsIntegralCurve.isIntegralCurveOn (h : IsIntegralCurve γ v) (s : Set ℝ) : + IsIntegralCurveOn γ v s := fun t _ ↦ h t + +lemma isIntegralCurve_iff_isIntegralCurveOn : IsIntegralCurve γ v ↔ IsIntegralCurveOn γ v univ := + ⟨fun h ↦ h.isIntegralCurveOn _, fun h t ↦ h t (mem_univ _)⟩ + +lemma isIntegralCurveAt_iff : + IsIntegralCurveAt γ v t₀ ↔ ∃ s ∈ 𝓝 t₀, IsIntegralCurveOn γ v s := by + simp_rw [IsIntegralCurveOn, ← Filter.eventually_iff_exists_mem, IsIntegralCurveAt] + +/-- `γ` is an integral curve for `v` at `t₀` iff `γ` is an integral curve on some interval +containing `t₀`. -/ +lemma isIntegralCurveAt_iff' : + IsIntegralCurveAt γ v t₀ ↔ ∃ ε > 0, IsIntegralCurveOn γ v (Metric.ball t₀ ε) := by + simp_rw [IsIntegralCurveOn, ← Metric.eventually_nhds_iff_ball, IsIntegralCurveAt] + +lemma IsIntegralCurve.isIntegralCurveAt (h : IsIntegralCurve γ v) (t : ℝ) : + IsIntegralCurveAt γ v t := isIntegralCurveAt_iff.mpr ⟨univ, Filter.univ_mem, fun t _ ↦ h t⟩ + +lemma isIntegralCurve_iff_isIntegralCurveAt : + IsIntegralCurve γ v ↔ ∀ t : ℝ, IsIntegralCurveAt γ v t := + ⟨fun h ↦ h.isIntegralCurveAt, fun h t ↦ by + obtain ⟨s, hs, h⟩ := isIntegralCurveAt_iff.mp (h t) + exact h t (mem_of_mem_nhds hs)⟩ + +lemma IsIntegralCurveOn.mono (h : IsIntegralCurveOn γ v s) (hs : s' ⊆ s) : + IsIntegralCurveOn γ v s' := fun t ht ↦ h t (mem_of_mem_of_subset ht hs) + +lemma IsIntegralCurveOn.of_union (h : IsIntegralCurveOn γ v s) (h' : IsIntegralCurveOn γ v s') : + IsIntegralCurveOn γ v (s ∪ s') := fun _ ↦ fun | .inl ht => h _ ht | .inr ht => h' _ ht + +lemma IsIntegralCurveAt.hasMFDerivAt (h : IsIntegralCurveAt γ v t₀) : + HasMFDerivAt 𝓘(ℝ, ℝ) I γ t₀ ((1 : ℝ →L[ℝ] ℝ).smulRight (v (γ t₀))) := + have ⟨_, hs, h⟩ := isIntegralCurveAt_iff.mp h + h t₀ (mem_of_mem_nhds hs) + +lemma IsIntegralCurveOn.isIntegralCurveAt (h : IsIntegralCurveOn γ v s) (hs : s ∈ 𝓝 t₀) : + IsIntegralCurveAt γ v t₀ := isIntegralCurveAt_iff.mpr ⟨s, hs, h⟩ + +/-- If `γ` is an integral curve at each `t ∈ s`, it is an integral curve on `s`. -/ +lemma IsIntegralCurveAt.isIntegralCurveOn (h : ∀ t ∈ s, IsIntegralCurveAt γ v t) : + IsIntegralCurveOn γ v s := by + intros t ht + obtain ⟨s, hs, h⟩ := isIntegralCurveAt_iff.mp (h t ht) + exact h t (mem_of_mem_nhds hs) + +lemma isIntegralCurveOn_iff_isIntegralCurveAt (hs : IsOpen s) : + IsIntegralCurveOn γ v s ↔ ∀ t ∈ s, IsIntegralCurveAt γ v t := + ⟨fun h _ ht ↦ h.isIntegralCurveAt (hs.mem_nhds ht), IsIntegralCurveAt.isIntegralCurveOn⟩ + +lemma IsIntegralCurveOn.continuousAt (hγ : IsIntegralCurveOn γ v s) (ht : t₀ ∈ s) : + ContinuousAt γ t₀ := (hγ t₀ ht).1 + +lemma IsIntegralCurveOn.continuousOn (hγ : IsIntegralCurveOn γ v s) : + ContinuousOn γ s := fun t ht ↦ (hγ t ht).1.continuousWithinAt + +lemma IsIntegralCurveAt.continuousAt (hγ : IsIntegralCurveAt γ v t₀) : + ContinuousAt γ t₀ := + have ⟨_, hs, hγ⟩ := isIntegralCurveAt_iff.mp hγ + hγ.continuousAt <| mem_of_mem_nhds hs + +lemma IsIntegralCurve.continuous (hγ : IsIntegralCurve γ v) : + Continuous γ := continuous_iff_continuousAt.mpr + fun _ ↦ (hγ.isIntegralCurveOn univ).continuousAt (mem_univ _) + +/-- If `γ` is an integral curve of a vector field `v`, then `γ t` is tangent to `v (γ t)` when + expressed in the local chart around the initial point `γ t₀`. -/ +lemma IsIntegralCurveOn.hasDerivAt (hγ : IsIntegralCurveOn γ v s) {t : ℝ} (ht : t ∈ s) + (hsrc : γ t ∈ (extChartAt I (γ t₀)).source) : + HasDerivAt ((extChartAt I (γ t₀)) ∘ γ) + (tangentCoordChange I (γ t) (γ t₀) (γ t) (v (γ t))) t := by + -- turn `HasDerivAt` into comp of `HasMFDerivAt` + have hsrc := extChartAt_source I (γ t₀) ▸ hsrc + rw [hasDerivAt_iff_hasFDerivAt, ← hasMFDerivAt_iff_hasFDerivAt] + apply (HasMFDerivAt.comp t + (hasMFDerivAt_extChartAt I hsrc) (hγ _ ht)).congr_mfderiv + rw [ContinuousLinearMap.ext_iff] + intro a + rw [ContinuousLinearMap.comp_apply, ContinuousLinearMap.smulRight_apply, map_smul, + ← ContinuousLinearMap.one_apply (R₁ := ℝ) a, ← ContinuousLinearMap.smulRight_apply, + mfderiv_chartAt_eq_tangentCoordChange I hsrc] + rfl + +lemma IsIntegralCurveAt.eventually_hasDerivAt (hγ : IsIntegralCurveAt γ v t₀) : + ∀ᶠ t in 𝓝 t₀, HasDerivAt ((extChartAt I (γ t₀)) ∘ γ) + (tangentCoordChange I (γ t) (γ t₀) (γ t) (v (γ t))) t := by + apply eventually_mem_nhds.mpr + (hγ.continuousAt.preimage_mem_nhds (extChartAt_source_mem_nhds I _)) |>.and hγ |>.mono + rintro t ⟨ht1, ht2⟩ + have hsrc := mem_of_mem_nhds ht1 + rw [mem_preimage, extChartAt_source I (γ t₀)] at hsrc + rw [hasDerivAt_iff_hasFDerivAt, ← hasMFDerivAt_iff_hasFDerivAt] + apply (HasMFDerivAt.comp t (hasMFDerivAt_extChartAt I hsrc) ht2).congr_mfderiv + rw [ContinuousLinearMap.ext_iff] + intro a + rw [ContinuousLinearMap.comp_apply, ContinuousLinearMap.smulRight_apply, map_smul, + ← ContinuousLinearMap.one_apply (R₁ := ℝ) a, ← ContinuousLinearMap.smulRight_apply, + mfderiv_chartAt_eq_tangentCoordChange I hsrc] + rfl + +/-! ### Translation lemmas -/ + +section Translation + +lemma IsIntegralCurveOn.comp_add (hγ : IsIntegralCurveOn γ v s) (dt : ℝ) : + IsIntegralCurveOn (γ ∘ (· + dt)) v { t | t + dt ∈ s } := by + intros t ht + rw [Function.comp_apply, + ← ContinuousLinearMap.comp_id (ContinuousLinearMap.smulRight 1 (v (γ (t + dt))))] + apply HasMFDerivAt.comp t (hγ (t + dt) ht) + refine ⟨(continuous_add_right _).continuousAt, ?_⟩ + simp only [mfld_simps, hasFDerivWithinAt_univ] + exact HasFDerivAt.add_const (hasFDerivAt_id _) _ + +lemma isIntegralCurveOn_comp_add {dt : ℝ} : + IsIntegralCurveOn γ v s ↔ IsIntegralCurveOn (γ ∘ (· + dt)) v { t | t + dt ∈ s } := by + refine ⟨fun hγ ↦ hγ.comp_add _, fun hγ ↦ ?_⟩ + convert hγ.comp_add (-dt) + · ext t + simp only [Function.comp_apply, neg_add_cancel_right] + · simp only [mem_setOf_eq, neg_add_cancel_right, setOf_mem_eq] + +lemma IsIntegralCurveAt.comp_add (hγ : IsIntegralCurveAt γ v t₀) (dt : ℝ) : + IsIntegralCurveAt (γ ∘ (· + dt)) v (t₀ - dt) := by + rw [isIntegralCurveAt_iff'] at * + obtain ⟨ε, hε, h⟩ := hγ + refine ⟨ε, hε, ?_⟩ + convert h.comp_add dt + ext t + rw [mem_setOf_eq, Metric.mem_ball, Metric.mem_ball, dist_sub_eq_dist_add_right] + +lemma isIntegralCurveAt_comp_add {dt : ℝ} : + IsIntegralCurveAt γ v t₀ ↔ IsIntegralCurveAt (γ ∘ (· + dt)) v (t₀ - dt) := by + refine ⟨fun hγ ↦ hγ.comp_add _, fun hγ ↦ ?_⟩ + convert hγ.comp_add (-dt) + · ext t + simp only [Function.comp_apply, neg_add_cancel_right] + · simp only [sub_neg_eq_add, sub_add_cancel] + +lemma IsIntegralCurve.comp_add (hγ : IsIntegralCurve γ v) (dt : ℝ) : + IsIntegralCurve (γ ∘ (· + dt)) v := by + rw [isIntegralCurve_iff_isIntegralCurveOn] at * + exact hγ.comp_add _ + +lemma isIntegralCurve_comp_add {dt : ℝ} : + IsIntegralCurve γ v ↔ IsIntegralCurve (γ ∘ (· + dt)) v := by + refine ⟨fun hγ ↦ hγ.comp_add _, fun hγ ↦ ?_⟩ + convert hγ.comp_add (-dt) + ext t + simp only [Function.comp_apply, neg_add_cancel_right] + +end Translation + +/-! ### Scaling lemmas -/ + +section Scaling + +lemma IsIntegralCurveOn.comp_mul (hγ : IsIntegralCurveOn γ v s) (a : ℝ) : + IsIntegralCurveOn (γ ∘ (· * a)) (a • v) { t | t * a ∈ s } := by + intros t ht + rw [Function.comp_apply, Pi.smul_apply, ← ContinuousLinearMap.smulRight_comp] + refine HasMFDerivAt.comp t (hγ (t * a) ht) ⟨(continuous_mul_right _).continuousAt, ?_⟩ + simp only [mfld_simps, hasFDerivWithinAt_univ] + exact HasFDerivAt.mul_const' (hasFDerivAt_id _) _ + +lemma isIntegralCurveOn_comp_mul_ne_zero {a : ℝ} (ha : a ≠ 0) : + IsIntegralCurveOn γ v s ↔ IsIntegralCurveOn (γ ∘ (· * a)) (a • v) { t | t * a ∈ s } := by + refine ⟨fun hγ ↦ hγ.comp_mul a, fun hγ ↦ ?_⟩ + convert hγ.comp_mul a⁻¹ + · ext t + simp only [Function.comp_apply, mul_assoc, inv_mul_eq_div, div_self ha, mul_one] + · simp only [smul_smul, inv_mul_eq_div, div_self ha, one_smul] + · simp only [mem_setOf_eq, mul_assoc, inv_mul_eq_div, div_self ha, mul_one, setOf_mem_eq] + +lemma IsIntegralCurveAt.comp_mul_ne_zero (hγ : IsIntegralCurveAt γ v t₀) {a : ℝ} (ha : a ≠ 0) : + IsIntegralCurveAt (γ ∘ (· * a)) (a • v) (t₀ / a) := by + rw [isIntegralCurveAt_iff'] at * + obtain ⟨ε, hε, h⟩ := hγ + refine ⟨ε / |a|, by positivity, ?_⟩ + convert h.comp_mul a + ext t + rw [mem_setOf_eq, Metric.mem_ball, Metric.mem_ball, Real.dist_eq, Real.dist_eq, + lt_div_iff (abs_pos.mpr ha), ← abs_mul, sub_mul, div_mul_cancel _ ha] + +lemma isIntegralCurveAt_comp_mul_ne_zero {a : ℝ} (ha : a ≠ 0) : + IsIntegralCurveAt γ v t₀ ↔ IsIntegralCurveAt (γ ∘ (· * a)) (a • v) (t₀ / a) := by + refine ⟨fun hγ ↦ hγ.comp_mul_ne_zero ha, fun hγ ↦ ?_⟩ + convert hγ.comp_mul_ne_zero (inv_ne_zero ha) + · ext t + simp only [Function.comp_apply, mul_assoc, inv_mul_eq_div, div_self ha, mul_one] + · simp only [smul_smul, inv_mul_eq_div, div_self ha, one_smul] + · simp only [div_inv_eq_mul, div_mul_cancel _ ha] + +lemma IsIntegralCurve.comp_mul (hγ : IsIntegralCurve γ v) (a : ℝ) : + IsIntegralCurve (γ ∘ (· * a)) (a • v) := by + rw [isIntegralCurve_iff_isIntegralCurveOn] at * + exact hγ.comp_mul _ + +lemma isIntegralCurve_comp_mul_ne_zero {a : ℝ} (ha : a ≠ 0) : + IsIntegralCurve γ v ↔ IsIntegralCurve (γ ∘ (· * a)) (a • v) := by + refine ⟨fun hγ ↦ hγ.comp_mul _, fun hγ ↦ ?_⟩ + convert hγ.comp_mul a⁻¹ + · ext t + simp only [Function.comp_apply, mul_assoc, inv_mul_eq_div, div_self ha, mul_one] + · simp only [smul_smul, inv_mul_eq_div, div_self ha, one_smul] + +/-- If the vector field `v` vanishes at `x₀`, then the constant curve at `x₀` +is a global integral curve of `v`. -/ +lemma isIntegralCurve_const {x : M} (h : v x = 0) : IsIntegralCurve (fun _ ↦ x) v := by + intro t + rw [h, ← ContinuousLinearMap.zero_apply (R₁ := ℝ) (R₂ := ℝ) (1 : ℝ), + ContinuousLinearMap.smulRight_one_one] + exact hasMFDerivAt_const .. + +end Scaling + +/-! ### Existence and uniqueness -/ + +section ExistUnique + +variable (t₀) {x₀ : M} + +/-- Existence of local integral curves for a $C^1$ vector field at interior points of a smooth +manifold. -/ +theorem exists_isIntegralCurveAt_of_contMDiffAt + (hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) x₀) + (hx : I.IsInteriorPoint x₀) : + ∃ γ : ℝ → M, γ t₀ = x₀ ∧ IsIntegralCurveAt γ v t₀ := by + -- express the differentiability of the vector field `v` in the local chart + rw [contMDiffAt_iff] at hv + obtain ⟨_, hv⟩ := hv + -- use Picard-Lindelöf theorem to extract a solution to the ODE in the local chart + obtain ⟨f, hf1, hf2⟩ := exists_forall_hasDerivAt_Ioo_eq_of_contDiffAt t₀ + (hv.contDiffAt (range_mem_nhds_isInteriorPoint hx)).snd + simp_rw [← Real.ball_eq_Ioo, ← Metric.eventually_nhds_iff_ball] at hf2 + -- use continuity of `f` so that `f t` remains inside `interior (extChartAt I x₀).target` + have ⟨a, ha, hf2'⟩ := Metric.eventually_nhds_iff_ball.mp hf2 + have hcont := (hf2' t₀ (Metric.mem_ball_self ha)).continuousAt + rw [continuousAt_def, hf1] at hcont + have hnhds : f ⁻¹' (interior (extChartAt I x₀).target) ∈ 𝓝 t₀ := + hcont _ (isOpen_interior.mem_nhds ((I.isInteriorPoint_iff).mp hx)) + rw [← eventually_mem_nhds] at hnhds + -- obtain a neighbourhood `s` so that the above conditions both hold in `s` + obtain ⟨s, hs, haux⟩ := (hf2.and hnhds).exists_mem + -- prove that `γ := (extChartAt I x₀).symm ∘ f` is a desired integral curve + refine ⟨(extChartAt I x₀).symm ∘ f, + Eq.symm (by rw [Function.comp_apply, hf1, PartialEquiv.left_inv _ (mem_extChartAt_source ..)]), + isIntegralCurveAt_iff.mpr ⟨s, hs, ?_⟩⟩ + intros t ht + -- collect useful terms in convenient forms + let xₜ : M := (extChartAt I x₀).symm (f t) -- `xₜ := γ t` + have h : HasDerivAt f (x := t) <| fderivWithin ℝ (extChartAt I x₀ ∘ (extChartAt I xₜ).symm) + (range I) (extChartAt I xₜ xₜ) (v xₜ) := (haux t ht).1 + rw [← tangentCoordChange_def] at h + have hf3 := mem_preimage.mp <| mem_of_mem_nhds (haux t ht).2 + have hf3' := mem_of_mem_of_subset hf3 interior_subset + have hft1 := mem_preimage.mp <| + mem_of_mem_of_subset hf3' (extChartAt I x₀).target_subset_preimage_source + have hft2 := mem_extChartAt_source I xₜ + -- express the derivative of the integral curve in the local chart + refine ⟨(continuousAt_extChartAt_symm'' _ _ hf3').comp h.continuousAt, + HasDerivWithinAt.hasFDerivWithinAt ?_⟩ + simp only [mfld_simps, hasDerivWithinAt_univ] + show HasDerivAt ((extChartAt I xₜ ∘ (extChartAt I x₀).symm) ∘ f) (v xₜ) t + -- express `v (γ t)` as `D⁻¹ D (v (γ t))`, where `D` is a change of coordinates, so we can use + -- `HasFDerivAt.comp_hasDerivAt` on `h` + rw [← tangentCoordChange_self (I := I) (x := xₜ) (z := xₜ) (v := v xₜ) hft2, + ← tangentCoordChange_comp (x := x₀) ⟨⟨hft2, hft1⟩, hft2⟩] + apply HasFDerivAt.comp_hasDerivAt _ _ h + apply HasFDerivWithinAt.hasFDerivAt (s := range I) _ <| + mem_nhds_iff.mpr ⟨interior (extChartAt I x₀).target, + subset_trans interior_subset (extChartAt_target_subset_range ..), + isOpen_interior, hf3⟩ + rw [← (extChartAt I x₀).right_inv hf3'] + exact hasFDerivWithinAt_tangentCoordChange ⟨hft1, hft2⟩ + +/-- Existence of local integral curves for a $C^1$ vector field on a smooth manifold without +boundary. -/ +lemma exists_isIntegralCurveAt_of_contMDiffAt_boundaryless [BoundarylessManifold I M] + (hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) x₀) : + ∃ γ : ℝ → M, γ t₀ = x₀ ∧ IsIntegralCurveAt γ v t₀ := + exists_isIntegralCurveAt_of_contMDiffAt t₀ hv (BoundarylessManifold.isInteriorPoint I) + +variable {t₀} + +/-- Local integral curves are unique. + +If a $C^1$ vector field `v` admits two local integral curves `γ γ' : ℝ → M` at `t₀` with +`γ t₀ = γ' t₀`, then `γ` and `γ'` agree on some open interval containing `t₀`. -/ +theorem isIntegralCurveAt_eventuallyEq_of_contMDiffAt (hγt₀ : I.IsInteriorPoint (γ t₀)) + (hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) (γ t₀)) + (hγ : IsIntegralCurveAt γ v t₀) (hγ' : IsIntegralCurveAt γ' v t₀) (h : γ t₀ = γ' t₀) : + γ =ᶠ[𝓝 t₀] γ' := by + -- first define `v'` as the vector field expressed in the local chart around `γ t₀` + -- this is basically what the function looks like when `hv` is unfolded + set v' : E → E := fun x ↦ + tangentCoordChange I ((extChartAt I (γ t₀)).symm x) (γ t₀) ((extChartAt I (γ t₀)).symm x) + (v ((extChartAt I (γ t₀)).symm x)) with hv' + -- extract a set `s` on which `v'` is Lipschitz + rw [contMDiffAt_iff] at hv + obtain ⟨_, hv⟩ := hv + obtain ⟨K, s, hs, hlip⟩ : ∃ K, ∃ s ∈ nhds _, LipschitzOnWith K v' s := + (hv.contDiffAt (range_mem_nhds_isInteriorPoint hγt₀)).snd.exists_lipschitzOnWith + have hlip (t : ℝ) : LipschitzOnWith K ((fun _ ↦ v') t) ((fun _ ↦ s) t) := hlip + -- internal lemmas to reduce code duplication + have hsrc {g} (hg : IsIntegralCurveAt g v t₀) : + ∀ᶠ t in 𝓝 t₀, g ⁻¹' (extChartAt I (g t₀)).source ∈ 𝓝 t := eventually_mem_nhds.mpr <| + continuousAt_def.mp hg.continuousAt _ <| extChartAt_source_mem_nhds I (g t₀) + have hmem {g : ℝ → M} {t} (ht : g ⁻¹' (extChartAt I (g t₀)).source ∈ 𝓝 t) : + g t ∈ (extChartAt I (g t₀)).source := mem_preimage.mp <| mem_of_mem_nhds ht + have hdrv {g} (hg : IsIntegralCurveAt g v t₀) (h' : γ t₀ = g t₀) : ∀ᶠ t in 𝓝 t₀, + HasDerivAt ((extChartAt I (g t₀)) ∘ g) ((fun _ ↦ v') t (((extChartAt I (g t₀)) ∘ g) t)) t ∧ + ((extChartAt I (g t₀)) ∘ g) t ∈ (fun _ ↦ s) t := by + apply Filter.Eventually.and + · apply (hsrc hg |>.and hg.eventually_hasDerivAt).mono + rintro t ⟨ht1, ht2⟩ + rw [hv', h'] + apply ht2.congr_deriv + congr <;> + rw [Function.comp_apply, PartialEquiv.left_inv _ (hmem ht1)] + · apply ((continuousAt_extChartAt I (g t₀)).comp hg.continuousAt).preimage_mem_nhds + rw [Function.comp_apply, ← h'] + exact hs + have heq {g} (hg : IsIntegralCurveAt g v t₀) : + g =ᶠ[𝓝 t₀] (extChartAt I (g t₀)).symm ∘ ↑(extChartAt I (g t₀)) ∘ g := by + apply (hsrc hg).mono + intros t ht + rw [Function.comp_apply, Function.comp_apply, PartialEquiv.left_inv _ (hmem ht)] + -- main proof + suffices (extChartAt I (γ t₀)) ∘ γ =ᶠ[𝓝 t₀] (extChartAt I (γ' t₀)) ∘ γ' from + (heq hγ).trans <| (this.fun_comp (extChartAt I (γ t₀)).symm).trans (h ▸ (heq hγ').symm) + exact ODE_solution_unique_of_eventually hlip + (hdrv hγ rfl) (hdrv hγ' h) (by rw [Function.comp_apply, Function.comp_apply, h]) + +theorem isIntegralCurveAt_eventuallyEq_of_contMDiffAt_boundaryless [BoundarylessManifold I M] + (hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) (γ t₀)) + (hγ : IsIntegralCurveAt γ v t₀) (hγ' : IsIntegralCurveAt γ' v t₀) (h : γ t₀ = γ' t₀) : + γ =ᶠ[𝓝 t₀] γ' := + isIntegralCurveAt_eventuallyEq_of_contMDiffAt (BoundarylessManifold.isInteriorPoint I) hv hγ hγ' h + +variable [T2Space M] {a b : ℝ} + +/-- Integral curves are unique on open intervals. + +If a $C^1$ vector field `v` admits two integral curves `γ γ' : ℝ → M` on some open interval +`Ioo a b`, and `γ t₀ = γ' t₀` for some `t ∈ Ioo a b`, then `γ` and `γ'` agree on `Ioo a b`. -/ +theorem isIntegralCurveOn_Ioo_eqOn_of_contMDiff (ht₀ : t₀ ∈ Ioo a b) + (hγt : ∀ t ∈ Ioo a b, I.IsInteriorPoint (γ t)) + (hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M))) + (hγ : IsIntegralCurveOn γ v (Ioo a b)) (hγ' : IsIntegralCurveOn γ' v (Ioo a b)) + (h : γ t₀ = γ' t₀) : EqOn γ γ' (Ioo a b) := by + set s := {t | γ t = γ' t} ∩ Ioo a b with hs + -- since `Ioo a b` is connected, we get `s = Ioo a b` by showing that `s` is clopen in `Ioo a b` + -- in the subtype toplogy (`s` is also non-empty by assumption) + -- here we use a slightly weaker alternative theorem + suffices hsub : Ioo a b ⊆ s from fun t ht ↦ mem_setOf.mp ((subset_def ▸ hsub) t ht).1 + apply isPreconnected_Ioo.subset_of_closure_inter_subset (s := Ioo a b) (u := s) _ + ⟨t₀, ⟨ht₀, ⟨h, ht₀⟩⟩⟩ + · -- is this really the most convenient way to pass to subtype topology? + -- TODO: shorten this when better API around subtype topology exists + rw [hs, ← Subtype.image_preimage_val, ← Subtype.image_preimage_val, + image_subset_image_iff Subtype.val_injective, preimage_setOf_eq] + intros t ht + rw [mem_preimage, ← closure_subtype] at ht + revert ht t + apply IsClosed.closure_subset (isClosed_eq _ _) + · rw [continuous_iff_continuousAt] + rintro ⟨_, ht⟩ + apply ContinuousAt.comp _ continuousAt_subtype_val + rw [Subtype.coe_mk] + exact hγ.continuousAt ht + · rw [continuous_iff_continuousAt] + rintro ⟨_, ht⟩ + apply ContinuousAt.comp _ continuousAt_subtype_val + rw [Subtype.coe_mk] + exact hγ'.continuousAt ht + · rw [isOpen_iff_mem_nhds] + intro t₁ ht₁ + have hmem := Ioo_mem_nhds ht₁.2.1 ht₁.2.2 + have heq : γ =ᶠ[𝓝 t₁] γ' := isIntegralCurveAt_eventuallyEq_of_contMDiffAt + (hγt _ ht₁.2) hv.contMDiffAt (hγ.isIntegralCurveAt hmem) (hγ'.isIntegralCurveAt hmem) ht₁.1 + apply (heq.and hmem).mono + exact fun _ ht ↦ ht + +theorem isIntegralCurveOn_Ioo_eqOn_of_contMDiff_boundaryless [BoundarylessManifold I M] + (ht₀ : t₀ ∈ Ioo a b) + (hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M))) + (hγ : IsIntegralCurveOn γ v (Ioo a b)) (hγ' : IsIntegralCurveOn γ' v (Ioo a b)) + (h : γ t₀ = γ' t₀) : EqOn γ γ' (Ioo a b) := + isIntegralCurveOn_Ioo_eqOn_of_contMDiff + ht₀ (fun _ _ ↦ BoundarylessManifold.isInteriorPoint I) hv hγ hγ' h + +/-- Global integral curves are unique. + +If a continuously differentiable vector field `v` admits two global integral curves +`γ γ' : ℝ → M`, and `γ t₀ = γ' t₀` for some `t₀`, then `γ` and `γ'` are equal. -/ +theorem isIntegralCurve_eq_of_contMDiff (hγt : ∀ t, I.IsInteriorPoint (γ t)) + (hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M))) + (hγ : IsIntegralCurve γ v) (hγ' : IsIntegralCurve γ' v) (h : γ t₀ = γ' t₀) : γ = γ' := by + ext t + obtain ⟨T, ht₀, ht⟩ : ∃ T, t ∈ Ioo (-T) T ∧ t₀ ∈ Ioo (-T) T := by + obtain ⟨T, hT₁, hT₂⟩ := exists_abs_lt t + obtain ⟨hT₂, hT₃⟩ := abs_lt.mp hT₂ + obtain ⟨S, hS₁, hS₂⟩ := exists_abs_lt t₀ + obtain ⟨hS₂, hS₃⟩ := abs_lt.mp hS₂ + exact ⟨T + S, by constructor <;> constructor <;> linarith⟩ + exact isIntegralCurveOn_Ioo_eqOn_of_contMDiff ht (fun t _ ↦ hγt t) hv + ((hγ.isIntegralCurveOn _).mono (subset_univ _)) + ((hγ'.isIntegralCurveOn _).mono (subset_univ _)) h ht₀ + +theorem isIntegralCurve_Ioo_eq_of_contMDiff_boundaryless [BoundarylessManifold I M] + (hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M))) + (hγ : IsIntegralCurve γ v) (hγ' : IsIntegralCurve γ' v) (h : γ t₀ = γ' t₀) : γ = γ' := + isIntegralCurve_eq_of_contMDiff (fun _ ↦ BoundarylessManifold.isInteriorPoint I) hv hγ hγ' h + +end ExistUnique diff --git a/Mathlib/Geometry/Manifold/InteriorBoundary.lean b/Mathlib/Geometry/Manifold/InteriorBoundary.lean index 970413b2edd42..a6671186f278e 100644 --- a/Mathlib/Geometry/Manifold/InteriorBoundary.lean +++ b/Mathlib/Geometry/Manifold/InteriorBoundary.lean @@ -73,24 +73,21 @@ lemma isBoundaryPoint_iff {x : M} : I.IsBoundaryPoint x ↔ extChartAt I x x ∈ /-- Every point is either an interior or a boundary point. -/ lemma isInteriorPoint_or_isBoundaryPoint (x : M) : I.IsInteriorPoint x ∨ I.IsBoundaryPoint x := by - by_cases h : extChartAt I x x ∈ interior (range I) - · exact Or.inl h - · right -- Otherwise, we have a boundary point. - rw [I.isBoundaryPoint_iff, ← closure_diff_interior, I.closed_range.closure_eq] - exact ⟨mem_range_self _, h⟩ + rw [IsInteriorPoint, or_iff_not_imp_left, I.isBoundaryPoint_iff, ← closure_diff_interior, + I.closed_range.closure_eq, mem_diff] + exact fun h => ⟨mem_range_self _, h⟩ /-- A manifold decomposes into interior and boundary. -/ lemma interior_union_boundary_eq_univ : (I.interior M) ∪ (I.boundary M) = (univ : Set M) := - le_antisymm (fun _ _ ↦ trivial) (fun x _ ↦ I.isInteriorPoint_or_isBoundaryPoint x) + eq_univ_of_forall fun x => (mem_union _ _ _).mpr (I.isInteriorPoint_or_isBoundaryPoint x) /-- The interior and boundary of a manifold `M` are disjoint. -/ lemma disjoint_interior_boundary : Disjoint (I.interior M) (I.boundary M) := by by_contra h -- Choose some x in the intersection of interior and boundary. - choose x hx using not_disjoint_iff.mp h - rcases hx with ⟨h1, h2⟩ - show (extChartAt I x) x ∈ (∅ : Set E) - rw [← disjoint_iff_inter_eq_empty.mp (disjoint_interior_frontier (s := range I))] + obtain ⟨x, h1, h2⟩ := not_disjoint_iff.mp h + rw [← mem_empty_iff_false (extChartAt I x x), + ← disjoint_iff_inter_eq_empty.mp (disjoint_interior_frontier (s := range I)), mem_inter_iff] exact ⟨h1, h2⟩ /-- The boundary is the complement of the interior. -/ @@ -98,6 +95,7 @@ lemma boundary_eq_complement_interior : I.boundary M = (I.interior M)ᶜ := by apply (compl_unique ?_ I.interior_union_boundary_eq_univ).symm exact disjoint_iff_inter_eq_empty.mp (I.disjoint_interior_boundary) +variable {I} in lemma _root_.range_mem_nhds_isInteriorPoint {x : M} (h : I.IsInteriorPoint x) : range I ∈ nhds (extChartAt I x x) := by rw [mem_nhds_iff] @@ -131,10 +129,9 @@ variable [BoundarylessManifold I M] lemma _root_.BoundarylessManifold.isInteriorPoint {x : M} : IsInteriorPoint I x := BoundarylessManifold.isInteriorPoint' x -/-- Boundaryless manifolds have full interior. -/ -lemma interior_eq_univ : I.interior M = univ := by - ext - refine ⟨fun _ ↦ trivial, fun _ ↦ BoundarylessManifold.isInteriorPoint I⟩ +/-- If `I` is boundaryless, `M` has full interior. -/ +lemma interior_eq_univ : I.interior M = univ := + eq_univ_of_forall fun _ => BoundarylessManifold.isInteriorPoint I /-- Boundaryless manifolds have empty boundary. -/ lemma Boundaryless.boundary_eq_empty : I.boundary M = ∅ := by diff --git a/Mathlib/Geometry/Manifold/LocalDiffeomorph.lean b/Mathlib/Geometry/Manifold/LocalDiffeomorph.lean index ced40318c844c..d2bc62fccd68b 100644 --- a/Mathlib/Geometry/Manifold/LocalDiffeomorph.lean +++ b/Mathlib/Geometry/Manifold/LocalDiffeomorph.lean @@ -77,7 +77,7 @@ structure PartialDiffeomorph extends PartialEquiv M N where contMDiffOn_invFun : ContMDiffOn J I n invFun target /-- Coercion of a `PartialDiffeomorph` to function. -Note that a `PartialDiffeomorph` is not `FunLike` (like `PartialHomeomorph`), +Note that a `PartialDiffeomorph` is not `DFunLike` (like `PartialHomeomorph`), as `toFun` doesn't determine `invFun` outside of `target`. -/ instance : CoeFun (PartialDiffeomorph I J M N n) fun _ => M → N := ⟨fun Φ => Φ.toFun⟩ diff --git a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean index 40c1e59e1ec26..c14a92da4d404 100644 --- a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean +++ b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean @@ -386,7 +386,7 @@ theorem liftPropOn_of_locally_liftPropOn rcases h x hx with ⟨u, u_open, xu, hu⟩ have := hu x ⟨hx, xu⟩ rwa [hG.liftPropWithinAt_inter] at this - exact IsOpen.mem_nhds u_open xu + exact u_open.mem_nhds xu #align structure_groupoid.local_invariant_prop.lift_prop_on_of_locally_lift_prop_on StructureGroupoid.LocalInvariantProp.liftPropOn_of_locally_liftPropOn theorem liftProp_of_locally_liftPropOn (h : ∀ x, ∃ u, IsOpen u ∧ x ∈ u ∧ LiftPropOn P g u) : @@ -484,7 +484,7 @@ theorem liftPropOn_of_mem_maximalAtlas [HasGroupoid M G] (hG : G.LocalInvariantP (hQ : ∀ y, Q id univ y) (he : e ∈ maximalAtlas M G) : LiftPropOn Q e e.source := by intro x hx apply hG.liftPropWithinAt_of_liftPropAt_of_mem_nhds (hG.liftPropAt_of_mem_maximalAtlas hQ he hx) - exact IsOpen.mem_nhds e.open_source hx + exact e.open_source.mem_nhds hx #align structure_groupoid.local_invariant_prop.lift_prop_on_of_mem_maximal_atlas StructureGroupoid.LocalInvariantProp.liftPropOn_of_mem_maximalAtlas theorem liftPropAt_symm_of_mem_maximalAtlas [HasGroupoid M G] {x : H} @@ -503,7 +503,7 @@ theorem liftPropOn_symm_of_mem_maximalAtlas [HasGroupoid M G] (hG : G.LocalInvar intro x hx apply hG.liftPropWithinAt_of_liftPropAt_of_mem_nhds (hG.liftPropAt_symm_of_mem_maximalAtlas hQ he hx) - exact IsOpen.mem_nhds e.open_target hx + exact e.open_target.mem_nhds hx #align structure_groupoid.local_invariant_prop.lift_prop_on_symm_of_mem_maximal_atlas StructureGroupoid.LocalInvariantProp.liftPropOn_symm_of_mem_maximalAtlas theorem liftPropAt_chart [HasGroupoid M G] (hG : G.LocalInvariantProp G Q) (hQ : ∀ y, Q id univ y) : @@ -709,7 +709,7 @@ theorem HasGroupoid.comp (f.symm ≫ₕ e.symm ≫ₕ e' ≫ₕ f').open_source refine' ⟨_, hs.inter φ.open_source, _, _⟩ · simp only [hx, hφ_dom, mfld_simps] - · refine' G₁.eq_on_source (closedUnderRestriction' hφG₁ hs) _ + · refine' G₁.mem_of_eqOnSource (closedUnderRestriction' hφG₁ hs) _ rw [PartialHomeomorph.restr_source_inter] refine' PartialHomeomorph.Set.EqOn.restr_eqOn_source (hφ.mono _) mfld_set_tac } diff --git a/Mathlib/Geometry/Manifold/MFDeriv.lean b/Mathlib/Geometry/Manifold/MFDeriv.lean deleted file mode 100644 index 49141ae1ceac7..0000000000000 --- a/Mathlib/Geometry/Manifold/MFDeriv.lean +++ /dev/null @@ -1,2162 +0,0 @@ -/- -Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Sébastien Gouëzel, Floris van Doorn --/ -import Mathlib.Geometry.Manifold.VectorBundle.Tangent - -#align_import geometry.manifold.mfderiv from "leanprover-community/mathlib"@"e473c3198bb41f68560cab68a0529c854b618833" - -/-! -# The derivative of functions between smooth manifolds - -Let `M` and `M'` be two smooth manifolds with corners over a field `𝕜` (with respective models with -corners `I` on `(E, H)` and `I'` on `(E', H')`), and let `f : M → M'`. We define the -derivative of the function at a point, within a set or along the whole space, mimicking the API -for (Fréchet) derivatives. It is denoted by `mfderiv I I' f x`, where "m" stands for "manifold" and -"f" for "Fréchet" (as in the usual derivative `fderiv 𝕜 f x`). - -## Main definitions - -* `UniqueMDiffOn I s` : predicate saying that, at each point of the set `s`, a function can have - at most one derivative. This technical condition is important when we define - `mfderivWithin` below, as otherwise there is an arbitrary choice in the derivative, - and many properties will fail (for instance the chain rule). This is analogous to - `UniqueDiffOn 𝕜 s` in a vector space. - -Let `f` be a map between smooth manifolds. The following definitions follow the `fderiv` API. - -* `mfderiv I I' f x` : the derivative of `f` at `x`, as a continuous linear map from the tangent - space at `x` to the tangent space at `f x`. If the map is not differentiable, this is `0`. -* `mfderivWithin I I' f s x` : the derivative of `f` at `x` within `s`, as a continuous linear map - from the tangent space at `x` to the tangent space at `f x`. If the map is not differentiable - within `s`, this is `0`. -* `MDifferentiableAt I I' f x` : Prop expressing whether `f` is differentiable at `x`. -* `MDifferentiableWithinAt 𝕜 f s x` : Prop expressing whether `f` is differentiable within `s` - at `x`. -* `HasMFDerivAt I I' f s x f'` : Prop expressing whether `f` has `f'` as a derivative at `x`. -* `HasMFDerivWithinAt I I' f s x f'` : Prop expressing whether `f` has `f'` as a derivative - within `s` at `x`. -* `MDifferentiableOn I I' f s` : Prop expressing that `f` is differentiable on the set `s`. -* `MDifferentiable I I' f` : Prop expressing that `f` is differentiable everywhere. -* `tangentMap I I' f` : the derivative of `f`, as a map from the tangent bundle of `M` to the - tangent bundle of `M'`. - -We also establish results on the differential of the identity, constant functions, charts, extended -charts. For functions between vector spaces, we show that the usual notions and the manifold notions -coincide. - -## Implementation notes - -The tangent bundle is constructed using the machinery of topological fiber bundles, for which one -can define bundled morphisms and construct canonically maps from the total space of one bundle to -the total space of another one. One could use this mechanism to construct directly the derivative -of a smooth map. However, we want to define the derivative of any map (and let it be zero if the map -is not differentiable) to avoid proof arguments everywhere. This means we have to go back to the -details of the definition of the total space of a fiber bundle constructed from core, to cook up a -suitable definition of the derivative. It is the following: at each point, we have a preferred chart -(used to identify the fiber above the point with the model vector space in fiber bundles). Then one -should read the function using these preferred charts at `x` and `f x`, and take the derivative -of `f` in these charts. - -Due to the fact that we are working in a model with corners, with an additional embedding `I` of the -model space `H` in the model vector space `E`, the charts taking values in `E` are not the original -charts of the manifold, but those ones composed with `I`, called extended charts. We define -`writtenInExtChartAt I I' x f` for the function `f` written in the preferred extended charts. Then -the manifold derivative of `f`, at `x`, is just the usual derivative of -`writtenInExtChartAt I I' x f`, at the point `(extChartAt I x) x`. - -There is a subtelty with respect to continuity: if the function is not continuous, then the image -of a small open set around `x` will not be contained in the source of the preferred chart around -`f x`, which means that when reading `f` in the chart one is losing some information. To avoid this, -we include continuity in the definition of differentiablity (which is reasonable since with any -definition, differentiability implies continuity). - -*Warning*: the derivative (even within a subset) is a linear map on the whole tangent space. Suppose -that one is given a smooth submanifold `N`, and a function which is smooth on `N` (i.e., its -restriction to the subtype `N` is smooth). Then, in the whole manifold `M`, the property -`MDifferentiableOn I I' f N` holds. However, `mfderivWithin I I' f N` is not uniquely defined -(what values would one choose for vectors that are transverse to `N`?), which can create issues down -the road. The problem here is that knowing the value of `f` along `N` does not determine the -differential of `f` in all directions. This is in contrast to the case where `N` would be an open -subset, or a submanifold with boundary of maximal dimension, where this issue does not appear. -The predicate `UniqueMDiffOn I N` indicates that the derivative along `N` is unique if it exists, -and is an assumption in most statements requiring a form of uniqueness. - -On a vector space, the manifold derivative and the usual derivative are equal. This means in -particular that they live on the same space, i.e., the tangent space is defeq to the original vector -space. To get this property is a motivation for our definition of the tangent space as a single -copy of the vector space, instead of more usual definitions such as the space of derivations, or -the space of equivalence classes of smooth curves in the manifold. - -## Tags -Derivative, manifold --/ - -set_option autoImplicit true - - -noncomputable section - -open scoped Classical Topology Manifold Bundle -open Set Bundle ChartedSpace - -universe u - -section DerivativesDefinitions - -/-! -### Derivative of maps between manifolds - -The derivative of a smooth map `f` between smooth manifold `M` and `M'` at `x` is a bounded linear -map from the tangent space to `M` at `x`, to the tangent space to `M'` at `f x`. Since we defined -the tangent space using one specific chart, the formula for the derivative is written in terms of -this specific chart. - -We use the names `MDifferentiable` and `mfderiv`, where the prefix letter `m` means "manifold". --/ - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M : Type*} - [TopologicalSpace M] [ChartedSpace H M] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] - {H' : Type*} [TopologicalSpace H'] (I' : ModelWithCorners 𝕜 E' H') {M' : Type*} - [TopologicalSpace M'] [ChartedSpace H' M'] - -/-- Property in the model space of a model with corners of being differentiable within at set at a -point, when read in the model vector space. This property will be lifted to manifolds to define -differentiable functions between manifolds. -/ -def DifferentiableWithinAtProp (f : H → H') (s : Set H) (x : H) : Prop := - DifferentiableWithinAt 𝕜 (I' ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ Set.range I) (I x) -#align differentiable_within_at_prop DifferentiableWithinAtProp - -/-- Being differentiable in the model space is a local property, invariant under smooth maps. -Therefore, it will lift nicely to manifolds. -/ -theorem differentiable_within_at_localInvariantProp : - (contDiffGroupoid ⊤ I).LocalInvariantProp (contDiffGroupoid ⊤ I') - (DifferentiableWithinAtProp I I') := - { is_local := by - intro s x u f u_open xu - have : I.symm ⁻¹' (s ∩ u) ∩ Set.range I = I.symm ⁻¹' s ∩ Set.range I ∩ I.symm ⁻¹' u := by - simp only [Set.inter_right_comm, Set.preimage_inter] - rw [DifferentiableWithinAtProp, DifferentiableWithinAtProp, this] - symm - apply differentiableWithinAt_inter - have : u ∈ 𝓝 (I.symm (I x)) := by - rw [ModelWithCorners.left_inv] - exact IsOpen.mem_nhds u_open xu - apply I.continuous_symm.continuousAt this - right_invariance' := by - intro s x f e he hx h - rw [DifferentiableWithinAtProp] at h ⊢ - have : I x = (I ∘ e.symm ∘ I.symm) (I (e x)) := by simp only [hx, mfld_simps] - rw [this] at h - have : I (e x) ∈ I.symm ⁻¹' e.target ∩ Set.range I := by simp only [hx, mfld_simps] - have := (mem_groupoid_of_pregroupoid.2 he).2.contDiffWithinAt this - convert (h.comp' _ (this.differentiableWithinAt le_top)).mono_of_mem _ using 1 - · ext y; simp only [mfld_simps] - refine' - mem_nhdsWithin.mpr - ⟨I.symm ⁻¹' e.target, e.open_target.preimage I.continuous_symm, by - simp_rw [Set.mem_preimage, I.left_inv, e.mapsTo hx], _⟩ - mfld_set_tac - congr_of_forall := by - intro s x f g h hx hf - apply hf.congr - · intro y hy - simp only [mfld_simps] at hy - simp only [h, hy, mfld_simps] - · simp only [hx, mfld_simps] - left_invariance' := by - intro s x f e' he' hs hx h - rw [DifferentiableWithinAtProp] at h ⊢ - have A : (I' ∘ f ∘ I.symm) (I x) ∈ I'.symm ⁻¹' e'.source ∩ Set.range I' := by - simp only [hx, mfld_simps] - have := (mem_groupoid_of_pregroupoid.2 he').1.contDiffWithinAt A - convert (this.differentiableWithinAt le_top).comp _ h _ - · ext y; simp only [mfld_simps] - · intro y hy; simp only [mfld_simps] at hy; simpa only [hy, mfld_simps] using hs hy.1 } -#align differentiable_within_at_local_invariant_prop differentiable_within_at_localInvariantProp - -/-- Predicate ensuring that, at a point and within a set, a function can have at most one -derivative. This is expressed using the preferred chart at the considered point. -/ -def UniqueMDiffWithinAt (s : Set M) (x : M) := - UniqueDiffWithinAt 𝕜 ((extChartAt I x).symm ⁻¹' s ∩ range I) ((extChartAt I x) x) -#align unique_mdiff_within_at UniqueMDiffWithinAt - -/-- Predicate ensuring that, at all points of a set, a function can have at most one derivative. -/ -def UniqueMDiffOn (s : Set M) := - ∀ x ∈ s, UniqueMDiffWithinAt I s x -#align unique_mdiff_on UniqueMDiffOn - -/-- `MDifferentiableWithinAt I I' f s x` indicates that the function `f` between manifolds -has a derivative at the point `x` within the set `s`. -This is a generalization of `DifferentiableWithinAt` to manifolds. - -We require continuity in the definition, as otherwise points close to `x` in `s` could be sent by -`f` outside of the chart domain around `f x`. Then the chart could do anything to the image points, -and in particular by coincidence `writtenInExtChartAt I I' x f` could be differentiable, while -this would not mean anything relevant. -/ -def MDifferentiableWithinAt (f : M → M') (s : Set M) (x : M) := - ContinuousWithinAt f s x ∧ - DifferentiableWithinAt 𝕜 (writtenInExtChartAt I I' x f) ((extChartAt I x).symm ⁻¹' s ∩ range I) - ((extChartAt I x) x) -#align mdifferentiable_within_at MDifferentiableWithinAt - -theorem mdifferentiableWithinAt_iff_liftPropWithinAt (f : M → M') (s : Set M) (x : M) : - MDifferentiableWithinAt I I' f s x ↔ LiftPropWithinAt (DifferentiableWithinAtProp I I') f s x := - by rfl -#align mdifferentiable_within_at_iff_lift_prop_within_at mdifferentiableWithinAt_iff_liftPropWithinAt - -/-- `MDifferentiableAt I I' f x` indicates that the function `f` between manifolds -has a derivative at the point `x`. -This is a generalization of `DifferentiableAt` to manifolds. - -We require continuity in the definition, as otherwise points close to `x` could be sent by -`f` outside of the chart domain around `f x`. Then the chart could do anything to the image points, -and in particular by coincidence `writtenInExtChartAt I I' x f` could be differentiable, while -this would not mean anything relevant. -/ -def MDifferentiableAt (f : M → M') (x : M) := - ContinuousAt f x ∧ - DifferentiableWithinAt 𝕜 (writtenInExtChartAt I I' x f) (range I) ((extChartAt I x) x) -#align mdifferentiable_at MDifferentiableAt - -theorem mdifferentiableAt_iff_liftPropAt (f : M → M') (x : M) : - MDifferentiableAt I I' f x ↔ LiftPropAt (DifferentiableWithinAtProp I I') f x := by - congrm ?_ ∧ ?_ - · rw [continuousWithinAt_univ] - · -- porting note: `rfl` wasn't needed - simp [DifferentiableWithinAtProp, Set.univ_inter]; rfl -#align mdifferentiable_at_iff_lift_prop_at mdifferentiableAt_iff_liftPropAt - -/-- `MDifferentiableOn I I' f s` indicates that the function `f` between manifolds -has a derivative within `s` at all points of `s`. -This is a generalization of `DifferentiableOn` to manifolds. -/ -def MDifferentiableOn (f : M → M') (s : Set M) := - ∀ x ∈ s, MDifferentiableWithinAt I I' f s x -#align mdifferentiable_on MDifferentiableOn - -/-- `MDifferentiable I I' f` indicates that the function `f` between manifolds -has a derivative everywhere. -This is a generalization of `Differentiable` to manifolds. -/ -def MDifferentiable (f : M → M') := - ∀ x, MDifferentiableAt I I' f x -#align mdifferentiable MDifferentiable - -/-- Prop registering if a partial homeomorphism is a local diffeomorphism on its source -/ -def PartialHomeomorph.MDifferentiable (f : PartialHomeomorph M M') := - MDifferentiableOn I I' f f.source ∧ MDifferentiableOn I' I f.symm f.target -#align local_homeomorph.mdifferentiable PartialHomeomorph.MDifferentiable - -variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] - -/-- `HasMFDerivWithinAt I I' f s x f'` indicates that the function `f` between manifolds -has, at the point `x` and within the set `s`, the derivative `f'`. Here, `f'` is a continuous linear -map from the tangent space at `x` to the tangent space at `f x`. - -This is a generalization of `HasFDerivWithinAt` to manifolds (as indicated by the prefix `m`). -The order of arguments is changed as the type of the derivative `f'` depends on the choice of `x`. - -We require continuity in the definition, as otherwise points close to `x` in `s` could be sent by -`f` outside of the chart domain around `f x`. Then the chart could do anything to the image points, -and in particular by coincidence `writtenInExtChartAt I I' x f` could be differentiable, while -this would not mean anything relevant. -/ -def HasMFDerivWithinAt (f : M → M') (s : Set M) (x : M) - (f' : TangentSpace I x →L[𝕜] TangentSpace I' (f x)) := - ContinuousWithinAt f s x ∧ - HasFDerivWithinAt (writtenInExtChartAt I I' x f : E → E') f' - ((extChartAt I x).symm ⁻¹' s ∩ range I) ((extChartAt I x) x) -#align has_mfderiv_within_at HasMFDerivWithinAt - -/-- `HasMFDerivAt I I' f x f'` indicates that the function `f` between manifolds -has, at the point `x`, the derivative `f'`. Here, `f'` is a continuous linear -map from the tangent space at `x` to the tangent space at `f x`. - -We require continuity in the definition, as otherwise points close to `x` `s` could be sent by -`f` outside of the chart domain around `f x`. Then the chart could do anything to the image points, -and in particular by coincidence `writtenInExtChartAt I I' x f` could be differentiable, while -this would not mean anything relevant. -/ -def HasMFDerivAt (f : M → M') (x : M) (f' : TangentSpace I x →L[𝕜] TangentSpace I' (f x)) := - ContinuousAt f x ∧ - HasFDerivWithinAt (writtenInExtChartAt I I' x f : E → E') f' (range I) ((extChartAt I x) x) -#align has_mfderiv_at HasMFDerivAt - -/-- Let `f` be a function between two smooth manifolds. Then `mfderivWithin I I' f s x` is the -derivative of `f` at `x` within `s`, as a continuous linear map from the tangent space at `x` to the -tangent space at `f x`. -/ -def mfderivWithin (f : M → M') (s : Set M) (x : M) : TangentSpace I x →L[𝕜] TangentSpace I' (f x) := - if MDifferentiableWithinAt I I' f s x then - (fderivWithin 𝕜 (writtenInExtChartAt I I' x f) ((extChartAt I x).symm ⁻¹' s ∩ range I) - ((extChartAt I x) x) : - _) - else 0 -#align mfderiv_within mfderivWithin - -/-- Let `f` be a function between two smooth manifolds. Then `mfderiv I I' f x` is the derivative of -`f` at `x`, as a continuous linear map from the tangent space at `x` to the tangent space at -`f x`. -/ -def mfderiv (f : M → M') (x : M) : TangentSpace I x →L[𝕜] TangentSpace I' (f x) := - if MDifferentiableAt I I' f x then - (fderivWithin 𝕜 (writtenInExtChartAt I I' x f : E → E') (range I) ((extChartAt I x) x) : _) - else 0 -#align mfderiv mfderiv - -/-- The derivative within a set, as a map between the tangent bundles -/ -def tangentMapWithin (f : M → M') (s : Set M) : TangentBundle I M → TangentBundle I' M' := fun p => - ⟨f p.1, (mfderivWithin I I' f s p.1 : TangentSpace I p.1 → TangentSpace I' (f p.1)) p.2⟩ -#align tangent_map_within tangentMapWithin - -/-- The derivative, as a map between the tangent bundles -/ -def tangentMap (f : M → M') : TangentBundle I M → TangentBundle I' M' := fun p => - ⟨f p.1, (mfderiv I I' f p.1 : TangentSpace I p.1 → TangentSpace I' (f p.1)) p.2⟩ -#align tangent_map tangentMap - -end DerivativesDefinitions - -section DerivativesProperties - -/-! ### Unique differentiability sets in manifolds -/ - -variable - {𝕜 : Type*} [NontriviallyNormedField 𝕜] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] - {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] - {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} - {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] - {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] - {H'' : Type*} [TopologicalSpace H''] {I'' : ModelWithCorners 𝕜 E'' H''} - {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H'' M''] - {f f₀ f₁ : M → M'} {x : M} {s t : Set M} {g : M' → M''} {u : Set M'} - -theorem uniqueMDiffWithinAt_univ : UniqueMDiffWithinAt I univ x := by - unfold UniqueMDiffWithinAt - simp only [preimage_univ, univ_inter] - exact I.unique_diff _ (mem_range_self _) -#align unique_mdiff_within_at_univ uniqueMDiffWithinAt_univ - -variable {I} - -theorem uniqueMDiffWithinAt_iff {s : Set M} {x : M} : - UniqueMDiffWithinAt I s x ↔ - UniqueDiffWithinAt 𝕜 ((extChartAt I x).symm ⁻¹' s ∩ (extChartAt I x).target) - ((extChartAt I x) x) := by - apply uniqueDiffWithinAt_congr - rw [nhdsWithin_inter, nhdsWithin_inter, nhdsWithin_extChartAt_target_eq] -#align unique_mdiff_within_at_iff uniqueMDiffWithinAt_iff - -nonrec theorem UniqueMDiffWithinAt.mono_nhds {s t : Set M} {x : M} (hs : UniqueMDiffWithinAt I s x) - (ht : 𝓝[s] x ≤ 𝓝[t] x) : UniqueMDiffWithinAt I t x := - hs.mono_nhds <| by simpa only [← map_extChartAt_nhdsWithin] using Filter.map_mono ht - -theorem UniqueMDiffWithinAt.mono_of_mem {s t : Set M} {x : M} (hs : UniqueMDiffWithinAt I s x) - (ht : t ∈ 𝓝[s] x) : UniqueMDiffWithinAt I t x := - hs.mono_nhds (nhdsWithin_le_iff.2 ht) - -theorem UniqueMDiffWithinAt.mono (h : UniqueMDiffWithinAt I s x) (st : s ⊆ t) : - UniqueMDiffWithinAt I t x := - UniqueDiffWithinAt.mono h <| inter_subset_inter (preimage_mono st) (Subset.refl _) -#align unique_mdiff_within_at.mono UniqueMDiffWithinAt.mono - -theorem UniqueMDiffWithinAt.inter' (hs : UniqueMDiffWithinAt I s x) (ht : t ∈ 𝓝[s] x) : - UniqueMDiffWithinAt I (s ∩ t) x := - hs.mono_of_mem (Filter.inter_mem self_mem_nhdsWithin ht) -#align unique_mdiff_within_at.inter' UniqueMDiffWithinAt.inter' - -theorem UniqueMDiffWithinAt.inter (hs : UniqueMDiffWithinAt I s x) (ht : t ∈ 𝓝 x) : - UniqueMDiffWithinAt I (s ∩ t) x := - hs.inter' (nhdsWithin_le_nhds ht) -#align unique_mdiff_within_at.inter UniqueMDiffWithinAt.inter - -theorem IsOpen.uniqueMDiffWithinAt (xs : x ∈ s) (hs : IsOpen s) : UniqueMDiffWithinAt I s x := - (uniqueMDiffWithinAt_univ I).mono_of_mem <| nhdsWithin_le_nhds <| hs.mem_nhds xs -#align is_open.unique_mdiff_within_at IsOpen.uniqueMDiffWithinAt - -theorem UniqueMDiffOn.inter (hs : UniqueMDiffOn I s) (ht : IsOpen t) : UniqueMDiffOn I (s ∩ t) := - fun _x hx => UniqueMDiffWithinAt.inter (hs _ hx.1) (IsOpen.mem_nhds ht hx.2) -#align unique_mdiff_on.inter UniqueMDiffOn.inter - -theorem IsOpen.uniqueMDiffOn (hs : IsOpen s) : UniqueMDiffOn I s := fun _x hx => - IsOpen.uniqueMDiffWithinAt hx hs -#align is_open.unique_mdiff_on IsOpen.uniqueMDiffOn - -theorem uniqueMDiffOn_univ : UniqueMDiffOn I (univ : Set M) := - isOpen_univ.uniqueMDiffOn -#align unique_mdiff_on_univ uniqueMDiffOn_univ - -/- We name the typeclass variables related to `SmoothManifoldWithCorners` structure as they are -necessary in lemmas mentioning the derivative, but not in lemmas about differentiability, so we -want to include them or omit them when necessary. -/ -variable [Is : SmoothManifoldWithCorners I M] [I's : SmoothManifoldWithCorners I' M'] - [I''s : SmoothManifoldWithCorners I'' M''] - {f' f₀' f₁' : TangentSpace I x →L[𝕜] TangentSpace I' (f x)} - {g' : TangentSpace I' (f x) →L[𝕜] TangentSpace I'' (g (f x))} - -/-- `UniqueMDiffWithinAt` achieves its goal: it implies the uniqueness of the derivative. -/ -nonrec theorem UniqueMDiffWithinAt.eq (U : UniqueMDiffWithinAt I s x) - (h : HasMFDerivWithinAt I I' f s x f') (h₁ : HasMFDerivWithinAt I I' f s x f₁') : f' = f₁' := by - -- porting note: didn't need `convert` because of finding instances by unification - convert U.eq h.2 h₁.2 -#align unique_mdiff_within_at.eq UniqueMDiffWithinAt.eq - -theorem UniqueMDiffOn.eq (U : UniqueMDiffOn I s) (hx : x ∈ s) (h : HasMFDerivWithinAt I I' f s x f') - (h₁ : HasMFDerivWithinAt I I' f s x f₁') : f' = f₁' := - UniqueMDiffWithinAt.eq (U _ hx) h h₁ -#align unique_mdiff_on.eq UniqueMDiffOn.eq - -nonrec theorem UniqueMDiffWithinAt.prod {x : M} {y : M'} {s t} (hs : UniqueMDiffWithinAt I s x) - (ht : UniqueMDiffWithinAt I' t y) : UniqueMDiffWithinAt (I.prod I') (s ×ˢ t) (x, y) := by - refine (hs.prod ht).mono ?_ - rw [ModelWithCorners.range_prod, ← prod_inter_prod] - rfl - -theorem UniqueMDiffOn.prod {s : Set M} {t : Set M'} (hs : UniqueMDiffOn I s) - (ht : UniqueMDiffOn I' t) : UniqueMDiffOn (I.prod I') (s ×ˢ t) := fun x h ↦ - (hs x.1 h.1).prod (ht x.2 h.2) - -/-! -### General lemmas on derivatives of functions between manifolds - -We mimick the API for functions between vector spaces --/ - -theorem mdifferentiableWithinAt_iff {f : M → M'} {s : Set M} {x : M} : - MDifferentiableWithinAt I I' f s x ↔ - ContinuousWithinAt f s x ∧ - DifferentiableWithinAt 𝕜 (writtenInExtChartAt I I' x f) - ((extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' s) ((extChartAt I x) x) := by - refine' and_congr Iff.rfl (exists_congr fun f' => _) - rw [inter_comm] - simp only [HasFDerivWithinAt, nhdsWithin_inter, nhdsWithin_extChartAt_target_eq] -#align mdifferentiable_within_at_iff mdifferentiableWithinAt_iff - -/-- One can reformulate differentiability within a set at a point as continuity within this set at -this point, and differentiability in any chart containing that point. -/ -theorem mdifferentiableWithinAt_iff_of_mem_source {x' : M} {y : M'} - (hx : x' ∈ (chartAt H x).source) (hy : f x' ∈ (chartAt H' y).source) : - MDifferentiableWithinAt I I' f s x' ↔ - ContinuousWithinAt f s x' ∧ - DifferentiableWithinAt 𝕜 (extChartAt I' y ∘ f ∘ (extChartAt I x).symm) - ((extChartAt I x).symm ⁻¹' s ∩ Set.range I) ((extChartAt I x) x') := - (differentiable_within_at_localInvariantProp I I').liftPropWithinAt_indep_chart - (StructureGroupoid.chart_mem_maximalAtlas _ x) hx (StructureGroupoid.chart_mem_maximalAtlas _ y) - hy -#align mdifferentiable_within_at_iff_of_mem_source mdifferentiableWithinAt_iff_of_mem_source - -theorem mfderivWithin_zero_of_not_mdifferentiableWithinAt - (h : ¬MDifferentiableWithinAt I I' f s x) : mfderivWithin I I' f s x = 0 := by - simp only [mfderivWithin, h, if_neg, not_false_iff] -#align mfderiv_within_zero_of_not_mdifferentiable_within_at mfderivWithin_zero_of_not_mdifferentiableWithinAt - -theorem mfderiv_zero_of_not_mdifferentiableAt (h : ¬MDifferentiableAt I I' f x) : - mfderiv I I' f x = 0 := by simp only [mfderiv, h, if_neg, not_false_iff] -#align mfderiv_zero_of_not_mdifferentiable_at mfderiv_zero_of_not_mdifferentiableAt - -theorem HasMFDerivWithinAt.mono (h : HasMFDerivWithinAt I I' f t x f') (hst : s ⊆ t) : - HasMFDerivWithinAt I I' f s x f' := - ⟨ContinuousWithinAt.mono h.1 hst, - HasFDerivWithinAt.mono h.2 (inter_subset_inter (preimage_mono hst) (Subset.refl _))⟩ -#align has_mfderiv_within_at.mono HasMFDerivWithinAt.mono - -theorem HasMFDerivAt.hasMFDerivWithinAt (h : HasMFDerivAt I I' f x f') : - HasMFDerivWithinAt I I' f s x f' := - ⟨ContinuousAt.continuousWithinAt h.1, HasFDerivWithinAt.mono h.2 (inter_subset_right _ _)⟩ -#align has_mfderiv_at.has_mfderiv_within_at HasMFDerivAt.hasMFDerivWithinAt - -theorem HasMFDerivWithinAt.mdifferentiableWithinAt (h : HasMFDerivWithinAt I I' f s x f') : - MDifferentiableWithinAt I I' f s x := - ⟨h.1, ⟨f', h.2⟩⟩ -#align has_mfderiv_within_at.mdifferentiable_within_at HasMFDerivWithinAt.mdifferentiableWithinAt - -theorem HasMFDerivAt.mdifferentiableAt (h : HasMFDerivAt I I' f x f') : - MDifferentiableAt I I' f x := - ⟨h.1, ⟨f', h.2⟩⟩ -#align has_mfderiv_at.mdifferentiable_at HasMFDerivAt.mdifferentiableAt - -@[simp, mfld_simps] -theorem hasMFDerivWithinAt_univ : HasMFDerivWithinAt I I' f univ x f' ↔ HasMFDerivAt I I' f x f' := - by simp only [HasMFDerivWithinAt, HasMFDerivAt, continuousWithinAt_univ, mfld_simps] -#align has_mfderiv_within_at_univ hasMFDerivWithinAt_univ - -theorem hasMFDerivAt_unique (h₀ : HasMFDerivAt I I' f x f₀') (h₁ : HasMFDerivAt I I' f x f₁') : - f₀' = f₁' := by - rw [← hasMFDerivWithinAt_univ] at h₀ h₁ - exact (uniqueMDiffWithinAt_univ I).eq h₀ h₁ -#align has_mfderiv_at_unique hasMFDerivAt_unique - -theorem hasMFDerivWithinAt_inter' (h : t ∈ 𝓝[s] x) : - HasMFDerivWithinAt I I' f (s ∩ t) x f' ↔ HasMFDerivWithinAt I I' f s x f' := by - rw [HasMFDerivWithinAt, HasMFDerivWithinAt, extChartAt_preimage_inter_eq, - hasFDerivWithinAt_inter', continuousWithinAt_inter' h] - exact extChartAt_preimage_mem_nhdsWithin I x h -#align has_mfderiv_within_at_inter' hasMFDerivWithinAt_inter' - -theorem hasMFDerivWithinAt_inter (h : t ∈ 𝓝 x) : - HasMFDerivWithinAt I I' f (s ∩ t) x f' ↔ HasMFDerivWithinAt I I' f s x f' := by - rw [HasMFDerivWithinAt, HasMFDerivWithinAt, extChartAt_preimage_inter_eq, hasFDerivWithinAt_inter, - continuousWithinAt_inter h] - exact extChartAt_preimage_mem_nhds I x h -#align has_mfderiv_within_at_inter hasMFDerivWithinAt_inter - -theorem HasMFDerivWithinAt.union (hs : HasMFDerivWithinAt I I' f s x f') - (ht : HasMFDerivWithinAt I I' f t x f') : HasMFDerivWithinAt I I' f (s ∪ t) x f' := by - constructor - · exact ContinuousWithinAt.union hs.1 ht.1 - · convert HasFDerivWithinAt.union hs.2 ht.2 using 1 - simp only [union_inter_distrib_right, preimage_union] -#align has_mfderiv_within_at.union HasMFDerivWithinAt.union - -theorem HasMFDerivWithinAt.mono_of_mem (h : HasMFDerivWithinAt I I' f s x f') (ht : s ∈ 𝓝[t] x) : - HasMFDerivWithinAt I I' f t x f' := - (hasMFDerivWithinAt_inter' ht).1 (h.mono (inter_subset_right _ _)) -#align has_mfderiv_within_at.nhds_within HasMFDerivWithinAt.mono_of_mem - -theorem HasMFDerivWithinAt.hasMFDerivAt (h : HasMFDerivWithinAt I I' f s x f') (hs : s ∈ 𝓝 x) : - HasMFDerivAt I I' f x f' := by - rwa [← univ_inter s, hasMFDerivWithinAt_inter hs, hasMFDerivWithinAt_univ] at h -#align has_mfderiv_within_at.has_mfderiv_at HasMFDerivWithinAt.hasMFDerivAt - -theorem MDifferentiableWithinAt.hasMFDerivWithinAt (h : MDifferentiableWithinAt I I' f s x) : - HasMFDerivWithinAt I I' f s x (mfderivWithin I I' f s x) := by - refine' ⟨h.1, _⟩ - simp only [mfderivWithin, h, if_pos, mfld_simps] - exact DifferentiableWithinAt.hasFDerivWithinAt h.2 -#align mdifferentiable_within_at.has_mfderiv_within_at MDifferentiableWithinAt.hasMFDerivWithinAt - -protected theorem MDifferentiableWithinAt.mfderivWithin (h : MDifferentiableWithinAt I I' f s x) : - mfderivWithin I I' f s x = - fderivWithin 𝕜 (writtenInExtChartAt I I' x f : _) ((extChartAt I x).symm ⁻¹' s ∩ range I) - ((extChartAt I x) x) := - by simp only [mfderivWithin, h, if_pos] -#align mdifferentiable_within_at.mfderiv_within MDifferentiableWithinAt.mfderivWithin - -theorem MDifferentiableAt.hasMFDerivAt (h : MDifferentiableAt I I' f x) : - HasMFDerivAt I I' f x (mfderiv I I' f x) := by - refine' ⟨h.1, _⟩ - simp only [mfderiv, h, if_pos, mfld_simps] - exact DifferentiableWithinAt.hasFDerivWithinAt h.2 -#align mdifferentiable_at.has_mfderiv_at MDifferentiableAt.hasMFDerivAt - -protected theorem MDifferentiableAt.mfderiv (h : MDifferentiableAt I I' f x) : - mfderiv I I' f x = - fderivWithin 𝕜 (writtenInExtChartAt I I' x f : _) (range I) ((extChartAt I x) x) := - by simp only [mfderiv, h, if_pos] -#align mdifferentiable_at.mfderiv MDifferentiableAt.mfderiv - -protected theorem HasMFDerivAt.mfderiv (h : HasMFDerivAt I I' f x f') : mfderiv I I' f x = f' := - (hasMFDerivAt_unique h h.mdifferentiableAt.hasMFDerivAt).symm -#align has_mfderiv_at.mfderiv HasMFDerivAt.mfderiv - -theorem HasMFDerivWithinAt.mfderivWithin (h : HasMFDerivWithinAt I I' f s x f') - (hxs : UniqueMDiffWithinAt I s x) : mfderivWithin I I' f s x = f' := by - ext - rw [hxs.eq h h.mdifferentiableWithinAt.hasMFDerivWithinAt] -#align has_mfderiv_within_at.mfderiv_within HasMFDerivWithinAt.mfderivWithin - -theorem MDifferentiable.mfderivWithin (h : MDifferentiableAt I I' f x) - (hxs : UniqueMDiffWithinAt I s x) : mfderivWithin I I' f s x = mfderiv I I' f x := by - apply HasMFDerivWithinAt.mfderivWithin _ hxs - exact h.hasMFDerivAt.hasMFDerivWithinAt -#align mdifferentiable.mfderiv_within MDifferentiable.mfderivWithin - -theorem mfderivWithin_subset (st : s ⊆ t) (hs : UniqueMDiffWithinAt I s x) - (h : MDifferentiableWithinAt I I' f t x) : - mfderivWithin I I' f s x = mfderivWithin I I' f t x := - ((MDifferentiableWithinAt.hasMFDerivWithinAt h).mono st).mfderivWithin hs -#align mfderiv_within_subset mfderivWithin_subset - -theorem MDifferentiableWithinAt.mono (hst : s ⊆ t) (h : MDifferentiableWithinAt I I' f t x) : - MDifferentiableWithinAt I I' f s x := - ⟨ContinuousWithinAt.mono h.1 hst, - DifferentiableWithinAt.mono h.2 (inter_subset_inter (preimage_mono hst) (Subset.refl _))⟩ -#align mdifferentiable_within_at.mono MDifferentiableWithinAt.mono - -theorem mdifferentiableWithinAt_univ : - MDifferentiableWithinAt I I' f univ x ↔ MDifferentiableAt I I' f x := by - simp only [MDifferentiableWithinAt, MDifferentiableAt, continuousWithinAt_univ, mfld_simps] -#align mdifferentiable_within_at_univ mdifferentiableWithinAt_univ - -theorem mdifferentiableWithinAt_inter (ht : t ∈ 𝓝 x) : - MDifferentiableWithinAt I I' f (s ∩ t) x ↔ MDifferentiableWithinAt I I' f s x := by - rw [MDifferentiableWithinAt, MDifferentiableWithinAt, extChartAt_preimage_inter_eq, - differentiableWithinAt_inter, continuousWithinAt_inter ht] - exact extChartAt_preimage_mem_nhds I x ht -#align mdifferentiable_within_at_inter mdifferentiableWithinAt_inter - -theorem mdifferentiableWithinAt_inter' (ht : t ∈ 𝓝[s] x) : - MDifferentiableWithinAt I I' f (s ∩ t) x ↔ MDifferentiableWithinAt I I' f s x := by - rw [MDifferentiableWithinAt, MDifferentiableWithinAt, extChartAt_preimage_inter_eq, - differentiableWithinAt_inter', continuousWithinAt_inter' ht] - exact extChartAt_preimage_mem_nhdsWithin I x ht -#align mdifferentiable_within_at_inter' mdifferentiableWithinAt_inter' - -theorem MDifferentiableAt.mdifferentiableWithinAt (h : MDifferentiableAt I I' f x) : - MDifferentiableWithinAt I I' f s x := - MDifferentiableWithinAt.mono (subset_univ _) (mdifferentiableWithinAt_univ.2 h) -#align mdifferentiable_at.mdifferentiable_within_at MDifferentiableAt.mdifferentiableWithinAt - -theorem MDifferentiableWithinAt.mdifferentiableAt (h : MDifferentiableWithinAt I I' f s x) - (hs : s ∈ 𝓝 x) : MDifferentiableAt I I' f x := by - have : s = univ ∩ s := by rw [univ_inter] - rwa [this, mdifferentiableWithinAt_inter hs, mdifferentiableWithinAt_univ] at h -#align mdifferentiable_within_at.mdifferentiable_at MDifferentiableWithinAt.mdifferentiableAt - -theorem MDifferentiableOn.mdifferentiableAt (h : MDifferentiableOn I I' f s) (hx : s ∈ 𝓝 x) : - MDifferentiableAt I I' f x := - (h x (mem_of_mem_nhds hx)).mdifferentiableAt hx - -theorem MDifferentiableOn.mono (h : MDifferentiableOn I I' f t) (st : s ⊆ t) : - MDifferentiableOn I I' f s := fun x hx => (h x (st hx)).mono st -#align mdifferentiable_on.mono MDifferentiableOn.mono - -theorem mdifferentiableOn_univ : MDifferentiableOn I I' f univ ↔ MDifferentiable I I' f := by - simp only [MDifferentiableOn, mdifferentiableWithinAt_univ, mfld_simps]; rfl -#align mdifferentiable_on_univ mdifferentiableOn_univ - -theorem MDifferentiable.mdifferentiableOn (h : MDifferentiable I I' f) : - MDifferentiableOn I I' f s := - (mdifferentiableOn_univ.2 h).mono (subset_univ _) -#align mdifferentiable.mdifferentiable_on MDifferentiable.mdifferentiableOn - -theorem mdifferentiableOn_of_locally_mdifferentiableOn - (h : ∀ x ∈ s, ∃ u, IsOpen u ∧ x ∈ u ∧ MDifferentiableOn I I' f (s ∩ u)) : - MDifferentiableOn I I' f s := by - intro x xs - rcases h x xs with ⟨t, t_open, xt, ht⟩ - exact (mdifferentiableWithinAt_inter (IsOpen.mem_nhds t_open xt)).1 (ht x ⟨xs, xt⟩) -#align mdifferentiable_on_of_locally_mdifferentiable_on mdifferentiableOn_of_locally_mdifferentiableOn - -@[simp, mfld_simps] -theorem mfderivWithin_univ : mfderivWithin I I' f univ = mfderiv I I' f := by - ext x : 1 - simp only [mfderivWithin, mfderiv, mfld_simps] - rw [mdifferentiableWithinAt_univ] -#align mfderiv_within_univ mfderivWithin_univ - -theorem mfderivWithin_inter (ht : t ∈ 𝓝 x) : - mfderivWithin I I' f (s ∩ t) x = mfderivWithin I I' f s x := by - rw [mfderivWithin, mfderivWithin, extChartAt_preimage_inter_eq, mdifferentiableWithinAt_inter ht, - fderivWithin_inter (extChartAt_preimage_mem_nhds I x ht)] -#align mfderiv_within_inter mfderivWithin_inter - -theorem mfderivWithin_of_mem_nhds (h : s ∈ 𝓝 x) : mfderivWithin I I' f s x = mfderiv I I' f x := by - rw [← mfderivWithin_univ, ← univ_inter s, mfderivWithin_inter h] - -lemma mfderivWithin_of_isOpen (hs : IsOpen s) (hx : x ∈ s) : - mfderivWithin I I' f s x = mfderiv I I' f x := - mfderivWithin_of_mem_nhds (hs.mem_nhds hx) - -theorem mfderivWithin_eq_mfderiv (hs : UniqueMDiffWithinAt I s x) (h : MDifferentiableAt I I' f x) : - mfderivWithin I I' f s x = mfderiv I I' f x := by - rw [← mfderivWithin_univ] - exact mfderivWithin_subset (subset_univ _) hs h.mdifferentiableWithinAt - -theorem mdifferentiableAt_iff_of_mem_source {x' : M} {y : M'} - (hx : x' ∈ (chartAt H x).source) (hy : f x' ∈ (chartAt H' y).source) : - MDifferentiableAt I I' f x' ↔ - ContinuousAt f x' ∧ - DifferentiableWithinAt 𝕜 (extChartAt I' y ∘ f ∘ (extChartAt I x).symm) (Set.range I) - ((extChartAt I x) x') := - mdifferentiableWithinAt_univ.symm.trans <| - (mdifferentiableWithinAt_iff_of_mem_source hx hy).trans <| by - rw [continuousWithinAt_univ, Set.preimage_univ, Set.univ_inter] -#align mdifferentiable_at_iff_of_mem_source mdifferentiableAt_iff_of_mem_source - -/-! ### Deducing differentiability from smoothness -/ - --- porting note: moved from `ContMDiffMFDeriv` - -theorem ContMDiffWithinAt.mdifferentiableWithinAt (hf : ContMDiffWithinAt I I' n f s x) - (hn : 1 ≤ n) : MDifferentiableWithinAt I I' f s x := by - suffices h : MDifferentiableWithinAt I I' f (s ∩ f ⁻¹' (extChartAt I' (f x)).source) x - · rwa [mdifferentiableWithinAt_inter'] at h - apply hf.1.preimage_mem_nhdsWithin - exact extChartAt_source_mem_nhds I' (f x) - rw [mdifferentiableWithinAt_iff] - exact ⟨hf.1.mono (inter_subset_left _ _), (hf.2.differentiableWithinAt hn).mono (by mfld_set_tac)⟩ -#align cont_mdiff_within_at.mdifferentiable_within_at ContMDiffWithinAt.mdifferentiableWithinAt - -theorem ContMDiffAt.mdifferentiableAt (hf : ContMDiffAt I I' n f x) (hn : 1 ≤ n) : - MDifferentiableAt I I' f x := - mdifferentiableWithinAt_univ.1 <| ContMDiffWithinAt.mdifferentiableWithinAt hf hn -#align cont_mdiff_at.mdifferentiable_at ContMDiffAt.mdifferentiableAt - -theorem ContMDiffOn.mdifferentiableOn (hf : ContMDiffOn I I' n f s) (hn : 1 ≤ n) : - MDifferentiableOn I I' f s := fun x hx => (hf x hx).mdifferentiableWithinAt hn -#align cont_mdiff_on.mdifferentiable_on ContMDiffOn.mdifferentiableOn - -theorem ContMDiff.mdifferentiable (hf : ContMDiff I I' n f) (hn : 1 ≤ n) : MDifferentiable I I' f := - fun x => (hf x).mdifferentiableAt hn -#align cont_mdiff.mdifferentiable ContMDiff.mdifferentiable - -nonrec theorem SmoothWithinAt.mdifferentiableWithinAt (hf : SmoothWithinAt I I' f s x) : - MDifferentiableWithinAt I I' f s x := - hf.mdifferentiableWithinAt le_top -#align smooth_within_at.mdifferentiable_within_at SmoothWithinAt.mdifferentiableWithinAt - -nonrec theorem SmoothAt.mdifferentiableAt (hf : SmoothAt I I' f x) : MDifferentiableAt I I' f x := - hf.mdifferentiableAt le_top -#align smooth_at.mdifferentiable_at SmoothAt.mdifferentiableAt - -nonrec theorem SmoothOn.mdifferentiableOn (hf : SmoothOn I I' f s) : MDifferentiableOn I I' f s := - hf.mdifferentiableOn le_top -#align smooth_on.mdifferentiable_on SmoothOn.mdifferentiableOn - -theorem Smooth.mdifferentiable (hf : Smooth I I' f) : MDifferentiable I I' f := - ContMDiff.mdifferentiable hf le_top -#align smooth.mdifferentiable Smooth.mdifferentiable - -theorem Smooth.mdifferentiableAt (hf : Smooth I I' f) : MDifferentiableAt I I' f x := - hf.mdifferentiable x -#align smooth.mdifferentiable_at Smooth.mdifferentiableAt - -theorem Smooth.mdifferentiableWithinAt (hf : Smooth I I' f) : MDifferentiableWithinAt I I' f s x := - hf.mdifferentiableAt.mdifferentiableWithinAt -#align smooth.mdifferentiable_within_at Smooth.mdifferentiableWithinAt - -/-! ### Deriving continuity from differentiability on manifolds -/ - -theorem HasMFDerivWithinAt.continuousWithinAt (h : HasMFDerivWithinAt I I' f s x f') : - ContinuousWithinAt f s x := - h.1 -#align has_mfderiv_within_at.continuous_within_at HasMFDerivWithinAt.continuousWithinAt - -theorem HasMFDerivAt.continuousAt (h : HasMFDerivAt I I' f x f') : ContinuousAt f x := - h.1 -#align has_mfderiv_at.continuous_at HasMFDerivAt.continuousAt - -theorem MDifferentiableWithinAt.continuousWithinAt (h : MDifferentiableWithinAt I I' f s x) : - ContinuousWithinAt f s x := - h.1 -#align mdifferentiable_within_at.continuous_within_at MDifferentiableWithinAt.continuousWithinAt - -theorem MDifferentiableAt.continuousAt (h : MDifferentiableAt I I' f x) : ContinuousAt f x := - h.1 -#align mdifferentiable_at.continuous_at MDifferentiableAt.continuousAt - -theorem MDifferentiableOn.continuousOn (h : MDifferentiableOn I I' f s) : ContinuousOn f s := - fun x hx => (h x hx).continuousWithinAt -#align mdifferentiable_on.continuous_on MDifferentiableOn.continuousOn - -theorem MDifferentiable.continuous (h : MDifferentiable I I' f) : Continuous f := - continuous_iff_continuousAt.2 fun x => (h x).continuousAt -#align mdifferentiable.continuous MDifferentiable.continuous - -theorem tangentMapWithin_subset {p : TangentBundle I M} (st : s ⊆ t) - (hs : UniqueMDiffWithinAt I s p.1) (h : MDifferentiableWithinAt I I' f t p.1) : - tangentMapWithin I I' f s p = tangentMapWithin I I' f t p := by - simp only [tangentMapWithin, mfld_simps] - rw [mfderivWithin_subset st hs h] -#align tangent_map_within_subset tangentMapWithin_subset - -theorem tangentMapWithin_univ : tangentMapWithin I I' f univ = tangentMap I I' f := by - ext p : 1 - simp only [tangentMapWithin, tangentMap, mfld_simps] -#align tangent_map_within_univ tangentMapWithin_univ - -theorem tangentMapWithin_eq_tangentMap {p : TangentBundle I M} (hs : UniqueMDiffWithinAt I s p.1) - (h : MDifferentiableAt I I' f p.1) : tangentMapWithin I I' f s p = tangentMap I I' f p := by - rw [← mdifferentiableWithinAt_univ] at h - rw [← tangentMapWithin_univ] - exact tangentMapWithin_subset (subset_univ _) hs h -#align tangent_map_within_eq_tangent_map tangentMapWithin_eq_tangentMap - -@[simp, mfld_simps] -theorem tangentMapWithin_proj {p : TangentBundle I M} : - (tangentMapWithin I I' f s p).proj = f p.proj := - rfl -#align tangent_map_within_proj tangentMapWithin_proj - -@[simp, mfld_simps] -theorem tangentMap_proj {p : TangentBundle I M} : (tangentMap I I' f p).proj = f p.proj := - rfl -#align tangent_map_proj tangentMap_proj - -theorem MDifferentiableWithinAt.prod_mk {f : M → M'} {g : M → M''} - (hf : MDifferentiableWithinAt I I' f s x) (hg : MDifferentiableWithinAt I I'' g s x) : - MDifferentiableWithinAt I (I'.prod I'') (fun x => (f x, g x)) s x := - ⟨hf.1.prod hg.1, hf.2.prod hg.2⟩ -#align mdifferentiable_within_at.prod_mk MDifferentiableWithinAt.prod_mk - -theorem MDifferentiableAt.prod_mk {f : M → M'} {g : M → M''} (hf : MDifferentiableAt I I' f x) - (hg : MDifferentiableAt I I'' g x) : - MDifferentiableAt I (I'.prod I'') (fun x => (f x, g x)) x := - ⟨hf.1.prod hg.1, hf.2.prod hg.2⟩ -#align mdifferentiable_at.prod_mk MDifferentiableAt.prod_mk - -theorem MDifferentiableOn.prod_mk {f : M → M'} {g : M → M''} (hf : MDifferentiableOn I I' f s) - (hg : MDifferentiableOn I I'' g s) : - MDifferentiableOn I (I'.prod I'') (fun x => (f x, g x)) s := fun x hx => - (hf x hx).prod_mk (hg x hx) -#align mdifferentiable_on.prod_mk MDifferentiableOn.prod_mk - -theorem MDifferentiable.prod_mk {f : M → M'} {g : M → M''} (hf : MDifferentiable I I' f) - (hg : MDifferentiable I I'' g) : MDifferentiable I (I'.prod I'') fun x => (f x, g x) := fun x => - (hf x).prod_mk (hg x) -#align mdifferentiable.prod_mk MDifferentiable.prod_mk - -theorem MDifferentiableWithinAt.prod_mk_space {f : M → E'} {g : M → E''} - (hf : MDifferentiableWithinAt I 𝓘(𝕜, E') f s x) - (hg : MDifferentiableWithinAt I 𝓘(𝕜, E'') g s x) : - MDifferentiableWithinAt I 𝓘(𝕜, E' × E'') (fun x => (f x, g x)) s x := - ⟨hf.1.prod hg.1, hf.2.prod hg.2⟩ -#align mdifferentiable_within_at.prod_mk_space MDifferentiableWithinAt.prod_mk_space - -theorem MDifferentiableAt.prod_mk_space {f : M → E'} {g : M → E''} - (hf : MDifferentiableAt I 𝓘(𝕜, E') f x) (hg : MDifferentiableAt I 𝓘(𝕜, E'') g x) : - MDifferentiableAt I 𝓘(𝕜, E' × E'') (fun x => (f x, g x)) x := - ⟨hf.1.prod hg.1, hf.2.prod hg.2⟩ -#align mdifferentiable_at.prod_mk_space MDifferentiableAt.prod_mk_space - -theorem MDifferentiableOn.prod_mk_space {f : M → E'} {g : M → E''} - (hf : MDifferentiableOn I 𝓘(𝕜, E') f s) (hg : MDifferentiableOn I 𝓘(𝕜, E'') g s) : - MDifferentiableOn I 𝓘(𝕜, E' × E'') (fun x => (f x, g x)) s := fun x hx => - (hf x hx).prod_mk_space (hg x hx) -#align mdifferentiable_on.prod_mk_space MDifferentiableOn.prod_mk_space - -theorem MDifferentiable.prod_mk_space {f : M → E'} {g : M → E''} (hf : MDifferentiable I 𝓘(𝕜, E') f) - (hg : MDifferentiable I 𝓘(𝕜, E'') g) : MDifferentiable I 𝓘(𝕜, E' × E'') fun x => (f x, g x) := - fun x => (hf x).prod_mk_space (hg x) -#align mdifferentiable.prod_mk_space MDifferentiable.prod_mk_space - -/-! ### Congruence lemmas for derivatives on manifolds -/ - -theorem HasMFDerivAt.congr_mfderiv (h : HasMFDerivAt I I' f x f') (h' : f' = f₁') : - HasMFDerivAt I I' f x f₁' := - h' ▸ h - -theorem HasMFDerivWithinAt.congr_mfderiv (h : HasMFDerivWithinAt I I' f s x f') (h' : f' = f₁') : - HasMFDerivWithinAt I I' f s x f₁' := - h' ▸ h - -theorem HasMFDerivWithinAt.congr_of_eventuallyEq (h : HasMFDerivWithinAt I I' f s x f') - (h₁ : f₁ =ᶠ[𝓝[s] x] f) (hx : f₁ x = f x) : HasMFDerivWithinAt I I' f₁ s x f' := by - refine' ⟨ContinuousWithinAt.congr_of_eventuallyEq h.1 h₁ hx, _⟩ - apply HasFDerivWithinAt.congr_of_eventuallyEq h.2 - · have : - (extChartAt I x).symm ⁻¹' {y | f₁ y = f y} ∈ - 𝓝[(extChartAt I x).symm ⁻¹' s ∩ range I] (extChartAt I x) x := - extChartAt_preimage_mem_nhdsWithin I x h₁ - apply Filter.mem_of_superset this fun y => _ - simp (config := { contextual := true }) only [hx, mfld_simps] - · simp only [hx, mfld_simps] -#align has_mfderiv_within_at.congr_of_eventually_eq HasMFDerivWithinAt.congr_of_eventuallyEq - -theorem HasMFDerivWithinAt.congr_mono (h : HasMFDerivWithinAt I I' f s x f') - (ht : ∀ x ∈ t, f₁ x = f x) (hx : f₁ x = f x) (h₁ : t ⊆ s) : HasMFDerivWithinAt I I' f₁ t x f' := - (h.mono h₁).congr_of_eventuallyEq (Filter.mem_inf_of_right ht) hx -#align has_mfderiv_within_at.congr_mono HasMFDerivWithinAt.congr_mono - -theorem HasMFDerivAt.congr_of_eventuallyEq (h : HasMFDerivAt I I' f x f') (h₁ : f₁ =ᶠ[𝓝 x] f) : - HasMFDerivAt I I' f₁ x f' := by - rw [← hasMFDerivWithinAt_univ] at h ⊢ - apply h.congr_of_eventuallyEq _ (mem_of_mem_nhds h₁ : _) - rwa [nhdsWithin_univ] -#align has_mfderiv_at.congr_of_eventually_eq HasMFDerivAt.congr_of_eventuallyEq - -theorem MDifferentiableWithinAt.congr_of_eventuallyEq (h : MDifferentiableWithinAt I I' f s x) - (h₁ : f₁ =ᶠ[𝓝[s] x] f) (hx : f₁ x = f x) : MDifferentiableWithinAt I I' f₁ s x := - (h.hasMFDerivWithinAt.congr_of_eventuallyEq h₁ hx).mdifferentiableWithinAt -#align mdifferentiable_within_at.congr_of_eventually_eq MDifferentiableWithinAt.congr_of_eventuallyEq - -variable (I I') - -theorem Filter.EventuallyEq.mdifferentiableWithinAt_iff (h₁ : f₁ =ᶠ[𝓝[s] x] f) (hx : f₁ x = f x) : - MDifferentiableWithinAt I I' f s x ↔ MDifferentiableWithinAt I I' f₁ s x := by - constructor - · intro h - apply h.congr_of_eventuallyEq h₁ hx - · intro h - apply h.congr_of_eventuallyEq _ hx.symm - apply h₁.mono - intro y - apply Eq.symm -#align filter.eventually_eq.mdifferentiable_within_at_iff Filter.EventuallyEq.mdifferentiableWithinAt_iff - -variable {I I'} - -theorem MDifferentiableWithinAt.congr_mono (h : MDifferentiableWithinAt I I' f s x) - (ht : ∀ x ∈ t, f₁ x = f x) (hx : f₁ x = f x) (h₁ : t ⊆ s) : - MDifferentiableWithinAt I I' f₁ t x := - (HasMFDerivWithinAt.congr_mono h.hasMFDerivWithinAt ht hx h₁).mdifferentiableWithinAt -#align mdifferentiable_within_at.congr_mono MDifferentiableWithinAt.congr_mono - -theorem MDifferentiableWithinAt.congr (h : MDifferentiableWithinAt I I' f s x) - (ht : ∀ x ∈ s, f₁ x = f x) (hx : f₁ x = f x) : MDifferentiableWithinAt I I' f₁ s x := - (HasMFDerivWithinAt.congr_mono h.hasMFDerivWithinAt ht hx (Subset.refl _)).mdifferentiableWithinAt -#align mdifferentiable_within_at.congr MDifferentiableWithinAt.congr - -theorem MDifferentiableOn.congr_mono (h : MDifferentiableOn I I' f s) (h' : ∀ x ∈ t, f₁ x = f x) - (h₁ : t ⊆ s) : MDifferentiableOn I I' f₁ t := fun x hx => - (h x (h₁ hx)).congr_mono h' (h' x hx) h₁ -#align mdifferentiable_on.congr_mono MDifferentiableOn.congr_mono - -theorem MDifferentiableAt.congr_of_eventuallyEq (h : MDifferentiableAt I I' f x) - (hL : f₁ =ᶠ[𝓝 x] f) : MDifferentiableAt I I' f₁ x := - (h.hasMFDerivAt.congr_of_eventuallyEq hL).mdifferentiableAt -#align mdifferentiable_at.congr_of_eventually_eq MDifferentiableAt.congr_of_eventuallyEq - -theorem MDifferentiableWithinAt.mfderivWithin_congr_mono (h : MDifferentiableWithinAt I I' f s x) - (hs : ∀ x ∈ t, f₁ x = f x) (hx : f₁ x = f x) (hxt : UniqueMDiffWithinAt I t x) (h₁ : t ⊆ s) : - mfderivWithin I I' f₁ t x = (mfderivWithin I I' f s x : _) := - (HasMFDerivWithinAt.congr_mono h.hasMFDerivWithinAt hs hx h₁).mfderivWithin hxt -#align mdifferentiable_within_at.mfderiv_within_congr_mono MDifferentiableWithinAt.mfderivWithin_congr_mono - -theorem Filter.EventuallyEq.mfderivWithin_eq (hs : UniqueMDiffWithinAt I s x) (hL : f₁ =ᶠ[𝓝[s] x] f) - (hx : f₁ x = f x) : mfderivWithin I I' f₁ s x = (mfderivWithin I I' f s x : _) := by - by_cases h : MDifferentiableWithinAt I I' f s x - · exact (h.hasMFDerivWithinAt.congr_of_eventuallyEq hL hx).mfderivWithin hs - · unfold mfderivWithin - rw [if_neg h, if_neg] - rwa [← hL.mdifferentiableWithinAt_iff I I' hx] -#align filter.eventually_eq.mfderiv_within_eq Filter.EventuallyEq.mfderivWithin_eq - -theorem mfderivWithin_congr (hs : UniqueMDiffWithinAt I s x) (hL : ∀ x ∈ s, f₁ x = f x) - (hx : f₁ x = f x) : mfderivWithin I I' f₁ s x = (mfderivWithin I I' f s x : _) := - Filter.EventuallyEq.mfderivWithin_eq hs (Filter.eventuallyEq_of_mem self_mem_nhdsWithin hL) hx -#align mfderiv_within_congr mfderivWithin_congr - -theorem tangentMapWithin_congr (h : ∀ x ∈ s, f x = f₁ x) (p : TangentBundle I M) (hp : p.1 ∈ s) - (hs : UniqueMDiffWithinAt I s p.1) : - tangentMapWithin I I' f s p = tangentMapWithin I I' f₁ s p := by - refine TotalSpace.ext _ _ (h p.1 hp) ?_ - -- This used to be `simp only`, but we need `erw` after leanprover/lean4#2644 - rw [tangentMapWithin, h p.1 hp, tangentMapWithin, mfderivWithin_congr hs h (h _ hp)] -#align tangent_map_within_congr tangentMapWithin_congr - -theorem Filter.EventuallyEq.mfderiv_eq (hL : f₁ =ᶠ[𝓝 x] f) : - mfderiv I I' f₁ x = (mfderiv I I' f x : _) := by - have A : f₁ x = f x := (mem_of_mem_nhds hL : _) - rw [← mfderivWithin_univ, ← mfderivWithin_univ] - rw [← nhdsWithin_univ] at hL - exact hL.mfderivWithin_eq (uniqueMDiffWithinAt_univ I) A -#align filter.eventually_eq.mfderiv_eq Filter.EventuallyEq.mfderiv_eq - -/-- A congruence lemma for `mfderiv`, (ab)using the fact that `TangentSpace I' (f x)` is -definitionally equal to `E'`. -/ -theorem mfderiv_congr_point {x' : M} (h : x = x') : - @Eq (E →L[𝕜] E') (mfderiv I I' f x) (mfderiv I I' f x') := by subst h; rfl -#align mfderiv_congr_point mfderiv_congr_point - -/-- A congruence lemma for `mfderiv`, (ab)using the fact that `TangentSpace I' (f x)` is -definitionally equal to `E'`. -/ -theorem mfderiv_congr {f' : M → M'} (h : f = f') : - @Eq (E →L[𝕜] E') (mfderiv I I' f x) (mfderiv I I' f' x) := by subst h; rfl -#align mfderiv_congr mfderiv_congr - -/-! ### Composition lemmas -/ - -theorem writtenInExtChartAt_comp (h : ContinuousWithinAt f s x) : - {y | writtenInExtChartAt I I'' x (g ∘ f) y = - (writtenInExtChartAt I' I'' (f x) g ∘ writtenInExtChartAt I I' x f) y} ∈ - 𝓝[(extChartAt I x).symm ⁻¹' s ∩ range I] (extChartAt I x) x := by - apply - @Filter.mem_of_superset _ _ (f ∘ (extChartAt I x).symm ⁻¹' (extChartAt I' (f x)).source) _ - (extChartAt_preimage_mem_nhdsWithin I x - (h.preimage_mem_nhdsWithin (extChartAt_source_mem_nhds _ _))) - mfld_set_tac -#align written_in_ext_chart_comp writtenInExtChartAt_comp - -variable (x) - -theorem HasMFDerivWithinAt.comp (hg : HasMFDerivWithinAt I' I'' g u (f x) g') - (hf : HasMFDerivWithinAt I I' f s x f') (hst : s ⊆ f ⁻¹' u) : - HasMFDerivWithinAt I I'' (g ∘ f) s x (g'.comp f') := by - refine' ⟨ContinuousWithinAt.comp hg.1 hf.1 hst, _⟩ - have A : - HasFDerivWithinAt (writtenInExtChartAt I' I'' (f x) g ∘ writtenInExtChartAt I I' x f) - (ContinuousLinearMap.comp g' f' : E →L[𝕜] E'') ((extChartAt I x).symm ⁻¹' s ∩ range I) - ((extChartAt I x) x) := by - have : - (extChartAt I x).symm ⁻¹' (f ⁻¹' (extChartAt I' (f x)).source) ∈ - 𝓝[(extChartAt I x).symm ⁻¹' s ∩ range I] (extChartAt I x) x := - extChartAt_preimage_mem_nhdsWithin I x - (hf.1.preimage_mem_nhdsWithin (extChartAt_source_mem_nhds _ _)) - unfold HasMFDerivWithinAt at * - rw [← hasFDerivWithinAt_inter' this, ← extChartAt_preimage_inter_eq] at hf ⊢ - have : writtenInExtChartAt I I' x f ((extChartAt I x) x) = (extChartAt I' (f x)) (f x) := by - simp only [mfld_simps] - rw [← this] at hg - apply HasFDerivWithinAt.comp ((extChartAt I x) x) hg.2 hf.2 _ - intro y hy - simp only [mfld_simps] at hy - have : f (((chartAt H x).symm : H → M) (I.symm y)) ∈ u := hst hy.1.1 - simp only [hy, this, mfld_simps] - apply A.congr_of_eventuallyEq (writtenInExtChartAt_comp hf.1) - simp only [mfld_simps] -#align has_mfderiv_within_at.comp HasMFDerivWithinAt.comp - -/-- The **chain rule for manifolds**. -/ -theorem HasMFDerivAt.comp (hg : HasMFDerivAt I' I'' g (f x) g') (hf : HasMFDerivAt I I' f x f') : - HasMFDerivAt I I'' (g ∘ f) x (g'.comp f') := by - rw [← hasMFDerivWithinAt_univ] at * - exact HasMFDerivWithinAt.comp x (hg.mono (subset_univ _)) hf subset_preimage_univ -#align has_mfderiv_at.comp HasMFDerivAt.comp - -theorem HasMFDerivAt.comp_hasMFDerivWithinAt (hg : HasMFDerivAt I' I'' g (f x) g') - (hf : HasMFDerivWithinAt I I' f s x f') : - HasMFDerivWithinAt I I'' (g ∘ f) s x (g'.comp f') := by - rw [← hasMFDerivWithinAt_univ] at * - exact HasMFDerivWithinAt.comp x (hg.mono (subset_univ _)) hf subset_preimage_univ -#align has_mfderiv_at.comp_has_mfderiv_within_at HasMFDerivAt.comp_hasMFDerivWithinAt - -theorem MDifferentiableWithinAt.comp (hg : MDifferentiableWithinAt I' I'' g u (f x)) - (hf : MDifferentiableWithinAt I I' f s x) (h : s ⊆ f ⁻¹' u) : - MDifferentiableWithinAt I I'' (g ∘ f) s x := by - rcases hf.2 with ⟨f', hf'⟩ - have F : HasMFDerivWithinAt I I' f s x f' := ⟨hf.1, hf'⟩ - rcases hg.2 with ⟨g', hg'⟩ - have G : HasMFDerivWithinAt I' I'' g u (f x) g' := ⟨hg.1, hg'⟩ - exact (HasMFDerivWithinAt.comp x G F h).mdifferentiableWithinAt -#align mdifferentiable_within_at.comp MDifferentiableWithinAt.comp - -theorem MDifferentiableAt.comp (hg : MDifferentiableAt I' I'' g (f x)) - (hf : MDifferentiableAt I I' f x) : MDifferentiableAt I I'' (g ∘ f) x := - (hg.hasMFDerivAt.comp x hf.hasMFDerivAt).mdifferentiableAt -#align mdifferentiable_at.comp MDifferentiableAt.comp - -theorem mfderivWithin_comp (hg : MDifferentiableWithinAt I' I'' g u (f x)) - (hf : MDifferentiableWithinAt I I' f s x) (h : s ⊆ f ⁻¹' u) (hxs : UniqueMDiffWithinAt I s x) : - mfderivWithin I I'' (g ∘ f) s x = - (mfderivWithin I' I'' g u (f x)).comp (mfderivWithin I I' f s x) := by - apply HasMFDerivWithinAt.mfderivWithin _ hxs - exact HasMFDerivWithinAt.comp x hg.hasMFDerivWithinAt hf.hasMFDerivWithinAt h -#align mfderiv_within_comp mfderivWithin_comp - -theorem mfderiv_comp (hg : MDifferentiableAt I' I'' g (f x)) (hf : MDifferentiableAt I I' f x) : - mfderiv I I'' (g ∘ f) x = (mfderiv I' I'' g (f x)).comp (mfderiv I I' f x) := by - apply HasMFDerivAt.mfderiv - exact HasMFDerivAt.comp x hg.hasMFDerivAt hf.hasMFDerivAt -#align mfderiv_comp mfderiv_comp - -theorem mfderiv_comp_of_eq {x : M} {y : M'} (hg : MDifferentiableAt I' I'' g y) - (hf : MDifferentiableAt I I' f x) (hy : f x = y) : - mfderiv I I'' (g ∘ f) x = (mfderiv I' I'' g (f x)).comp (mfderiv I I' f x) := by - subst hy; exact mfderiv_comp x hg hf -#align mfderiv_comp_of_eq mfderiv_comp_of_eq - -theorem MDifferentiableOn.comp (hg : MDifferentiableOn I' I'' g u) (hf : MDifferentiableOn I I' f s) - (st : s ⊆ f ⁻¹' u) : MDifferentiableOn I I'' (g ∘ f) s := fun x hx => - MDifferentiableWithinAt.comp x (hg (f x) (st hx)) (hf x hx) st -#align mdifferentiable_on.comp MDifferentiableOn.comp - -theorem MDifferentiable.comp (hg : MDifferentiable I' I'' g) (hf : MDifferentiable I I' f) : - MDifferentiable I I'' (g ∘ f) := fun x => MDifferentiableAt.comp x (hg (f x)) (hf x) -#align mdifferentiable.comp MDifferentiable.comp - -theorem tangentMapWithin_comp_at (p : TangentBundle I M) - (hg : MDifferentiableWithinAt I' I'' g u (f p.1)) (hf : MDifferentiableWithinAt I I' f s p.1) - (h : s ⊆ f ⁻¹' u) (hps : UniqueMDiffWithinAt I s p.1) : - tangentMapWithin I I'' (g ∘ f) s p = - tangentMapWithin I' I'' g u (tangentMapWithin I I' f s p) := by - simp only [tangentMapWithin, mfld_simps] - rw [mfderivWithin_comp p.1 hg hf h hps] - rfl -#align tangent_map_within_comp_at tangentMapWithin_comp_at - -theorem tangentMap_comp_at (p : TangentBundle I M) (hg : MDifferentiableAt I' I'' g (f p.1)) - (hf : MDifferentiableAt I I' f p.1) : - tangentMap I I'' (g ∘ f) p = tangentMap I' I'' g (tangentMap I I' f p) := by - simp only [tangentMap, mfld_simps] - rw [mfderiv_comp p.1 hg hf] - rfl -#align tangent_map_comp_at tangentMap_comp_at - -theorem tangentMap_comp (hg : MDifferentiable I' I'' g) (hf : MDifferentiable I I' f) : - tangentMap I I'' (g ∘ f) = tangentMap I' I'' g ∘ tangentMap I I' f := by - ext p : 1; exact tangentMap_comp_at _ (hg _) (hf _) -#align tangent_map_comp tangentMap_comp - -end DerivativesProperties - -section MFDerivFderiv - -/-! -### Relations between vector space derivative and manifold derivative - -The manifold derivative `mfderiv`, when considered on the model vector space with its trivial -manifold structure, coincides with the usual Frechet derivative `fderiv`. In this section, we prove -this and related statements. --/ - - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {f : E → E'} - {s : Set E} {x : E} - -theorem uniqueMDiffWithinAt_iff_uniqueDiffWithinAt : - UniqueMDiffWithinAt 𝓘(𝕜, E) s x ↔ UniqueDiffWithinAt 𝕜 s x := by - simp only [UniqueMDiffWithinAt, mfld_simps] -#align unique_mdiff_within_at_iff_unique_diff_within_at uniqueMDiffWithinAt_iff_uniqueDiffWithinAt - -alias ⟨UniqueMDiffWithinAt.uniqueDiffWithinAt, UniqueDiffWithinAt.uniqueMDiffWithinAt⟩ := - uniqueMDiffWithinAt_iff_uniqueDiffWithinAt -#align unique_mdiff_within_at.unique_diff_within_at UniqueMDiffWithinAt.uniqueDiffWithinAt -#align unique_diff_within_at.unique_mdiff_within_at UniqueDiffWithinAt.uniqueMDiffWithinAt - -theorem uniqueMDiffOn_iff_uniqueDiffOn : UniqueMDiffOn 𝓘(𝕜, E) s ↔ UniqueDiffOn 𝕜 s := by - simp [UniqueMDiffOn, UniqueDiffOn, uniqueMDiffWithinAt_iff_uniqueDiffWithinAt] -#align unique_mdiff_on_iff_unique_diff_on uniqueMDiffOn_iff_uniqueDiffOn - -alias ⟨UniqueMDiffOn.uniqueDiffOn, UniqueDiffOn.uniqueMDiffOn⟩ := uniqueMDiffOn_iff_uniqueDiffOn -#align unique_mdiff_on.unique_diff_on UniqueMDiffOn.uniqueDiffOn -#align unique_diff_on.unique_mdiff_on UniqueDiffOn.uniqueMDiffOn - --- porting note: was `@[simp, mfld_simps]` but `simp` can prove it -theorem writtenInExtChartAt_model_space : writtenInExtChartAt 𝓘(𝕜, E) 𝓘(𝕜, E') x f = f := - rfl -#align written_in_ext_chart_model_space writtenInExtChartAt_model_space - -theorem hasMFDerivWithinAt_iff_hasFDerivWithinAt {f'} : - HasMFDerivWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x f' ↔ HasFDerivWithinAt f f' s x := by - simpa only [HasMFDerivWithinAt, and_iff_right_iff_imp, mfld_simps] using - HasFDerivWithinAt.continuousWithinAt -#align has_mfderiv_within_at_iff_has_fderiv_within_at hasMFDerivWithinAt_iff_hasFDerivWithinAt - -alias ⟨HasMFDerivWithinAt.hasFDerivWithinAt, HasFDerivWithinAt.hasMFDerivWithinAt⟩ := - hasMFDerivWithinAt_iff_hasFDerivWithinAt -#align has_mfderiv_within_at.has_fderiv_within_at HasMFDerivWithinAt.hasFDerivWithinAt -#align has_fderiv_within_at.has_mfderiv_within_at HasFDerivWithinAt.hasMFDerivWithinAt - -theorem hasMFDerivAt_iff_hasFDerivAt {f'} : - HasMFDerivAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x f' ↔ HasFDerivAt f f' x := by - rw [← hasMFDerivWithinAt_univ, hasMFDerivWithinAt_iff_hasFDerivWithinAt, hasFDerivWithinAt_univ] -#align has_mfderiv_at_iff_has_fderiv_at hasMFDerivAt_iff_hasFDerivAt - -alias ⟨HasMFDerivAt.hasFDerivAt, HasFDerivAt.hasMFDerivAt⟩ := hasMFDerivAt_iff_hasFDerivAt -#align has_mfderiv_at.has_fderiv_at HasMFDerivAt.hasFDerivAt -#align has_fderiv_at.has_mfderiv_at HasFDerivAt.hasMFDerivAt - -/-- For maps between vector spaces, `MDifferentiableWithinAt` and `DifferentiableWithinAt` -coincide -/ -theorem mdifferentiableWithinAt_iff_differentiableWithinAt : - MDifferentiableWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x ↔ DifferentiableWithinAt 𝕜 f s x := by - simp only [MDifferentiableWithinAt, mfld_simps] - exact ⟨fun H => H.2, fun H => ⟨H.continuousWithinAt, H⟩⟩ -#align mdifferentiable_within_at_iff_differentiable_within_at mdifferentiableWithinAt_iff_differentiableWithinAt - -alias ⟨MDifferentiableWithinAt.differentiableWithinAt, - DifferentiableWithinAt.mdifferentiableWithinAt⟩ := - mdifferentiableWithinAt_iff_differentiableWithinAt -#align mdifferentiable_within_at.differentiable_within_at MDifferentiableWithinAt.differentiableWithinAt -#align differentiable_within_at.mdifferentiable_within_at DifferentiableWithinAt.mdifferentiableWithinAt - -/-- For maps between vector spaces, `MDifferentiableAt` and `DifferentiableAt` coincide -/ -theorem mdifferentiableAt_iff_differentiableAt : - MDifferentiableAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x ↔ DifferentiableAt 𝕜 f x := by - simp only [MDifferentiableAt, differentiableWithinAt_univ, mfld_simps] - exact ⟨fun H => H.2, fun H => ⟨H.continuousAt, H⟩⟩ -#align mdifferentiable_at_iff_differentiable_at mdifferentiableAt_iff_differentiableAt - -alias ⟨MDifferentiableAt.differentiableAt, DifferentiableAt.mdifferentiableAt⟩ := - mdifferentiableAt_iff_differentiableAt -#align mdifferentiable_at.differentiable_at MDifferentiableAt.differentiableAt -#align differentiable_at.mdifferentiable_at DifferentiableAt.mdifferentiableAt - -/-- For maps between vector spaces, `MDifferentiableOn` and `DifferentiableOn` coincide -/ -theorem mdifferentiableOn_iff_differentiableOn : - MDifferentiableOn 𝓘(𝕜, E) 𝓘(𝕜, E') f s ↔ DifferentiableOn 𝕜 f s := by - simp only [MDifferentiableOn, DifferentiableOn, - mdifferentiableWithinAt_iff_differentiableWithinAt] -#align mdifferentiable_on_iff_differentiable_on mdifferentiableOn_iff_differentiableOn - -alias ⟨MDifferentiableOn.differentiableOn, DifferentiableOn.mdifferentiableOn⟩ := - mdifferentiableOn_iff_differentiableOn -#align mdifferentiable_on.differentiable_on MDifferentiableOn.differentiableOn -#align differentiable_on.mdifferentiable_on DifferentiableOn.mdifferentiableOn - -/-- For maps between vector spaces, `MDifferentiable` and `Differentiable` coincide -/ -theorem mdifferentiable_iff_differentiable : - MDifferentiable 𝓘(𝕜, E) 𝓘(𝕜, E') f ↔ Differentiable 𝕜 f := by - simp only [MDifferentiable, Differentiable, mdifferentiableAt_iff_differentiableAt] -#align mdifferentiable_iff_differentiable mdifferentiable_iff_differentiable - -alias ⟨MDifferentiable.differentiable, Differentiable.mdifferentiable⟩ := - mdifferentiable_iff_differentiable -#align mdifferentiable.differentiable MDifferentiable.differentiable -#align differentiable.mdifferentiable Differentiable.mdifferentiable - -/-- For maps between vector spaces, `mfderivWithin` and `fderivWithin` coincide -/ -@[simp] -theorem mfderivWithin_eq_fderivWithin : - mfderivWithin 𝓘(𝕜, E) 𝓘(𝕜, E') f s x = fderivWithin 𝕜 f s x := by - by_cases h : MDifferentiableWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x - · simp only [mfderivWithin, h, if_pos, mfld_simps] - · simp only [mfderivWithin, h, if_neg, not_false_iff] - rw [mdifferentiableWithinAt_iff_differentiableWithinAt] at h - exact (fderivWithin_zero_of_not_differentiableWithinAt h).symm -#align mfderiv_within_eq_fderiv_within mfderivWithin_eq_fderivWithin - -/-- For maps between vector spaces, `mfderiv` and `fderiv` coincide -/ -@[simp] -theorem mfderiv_eq_fderiv : mfderiv 𝓘(𝕜, E) 𝓘(𝕜, E') f x = fderiv 𝕜 f x := by - rw [← mfderivWithin_univ, ← fderivWithin_univ] - exact mfderivWithin_eq_fderivWithin -#align mfderiv_eq_fderiv mfderiv_eq_fderiv - -end MFDerivFderiv - -section SpecificFunctions - -/-! ### Differentiability of specific functions -/ - - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M : Type*} - [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] {E' : Type*} - [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] - (I' : ModelWithCorners 𝕜 E' H') {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] - [SmoothManifoldWithCorners I' M'] {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] - {H'' : Type*} [TopologicalSpace H''] (I'' : ModelWithCorners 𝕜 E'' H'') {M'' : Type*} - [TopologicalSpace M''] [ChartedSpace H'' M''] [SmoothManifoldWithCorners I'' M''] - -namespace ContinuousLinearMap - -variable (f : E →L[𝕜] E') {s : Set E} {x : E} - -protected theorem hasMFDerivWithinAt : HasMFDerivWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x f := - f.hasFDerivWithinAt.hasMFDerivWithinAt -#align continuous_linear_map.has_mfderiv_within_at ContinuousLinearMap.hasMFDerivWithinAt - -protected theorem hasMFDerivAt : HasMFDerivAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x f := - f.hasFDerivAt.hasMFDerivAt -#align continuous_linear_map.has_mfderiv_at ContinuousLinearMap.hasMFDerivAt - -protected theorem mdifferentiableWithinAt : MDifferentiableWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x := - f.differentiableWithinAt.mdifferentiableWithinAt -#align continuous_linear_map.mdifferentiable_within_at ContinuousLinearMap.mdifferentiableWithinAt - -protected theorem mdifferentiableOn : MDifferentiableOn 𝓘(𝕜, E) 𝓘(𝕜, E') f s := - f.differentiableOn.mdifferentiableOn -#align continuous_linear_map.mdifferentiable_on ContinuousLinearMap.mdifferentiableOn - -protected theorem mdifferentiableAt : MDifferentiableAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x := - f.differentiableAt.mdifferentiableAt -#align continuous_linear_map.mdifferentiable_at ContinuousLinearMap.mdifferentiableAt - -protected theorem mdifferentiable : MDifferentiable 𝓘(𝕜, E) 𝓘(𝕜, E') f := - f.differentiable.mdifferentiable -#align continuous_linear_map.mdifferentiable ContinuousLinearMap.mdifferentiable - -theorem mfderiv_eq : mfderiv 𝓘(𝕜, E) 𝓘(𝕜, E') f x = f := - f.hasMFDerivAt.mfderiv -#align continuous_linear_map.mfderiv_eq ContinuousLinearMap.mfderiv_eq - -theorem mfderivWithin_eq (hs : UniqueMDiffWithinAt 𝓘(𝕜, E) s x) : - mfderivWithin 𝓘(𝕜, E) 𝓘(𝕜, E') f s x = f := - f.hasMFDerivWithinAt.mfderivWithin hs -#align continuous_linear_map.mfderiv_within_eq ContinuousLinearMap.mfderivWithin_eq - -end ContinuousLinearMap - -namespace ContinuousLinearEquiv - -variable (f : E ≃L[𝕜] E') {s : Set E} {x : E} - -protected theorem hasMFDerivWithinAt : HasMFDerivWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x (f : E →L[𝕜] E') := - f.hasFDerivWithinAt.hasMFDerivWithinAt -#align continuous_linear_equiv.has_mfderiv_within_at ContinuousLinearEquiv.hasMFDerivWithinAt - -protected theorem hasMFDerivAt : HasMFDerivAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x (f : E →L[𝕜] E') := - f.hasFDerivAt.hasMFDerivAt -#align continuous_linear_equiv.has_mfderiv_at ContinuousLinearEquiv.hasMFDerivAt - -protected theorem mdifferentiableWithinAt : MDifferentiableWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x := - f.differentiableWithinAt.mdifferentiableWithinAt -#align continuous_linear_equiv.mdifferentiable_within_at ContinuousLinearEquiv.mdifferentiableWithinAt - -protected theorem mdifferentiableOn : MDifferentiableOn 𝓘(𝕜, E) 𝓘(𝕜, E') f s := - f.differentiableOn.mdifferentiableOn -#align continuous_linear_equiv.mdifferentiable_on ContinuousLinearEquiv.mdifferentiableOn - -protected theorem mdifferentiableAt : MDifferentiableAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x := - f.differentiableAt.mdifferentiableAt -#align continuous_linear_equiv.mdifferentiable_at ContinuousLinearEquiv.mdifferentiableAt - -protected theorem mdifferentiable : MDifferentiable 𝓘(𝕜, E) 𝓘(𝕜, E') f := - f.differentiable.mdifferentiable -#align continuous_linear_equiv.mdifferentiable ContinuousLinearEquiv.mdifferentiable - -theorem mfderiv_eq : mfderiv 𝓘(𝕜, E) 𝓘(𝕜, E') f x = (f : E →L[𝕜] E') := - f.hasMFDerivAt.mfderiv -#align continuous_linear_equiv.mfderiv_eq ContinuousLinearEquiv.mfderiv_eq - -theorem mfderivWithin_eq (hs : UniqueMDiffWithinAt 𝓘(𝕜, E) s x) : - mfderivWithin 𝓘(𝕜, E) 𝓘(𝕜, E') f s x = (f : E →L[𝕜] E') := - f.hasMFDerivWithinAt.mfderivWithin hs -#align continuous_linear_equiv.mfderiv_within_eq ContinuousLinearEquiv.mfderivWithin_eq - -end ContinuousLinearEquiv - -variable {s : Set M} {x : M} - -section id - -/-! #### Identity -/ - -theorem hasMFDerivAt_id (x : M) : - HasMFDerivAt I I (@id M) x (ContinuousLinearMap.id 𝕜 (TangentSpace I x)) := by - refine' ⟨continuousAt_id, _⟩ - have : ∀ᶠ y in 𝓝[range I] (extChartAt I x) x, (extChartAt I x ∘ (extChartAt I x).symm) y = y - · apply Filter.mem_of_superset (extChartAt_target_mem_nhdsWithin I x) - mfld_set_tac - apply HasFDerivWithinAt.congr_of_eventuallyEq (hasFDerivWithinAt_id _ _) this - simp only [mfld_simps] -#align has_mfderiv_at_id hasMFDerivAt_id - -theorem hasMFDerivWithinAt_id (s : Set M) (x : M) : - HasMFDerivWithinAt I I (@id M) s x (ContinuousLinearMap.id 𝕜 (TangentSpace I x)) := - (hasMFDerivAt_id I x).hasMFDerivWithinAt -#align has_mfderiv_within_at_id hasMFDerivWithinAt_id - -theorem mdifferentiableAt_id : MDifferentiableAt I I (@id M) x := - (hasMFDerivAt_id I x).mdifferentiableAt -#align mdifferentiable_at_id mdifferentiableAt_id - -theorem mdifferentiableWithinAt_id : MDifferentiableWithinAt I I (@id M) s x := - (mdifferentiableAt_id I).mdifferentiableWithinAt -#align mdifferentiable_within_at_id mdifferentiableWithinAt_id - -theorem mdifferentiable_id : MDifferentiable I I (@id M) := fun _ => mdifferentiableAt_id I -#align mdifferentiable_id mdifferentiable_id - -theorem mdifferentiableOn_id : MDifferentiableOn I I (@id M) s := - (mdifferentiable_id I).mdifferentiableOn -#align mdifferentiable_on_id mdifferentiableOn_id - -@[simp, mfld_simps] -theorem mfderiv_id : mfderiv I I (@id M) x = ContinuousLinearMap.id 𝕜 (TangentSpace I x) := - HasMFDerivAt.mfderiv (hasMFDerivAt_id I x) -#align mfderiv_id mfderiv_id - -theorem mfderivWithin_id (hxs : UniqueMDiffWithinAt I s x) : - mfderivWithin I I (@id M) s x = ContinuousLinearMap.id 𝕜 (TangentSpace I x) := by - rw [MDifferentiable.mfderivWithin (mdifferentiableAt_id I) hxs] - exact mfderiv_id I -#align mfderiv_within_id mfderivWithin_id - -@[simp, mfld_simps] -theorem tangentMap_id : tangentMap I I (id : M → M) = id := by ext1 ⟨x, v⟩; simp [tangentMap] -#align tangent_map_id tangentMap_id - -theorem tangentMapWithin_id {p : TangentBundle I M} (hs : UniqueMDiffWithinAt I s p.proj) : - tangentMapWithin I I (id : M → M) s p = p := by - simp only [tangentMapWithin, id.def] - rw [mfderivWithin_id] - · rcases p with ⟨⟩; rfl - · exact hs -#align tangent_map_within_id tangentMapWithin_id - -end id - -section Const - -/-! #### Constants -/ - - -variable {c : M'} - -theorem hasMFDerivAt_const (c : M') (x : M) : - HasMFDerivAt I I' (fun _ : M => c) x (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := by - refine' ⟨continuous_const.continuousAt, _⟩ - simp only [writtenInExtChartAt, (· ∘ ·), hasFDerivWithinAt_const] -#align has_mfderiv_at_const hasMFDerivAt_const - -theorem hasMFDerivWithinAt_const (c : M') (s : Set M) (x : M) : - HasMFDerivWithinAt I I' (fun _ : M => c) s x (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := - (hasMFDerivAt_const I I' c x).hasMFDerivWithinAt -#align has_mfderiv_within_at_const hasMFDerivWithinAt_const - -theorem mdifferentiableAt_const : MDifferentiableAt I I' (fun _ : M => c) x := - (hasMFDerivAt_const I I' c x).mdifferentiableAt -#align mdifferentiable_at_const mdifferentiableAt_const - -theorem mdifferentiableWithinAt_const : MDifferentiableWithinAt I I' (fun _ : M => c) s x := - (mdifferentiableAt_const I I').mdifferentiableWithinAt -#align mdifferentiable_within_at_const mdifferentiableWithinAt_const - -theorem mdifferentiable_const : MDifferentiable I I' fun _ : M => c := fun _ => - mdifferentiableAt_const I I' -#align mdifferentiable_const mdifferentiable_const - -theorem mdifferentiableOn_const : MDifferentiableOn I I' (fun _ : M => c) s := - (mdifferentiable_const I I').mdifferentiableOn -#align mdifferentiable_on_const mdifferentiableOn_const - -@[simp, mfld_simps] -theorem mfderiv_const : - mfderiv I I' (fun _ : M => c) x = (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := - HasMFDerivAt.mfderiv (hasMFDerivAt_const I I' c x) -#align mfderiv_const mfderiv_const - -theorem mfderivWithin_const (hxs : UniqueMDiffWithinAt I s x) : - mfderivWithin I I' (fun _ : M => c) s x = (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := - (hasMFDerivWithinAt_const _ _ _ _ _).mfderivWithin hxs -#align mfderiv_within_const mfderivWithin_const - -end Const - -section Prod - -/-! ### Operations on the product of two manifolds -/ - -theorem hasMFDerivAt_fst (x : M × M') : - HasMFDerivAt (I.prod I') I Prod.fst x - (ContinuousLinearMap.fst 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2)) := by - refine' ⟨continuous_fst.continuousAt, _⟩ - have : - ∀ᶠ y in 𝓝[range (I.prod I')] extChartAt (I.prod I') x x, - (extChartAt I x.1 ∘ Prod.fst ∘ (extChartAt (I.prod I') x).symm) y = y.1 := by - /- porting note: was - apply Filter.mem_of_superset (extChartAt_target_mem_nhdsWithin (I.prod I') x) - mfld_set_tac - -/ - filter_upwards [extChartAt_target_mem_nhdsWithin (I.prod I') x] with y hy - rw [extChartAt_prod] at hy - exact (extChartAt I x.1).right_inv hy.1 - apply HasFDerivWithinAt.congr_of_eventuallyEq hasFDerivWithinAt_fst this - -- porting note: next line was `simp only [mfld_simps]` - exact (extChartAt I x.1).right_inv <| (extChartAt I x.1).map_source (mem_extChartAt_source _ _) -#align has_mfderiv_at_fst hasMFDerivAt_fst - -theorem hasMFDerivWithinAt_fst (s : Set (M × M')) (x : M × M') : - HasMFDerivWithinAt (I.prod I') I Prod.fst s x - (ContinuousLinearMap.fst 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2)) := - (hasMFDerivAt_fst I I' x).hasMFDerivWithinAt -#align has_mfderiv_within_at_fst hasMFDerivWithinAt_fst - -theorem mdifferentiableAt_fst {x : M × M'} : MDifferentiableAt (I.prod I') I Prod.fst x := - (hasMFDerivAt_fst I I' x).mdifferentiableAt -#align mdifferentiable_at_fst mdifferentiableAt_fst - -theorem mdifferentiableWithinAt_fst {s : Set (M × M')} {x : M × M'} : - MDifferentiableWithinAt (I.prod I') I Prod.fst s x := - (mdifferentiableAt_fst I I').mdifferentiableWithinAt -#align mdifferentiable_within_at_fst mdifferentiableWithinAt_fst - -theorem mdifferentiable_fst : MDifferentiable (I.prod I') I (Prod.fst : M × M' → M) := fun _ => - mdifferentiableAt_fst I I' -#align mdifferentiable_fst mdifferentiable_fst - -theorem mdifferentiableOn_fst {s : Set (M × M')} : MDifferentiableOn (I.prod I') I Prod.fst s := - (mdifferentiable_fst I I').mdifferentiableOn -#align mdifferentiable_on_fst mdifferentiableOn_fst - -@[simp, mfld_simps] -theorem mfderiv_fst {x : M × M'} : - mfderiv (I.prod I') I Prod.fst x = - ContinuousLinearMap.fst 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2) := - (hasMFDerivAt_fst I I' x).mfderiv -#align mfderiv_fst mfderiv_fst - -theorem mfderivWithin_fst {s : Set (M × M')} {x : M × M'} - (hxs : UniqueMDiffWithinAt (I.prod I') s x) : - mfderivWithin (I.prod I') I Prod.fst s x = - ContinuousLinearMap.fst 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2) := - by rw [MDifferentiable.mfderivWithin (mdifferentiableAt_fst I I') hxs]; exact mfderiv_fst I I' -#align mfderiv_within_fst mfderivWithin_fst - -@[simp, mfld_simps] -theorem tangentMap_prod_fst {p : TangentBundle (I.prod I') (M × M')} : - tangentMap (I.prod I') I Prod.fst p = ⟨p.proj.1, p.2.1⟩ := by - -- porting note: `rfl` wasn't needed - simp [tangentMap]; rfl -#align tangent_map_prod_fst tangentMap_prod_fst - -theorem tangentMapWithin_prod_fst {s : Set (M × M')} {p : TangentBundle (I.prod I') (M × M')} - (hs : UniqueMDiffWithinAt (I.prod I') s p.proj) : - tangentMapWithin (I.prod I') I Prod.fst s p = ⟨p.proj.1, p.2.1⟩ := by - simp only [tangentMapWithin] - rw [mfderivWithin_fst] - · rcases p with ⟨⟩; rfl - · exact hs -#align tangent_map_within_prod_fst tangentMapWithin_prod_fst - -theorem hasMFDerivAt_snd (x : M × M') : - HasMFDerivAt (I.prod I') I' Prod.snd x - (ContinuousLinearMap.snd 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2)) := by - refine' ⟨continuous_snd.continuousAt, _⟩ - have : - ∀ᶠ y in 𝓝[range (I.prod I')] extChartAt (I.prod I') x x, - (extChartAt I' x.2 ∘ Prod.snd ∘ (extChartAt (I.prod I') x).symm) y = y.2 := by - /- porting note: was - apply Filter.mem_of_superset (extChartAt_target_mem_nhdsWithin (I.prod I') x) - mfld_set_tac - -/ - filter_upwards [extChartAt_target_mem_nhdsWithin (I.prod I') x] with y hy - rw [extChartAt_prod] at hy - exact (extChartAt I' x.2).right_inv hy.2 - apply HasFDerivWithinAt.congr_of_eventuallyEq hasFDerivWithinAt_snd this - -- porting note: the next line was `simp only [mfld_simps]` - exact (extChartAt I' x.2).right_inv <| (extChartAt I' x.2).map_source (mem_extChartAt_source _ _) -#align has_mfderiv_at_snd hasMFDerivAt_snd - -theorem hasMFDerivWithinAt_snd (s : Set (M × M')) (x : M × M') : - HasMFDerivWithinAt (I.prod I') I' Prod.snd s x - (ContinuousLinearMap.snd 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2)) := - (hasMFDerivAt_snd I I' x).hasMFDerivWithinAt -#align has_mfderiv_within_at_snd hasMFDerivWithinAt_snd - -theorem mdifferentiableAt_snd {x : M × M'} : MDifferentiableAt (I.prod I') I' Prod.snd x := - (hasMFDerivAt_snd I I' x).mdifferentiableAt -#align mdifferentiable_at_snd mdifferentiableAt_snd - -theorem mdifferentiableWithinAt_snd {s : Set (M × M')} {x : M × M'} : - MDifferentiableWithinAt (I.prod I') I' Prod.snd s x := - (mdifferentiableAt_snd I I').mdifferentiableWithinAt -#align mdifferentiable_within_at_snd mdifferentiableWithinAt_snd - -theorem mdifferentiable_snd : MDifferentiable (I.prod I') I' (Prod.snd : M × M' → M') := fun _ => - mdifferentiableAt_snd I I' -#align mdifferentiable_snd mdifferentiable_snd - -theorem mdifferentiableOn_snd {s : Set (M × M')} : MDifferentiableOn (I.prod I') I' Prod.snd s := - (mdifferentiable_snd I I').mdifferentiableOn -#align mdifferentiable_on_snd mdifferentiableOn_snd - -@[simp, mfld_simps] -theorem mfderiv_snd {x : M × M'} : - mfderiv (I.prod I') I' Prod.snd x = - ContinuousLinearMap.snd 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2) := - (hasMFDerivAt_snd I I' x).mfderiv -#align mfderiv_snd mfderiv_snd - -theorem mfderivWithin_snd {s : Set (M × M')} {x : M × M'} - (hxs : UniqueMDiffWithinAt (I.prod I') s x) : - mfderivWithin (I.prod I') I' Prod.snd s x = - ContinuousLinearMap.snd 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2) := - by rw [MDifferentiable.mfderivWithin (mdifferentiableAt_snd I I') hxs]; exact mfderiv_snd I I' -#align mfderiv_within_snd mfderivWithin_snd - -@[simp, mfld_simps] -theorem tangentMap_prod_snd {p : TangentBundle (I.prod I') (M × M')} : - tangentMap (I.prod I') I' Prod.snd p = ⟨p.proj.2, p.2.2⟩ := by - -- porting note: `rfl` wasn't needed - simp [tangentMap]; rfl -#align tangent_map_prod_snd tangentMap_prod_snd - -theorem tangentMapWithin_prod_snd {s : Set (M × M')} {p : TangentBundle (I.prod I') (M × M')} - (hs : UniqueMDiffWithinAt (I.prod I') s p.proj) : - tangentMapWithin (I.prod I') I' Prod.snd s p = ⟨p.proj.2, p.2.2⟩ := by - simp only [tangentMapWithin] - rw [mfderivWithin_snd] - · rcases p with ⟨⟩; rfl - · exact hs -#align tangent_map_within_prod_snd tangentMapWithin_prod_snd - -variable {I I' I''} - -theorem MDifferentiableAt.mfderiv_prod {f : M → M'} {g : M → M''} {x : M} - (hf : MDifferentiableAt I I' f x) (hg : MDifferentiableAt I I'' g x) : - mfderiv I (I'.prod I'') (fun x => (f x, g x)) x = - (mfderiv I I' f x).prod (mfderiv I I'' g x) := by - classical - simp_rw [mfderiv, if_pos (hf.prod_mk hg), if_pos hf, if_pos hg] - exact hf.2.fderivWithin_prod hg.2 (I.unique_diff _ (mem_range_self _)) -#align mdifferentiable_at.mfderiv_prod MDifferentiableAt.mfderiv_prod - -variable (I I' I'') - -theorem mfderiv_prod_left {x₀ : M} {y₀ : M'} : - mfderiv I (I.prod I') (fun x => (x, y₀)) x₀ = - ContinuousLinearMap.inl 𝕜 (TangentSpace I x₀) (TangentSpace I' y₀) := by - refine' ((mdifferentiableAt_id I).mfderiv_prod (mdifferentiableAt_const I I')).trans _ - rw [mfderiv_id, mfderiv_const, ContinuousLinearMap.inl] -#align mfderiv_prod_left mfderiv_prod_left - -theorem mfderiv_prod_right {x₀ : M} {y₀ : M'} : - mfderiv I' (I.prod I') (fun y => (x₀, y)) y₀ = - ContinuousLinearMap.inr 𝕜 (TangentSpace I x₀) (TangentSpace I' y₀) := by - refine' ((mdifferentiableAt_const I' I).mfderiv_prod (mdifferentiableAt_id I')).trans _ - rw [mfderiv_id, mfderiv_const, ContinuousLinearMap.inr] -#align mfderiv_prod_right mfderiv_prod_right - -/-- The total derivative of a function in two variables is the sum of the partial derivatives. - Note that to state this (without casts) we need to be able to see through the definition of - `TangentSpace`. -/ -theorem mfderiv_prod_eq_add {f : M × M' → M''} {p : M × M'} - (hf : MDifferentiableAt (I.prod I') I'' f p) : - mfderiv (I.prod I') I'' f p = - show E × E' →L[𝕜] E'' from - mfderiv (I.prod I') I'' (fun z : M × M' => f (z.1, p.2)) p + - mfderiv (I.prod I') I'' (fun z : M × M' => f (p.1, z.2)) p := by - dsimp only - erw [mfderiv_comp_of_eq hf ((mdifferentiableAt_fst I I').prod_mk (mdifferentiableAt_const _ _)) - rfl, - mfderiv_comp_of_eq hf ((mdifferentiableAt_const _ _).prod_mk (mdifferentiableAt_snd I I')) rfl, - ← ContinuousLinearMap.comp_add, - (mdifferentiableAt_fst I I').mfderiv_prod (mdifferentiableAt_const (I.prod I') I'), - (mdifferentiableAt_const (I.prod I') I).mfderiv_prod (mdifferentiableAt_snd I I'), mfderiv_fst, - mfderiv_snd, mfderiv_const, mfderiv_const] - symm - convert ContinuousLinearMap.comp_id <| mfderiv (.prod I I') I'' f (p.1, p.2) - · exact ContinuousLinearMap.coprod_inl_inr -#align mfderiv_prod_eq_add mfderiv_prod_eq_add - -end Prod - -section Arithmetic - -/-! #### Arithmetic - -Note that in the `HasMFDerivAt` lemmas there is an abuse of the defeq between `E'` and -`TangentSpace 𝓘(𝕜, E') (f z)` (similarly for `g',F',p',q'`). In general this defeq is not -canonical, but in this case (the tangent space of a vector space) it is canonical. - -/ - -section Group - -variable {I} {z : M} {f g : M → E'} {f' g' : TangentSpace I z →L[𝕜] E'} - -theorem HasMFDerivAt.add (hf : HasMFDerivAt I 𝓘(𝕜, E') f z f') - (hg : HasMFDerivAt I 𝓘(𝕜, E') g z g') : HasMFDerivAt I 𝓘(𝕜, E') (f + g) z (f' + g') := - ⟨hf.1.add hg.1, hf.2.add hg.2⟩ -#align has_mfderiv_at.add HasMFDerivAt.add - -theorem MDifferentiableAt.add (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) - (hg : MDifferentiableAt I 𝓘(𝕜, E') g z) : MDifferentiableAt I 𝓘(𝕜, E') (f + g) z := - (hf.hasMFDerivAt.add hg.hasMFDerivAt).mdifferentiableAt -#align mdifferentiable_at.add MDifferentiableAt.add - -theorem MDifferentiable.add (hf : MDifferentiable I 𝓘(𝕜, E') f) - (hg : MDifferentiable I 𝓘(𝕜, E') g) : MDifferentiable I 𝓘(𝕜, E') (f + g) := fun x => - (hf x).add (hg x) -#align mdifferentiable.add MDifferentiable.add - --- porting note: forcing types using `by exact` -theorem mfderiv_add (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) - (hg : MDifferentiableAt I 𝓘(𝕜, E') g z) : - (by exact mfderiv I 𝓘(𝕜, E') (f + g) z : TangentSpace I z →L[𝕜] E') = - (by exact mfderiv I 𝓘(𝕜, E') f z) + (by exact mfderiv I 𝓘(𝕜, E') g z) := - (hf.hasMFDerivAt.add hg.hasMFDerivAt).mfderiv -#align mfderiv_add mfderiv_add - -theorem HasMFDerivAt.const_smul (hf : HasMFDerivAt I 𝓘(𝕜, E') f z f') (s : 𝕜) : - HasMFDerivAt I 𝓘(𝕜, E') (s • f) z (s • f') := - ⟨hf.1.const_smul s, hf.2.const_smul s⟩ -#align has_mfderiv_at.const_smul HasMFDerivAt.const_smul - -theorem MDifferentiableAt.const_smul (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) (s : 𝕜) : - MDifferentiableAt I 𝓘(𝕜, E') (s • f) z := - (hf.hasMFDerivAt.const_smul s).mdifferentiableAt -#align mdifferentiable_at.const_smul MDifferentiableAt.const_smul - -theorem MDifferentiable.const_smul (s : 𝕜) (hf : MDifferentiable I 𝓘(𝕜, E') f) : - MDifferentiable I 𝓘(𝕜, E') (s • f) := fun x => (hf x).const_smul s -#align mdifferentiable.const_smul MDifferentiable.const_smul - -theorem const_smul_mfderiv (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) (s : 𝕜) : - (mfderiv I 𝓘(𝕜, E') (s • f) z : TangentSpace I z →L[𝕜] E') = - (s • mfderiv I 𝓘(𝕜, E') f z : TangentSpace I z →L[𝕜] E') := - (hf.hasMFDerivAt.const_smul s).mfderiv -#align const_smul_mfderiv const_smul_mfderiv - -theorem HasMFDerivAt.neg (hf : HasMFDerivAt I 𝓘(𝕜, E') f z f') : - HasMFDerivAt I 𝓘(𝕜, E') (-f) z (-f') := - ⟨hf.1.neg, hf.2.neg⟩ -#align has_mfderiv_at.neg HasMFDerivAt.neg - -theorem hasMFDerivAt_neg : HasMFDerivAt I 𝓘(𝕜, E') (-f) z (-f') ↔ HasMFDerivAt I 𝓘(𝕜, E') f z f' := - ⟨fun hf => by convert hf.neg <;> rw [neg_neg], fun hf => hf.neg⟩ -#align has_mfderiv_at_neg hasMFDerivAt_neg - -theorem MDifferentiableAt.neg (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) : - MDifferentiableAt I 𝓘(𝕜, E') (-f) z := - hf.hasMFDerivAt.neg.mdifferentiableAt -#align mdifferentiable_at.neg MDifferentiableAt.neg - -theorem mdifferentiableAt_neg : - MDifferentiableAt I 𝓘(𝕜, E') (-f) z ↔ MDifferentiableAt I 𝓘(𝕜, E') f z := - ⟨fun hf => by convert hf.neg; rw [neg_neg], fun hf => hf.neg⟩ -#align mdifferentiable_at_neg mdifferentiableAt_neg - -theorem MDifferentiable.neg (hf : MDifferentiable I 𝓘(𝕜, E') f) : MDifferentiable I 𝓘(𝕜, E') (-f) := - fun x => (hf x).neg -#align mdifferentiable.neg MDifferentiable.neg - -theorem mfderiv_neg (f : M → E') (x : M) : - (mfderiv I 𝓘(𝕜, E') (-f) x : TangentSpace I x →L[𝕜] E') = - (-mfderiv I 𝓘(𝕜, E') f x : TangentSpace I x →L[𝕜] E') := by - simp_rw [mfderiv] - by_cases hf : MDifferentiableAt I 𝓘(𝕜, E') f x - · exact hf.hasMFDerivAt.neg.mfderiv - · rw [if_neg hf]; rw [← mdifferentiableAt_neg] at hf; rw [if_neg hf, neg_zero] -#align mfderiv_neg mfderiv_neg - -theorem HasMFDerivAt.sub (hf : HasMFDerivAt I 𝓘(𝕜, E') f z f') - (hg : HasMFDerivAt I 𝓘(𝕜, E') g z g') : HasMFDerivAt I 𝓘(𝕜, E') (f - g) z (f' - g') := - ⟨hf.1.sub hg.1, hf.2.sub hg.2⟩ -#align has_mfderiv_at.sub HasMFDerivAt.sub - -theorem MDifferentiableAt.sub (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) - (hg : MDifferentiableAt I 𝓘(𝕜, E') g z) : MDifferentiableAt I 𝓘(𝕜, E') (f - g) z := - (hf.hasMFDerivAt.sub hg.hasMFDerivAt).mdifferentiableAt -#align mdifferentiable_at.sub MDifferentiableAt.sub - -theorem MDifferentiable.sub (hf : MDifferentiable I 𝓘(𝕜, E') f) - (hg : MDifferentiable I 𝓘(𝕜, E') g) : MDifferentiable I 𝓘(𝕜, E') (f - g) := fun x => - (hf x).sub (hg x) -#align mdifferentiable.sub MDifferentiable.sub - -theorem mfderiv_sub (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) - (hg : MDifferentiableAt I 𝓘(𝕜, E') g z) : - (by exact mfderiv I 𝓘(𝕜, E') (f - g) z : TangentSpace I z →L[𝕜] E') = - (by exact mfderiv I 𝓘(𝕜, E') f z) - (by exact mfderiv I 𝓘(𝕜, E') g z) := - (hf.hasMFDerivAt.sub hg.hasMFDerivAt).mfderiv -#align mfderiv_sub mfderiv_sub - -end Group - -section AlgebraOverRing - -variable {I} {z : M} {F' : Type*} [NormedRing F'] [NormedAlgebra 𝕜 F'] {p q : M → F'} - {p' q' : TangentSpace I z →L[𝕜] F'} - -theorem HasMFDerivWithinAt.mul' (hp : HasMFDerivWithinAt I 𝓘(𝕜, F') p s z p') - (hq : HasMFDerivWithinAt I 𝓘(𝕜, F') q s z q') : - HasMFDerivWithinAt I 𝓘(𝕜, F') (p * q) s z (p z • q' + p'.smulRight (q z) : E →L[𝕜] F') := - ⟨hp.1.mul hq.1, by simpa only [mfld_simps] using hp.2.mul' hq.2⟩ -#align has_mfderiv_within_at.mul' HasMFDerivWithinAt.mul' - -theorem HasMFDerivAt.mul' (hp : HasMFDerivAt I 𝓘(𝕜, F') p z p') - (hq : HasMFDerivAt I 𝓘(𝕜, F') q z q') : - HasMFDerivAt I 𝓘(𝕜, F') (p * q) z (p z • q' + p'.smulRight (q z) : E →L[𝕜] F') := - hasMFDerivWithinAt_univ.mp <| hp.hasMFDerivWithinAt.mul' hq.hasMFDerivWithinAt -#align has_mfderiv_at.mul' HasMFDerivAt.mul' - -theorem MDifferentiableWithinAt.mul (hp : MDifferentiableWithinAt I 𝓘(𝕜, F') p s z) - (hq : MDifferentiableWithinAt I 𝓘(𝕜, F') q s z) : - MDifferentiableWithinAt I 𝓘(𝕜, F') (p * q) s z := - (hp.hasMFDerivWithinAt.mul' hq.hasMFDerivWithinAt).mdifferentiableWithinAt -#align mdifferentiable_within_at.mul MDifferentiableWithinAt.mul - -theorem MDifferentiableAt.mul (hp : MDifferentiableAt I 𝓘(𝕜, F') p z) - (hq : MDifferentiableAt I 𝓘(𝕜, F') q z) : MDifferentiableAt I 𝓘(𝕜, F') (p * q) z := - (hp.hasMFDerivAt.mul' hq.hasMFDerivAt).mdifferentiableAt -#align mdifferentiable_at.mul MDifferentiableAt.mul - -theorem MDifferentiableOn.mul (hp : MDifferentiableOn I 𝓘(𝕜, F') p s) - (hq : MDifferentiableOn I 𝓘(𝕜, F') q s) : MDifferentiableOn I 𝓘(𝕜, F') (p * q) s := fun x hx => - (hp x hx).mul <| hq x hx -#align mdifferentiable_on.mul MDifferentiableOn.mul - -theorem MDifferentiable.mul (hp : MDifferentiable I 𝓘(𝕜, F') p) - (hq : MDifferentiable I 𝓘(𝕜, F') q) : MDifferentiable I 𝓘(𝕜, F') (p * q) := fun x => - (hp x).mul (hq x) -#align mdifferentiable.mul MDifferentiable.mul - -end AlgebraOverRing - -section AlgebraOverCommRing - -variable {I} {z : M} {F' : Type*} [NormedCommRing F'] [NormedAlgebra 𝕜 F'] {p q : M → F'} - {p' q' : TangentSpace I z →L[𝕜] F'} - -theorem HasMFDerivWithinAt.mul (hp : HasMFDerivWithinAt I 𝓘(𝕜, F') p s z p') - (hq : HasMFDerivWithinAt I 𝓘(𝕜, F') q s z q') : - HasMFDerivWithinAt I 𝓘(𝕜, F') (p * q) s z (p z • q' + q z • p' : E →L[𝕜] F') := by - convert hp.mul' hq; ext _; apply mul_comm -#align has_mfderiv_within_at.mul HasMFDerivWithinAt.mul - -theorem HasMFDerivAt.mul (hp : HasMFDerivAt I 𝓘(𝕜, F') p z p') - (hq : HasMFDerivAt I 𝓘(𝕜, F') q z q') : - HasMFDerivAt I 𝓘(𝕜, F') (p * q) z (p z • q' + q z • p' : E →L[𝕜] F') := - hasMFDerivWithinAt_univ.mp <| hp.hasMFDerivWithinAt.mul hq.hasMFDerivWithinAt -#align has_mfderiv_at.mul HasMFDerivAt.mul - -end AlgebraOverCommRing - -end Arithmetic - -namespace ModelWithCorners - -/-! #### Model with corners -/ - - -protected theorem hasMFDerivAt {x} : HasMFDerivAt I 𝓘(𝕜, E) I x (ContinuousLinearMap.id _ _) := - ⟨I.continuousAt, (hasFDerivWithinAt_id _ _).congr' I.rightInvOn (mem_range_self _)⟩ -#align model_with_corners.has_mfderiv_at ModelWithCorners.hasMFDerivAt - -protected theorem hasMFDerivWithinAt {s x} : - HasMFDerivWithinAt I 𝓘(𝕜, E) I s x (ContinuousLinearMap.id _ _) := - I.hasMFDerivAt.hasMFDerivWithinAt -#align model_with_corners.has_mfderiv_within_at ModelWithCorners.hasMFDerivWithinAt - -protected theorem mdifferentiableWithinAt {s x} : MDifferentiableWithinAt I 𝓘(𝕜, E) I s x := - I.hasMFDerivWithinAt.mdifferentiableWithinAt -#align model_with_corners.mdifferentiable_within_at ModelWithCorners.mdifferentiableWithinAt - -protected theorem mdifferentiableAt {x} : MDifferentiableAt I 𝓘(𝕜, E) I x := - I.hasMFDerivAt.mdifferentiableAt -#align model_with_corners.mdifferentiable_at ModelWithCorners.mdifferentiableAt - -protected theorem mdifferentiableOn {s} : MDifferentiableOn I 𝓘(𝕜, E) I s := fun _ _ => - I.mdifferentiableWithinAt -#align model_with_corners.mdifferentiable_on ModelWithCorners.mdifferentiableOn - -protected theorem mdifferentiable : MDifferentiable I 𝓘(𝕜, E) I := fun _ => I.mdifferentiableAt -#align model_with_corners.mdifferentiable ModelWithCorners.mdifferentiable - -theorem hasMFDerivWithinAt_symm {x} (hx : x ∈ range I) : - HasMFDerivWithinAt 𝓘(𝕜, E) I I.symm (range I) x (ContinuousLinearMap.id _ _) := - ⟨I.continuousWithinAt_symm, - (hasFDerivWithinAt_id _ _).congr' (fun _y hy => I.rightInvOn hy.1) ⟨hx, mem_range_self _⟩⟩ -#align model_with_corners.has_mfderiv_within_at_symm ModelWithCorners.hasMFDerivWithinAt_symm - -theorem mdifferentiableOn_symm : MDifferentiableOn 𝓘(𝕜, E) I I.symm (range I) := fun _x hx => - (I.hasMFDerivWithinAt_symm hx).mdifferentiableWithinAt -#align model_with_corners.mdifferentiable_on_symm ModelWithCorners.mdifferentiableOn_symm - -end ModelWithCorners - -section Charts - -variable {e : PartialHomeomorph M H} - -theorem mdifferentiableAt_atlas (h : e ∈ atlas H M) {x : M} (hx : x ∈ e.source) : - MDifferentiableAt I I e x := by - refine' ⟨(e.continuousOn x hx).continuousAt (IsOpen.mem_nhds e.open_source hx), _⟩ - have mem : - I ((chartAt H x : M → H) x) ∈ I.symm ⁻¹' ((chartAt H x).symm ≫ₕ e).source ∩ range I := by - simp only [hx, mfld_simps] - have : (chartAt H x).symm.trans e ∈ contDiffGroupoid ∞ I := - HasGroupoid.compatible (chart_mem_atlas H x) h - have A : - ContDiffOn 𝕜 ∞ (I ∘ (chartAt H x).symm.trans e ∘ I.symm) - (I.symm ⁻¹' ((chartAt H x).symm.trans e).source ∩ range I) := - this.1 - have B := A.differentiableOn le_top (I ((chartAt H x : M → H) x)) mem - simp only [mfld_simps] at B - rw [inter_comm, differentiableWithinAt_inter] at B - · simpa only [mfld_simps] - · apply IsOpen.mem_nhds ((PartialHomeomorph.open_source _).preimage I.continuous_symm) mem.1 -#align mdifferentiable_at_atlas mdifferentiableAt_atlas - -theorem mdifferentiableOn_atlas (h : e ∈ atlas H M) : MDifferentiableOn I I e e.source := - fun _x hx => (mdifferentiableAt_atlas I h hx).mdifferentiableWithinAt -#align mdifferentiable_on_atlas mdifferentiableOn_atlas - -theorem mdifferentiableAt_atlas_symm (h : e ∈ atlas H M) {x : H} (hx : x ∈ e.target) : - MDifferentiableAt I I e.symm x := by - refine' ⟨(e.continuousOn_symm x hx).continuousAt (IsOpen.mem_nhds e.open_target hx), _⟩ - have mem : I x ∈ I.symm ⁻¹' (e.symm ≫ₕ chartAt H (e.symm x)).source ∩ range I := by - simp only [hx, mfld_simps] - have : e.symm.trans (chartAt H (e.symm x)) ∈ contDiffGroupoid ∞ I := - HasGroupoid.compatible h (chart_mem_atlas H _) - have A : - ContDiffOn 𝕜 ∞ (I ∘ e.symm.trans (chartAt H (e.symm x)) ∘ I.symm) - (I.symm ⁻¹' (e.symm.trans (chartAt H (e.symm x))).source ∩ range I) := - this.1 - have B := A.differentiableOn le_top (I x) mem - simp only [mfld_simps] at B - rw [inter_comm, differentiableWithinAt_inter] at B - · simpa only [mfld_simps] - · apply IsOpen.mem_nhds ((PartialHomeomorph.open_source _).preimage I.continuous_symm) mem.1 -#align mdifferentiable_at_atlas_symm mdifferentiableAt_atlas_symm - -theorem mdifferentiableOn_atlas_symm (h : e ∈ atlas H M) : MDifferentiableOn I I e.symm e.target := - fun _x hx => (mdifferentiableAt_atlas_symm I h hx).mdifferentiableWithinAt -#align mdifferentiable_on_atlas_symm mdifferentiableOn_atlas_symm - -theorem mdifferentiable_of_mem_atlas (h : e ∈ atlas H M) : e.MDifferentiable I I := - ⟨mdifferentiableOn_atlas I h, mdifferentiableOn_atlas_symm I h⟩ -#align mdifferentiable_of_mem_atlas mdifferentiable_of_mem_atlas - -theorem mdifferentiable_chart (x : M) : (chartAt H x).MDifferentiable I I := - mdifferentiable_of_mem_atlas _ (chart_mem_atlas _ _) -#align mdifferentiable_chart mdifferentiable_chart - -/-- The derivative of the chart at a base point is the chart of the tangent bundle, composed with -the identification between the tangent bundle of the model space and the product space. -/ -theorem tangentMap_chart {p q : TangentBundle I M} (h : q.1 ∈ (chartAt H p.1).source) : - tangentMap I I (chartAt H p.1) q = - (TotalSpace.toProd _ _).symm - ((chartAt (ModelProd H E) p : TangentBundle I M → ModelProd H E) q) := by - dsimp [tangentMap] - rw [MDifferentiableAt.mfderiv] - · rfl - · exact mdifferentiableAt_atlas _ (chart_mem_atlas _ _) h -#align tangent_map_chart tangentMap_chart - -/-- The derivative of the inverse of the chart at a base point is the inverse of the chart of the -tangent bundle, composed with the identification between the tangent bundle of the model space and -the product space. -/ -theorem tangentMap_chart_symm {p : TangentBundle I M} {q : TangentBundle I H} - (h : q.1 ∈ (chartAt H p.1).target) : - tangentMap I I (chartAt H p.1).symm q = - (chartAt (ModelProd H E) p).symm (TotalSpace.toProd H E q) := by - dsimp only [tangentMap] - rw [MDifferentiableAt.mfderiv (mdifferentiableAt_atlas_symm _ (chart_mem_atlas _ _) h)] - simp only [ContinuousLinearMap.coe_coe, TangentBundle.chartAt, h, tangentBundleCore, - mfld_simps, (· ∘ ·)] - -- `simp` fails to apply `PartialEquiv.prod_symm` with `ModelProd` - congr - exact ((chartAt H (TotalSpace.proj p)).right_inv h).symm -#align tangent_map_chart_symm tangentMap_chart_symm - -end Charts - -end SpecificFunctions - -/-! ### Differentiable partial homeomorphisms -/ - -namespace PartialHomeomorph.MDifferentiable - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {M : Type*} - [TopologicalSpace M] [ChartedSpace H M] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] - {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M' : Type*} - [TopologicalSpace M'] [ChartedSpace H' M'] {E'' : Type*} [NormedAddCommGroup E''] - [NormedSpace 𝕜 E''] {H'' : Type*} [TopologicalSpace H''] {I'' : ModelWithCorners 𝕜 E'' H''} - {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H'' M''] {e : PartialHomeomorph M M'} - (he : e.MDifferentiable I I') {e' : PartialHomeomorph M' M''} - -nonrec theorem symm : e.symm.MDifferentiable I' I := he.symm -#align local_homeomorph.mdifferentiable.symm PartialHomeomorph.MDifferentiable.symm - -protected theorem mdifferentiableAt {x : M} (hx : x ∈ e.source) : MDifferentiableAt I I' e x := - (he.1 x hx).mdifferentiableAt (IsOpen.mem_nhds e.open_source hx) -#align local_homeomorph.mdifferentiable.mdifferentiable_at PartialHomeomorph.MDifferentiable.mdifferentiableAt - -theorem mdifferentiableAt_symm {x : M'} (hx : x ∈ e.target) : MDifferentiableAt I' I e.symm x := - (he.2 x hx).mdifferentiableAt (IsOpen.mem_nhds e.open_target hx) -#align local_homeomorph.mdifferentiable.mdifferentiable_at_symm PartialHomeomorph.MDifferentiable.mdifferentiableAt_symm - -variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] - [SmoothManifoldWithCorners I'' M''] - -theorem symm_comp_deriv {x : M} (hx : x ∈ e.source) : - (mfderiv I' I e.symm (e x)).comp (mfderiv I I' e x) = - ContinuousLinearMap.id 𝕜 (TangentSpace I x) := by - have : mfderiv I I (e.symm ∘ e) x = (mfderiv I' I e.symm (e x)).comp (mfderiv I I' e x) := - mfderiv_comp x (he.mdifferentiableAt_symm (e.map_source hx)) (he.mdifferentiableAt hx) - rw [← this] - have : mfderiv I I (_root_.id : M → M) x = ContinuousLinearMap.id _ _ := mfderiv_id I - rw [← this] - apply Filter.EventuallyEq.mfderiv_eq - have : e.source ∈ 𝓝 x := IsOpen.mem_nhds e.open_source hx - exact Filter.mem_of_superset this (by mfld_set_tac) -#align local_homeomorph.mdifferentiable.symm_comp_deriv PartialHomeomorph.MDifferentiable.symm_comp_deriv - -theorem comp_symm_deriv {x : M'} (hx : x ∈ e.target) : - (mfderiv I I' e (e.symm x)).comp (mfderiv I' I e.symm x) = - ContinuousLinearMap.id 𝕜 (TangentSpace I' x) := - he.symm.symm_comp_deriv hx -#align local_homeomorph.mdifferentiable.comp_symm_deriv PartialHomeomorph.MDifferentiable.comp_symm_deriv - -/-- The derivative of a differentiable partial homeomorphism, as a continuous linear equivalence -between the tangent spaces at `x` and `e x`. -/ -protected def mfderiv {x : M} (hx : x ∈ e.source) : TangentSpace I x ≃L[𝕜] TangentSpace I' (e x) := - { mfderiv I I' e x with - invFun := mfderiv I' I e.symm (e x) - continuous_toFun := (mfderiv I I' e x).cont - continuous_invFun := (mfderiv I' I e.symm (e x)).cont - left_inv := fun y => by - have : (ContinuousLinearMap.id _ _ : TangentSpace I x →L[𝕜] TangentSpace I x) y = y := rfl - conv_rhs => rw [← this, ← he.symm_comp_deriv hx] - right_inv := fun y => by - have : - (ContinuousLinearMap.id 𝕜 _ : TangentSpace I' (e x) →L[𝕜] TangentSpace I' (e x)) y = y := - rfl - conv_rhs => rw [← this, ← he.comp_symm_deriv (e.map_source hx)] - rw [e.left_inv hx] - rfl } -#align local_homeomorph.mdifferentiable.mfderiv PartialHomeomorph.MDifferentiable.mfderiv - -theorem mfderiv_bijective {x : M} (hx : x ∈ e.source) : Function.Bijective (mfderiv I I' e x) := - (he.mfderiv hx).bijective -#align local_homeomorph.mdifferentiable.mfderiv_bijective PartialHomeomorph.MDifferentiable.mfderiv_bijective - -theorem mfderiv_injective {x : M} (hx : x ∈ e.source) : Function.Injective (mfderiv I I' e x) := - (he.mfderiv hx).injective -#align local_homeomorph.mdifferentiable.mfderiv_injective PartialHomeomorph.MDifferentiable.mfderiv_injective - -theorem mfderiv_surjective {x : M} (hx : x ∈ e.source) : Function.Surjective (mfderiv I I' e x) := - (he.mfderiv hx).surjective -#align local_homeomorph.mdifferentiable.mfderiv_surjective PartialHomeomorph.MDifferentiable.mfderiv_surjective - -theorem ker_mfderiv_eq_bot {x : M} (hx : x ∈ e.source) : LinearMap.ker (mfderiv I I' e x) = ⊥ := - (he.mfderiv hx).toLinearEquiv.ker -#align local_homeomorph.mdifferentiable.ker_mfderiv_eq_bot PartialHomeomorph.MDifferentiable.ker_mfderiv_eq_bot - -theorem range_mfderiv_eq_top {x : M} (hx : x ∈ e.source) : LinearMap.range (mfderiv I I' e x) = ⊤ := - (he.mfderiv hx).toLinearEquiv.range -#align local_homeomorph.mdifferentiable.range_mfderiv_eq_top PartialHomeomorph.MDifferentiable.range_mfderiv_eq_top - -theorem range_mfderiv_eq_univ {x : M} (hx : x ∈ e.source) : range (mfderiv I I' e x) = univ := - (he.mfderiv_surjective hx).range_eq -#align local_homeomorph.mdifferentiable.range_mfderiv_eq_univ PartialHomeomorph.MDifferentiable.range_mfderiv_eq_univ - -theorem trans (he' : e'.MDifferentiable I' I'') : (e.trans e').MDifferentiable I I'' := by - constructor - · intro x hx - simp only [mfld_simps] at hx - exact - ((he'.mdifferentiableAt hx.2).comp _ (he.mdifferentiableAt hx.1)).mdifferentiableWithinAt - · intro x hx - simp only [mfld_simps] at hx - exact - ((he.symm.mdifferentiableAt hx.2).comp _ - (he'.symm.mdifferentiableAt hx.1)).mdifferentiableWithinAt -#align local_homeomorph.mdifferentiable.trans PartialHomeomorph.MDifferentiable.trans - -end PartialHomeomorph.MDifferentiable - -/-! ### Differentiability of `extChartAt` -/ - -section extChartAt - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M : Type*} - [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] {s : Set M} {x y : M} - -theorem hasMFDerivAt_extChartAt (h : y ∈ (chartAt H x).source) : - HasMFDerivAt I 𝓘(𝕜, E) (extChartAt I x) y (mfderiv I I (chartAt H x) y : _) := - I.hasMFDerivAt.comp y ((mdifferentiable_chart I x).mdifferentiableAt h).hasMFDerivAt -#align has_mfderiv_at_ext_chart_at hasMFDerivAt_extChartAt - -theorem hasMFDerivWithinAt_extChartAt (h : y ∈ (chartAt H x).source) : - HasMFDerivWithinAt I 𝓘(𝕜, E) (extChartAt I x) s y (mfderiv I I (chartAt H x) y : _) := - (hasMFDerivAt_extChartAt I h).hasMFDerivWithinAt -#align has_mfderiv_within_at_ext_chart_at hasMFDerivWithinAt_extChartAt - -theorem mdifferentiableAt_extChartAt (h : y ∈ (chartAt H x).source) : - MDifferentiableAt I 𝓘(𝕜, E) (extChartAt I x) y := - (hasMFDerivAt_extChartAt I h).mdifferentiableAt -#align mdifferentiable_at_ext_chart_at mdifferentiableAt_extChartAt - -theorem mdifferentiableOn_extChartAt : - MDifferentiableOn I 𝓘(𝕜, E) (extChartAt I x) (chartAt H x).source := fun _y hy => - (hasMFDerivWithinAt_extChartAt I hy).mdifferentiableWithinAt -#align mdifferentiable_on_ext_chart_at mdifferentiableOn_extChartAt - -end extChartAt - -/-! ### Unique derivative sets in manifolds -/ - -section UniqueMDiff - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {M : Type*} - [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] {E' : Type*} - [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] - {I' : ModelWithCorners 𝕜 E' H'} {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] - [SmoothManifoldWithCorners I' M'] {s : Set M} - -/-- If `s` has the unique differential property at `x`, `f` is differentiable within `s` at x` and -its derivative has Dense range, then `f '' s` has the Unique differential property at `f x`. -/ -theorem UniqueMDiffWithinAt.image_denseRange (hs : UniqueMDiffWithinAt I s x) - {f : M → M'} {f' : E →L[𝕜] E'} (hf : HasMFDerivWithinAt I I' f s x f') - (hd : DenseRange f') : UniqueMDiffWithinAt I' (f '' s) (f x) := by - /- Rewrite in coordinates, apply `HasFDerivWithinAt.uniqueDiffWithinAt`. -/ - have := hs.inter' <| hf.1 (extChartAt_source_mem_nhds I' (f x)) - refine (((hf.2.mono ?sub1).uniqueDiffWithinAt this hd).mono ?sub2).congr_pt ?pt - case pt => simp only [mfld_simps] - case sub1 => mfld_set_tac - case sub2 => - rintro _ ⟨y, ⟨⟨hys, hfy⟩, -⟩, rfl⟩ - exact ⟨⟨_, hys, ((extChartAt I' (f x)).left_inv hfy).symm⟩, mem_range_self _⟩ - -/-- If `s` has the unique differential, `f` is differentiable on `s` and its derivative at every -point of `s` has dense range, then `f '' s` has the unique differential property. This version -uses `HaMFDerivWithinAt` predicate. -/ -theorem UniqueMDiffOn.image_denseRange' (hs : UniqueMDiffOn I s) {f : M → M'} - {f' : M → E →L[𝕜] E'} (hf : ∀ x ∈ s, HasMFDerivWithinAt I I' f s x (f' x)) - (hd : ∀ x ∈ s, DenseRange (f' x)) : - UniqueMDiffOn I' (f '' s) := - ball_image_iff.2 fun x hx ↦ (hs x hx).image_denseRange (hf x hx) (hd x hx) - -/-- If `s` has the unique differential, `f` is differentiable on `s` and its derivative at every -point of `s` has dense range, then `f '' s` has the unique differential property. -/ -theorem UniqueMDiffOn.image_denseRange (hs : UniqueMDiffOn I s) {f : M → M'} - (hf : MDifferentiableOn I I' f s) (hd : ∀ x ∈ s, DenseRange (mfderivWithin I I' f s x)) : - UniqueMDiffOn I' (f '' s) := - hs.image_denseRange' (fun x hx ↦ (hf x hx).hasMFDerivWithinAt) hd - -protected theorem UniqueMDiffWithinAt.preimage_localHomeomorph (hs : UniqueMDiffWithinAt I s x) - {e : PartialHomeomorph M M'} (he : e.MDifferentiable I I') (hx : x ∈ e.source) : - UniqueMDiffWithinAt I' (e.target ∩ e.symm ⁻¹' s) (e x) := by - rw [← e.image_source_inter_eq', inter_comm] - exact (hs.inter (e.open_source.mem_nhds hx)).image_denseRange - (he.mdifferentiableAt hx).hasMFDerivAt.hasMFDerivWithinAt - (he.mfderiv_surjective hx).denseRange - -/-- If a set has the unique differential property, then its image under a local -diffeomorphism also has the unique differential property. -/ -theorem UniqueMDiffOn.uniqueMDiffOn_preimage (hs : UniqueMDiffOn I s) {e : PartialHomeomorph M M'} - (he : e.MDifferentiable I I') : UniqueMDiffOn I' (e.target ∩ e.symm ⁻¹' s) := fun _x hx ↦ - e.right_inv hx.1 ▸ (hs _ hx.2).preimage_localHomeomorph he (e.map_target hx.1) -#align unique_mdiff_on.unique_mdiff_on_preimage UniqueMDiffOn.uniqueMDiffOn_preimage - -/-- If a set in a manifold has the unique derivative property, then its pullback by any extended -chart, in the vector space, also has the unique derivative property. -/ -theorem UniqueMDiffOn.uniqueDiffOn_target_inter (hs : UniqueMDiffOn I s) (x : M) : - UniqueDiffOn 𝕜 ((extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' s) := by - -- this is just a reformulation of `UniqueMDiffOn.uniqueMDiffOn_preimage`, using as `e` - -- the local chart at `x`. - apply UniqueMDiffOn.uniqueDiffOn - rw [← PartialEquiv.image_source_inter_eq', inter_comm, extChartAt_source] - exact (hs.inter (chartAt H x).open_source).image_denseRange' - (fun y hy ↦ hasMFDerivWithinAt_extChartAt I hy.2) - fun y hy ↦ ((mdifferentiable_chart _ _).mfderiv_surjective hy.2).denseRange -#align unique_mdiff_on.unique_diff_on_target_inter UniqueMDiffOn.uniqueDiffOn_target_inter - -/-- When considering functions between manifolds, this statement shows up often. It entails -the unique differential of the pullback in extended charts of the set where the function can -be read in the charts. -/ -theorem UniqueMDiffOn.uniqueDiffOn_inter_preimage (hs : UniqueMDiffOn I s) (x : M) (y : M') - {f : M → M'} (hf : ContinuousOn f s) : - UniqueDiffOn 𝕜 - ((extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' (s ∩ f ⁻¹' (extChartAt I' y).source)) := - haveI : UniqueMDiffOn I (s ∩ f ⁻¹' (extChartAt I' y).source) := by - intro z hz - apply (hs z hz.1).inter' - apply (hf z hz.1).preimage_mem_nhdsWithin - exact (isOpen_extChartAt_source I' y).mem_nhds hz.2 - this.uniqueDiffOn_target_inter _ -#align unique_mdiff_on.unique_diff_on_inter_preimage UniqueMDiffOn.uniqueDiffOn_inter_preimage - -open Bundle - -variable {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {Z : M → Type*} - [TopologicalSpace (TotalSpace F Z)] [∀ b, TopologicalSpace (Z b)] [∀ b, AddCommMonoid (Z b)] - [∀ b, Module 𝕜 (Z b)] [FiberBundle F Z] [VectorBundle 𝕜 F Z] [SmoothVectorBundle F Z I] - -theorem Trivialization.mdifferentiable (e : Trivialization F (π F Z)) [MemTrivializationAtlas e] : - e.toPartialHomeomorph.MDifferentiable (I.prod 𝓘(𝕜, F)) (I.prod 𝓘(𝕜, F)) := - ⟨(e.smoothOn I).mdifferentiableOn, (e.smoothOn_symm I).mdifferentiableOn⟩ - -theorem UniqueMDiffWithinAt.smooth_bundle_preimage {p : TotalSpace F Z} - (hs : UniqueMDiffWithinAt I s p.proj) : - UniqueMDiffWithinAt (I.prod 𝓘(𝕜, F)) (π F Z ⁻¹' s) p := by - set e := trivializationAt F Z p.proj - have hp : p ∈ e.source := FiberBundle.mem_trivializationAt_proj_source - have : UniqueMDiffWithinAt (I.prod 𝓘(𝕜, F)) (s ×ˢ univ) (e p) - · rw [← Prod.mk.eta (p := e p), FiberBundle.trivializationAt_proj_fst] - exact hs.prod (uniqueMDiffWithinAt_univ _) - rw [← e.left_inv hp] - refine (this.preimage_localHomeomorph e.mdifferentiable.symm (e.map_source hp)).mono ?_ - rintro y ⟨hy, hys, -⟩ - rwa [PartialHomeomorph.symm_symm, e.coe_coe, e.coe_fst hy] at hys - -variable (Z) - -theorem UniqueMDiffWithinAt.smooth_bundle_preimage' {b : M} (hs : UniqueMDiffWithinAt I s b) - (x : Z b) : UniqueMDiffWithinAt (I.prod 𝓘(𝕜, F)) (π F Z ⁻¹' s) ⟨b, x⟩ := - hs.smooth_bundle_preimage (p := ⟨b, x⟩) - -/-- In a smooth fiber bundle, the preimage under the projection of a set with -unique differential in the basis also has unique differential. -/ -theorem UniqueMDiffOn.smooth_bundle_preimage (hs : UniqueMDiffOn I s) : - UniqueMDiffOn (I.prod 𝓘(𝕜, F)) (π F Z ⁻¹' s) := fun _p hp ↦ - (hs _ hp).smooth_bundle_preimage -#align unique_mdiff_on.smooth_bundle_preimage UniqueMDiffOn.smooth_bundle_preimage - -/-- The preimage under the projection from the tangent bundle of a set with unique differential in -the basis also has unique differential. -/ -theorem UniqueMDiffOn.tangentBundle_proj_preimage (hs : UniqueMDiffOn I s) : - UniqueMDiffOn I.tangent (π E (TangentSpace I) ⁻¹' s) := - hs.smooth_bundle_preimage _ -#align unique_mdiff_on.tangent_bundle_proj_preimage UniqueMDiffOn.tangentBundle_proj_preimage - -end UniqueMDiff diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean new file mode 100644 index 0000000000000..40dfbe815cad2 --- /dev/null +++ b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean @@ -0,0 +1,303 @@ +/- +Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sébastien Gouëzel, Floris van Doorn +-/ +import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions + +/-! +# Differentiability of models with corners and (extended) charts + +In this file, we analyse the differentiability of charts, models with corners and extended charts. +We show that +* models with corners are differentiable +* charts are differentiable on their source +* `mdifferentiableOn_extChartAt`: `extChartAt` is differentiable on its source + +Suppose a partial homeomorphism `e` is differentiable. This file shows +* `PartialHomeomorph.MDifferentiable.mfderiv`: its derivative is a continuous linear equivalence +* `PartialHomeomorph.MDifferentiable.mfderiv_bijective`: its derivative is bijective; + there are also spelling with trivial kernel and full range + +In particular, (extended) charts have bijective differential. + +## Tags +charts, differentiable, bijective +-/ + +noncomputable section + +open scoped Manifold +open Bundle Set Topology + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] + (I : ModelWithCorners 𝕜 E H) {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] + (I' : ModelWithCorners 𝕜 E' H') {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] + {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] {H'' : Type*} [TopologicalSpace H''] + (I'' : ModelWithCorners 𝕜 E'' H'') {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H'' M''] + +section ModelWithCorners +namespace ModelWithCorners + +/-! #### Model with corners -/ + +protected theorem hasMFDerivAt {x} : HasMFDerivAt I 𝓘(𝕜, E) I x (ContinuousLinearMap.id _ _) := + ⟨I.continuousAt, (hasFDerivWithinAt_id _ _).congr' I.rightInvOn (mem_range_self _)⟩ +#align model_with_corners.has_mfderiv_at ModelWithCorners.hasMFDerivAt + +protected theorem hasMFDerivWithinAt {s x} : + HasMFDerivWithinAt I 𝓘(𝕜, E) I s x (ContinuousLinearMap.id _ _) := + I.hasMFDerivAt.hasMFDerivWithinAt +#align model_with_corners.has_mfderiv_within_at ModelWithCorners.hasMFDerivWithinAt + +protected theorem mdifferentiableWithinAt {s x} : MDifferentiableWithinAt I 𝓘(𝕜, E) I s x := + I.hasMFDerivWithinAt.mdifferentiableWithinAt +#align model_with_corners.mdifferentiable_within_at ModelWithCorners.mdifferentiableWithinAt + +protected theorem mdifferentiableAt {x} : MDifferentiableAt I 𝓘(𝕜, E) I x := + I.hasMFDerivAt.mdifferentiableAt +#align model_with_corners.mdifferentiable_at ModelWithCorners.mdifferentiableAt + +protected theorem mdifferentiableOn {s} : MDifferentiableOn I 𝓘(𝕜, E) I s := fun _ _ => + I.mdifferentiableWithinAt +#align model_with_corners.mdifferentiable_on ModelWithCorners.mdifferentiableOn + +protected theorem mdifferentiable : MDifferentiable I 𝓘(𝕜, E) I := fun _ => I.mdifferentiableAt +#align model_with_corners.mdifferentiable ModelWithCorners.mdifferentiable + +theorem hasMFDerivWithinAt_symm {x} (hx : x ∈ range I) : + HasMFDerivWithinAt 𝓘(𝕜, E) I I.symm (range I) x (ContinuousLinearMap.id _ _) := + ⟨I.continuousWithinAt_symm, + (hasFDerivWithinAt_id _ _).congr' (fun _y hy => I.rightInvOn hy.1) ⟨hx, mem_range_self _⟩⟩ +#align model_with_corners.has_mfderiv_within_at_symm ModelWithCorners.hasMFDerivWithinAt_symm + +theorem mdifferentiableOn_symm : MDifferentiableOn 𝓘(𝕜, E) I I.symm (range I) := fun _x hx => + (I.hasMFDerivWithinAt_symm hx).mdifferentiableWithinAt +#align model_with_corners.mdifferentiable_on_symm ModelWithCorners.mdifferentiableOn_symm + +end ModelWithCorners + +end ModelWithCorners + +section Charts + +variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] + [SmoothManifoldWithCorners I'' M''] {e : PartialHomeomorph M H} + +theorem mdifferentiableAt_atlas (h : e ∈ atlas H M) {x : M} (hx : x ∈ e.source) : + MDifferentiableAt I I e x := by + refine' ⟨(e.continuousOn x hx).continuousAt (e.open_source.mem_nhds hx), _⟩ + have mem : + I ((chartAt H x : M → H) x) ∈ I.symm ⁻¹' ((chartAt H x).symm ≫ₕ e).source ∩ range I := by + simp only [hx, mfld_simps] + have : (chartAt H x).symm.trans e ∈ contDiffGroupoid ∞ I := + HasGroupoid.compatible (chart_mem_atlas H x) h + have A : + ContDiffOn 𝕜 ∞ (I ∘ (chartAt H x).symm.trans e ∘ I.symm) + (I.symm ⁻¹' ((chartAt H x).symm.trans e).source ∩ range I) := + this.1 + have B := A.differentiableOn le_top (I ((chartAt H x : M → H) x)) mem + simp only [mfld_simps] at B + rw [inter_comm, differentiableWithinAt_inter] at B + · simpa only [mfld_simps] + · apply IsOpen.mem_nhds ((PartialHomeomorph.open_source _).preimage I.continuous_symm) mem.1 +#align mdifferentiable_at_atlas mdifferentiableAt_atlas + +theorem mdifferentiableOn_atlas (h : e ∈ atlas H M) : MDifferentiableOn I I e e.source := + fun _x hx => (mdifferentiableAt_atlas I h hx).mdifferentiableWithinAt +#align mdifferentiable_on_atlas mdifferentiableOn_atlas + +theorem mdifferentiableAt_atlas_symm (h : e ∈ atlas H M) {x : H} (hx : x ∈ e.target) : + MDifferentiableAt I I e.symm x := by + refine' ⟨(e.continuousOn_symm x hx).continuousAt (e.open_target.mem_nhds hx), _⟩ + have mem : I x ∈ I.symm ⁻¹' (e.symm ≫ₕ chartAt H (e.symm x)).source ∩ range I := by + simp only [hx, mfld_simps] + have : e.symm.trans (chartAt H (e.symm x)) ∈ contDiffGroupoid ∞ I := + HasGroupoid.compatible h (chart_mem_atlas H _) + have A : + ContDiffOn 𝕜 ∞ (I ∘ e.symm.trans (chartAt H (e.symm x)) ∘ I.symm) + (I.symm ⁻¹' (e.symm.trans (chartAt H (e.symm x))).source ∩ range I) := + this.1 + have B := A.differentiableOn le_top (I x) mem + simp only [mfld_simps] at B + rw [inter_comm, differentiableWithinAt_inter] at B + · simpa only [mfld_simps] + · apply IsOpen.mem_nhds ((PartialHomeomorph.open_source _).preimage I.continuous_symm) mem.1 +#align mdifferentiable_at_atlas_symm mdifferentiableAt_atlas_symm + +theorem mdifferentiableOn_atlas_symm (h : e ∈ atlas H M) : MDifferentiableOn I I e.symm e.target := + fun _x hx => (mdifferentiableAt_atlas_symm I h hx).mdifferentiableWithinAt +#align mdifferentiable_on_atlas_symm mdifferentiableOn_atlas_symm + +theorem mdifferentiable_of_mem_atlas (h : e ∈ atlas H M) : e.MDifferentiable I I := + ⟨mdifferentiableOn_atlas I h, mdifferentiableOn_atlas_symm I h⟩ +#align mdifferentiable_of_mem_atlas mdifferentiable_of_mem_atlas + +theorem mdifferentiable_chart (x : M) : (chartAt H x).MDifferentiable I I := + mdifferentiable_of_mem_atlas _ (chart_mem_atlas _ _) +#align mdifferentiable_chart mdifferentiable_chart + +/-- The derivative of the chart at a base point is the chart of the tangent bundle, composed with +the identification between the tangent bundle of the model space and the product space. -/ +theorem tangentMap_chart {p q : TangentBundle I M} (h : q.1 ∈ (chartAt H p.1).source) : + tangentMap I I (chartAt H p.1) q = + (TotalSpace.toProd _ _).symm + ((chartAt (ModelProd H E) p : TangentBundle I M → ModelProd H E) q) := by + dsimp [tangentMap] + rw [MDifferentiableAt.mfderiv] + · rfl + · exact mdifferentiableAt_atlas _ (chart_mem_atlas _ _) h +#align tangent_map_chart tangentMap_chart + +/-- The derivative of the inverse of the chart at a base point is the inverse of the chart of the +tangent bundle, composed with the identification between the tangent bundle of the model space and +the product space. -/ +theorem tangentMap_chart_symm {p : TangentBundle I M} {q : TangentBundle I H} + (h : q.1 ∈ (chartAt H p.1).target) : + tangentMap I I (chartAt H p.1).symm q = + (chartAt (ModelProd H E) p).symm (TotalSpace.toProd H E q) := by + dsimp only [tangentMap] + rw [MDifferentiableAt.mfderiv (mdifferentiableAt_atlas_symm _ (chart_mem_atlas _ _) h)] + simp only [ContinuousLinearMap.coe_coe, TangentBundle.chartAt, h, tangentBundleCore, + mfld_simps, (· ∘ ·)] + -- `simp` fails to apply `PartialEquiv.prod_symm` with `ModelProd` + congr + exact ((chartAt H (TotalSpace.proj p)).right_inv h).symm +#align tangent_map_chart_symm tangentMap_chart_symm + +lemma mfderiv_chartAt_eq_tangentCoordChange {x y : M} (hsrc : x ∈ (chartAt H y).source) : + mfderiv I I (chartAt H y) x = tangentCoordChange I x y x := by + have := mdifferentiableAt_atlas I (ChartedSpace.chart_mem_atlas _) (extChartAt_source I y ▸ hsrc) + simp [mfderiv, if_pos this, Function.comp.assoc] + +end Charts + + +/-! ### Differentiable partial homeomorphisms -/ + +namespace PartialHomeomorph.MDifferentiable +variable {I I' I''} +variable {e : PartialHomeomorph M M'} (he : e.MDifferentiable I I') {e' : PartialHomeomorph M' M''} + +nonrec theorem symm : e.symm.MDifferentiable I' I := he.symm +#align local_homeomorph.mdifferentiable.symm PartialHomeomorph.MDifferentiable.symm + +protected theorem mdifferentiableAt {x : M} (hx : x ∈ e.source) : MDifferentiableAt I I' e x := + (he.1 x hx).mdifferentiableAt (e.open_source.mem_nhds hx) +#align local_homeomorph.mdifferentiable.mdifferentiable_at PartialHomeomorph.MDifferentiable.mdifferentiableAt + +theorem mdifferentiableAt_symm {x : M'} (hx : x ∈ e.target) : MDifferentiableAt I' I e.symm x := + (he.2 x hx).mdifferentiableAt (e.open_target.mem_nhds hx) +#align local_homeomorph.mdifferentiable.mdifferentiable_at_symm PartialHomeomorph.MDifferentiable.mdifferentiableAt_symm + +variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] + [SmoothManifoldWithCorners I'' M''] + +theorem symm_comp_deriv {x : M} (hx : x ∈ e.source) : + (mfderiv I' I e.symm (e x)).comp (mfderiv I I' e x) = + ContinuousLinearMap.id 𝕜 (TangentSpace I x) := by + have : mfderiv I I (e.symm ∘ e) x = (mfderiv I' I e.symm (e x)).comp (mfderiv I I' e x) := + mfderiv_comp x (he.mdifferentiableAt_symm (e.map_source hx)) (he.mdifferentiableAt hx) + rw [← this] + have : mfderiv I I (_root_.id : M → M) x = ContinuousLinearMap.id _ _ := mfderiv_id I + rw [← this] + apply Filter.EventuallyEq.mfderiv_eq + have : e.source ∈ 𝓝 x := e.open_source.mem_nhds hx + exact Filter.mem_of_superset this (by mfld_set_tac) +#align local_homeomorph.mdifferentiable.symm_comp_deriv PartialHomeomorph.MDifferentiable.symm_comp_deriv + +theorem comp_symm_deriv {x : M'} (hx : x ∈ e.target) : + (mfderiv I I' e (e.symm x)).comp (mfderiv I' I e.symm x) = + ContinuousLinearMap.id 𝕜 (TangentSpace I' x) := + he.symm.symm_comp_deriv hx +#align local_homeomorph.mdifferentiable.comp_symm_deriv PartialHomeomorph.MDifferentiable.comp_symm_deriv + +/-- The derivative of a differentiable partial homeomorphism, as a continuous linear equivalence +between the tangent spaces at `x` and `e x`. -/ +protected def mfderiv {x : M} (hx : x ∈ e.source) : TangentSpace I x ≃L[𝕜] TangentSpace I' (e x) := + { mfderiv I I' e x with + invFun := mfderiv I' I e.symm (e x) + continuous_toFun := (mfderiv I I' e x).cont + continuous_invFun := (mfderiv I' I e.symm (e x)).cont + left_inv := fun y => by + have : (ContinuousLinearMap.id _ _ : TangentSpace I x →L[𝕜] TangentSpace I x) y = y := rfl + conv_rhs => rw [← this, ← he.symm_comp_deriv hx] + right_inv := fun y => by + have : + (ContinuousLinearMap.id 𝕜 _ : TangentSpace I' (e x) →L[𝕜] TangentSpace I' (e x)) y = y := + rfl + conv_rhs => rw [← this, ← he.comp_symm_deriv (e.map_source hx)] + rw [e.left_inv hx] + rfl } +#align local_homeomorph.mdifferentiable.mfderiv PartialHomeomorph.MDifferentiable.mfderiv + +theorem mfderiv_bijective {x : M} (hx : x ∈ e.source) : Function.Bijective (mfderiv I I' e x) := + (he.mfderiv hx).bijective +#align local_homeomorph.mdifferentiable.mfderiv_bijective PartialHomeomorph.MDifferentiable.mfderiv_bijective + +theorem mfderiv_injective {x : M} (hx : x ∈ e.source) : Function.Injective (mfderiv I I' e x) := + (he.mfderiv hx).injective +#align local_homeomorph.mdifferentiable.mfderiv_injective PartialHomeomorph.MDifferentiable.mfderiv_injective + +theorem mfderiv_surjective {x : M} (hx : x ∈ e.source) : Function.Surjective (mfderiv I I' e x) := + (he.mfderiv hx).surjective +#align local_homeomorph.mdifferentiable.mfderiv_surjective PartialHomeomorph.MDifferentiable.mfderiv_surjective + +theorem ker_mfderiv_eq_bot {x : M} (hx : x ∈ e.source) : LinearMap.ker (mfderiv I I' e x) = ⊥ := + (he.mfderiv hx).toLinearEquiv.ker +#align local_homeomorph.mdifferentiable.ker_mfderiv_eq_bot PartialHomeomorph.MDifferentiable.ker_mfderiv_eq_bot + +theorem range_mfderiv_eq_top {x : M} (hx : x ∈ e.source) : LinearMap.range (mfderiv I I' e x) = ⊤ := + (he.mfderiv hx).toLinearEquiv.range +#align local_homeomorph.mdifferentiable.range_mfderiv_eq_top PartialHomeomorph.MDifferentiable.range_mfderiv_eq_top + +theorem range_mfderiv_eq_univ {x : M} (hx : x ∈ e.source) : range (mfderiv I I' e x) = univ := + (he.mfderiv_surjective hx).range_eq +#align local_homeomorph.mdifferentiable.range_mfderiv_eq_univ PartialHomeomorph.MDifferentiable.range_mfderiv_eq_univ + +theorem trans (he' : e'.MDifferentiable I' I'') : (e.trans e').MDifferentiable I I'' := by + constructor + · intro x hx + simp only [mfld_simps] at hx + exact + ((he'.mdifferentiableAt hx.2).comp _ (he.mdifferentiableAt hx.1)).mdifferentiableWithinAt + · intro x hx + simp only [mfld_simps] at hx + exact + ((he.symm.mdifferentiableAt hx.2).comp _ + (he'.symm.mdifferentiableAt hx.1)).mdifferentiableWithinAt +#align local_homeomorph.mdifferentiable.trans PartialHomeomorph.MDifferentiable.trans + +end PartialHomeomorph.MDifferentiable + +/-! ### Differentiability of `extChartAt` -/ + +section extChartAt + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] + [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M : Type*} + [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] {s : Set M} {x y : M} + +theorem hasMFDerivAt_extChartAt (h : y ∈ (chartAt H x).source) : + HasMFDerivAt I 𝓘(𝕜, E) (extChartAt I x) y (mfderiv I I (chartAt H x) y : _) := + I.hasMFDerivAt.comp y ((mdifferentiable_chart I x).mdifferentiableAt h).hasMFDerivAt +#align has_mfderiv_at_ext_chart_at hasMFDerivAt_extChartAt + +theorem hasMFDerivWithinAt_extChartAt (h : y ∈ (chartAt H x).source) : + HasMFDerivWithinAt I 𝓘(𝕜, E) (extChartAt I x) s y (mfderiv I I (chartAt H x) y : _) := + (hasMFDerivAt_extChartAt I h).hasMFDerivWithinAt +#align has_mfderiv_within_at_ext_chart_at hasMFDerivWithinAt_extChartAt + +theorem mdifferentiableAt_extChartAt (h : y ∈ (chartAt H x).source) : + MDifferentiableAt I 𝓘(𝕜, E) (extChartAt I x) y := + (hasMFDerivAt_extChartAt I h).mdifferentiableAt +#align mdifferentiable_at_ext_chart_at mdifferentiableAt_extChartAt + +theorem mdifferentiableOn_extChartAt : + MDifferentiableOn I 𝓘(𝕜, E) (extChartAt I x) (chartAt H x).source := fun _y hy => + (hasMFDerivWithinAt_extChartAt I hy).mdifferentiableWithinAt +#align mdifferentiable_on_ext_chart_at mdifferentiableOn_extChartAt + +end extChartAt diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean new file mode 100644 index 0000000000000..c77cbb921a395 --- /dev/null +++ b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean @@ -0,0 +1,785 @@ +/- +Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sébastien Gouëzel, Floris van Doorn +-/ +import Mathlib.Geometry.Manifold.MFDeriv.Defs + +#align_import geometry.manifold.mfderiv from "leanprover-community/mathlib"@"e473c3198bb41f68560cab68a0529c854b618833" + +/-! +# Basic properties of the manifold Fréchet derivative + +In this file, we show various properties of the manifold Fréchet derivative, +mimicking the API for Fréchet derivatives. +- basic properties of unique differentiability sets +- various general lemmas about the manifold Fréchet derivative +- deducing differentiability from smoothness, +- deriving continuity from differentiability on manifolds, +- congruence lemmas for derivatives on manifolds +- composition lemmas and the chain rule + +-/ + +noncomputable section + +open scoped Topology Manifold +open Set Bundle + +section DerivativesProperties + +/-! ### Unique differentiability sets in manifolds -/ + +variable + {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] + {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} + {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] + {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] + {H'' : Type*} [TopologicalSpace H''] {I'' : ModelWithCorners 𝕜 E'' H''} + {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H'' M''] + {f f₀ f₁ : M → M'} {x : M} {s t : Set M} {g : M' → M''} {u : Set M'} + +theorem uniqueMDiffWithinAt_univ : UniqueMDiffWithinAt I univ x := by + unfold UniqueMDiffWithinAt + simp only [preimage_univ, univ_inter] + exact I.unique_diff _ (mem_range_self _) +#align unique_mdiff_within_at_univ uniqueMDiffWithinAt_univ + +variable {I} + +theorem uniqueMDiffWithinAt_iff {s : Set M} {x : M} : + UniqueMDiffWithinAt I s x ↔ + UniqueDiffWithinAt 𝕜 ((extChartAt I x).symm ⁻¹' s ∩ (extChartAt I x).target) + ((extChartAt I x) x) := by + apply uniqueDiffWithinAt_congr + rw [nhdsWithin_inter, nhdsWithin_inter, nhdsWithin_extChartAt_target_eq] +#align unique_mdiff_within_at_iff uniqueMDiffWithinAt_iff + +nonrec theorem UniqueMDiffWithinAt.mono_nhds {s t : Set M} {x : M} (hs : UniqueMDiffWithinAt I s x) + (ht : 𝓝[s] x ≤ 𝓝[t] x) : UniqueMDiffWithinAt I t x := + hs.mono_nhds <| by simpa only [← map_extChartAt_nhdsWithin] using Filter.map_mono ht + +theorem UniqueMDiffWithinAt.mono_of_mem {s t : Set M} {x : M} (hs : UniqueMDiffWithinAt I s x) + (ht : t ∈ 𝓝[s] x) : UniqueMDiffWithinAt I t x := + hs.mono_nhds (nhdsWithin_le_iff.2 ht) + +theorem UniqueMDiffWithinAt.mono (h : UniqueMDiffWithinAt I s x) (st : s ⊆ t) : + UniqueMDiffWithinAt I t x := + UniqueDiffWithinAt.mono h <| inter_subset_inter (preimage_mono st) (Subset.refl _) +#align unique_mdiff_within_at.mono UniqueMDiffWithinAt.mono + +theorem UniqueMDiffWithinAt.inter' (hs : UniqueMDiffWithinAt I s x) (ht : t ∈ 𝓝[s] x) : + UniqueMDiffWithinAt I (s ∩ t) x := + hs.mono_of_mem (Filter.inter_mem self_mem_nhdsWithin ht) +#align unique_mdiff_within_at.inter' UniqueMDiffWithinAt.inter' + +theorem UniqueMDiffWithinAt.inter (hs : UniqueMDiffWithinAt I s x) (ht : t ∈ 𝓝 x) : + UniqueMDiffWithinAt I (s ∩ t) x := + hs.inter' (nhdsWithin_le_nhds ht) +#align unique_mdiff_within_at.inter UniqueMDiffWithinAt.inter + +theorem IsOpen.uniqueMDiffWithinAt (hs : IsOpen s) (xs : x ∈ s) : UniqueMDiffWithinAt I s x := + (uniqueMDiffWithinAt_univ I).mono_of_mem <| nhdsWithin_le_nhds <| hs.mem_nhds xs +#align is_open.unique_mdiff_within_at IsOpen.uniqueMDiffWithinAt + +theorem UniqueMDiffOn.inter (hs : UniqueMDiffOn I s) (ht : IsOpen t) : UniqueMDiffOn I (s ∩ t) := + fun _x hx => UniqueMDiffWithinAt.inter (hs _ hx.1) (ht.mem_nhds hx.2) +#align unique_mdiff_on.inter UniqueMDiffOn.inter + +theorem IsOpen.uniqueMDiffOn (hs : IsOpen s) : UniqueMDiffOn I s := + fun _x hx => hs.uniqueMDiffWithinAt hx +#align is_open.unique_mdiff_on IsOpen.uniqueMDiffOn + +theorem uniqueMDiffOn_univ : UniqueMDiffOn I (univ : Set M) := + isOpen_univ.uniqueMDiffOn +#align unique_mdiff_on_univ uniqueMDiffOn_univ + +/- We name the typeclass variables related to `SmoothManifoldWithCorners` structure as they are +necessary in lemmas mentioning the derivative, but not in lemmas about differentiability, so we +want to include them or omit them when necessary. -/ +variable [Is : SmoothManifoldWithCorners I M] [I's : SmoothManifoldWithCorners I' M'] + [I''s : SmoothManifoldWithCorners I'' M''] + {f' f₀' f₁' : TangentSpace I x →L[𝕜] TangentSpace I' (f x)} + {g' : TangentSpace I' (f x) →L[𝕜] TangentSpace I'' (g (f x))} + +/-- `UniqueMDiffWithinAt` achieves its goal: it implies the uniqueness of the derivative. -/ +nonrec theorem UniqueMDiffWithinAt.eq (U : UniqueMDiffWithinAt I s x) + (h : HasMFDerivWithinAt I I' f s x f') (h₁ : HasMFDerivWithinAt I I' f s x f₁') : f' = f₁' := by + -- porting note: didn't need `convert` because of finding instances by unification + convert U.eq h.2 h₁.2 +#align unique_mdiff_within_at.eq UniqueMDiffWithinAt.eq + +theorem UniqueMDiffOn.eq (U : UniqueMDiffOn I s) (hx : x ∈ s) (h : HasMFDerivWithinAt I I' f s x f') + (h₁ : HasMFDerivWithinAt I I' f s x f₁') : f' = f₁' := + UniqueMDiffWithinAt.eq (U _ hx) h h₁ +#align unique_mdiff_on.eq UniqueMDiffOn.eq + +nonrec theorem UniqueMDiffWithinAt.prod {x : M} {y : M'} {s t} (hs : UniqueMDiffWithinAt I s x) + (ht : UniqueMDiffWithinAt I' t y) : UniqueMDiffWithinAt (I.prod I') (s ×ˢ t) (x, y) := by + refine (hs.prod ht).mono ?_ + rw [ModelWithCorners.range_prod, ← prod_inter_prod] + rfl + +theorem UniqueMDiffOn.prod {s : Set M} {t : Set M'} (hs : UniqueMDiffOn I s) + (ht : UniqueMDiffOn I' t) : UniqueMDiffOn (I.prod I') (s ×ˢ t) := fun x h ↦ + (hs x.1 h.1).prod (ht x.2 h.2) + +/-! +### General lemmas on derivatives of functions between manifolds + +We mimick the API for functions between vector spaces +-/ + +theorem mdifferentiableWithinAt_iff {f : M → M'} {s : Set M} {x : M} : + MDifferentiableWithinAt I I' f s x ↔ + ContinuousWithinAt f s x ∧ + DifferentiableWithinAt 𝕜 (writtenInExtChartAt I I' x f) + ((extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' s) ((extChartAt I x) x) := by + refine' and_congr Iff.rfl (exists_congr fun f' => _) + rw [inter_comm] + simp only [HasFDerivWithinAt, nhdsWithin_inter, nhdsWithin_extChartAt_target_eq] +#align mdifferentiable_within_at_iff mdifferentiableWithinAt_iff + +/-- One can reformulate differentiability within a set at a point as continuity within this set at +this point, and differentiability in any chart containing that point. -/ +theorem mdifferentiableWithinAt_iff_of_mem_source {x' : M} {y : M'} + (hx : x' ∈ (chartAt H x).source) (hy : f x' ∈ (chartAt H' y).source) : + MDifferentiableWithinAt I I' f s x' ↔ + ContinuousWithinAt f s x' ∧ + DifferentiableWithinAt 𝕜 (extChartAt I' y ∘ f ∘ (extChartAt I x).symm) + ((extChartAt I x).symm ⁻¹' s ∩ Set.range I) ((extChartAt I x) x') := + (differentiable_within_at_localInvariantProp I I').liftPropWithinAt_indep_chart + (StructureGroupoid.chart_mem_maximalAtlas _ x) hx (StructureGroupoid.chart_mem_maximalAtlas _ y) + hy +#align mdifferentiable_within_at_iff_of_mem_source mdifferentiableWithinAt_iff_of_mem_source + +theorem mfderivWithin_zero_of_not_mdifferentiableWithinAt + (h : ¬MDifferentiableWithinAt I I' f s x) : mfderivWithin I I' f s x = 0 := by + simp only [mfderivWithin, h, if_neg, not_false_iff] +#align mfderiv_within_zero_of_not_mdifferentiable_within_at mfderivWithin_zero_of_not_mdifferentiableWithinAt + +theorem mfderiv_zero_of_not_mdifferentiableAt (h : ¬MDifferentiableAt I I' f x) : + mfderiv I I' f x = 0 := by simp only [mfderiv, h, if_neg, not_false_iff] +#align mfderiv_zero_of_not_mdifferentiable_at mfderiv_zero_of_not_mdifferentiableAt + +theorem HasMFDerivWithinAt.mono (h : HasMFDerivWithinAt I I' f t x f') (hst : s ⊆ t) : + HasMFDerivWithinAt I I' f s x f' := + ⟨ContinuousWithinAt.mono h.1 hst, + HasFDerivWithinAt.mono h.2 (inter_subset_inter (preimage_mono hst) (Subset.refl _))⟩ +#align has_mfderiv_within_at.mono HasMFDerivWithinAt.mono + +theorem HasMFDerivAt.hasMFDerivWithinAt (h : HasMFDerivAt I I' f x f') : + HasMFDerivWithinAt I I' f s x f' := + ⟨ContinuousAt.continuousWithinAt h.1, HasFDerivWithinAt.mono h.2 (inter_subset_right _ _)⟩ +#align has_mfderiv_at.has_mfderiv_within_at HasMFDerivAt.hasMFDerivWithinAt + +theorem HasMFDerivWithinAt.mdifferentiableWithinAt (h : HasMFDerivWithinAt I I' f s x f') : + MDifferentiableWithinAt I I' f s x := + ⟨h.1, ⟨f', h.2⟩⟩ +#align has_mfderiv_within_at.mdifferentiable_within_at HasMFDerivWithinAt.mdifferentiableWithinAt + +theorem HasMFDerivAt.mdifferentiableAt (h : HasMFDerivAt I I' f x f') : + MDifferentiableAt I I' f x := + ⟨h.1, ⟨f', h.2⟩⟩ +#align has_mfderiv_at.mdifferentiable_at HasMFDerivAt.mdifferentiableAt + +@[simp, mfld_simps] +theorem hasMFDerivWithinAt_univ : HasMFDerivWithinAt I I' f univ x f' ↔ HasMFDerivAt I I' f x f' := + by simp only [HasMFDerivWithinAt, HasMFDerivAt, continuousWithinAt_univ, mfld_simps] +#align has_mfderiv_within_at_univ hasMFDerivWithinAt_univ + +theorem hasMFDerivAt_unique (h₀ : HasMFDerivAt I I' f x f₀') (h₁ : HasMFDerivAt I I' f x f₁') : + f₀' = f₁' := by + rw [← hasMFDerivWithinAt_univ] at h₀ h₁ + exact (uniqueMDiffWithinAt_univ I).eq h₀ h₁ +#align has_mfderiv_at_unique hasMFDerivAt_unique + +theorem hasMFDerivWithinAt_inter' (h : t ∈ 𝓝[s] x) : + HasMFDerivWithinAt I I' f (s ∩ t) x f' ↔ HasMFDerivWithinAt I I' f s x f' := by + rw [HasMFDerivWithinAt, HasMFDerivWithinAt, extChartAt_preimage_inter_eq, + hasFDerivWithinAt_inter', continuousWithinAt_inter' h] + exact extChartAt_preimage_mem_nhdsWithin I x h +#align has_mfderiv_within_at_inter' hasMFDerivWithinAt_inter' + +theorem hasMFDerivWithinAt_inter (h : t ∈ 𝓝 x) : + HasMFDerivWithinAt I I' f (s ∩ t) x f' ↔ HasMFDerivWithinAt I I' f s x f' := by + rw [HasMFDerivWithinAt, HasMFDerivWithinAt, extChartAt_preimage_inter_eq, hasFDerivWithinAt_inter, + continuousWithinAt_inter h] + exact extChartAt_preimage_mem_nhds I x h +#align has_mfderiv_within_at_inter hasMFDerivWithinAt_inter + +theorem HasMFDerivWithinAt.union (hs : HasMFDerivWithinAt I I' f s x f') + (ht : HasMFDerivWithinAt I I' f t x f') : HasMFDerivWithinAt I I' f (s ∪ t) x f' := by + constructor + · exact ContinuousWithinAt.union hs.1 ht.1 + · convert HasFDerivWithinAt.union hs.2 ht.2 using 1 + simp only [union_inter_distrib_right, preimage_union] +#align has_mfderiv_within_at.union HasMFDerivWithinAt.union + +theorem HasMFDerivWithinAt.mono_of_mem (h : HasMFDerivWithinAt I I' f s x f') (ht : s ∈ 𝓝[t] x) : + HasMFDerivWithinAt I I' f t x f' := + (hasMFDerivWithinAt_inter' ht).1 (h.mono (inter_subset_right _ _)) +#align has_mfderiv_within_at.nhds_within HasMFDerivWithinAt.mono_of_mem + +theorem HasMFDerivWithinAt.hasMFDerivAt (h : HasMFDerivWithinAt I I' f s x f') (hs : s ∈ 𝓝 x) : + HasMFDerivAt I I' f x f' := by + rwa [← univ_inter s, hasMFDerivWithinAt_inter hs, hasMFDerivWithinAt_univ] at h +#align has_mfderiv_within_at.has_mfderiv_at HasMFDerivWithinAt.hasMFDerivAt + +theorem MDifferentiableWithinAt.hasMFDerivWithinAt (h : MDifferentiableWithinAt I I' f s x) : + HasMFDerivWithinAt I I' f s x (mfderivWithin I I' f s x) := by + refine' ⟨h.1, _⟩ + simp only [mfderivWithin, h, if_pos, mfld_simps] + exact DifferentiableWithinAt.hasFDerivWithinAt h.2 +#align mdifferentiable_within_at.has_mfderiv_within_at MDifferentiableWithinAt.hasMFDerivWithinAt + +protected theorem MDifferentiableWithinAt.mfderivWithin (h : MDifferentiableWithinAt I I' f s x) : + mfderivWithin I I' f s x = + fderivWithin 𝕜 (writtenInExtChartAt I I' x f : _) ((extChartAt I x).symm ⁻¹' s ∩ range I) + ((extChartAt I x) x) := + by simp only [mfderivWithin, h, if_pos] +#align mdifferentiable_within_at.mfderiv_within MDifferentiableWithinAt.mfderivWithin + +theorem MDifferentiableAt.hasMFDerivAt (h : MDifferentiableAt I I' f x) : + HasMFDerivAt I I' f x (mfderiv I I' f x) := by + refine' ⟨h.1, _⟩ + simp only [mfderiv, h, if_pos, mfld_simps] + exact DifferentiableWithinAt.hasFDerivWithinAt h.2 +#align mdifferentiable_at.has_mfderiv_at MDifferentiableAt.hasMFDerivAt + +protected theorem MDifferentiableAt.mfderiv (h : MDifferentiableAt I I' f x) : + mfderiv I I' f x = + fderivWithin 𝕜 (writtenInExtChartAt I I' x f : _) (range I) ((extChartAt I x) x) := + by simp only [mfderiv, h, if_pos] +#align mdifferentiable_at.mfderiv MDifferentiableAt.mfderiv + +protected theorem HasMFDerivAt.mfderiv (h : HasMFDerivAt I I' f x f') : mfderiv I I' f x = f' := + (hasMFDerivAt_unique h h.mdifferentiableAt.hasMFDerivAt).symm +#align has_mfderiv_at.mfderiv HasMFDerivAt.mfderiv + +theorem HasMFDerivWithinAt.mfderivWithin (h : HasMFDerivWithinAt I I' f s x f') + (hxs : UniqueMDiffWithinAt I s x) : mfderivWithin I I' f s x = f' := by + ext + rw [hxs.eq h h.mdifferentiableWithinAt.hasMFDerivWithinAt] +#align has_mfderiv_within_at.mfderiv_within HasMFDerivWithinAt.mfderivWithin + +theorem MDifferentiable.mfderivWithin (h : MDifferentiableAt I I' f x) + (hxs : UniqueMDiffWithinAt I s x) : mfderivWithin I I' f s x = mfderiv I I' f x := by + apply HasMFDerivWithinAt.mfderivWithin _ hxs + exact h.hasMFDerivAt.hasMFDerivWithinAt +#align mdifferentiable.mfderiv_within MDifferentiable.mfderivWithin + +theorem mfderivWithin_subset (st : s ⊆ t) (hs : UniqueMDiffWithinAt I s x) + (h : MDifferentiableWithinAt I I' f t x) : + mfderivWithin I I' f s x = mfderivWithin I I' f t x := + ((MDifferentiableWithinAt.hasMFDerivWithinAt h).mono st).mfderivWithin hs +#align mfderiv_within_subset mfderivWithin_subset + +theorem MDifferentiableWithinAt.mono (hst : s ⊆ t) (h : MDifferentiableWithinAt I I' f t x) : + MDifferentiableWithinAt I I' f s x := + ⟨ContinuousWithinAt.mono h.1 hst, + DifferentiableWithinAt.mono h.2 (inter_subset_inter (preimage_mono hst) (Subset.refl _))⟩ +#align mdifferentiable_within_at.mono MDifferentiableWithinAt.mono + +theorem mdifferentiableWithinAt_univ : + MDifferentiableWithinAt I I' f univ x ↔ MDifferentiableAt I I' f x := by + simp only [MDifferentiableWithinAt, MDifferentiableAt, continuousWithinAt_univ, mfld_simps] +#align mdifferentiable_within_at_univ mdifferentiableWithinAt_univ + +theorem mdifferentiableWithinAt_inter (ht : t ∈ 𝓝 x) : + MDifferentiableWithinAt I I' f (s ∩ t) x ↔ MDifferentiableWithinAt I I' f s x := by + rw [MDifferentiableWithinAt, MDifferentiableWithinAt, extChartAt_preimage_inter_eq, + differentiableWithinAt_inter, continuousWithinAt_inter ht] + exact extChartAt_preimage_mem_nhds I x ht +#align mdifferentiable_within_at_inter mdifferentiableWithinAt_inter + +theorem mdifferentiableWithinAt_inter' (ht : t ∈ 𝓝[s] x) : + MDifferentiableWithinAt I I' f (s ∩ t) x ↔ MDifferentiableWithinAt I I' f s x := by + rw [MDifferentiableWithinAt, MDifferentiableWithinAt, extChartAt_preimage_inter_eq, + differentiableWithinAt_inter', continuousWithinAt_inter' ht] + exact extChartAt_preimage_mem_nhdsWithin I x ht +#align mdifferentiable_within_at_inter' mdifferentiableWithinAt_inter' + +theorem MDifferentiableAt.mdifferentiableWithinAt (h : MDifferentiableAt I I' f x) : + MDifferentiableWithinAt I I' f s x := + MDifferentiableWithinAt.mono (subset_univ _) (mdifferentiableWithinAt_univ.2 h) +#align mdifferentiable_at.mdifferentiable_within_at MDifferentiableAt.mdifferentiableWithinAt + +theorem MDifferentiableWithinAt.mdifferentiableAt (h : MDifferentiableWithinAt I I' f s x) + (hs : s ∈ 𝓝 x) : MDifferentiableAt I I' f x := by + have : s = univ ∩ s := by rw [univ_inter] + rwa [this, mdifferentiableWithinAt_inter hs, mdifferentiableWithinAt_univ] at h +#align mdifferentiable_within_at.mdifferentiable_at MDifferentiableWithinAt.mdifferentiableAt + +theorem MDifferentiableOn.mdifferentiableAt (h : MDifferentiableOn I I' f s) (hx : s ∈ 𝓝 x) : + MDifferentiableAt I I' f x := + (h x (mem_of_mem_nhds hx)).mdifferentiableAt hx + +theorem MDifferentiableOn.mono (h : MDifferentiableOn I I' f t) (st : s ⊆ t) : + MDifferentiableOn I I' f s := fun x hx => (h x (st hx)).mono st +#align mdifferentiable_on.mono MDifferentiableOn.mono + +theorem mdifferentiableOn_univ : MDifferentiableOn I I' f univ ↔ MDifferentiable I I' f := by + simp only [MDifferentiableOn, mdifferentiableWithinAt_univ, mfld_simps]; rfl +#align mdifferentiable_on_univ mdifferentiableOn_univ + +theorem MDifferentiable.mdifferentiableOn (h : MDifferentiable I I' f) : + MDifferentiableOn I I' f s := + (mdifferentiableOn_univ.2 h).mono (subset_univ _) +#align mdifferentiable.mdifferentiable_on MDifferentiable.mdifferentiableOn + +theorem mdifferentiableOn_of_locally_mdifferentiableOn + (h : ∀ x ∈ s, ∃ u, IsOpen u ∧ x ∈ u ∧ MDifferentiableOn I I' f (s ∩ u)) : + MDifferentiableOn I I' f s := by + intro x xs + rcases h x xs with ⟨t, t_open, xt, ht⟩ + exact (mdifferentiableWithinAt_inter (t_open.mem_nhds xt)).1 (ht x ⟨xs, xt⟩) +#align mdifferentiable_on_of_locally_mdifferentiable_on mdifferentiableOn_of_locally_mdifferentiableOn + +@[simp, mfld_simps] +theorem mfderivWithin_univ : mfderivWithin I I' f univ = mfderiv I I' f := by + ext x : 1 + simp only [mfderivWithin, mfderiv, mfld_simps] + rw [mdifferentiableWithinAt_univ] +#align mfderiv_within_univ mfderivWithin_univ + +theorem mfderivWithin_inter (ht : t ∈ 𝓝 x) : + mfderivWithin I I' f (s ∩ t) x = mfderivWithin I I' f s x := by + rw [mfderivWithin, mfderivWithin, extChartAt_preimage_inter_eq, mdifferentiableWithinAt_inter ht, + fderivWithin_inter (extChartAt_preimage_mem_nhds I x ht)] +#align mfderiv_within_inter mfderivWithin_inter + +theorem mfderivWithin_of_mem_nhds (h : s ∈ 𝓝 x) : mfderivWithin I I' f s x = mfderiv I I' f x := by + rw [← mfderivWithin_univ, ← univ_inter s, mfderivWithin_inter h] + +lemma mfderivWithin_of_isOpen (hs : IsOpen s) (hx : x ∈ s) : + mfderivWithin I I' f s x = mfderiv I I' f x := + mfderivWithin_of_mem_nhds (hs.mem_nhds hx) + +theorem mfderivWithin_eq_mfderiv (hs : UniqueMDiffWithinAt I s x) (h : MDifferentiableAt I I' f x) : + mfderivWithin I I' f s x = mfderiv I I' f x := by + rw [← mfderivWithin_univ] + exact mfderivWithin_subset (subset_univ _) hs h.mdifferentiableWithinAt + +theorem mdifferentiableAt_iff_of_mem_source {x' : M} {y : M'} + (hx : x' ∈ (chartAt H x).source) (hy : f x' ∈ (chartAt H' y).source) : + MDifferentiableAt I I' f x' ↔ + ContinuousAt f x' ∧ + DifferentiableWithinAt 𝕜 (extChartAt I' y ∘ f ∘ (extChartAt I x).symm) (Set.range I) + ((extChartAt I x) x') := + mdifferentiableWithinAt_univ.symm.trans <| + (mdifferentiableWithinAt_iff_of_mem_source hx hy).trans <| by + rw [continuousWithinAt_univ, Set.preimage_univ, Set.univ_inter] +#align mdifferentiable_at_iff_of_mem_source mdifferentiableAt_iff_of_mem_source + +/-! ### Deducing differentiability from smoothness -/ + +-- porting note: moved from `ContMDiffMFDeriv` +variable {n : ℕ∞} + +theorem ContMDiffWithinAt.mdifferentiableWithinAt (hf : ContMDiffWithinAt I I' n f s x) + (hn : 1 ≤ n) : MDifferentiableWithinAt I I' f s x := by + suffices h : MDifferentiableWithinAt I I' f (s ∩ f ⁻¹' (extChartAt I' (f x)).source) x + · rwa [mdifferentiableWithinAt_inter'] at h + apply hf.1.preimage_mem_nhdsWithin + exact extChartAt_source_mem_nhds I' (f x) + rw [mdifferentiableWithinAt_iff] + exact ⟨hf.1.mono (inter_subset_left _ _), (hf.2.differentiableWithinAt hn).mono (by mfld_set_tac)⟩ +#align cont_mdiff_within_at.mdifferentiable_within_at ContMDiffWithinAt.mdifferentiableWithinAt + +theorem ContMDiffAt.mdifferentiableAt (hf : ContMDiffAt I I' n f x) (hn : 1 ≤ n) : + MDifferentiableAt I I' f x := + mdifferentiableWithinAt_univ.1 <| ContMDiffWithinAt.mdifferentiableWithinAt hf hn +#align cont_mdiff_at.mdifferentiable_at ContMDiffAt.mdifferentiableAt + +theorem ContMDiffOn.mdifferentiableOn (hf : ContMDiffOn I I' n f s) (hn : 1 ≤ n) : + MDifferentiableOn I I' f s := fun x hx => (hf x hx).mdifferentiableWithinAt hn +#align cont_mdiff_on.mdifferentiable_on ContMDiffOn.mdifferentiableOn + +theorem ContMDiff.mdifferentiable (hf : ContMDiff I I' n f) (hn : 1 ≤ n) : MDifferentiable I I' f := + fun x => (hf x).mdifferentiableAt hn +#align cont_mdiff.mdifferentiable ContMDiff.mdifferentiable + +nonrec theorem SmoothWithinAt.mdifferentiableWithinAt (hf : SmoothWithinAt I I' f s x) : + MDifferentiableWithinAt I I' f s x := + hf.mdifferentiableWithinAt le_top +#align smooth_within_at.mdifferentiable_within_at SmoothWithinAt.mdifferentiableWithinAt + +nonrec theorem SmoothAt.mdifferentiableAt (hf : SmoothAt I I' f x) : MDifferentiableAt I I' f x := + hf.mdifferentiableAt le_top +#align smooth_at.mdifferentiable_at SmoothAt.mdifferentiableAt + +nonrec theorem SmoothOn.mdifferentiableOn (hf : SmoothOn I I' f s) : MDifferentiableOn I I' f s := + hf.mdifferentiableOn le_top +#align smooth_on.mdifferentiable_on SmoothOn.mdifferentiableOn + +theorem Smooth.mdifferentiable (hf : Smooth I I' f) : MDifferentiable I I' f := + ContMDiff.mdifferentiable hf le_top +#align smooth.mdifferentiable Smooth.mdifferentiable + +theorem Smooth.mdifferentiableAt (hf : Smooth I I' f) : MDifferentiableAt I I' f x := + hf.mdifferentiable x +#align smooth.mdifferentiable_at Smooth.mdifferentiableAt + +theorem Smooth.mdifferentiableWithinAt (hf : Smooth I I' f) : MDifferentiableWithinAt I I' f s x := + hf.mdifferentiableAt.mdifferentiableWithinAt +#align smooth.mdifferentiable_within_at Smooth.mdifferentiableWithinAt + +/-! ### Deriving continuity from differentiability on manifolds -/ + +theorem HasMFDerivWithinAt.continuousWithinAt (h : HasMFDerivWithinAt I I' f s x f') : + ContinuousWithinAt f s x := + h.1 +#align has_mfderiv_within_at.continuous_within_at HasMFDerivWithinAt.continuousWithinAt + +theorem HasMFDerivAt.continuousAt (h : HasMFDerivAt I I' f x f') : ContinuousAt f x := + h.1 +#align has_mfderiv_at.continuous_at HasMFDerivAt.continuousAt + +theorem MDifferentiableWithinAt.continuousWithinAt (h : MDifferentiableWithinAt I I' f s x) : + ContinuousWithinAt f s x := + h.1 +#align mdifferentiable_within_at.continuous_within_at MDifferentiableWithinAt.continuousWithinAt + +theorem MDifferentiableAt.continuousAt (h : MDifferentiableAt I I' f x) : ContinuousAt f x := + h.1 +#align mdifferentiable_at.continuous_at MDifferentiableAt.continuousAt + +theorem MDifferentiableOn.continuousOn (h : MDifferentiableOn I I' f s) : ContinuousOn f s := + fun x hx => (h x hx).continuousWithinAt +#align mdifferentiable_on.continuous_on MDifferentiableOn.continuousOn + +theorem MDifferentiable.continuous (h : MDifferentiable I I' f) : Continuous f := + continuous_iff_continuousAt.2 fun x => (h x).continuousAt +#align mdifferentiable.continuous MDifferentiable.continuous + +theorem tangentMapWithin_subset {p : TangentBundle I M} (st : s ⊆ t) + (hs : UniqueMDiffWithinAt I s p.1) (h : MDifferentiableWithinAt I I' f t p.1) : + tangentMapWithin I I' f s p = tangentMapWithin I I' f t p := by + simp only [tangentMapWithin, mfld_simps] + rw [mfderivWithin_subset st hs h] +#align tangent_map_within_subset tangentMapWithin_subset + +theorem tangentMapWithin_univ : tangentMapWithin I I' f univ = tangentMap I I' f := by + ext p : 1 + simp only [tangentMapWithin, tangentMap, mfld_simps] +#align tangent_map_within_univ tangentMapWithin_univ + +theorem tangentMapWithin_eq_tangentMap {p : TangentBundle I M} (hs : UniqueMDiffWithinAt I s p.1) + (h : MDifferentiableAt I I' f p.1) : tangentMapWithin I I' f s p = tangentMap I I' f p := by + rw [← mdifferentiableWithinAt_univ] at h + rw [← tangentMapWithin_univ] + exact tangentMapWithin_subset (subset_univ _) hs h +#align tangent_map_within_eq_tangent_map tangentMapWithin_eq_tangentMap + +@[simp, mfld_simps] +theorem tangentMapWithin_proj {p : TangentBundle I M} : + (tangentMapWithin I I' f s p).proj = f p.proj := + rfl +#align tangent_map_within_proj tangentMapWithin_proj + +@[simp, mfld_simps] +theorem tangentMap_proj {p : TangentBundle I M} : (tangentMap I I' f p).proj = f p.proj := + rfl +#align tangent_map_proj tangentMap_proj + +theorem MDifferentiableWithinAt.prod_mk {f : M → M'} {g : M → M''} + (hf : MDifferentiableWithinAt I I' f s x) (hg : MDifferentiableWithinAt I I'' g s x) : + MDifferentiableWithinAt I (I'.prod I'') (fun x => (f x, g x)) s x := + ⟨hf.1.prod hg.1, hf.2.prod hg.2⟩ +#align mdifferentiable_within_at.prod_mk MDifferentiableWithinAt.prod_mk + +theorem MDifferentiableAt.prod_mk {f : M → M'} {g : M → M''} (hf : MDifferentiableAt I I' f x) + (hg : MDifferentiableAt I I'' g x) : + MDifferentiableAt I (I'.prod I'') (fun x => (f x, g x)) x := + ⟨hf.1.prod hg.1, hf.2.prod hg.2⟩ +#align mdifferentiable_at.prod_mk MDifferentiableAt.prod_mk + +theorem MDifferentiableOn.prod_mk {f : M → M'} {g : M → M''} (hf : MDifferentiableOn I I' f s) + (hg : MDifferentiableOn I I'' g s) : + MDifferentiableOn I (I'.prod I'') (fun x => (f x, g x)) s := fun x hx => + (hf x hx).prod_mk (hg x hx) +#align mdifferentiable_on.prod_mk MDifferentiableOn.prod_mk + +theorem MDifferentiable.prod_mk {f : M → M'} {g : M → M''} (hf : MDifferentiable I I' f) + (hg : MDifferentiable I I'' g) : MDifferentiable I (I'.prod I'') fun x => (f x, g x) := fun x => + (hf x).prod_mk (hg x) +#align mdifferentiable.prod_mk MDifferentiable.prod_mk + +theorem MDifferentiableWithinAt.prod_mk_space {f : M → E'} {g : M → E''} + (hf : MDifferentiableWithinAt I 𝓘(𝕜, E') f s x) + (hg : MDifferentiableWithinAt I 𝓘(𝕜, E'') g s x) : + MDifferentiableWithinAt I 𝓘(𝕜, E' × E'') (fun x => (f x, g x)) s x := + ⟨hf.1.prod hg.1, hf.2.prod hg.2⟩ +#align mdifferentiable_within_at.prod_mk_space MDifferentiableWithinAt.prod_mk_space + +theorem MDifferentiableAt.prod_mk_space {f : M → E'} {g : M → E''} + (hf : MDifferentiableAt I 𝓘(𝕜, E') f x) (hg : MDifferentiableAt I 𝓘(𝕜, E'') g x) : + MDifferentiableAt I 𝓘(𝕜, E' × E'') (fun x => (f x, g x)) x := + ⟨hf.1.prod hg.1, hf.2.prod hg.2⟩ +#align mdifferentiable_at.prod_mk_space MDifferentiableAt.prod_mk_space + +theorem MDifferentiableOn.prod_mk_space {f : M → E'} {g : M → E''} + (hf : MDifferentiableOn I 𝓘(𝕜, E') f s) (hg : MDifferentiableOn I 𝓘(𝕜, E'') g s) : + MDifferentiableOn I 𝓘(𝕜, E' × E'') (fun x => (f x, g x)) s := fun x hx => + (hf x hx).prod_mk_space (hg x hx) +#align mdifferentiable_on.prod_mk_space MDifferentiableOn.prod_mk_space + +theorem MDifferentiable.prod_mk_space {f : M → E'} {g : M → E''} (hf : MDifferentiable I 𝓘(𝕜, E') f) + (hg : MDifferentiable I 𝓘(𝕜, E'') g) : MDifferentiable I 𝓘(𝕜, E' × E'') fun x => (f x, g x) := + fun x => (hf x).prod_mk_space (hg x) +#align mdifferentiable.prod_mk_space MDifferentiable.prod_mk_space + +/-! ### Congruence lemmas for derivatives on manifolds -/ + +theorem HasMFDerivAt.congr_mfderiv (h : HasMFDerivAt I I' f x f') (h' : f' = f₁') : + HasMFDerivAt I I' f x f₁' := + h' ▸ h + +theorem HasMFDerivWithinAt.congr_mfderiv (h : HasMFDerivWithinAt I I' f s x f') (h' : f' = f₁') : + HasMFDerivWithinAt I I' f s x f₁' := + h' ▸ h + +theorem HasMFDerivWithinAt.congr_of_eventuallyEq (h : HasMFDerivWithinAt I I' f s x f') + (h₁ : f₁ =ᶠ[𝓝[s] x] f) (hx : f₁ x = f x) : HasMFDerivWithinAt I I' f₁ s x f' := by + refine' ⟨ContinuousWithinAt.congr_of_eventuallyEq h.1 h₁ hx, _⟩ + apply HasFDerivWithinAt.congr_of_eventuallyEq h.2 + · have : + (extChartAt I x).symm ⁻¹' {y | f₁ y = f y} ∈ + 𝓝[(extChartAt I x).symm ⁻¹' s ∩ range I] (extChartAt I x) x := + extChartAt_preimage_mem_nhdsWithin I x h₁ + apply Filter.mem_of_superset this fun y => _ + simp (config := { contextual := true }) only [hx, mfld_simps] + · simp only [hx, mfld_simps] +#align has_mfderiv_within_at.congr_of_eventually_eq HasMFDerivWithinAt.congr_of_eventuallyEq + +theorem HasMFDerivWithinAt.congr_mono (h : HasMFDerivWithinAt I I' f s x f') + (ht : ∀ x ∈ t, f₁ x = f x) (hx : f₁ x = f x) (h₁ : t ⊆ s) : HasMFDerivWithinAt I I' f₁ t x f' := + (h.mono h₁).congr_of_eventuallyEq (Filter.mem_inf_of_right ht) hx +#align has_mfderiv_within_at.congr_mono HasMFDerivWithinAt.congr_mono + +theorem HasMFDerivAt.congr_of_eventuallyEq (h : HasMFDerivAt I I' f x f') (h₁ : f₁ =ᶠ[𝓝 x] f) : + HasMFDerivAt I I' f₁ x f' := by + rw [← hasMFDerivWithinAt_univ] at h ⊢ + apply h.congr_of_eventuallyEq _ (mem_of_mem_nhds h₁ : _) + rwa [nhdsWithin_univ] +#align has_mfderiv_at.congr_of_eventually_eq HasMFDerivAt.congr_of_eventuallyEq + +theorem MDifferentiableWithinAt.congr_of_eventuallyEq (h : MDifferentiableWithinAt I I' f s x) + (h₁ : f₁ =ᶠ[𝓝[s] x] f) (hx : f₁ x = f x) : MDifferentiableWithinAt I I' f₁ s x := + (h.hasMFDerivWithinAt.congr_of_eventuallyEq h₁ hx).mdifferentiableWithinAt +#align mdifferentiable_within_at.congr_of_eventually_eq MDifferentiableWithinAt.congr_of_eventuallyEq + +variable (I I') + +theorem Filter.EventuallyEq.mdifferentiableWithinAt_iff (h₁ : f₁ =ᶠ[𝓝[s] x] f) (hx : f₁ x = f x) : + MDifferentiableWithinAt I I' f s x ↔ MDifferentiableWithinAt I I' f₁ s x := by + constructor + · intro h + apply h.congr_of_eventuallyEq h₁ hx + · intro h + apply h.congr_of_eventuallyEq _ hx.symm + apply h₁.mono + intro y + apply Eq.symm +#align filter.eventually_eq.mdifferentiable_within_at_iff Filter.EventuallyEq.mdifferentiableWithinAt_iff + +variable {I I'} + +theorem MDifferentiableWithinAt.congr_mono (h : MDifferentiableWithinAt I I' f s x) + (ht : ∀ x ∈ t, f₁ x = f x) (hx : f₁ x = f x) (h₁ : t ⊆ s) : + MDifferentiableWithinAt I I' f₁ t x := + (HasMFDerivWithinAt.congr_mono h.hasMFDerivWithinAt ht hx h₁).mdifferentiableWithinAt +#align mdifferentiable_within_at.congr_mono MDifferentiableWithinAt.congr_mono + +theorem MDifferentiableWithinAt.congr (h : MDifferentiableWithinAt I I' f s x) + (ht : ∀ x ∈ s, f₁ x = f x) (hx : f₁ x = f x) : MDifferentiableWithinAt I I' f₁ s x := + (HasMFDerivWithinAt.congr_mono h.hasMFDerivWithinAt ht hx (Subset.refl _)).mdifferentiableWithinAt +#align mdifferentiable_within_at.congr MDifferentiableWithinAt.congr + +theorem MDifferentiableOn.congr_mono (h : MDifferentiableOn I I' f s) (h' : ∀ x ∈ t, f₁ x = f x) + (h₁ : t ⊆ s) : MDifferentiableOn I I' f₁ t := fun x hx => + (h x (h₁ hx)).congr_mono h' (h' x hx) h₁ +#align mdifferentiable_on.congr_mono MDifferentiableOn.congr_mono + +theorem MDifferentiableAt.congr_of_eventuallyEq (h : MDifferentiableAt I I' f x) + (hL : f₁ =ᶠ[𝓝 x] f) : MDifferentiableAt I I' f₁ x := + (h.hasMFDerivAt.congr_of_eventuallyEq hL).mdifferentiableAt +#align mdifferentiable_at.congr_of_eventually_eq MDifferentiableAt.congr_of_eventuallyEq + +theorem MDifferentiableWithinAt.mfderivWithin_congr_mono (h : MDifferentiableWithinAt I I' f s x) + (hs : ∀ x ∈ t, f₁ x = f x) (hx : f₁ x = f x) (hxt : UniqueMDiffWithinAt I t x) (h₁ : t ⊆ s) : + mfderivWithin I I' f₁ t x = (mfderivWithin I I' f s x : _) := + (HasMFDerivWithinAt.congr_mono h.hasMFDerivWithinAt hs hx h₁).mfderivWithin hxt +#align mdifferentiable_within_at.mfderiv_within_congr_mono MDifferentiableWithinAt.mfderivWithin_congr_mono + +theorem Filter.EventuallyEq.mfderivWithin_eq (hs : UniqueMDiffWithinAt I s x) (hL : f₁ =ᶠ[𝓝[s] x] f) + (hx : f₁ x = f x) : mfderivWithin I I' f₁ s x = (mfderivWithin I I' f s x : _) := by + by_cases h : MDifferentiableWithinAt I I' f s x + · exact (h.hasMFDerivWithinAt.congr_of_eventuallyEq hL hx).mfderivWithin hs + · unfold mfderivWithin + rw [if_neg h, if_neg] + rwa [← hL.mdifferentiableWithinAt_iff I I' hx] +#align filter.eventually_eq.mfderiv_within_eq Filter.EventuallyEq.mfderivWithin_eq + +theorem mfderivWithin_congr (hs : UniqueMDiffWithinAt I s x) (hL : ∀ x ∈ s, f₁ x = f x) + (hx : f₁ x = f x) : mfderivWithin I I' f₁ s x = (mfderivWithin I I' f s x : _) := + Filter.EventuallyEq.mfderivWithin_eq hs (Filter.eventuallyEq_of_mem self_mem_nhdsWithin hL) hx +#align mfderiv_within_congr mfderivWithin_congr + +theorem tangentMapWithin_congr (h : ∀ x ∈ s, f x = f₁ x) (p : TangentBundle I M) (hp : p.1 ∈ s) + (hs : UniqueMDiffWithinAt I s p.1) : + tangentMapWithin I I' f s p = tangentMapWithin I I' f₁ s p := by + refine TotalSpace.ext _ _ (h p.1 hp) ?_ + -- This used to be `simp only`, but we need `erw` after leanprover/lean4#2644 + rw [tangentMapWithin, h p.1 hp, tangentMapWithin, mfderivWithin_congr hs h (h _ hp)] +#align tangent_map_within_congr tangentMapWithin_congr + +theorem Filter.EventuallyEq.mfderiv_eq (hL : f₁ =ᶠ[𝓝 x] f) : + mfderiv I I' f₁ x = (mfderiv I I' f x : _) := by + have A : f₁ x = f x := (mem_of_mem_nhds hL : _) + rw [← mfderivWithin_univ, ← mfderivWithin_univ] + rw [← nhdsWithin_univ] at hL + exact hL.mfderivWithin_eq (uniqueMDiffWithinAt_univ I) A +#align filter.eventually_eq.mfderiv_eq Filter.EventuallyEq.mfderiv_eq + +/-- A congruence lemma for `mfderiv`, (ab)using the fact that `TangentSpace I' (f x)` is +definitionally equal to `E'`. -/ +theorem mfderiv_congr_point {x' : M} (h : x = x') : + @Eq (E →L[𝕜] E') (mfderiv I I' f x) (mfderiv I I' f x') := by subst h; rfl +#align mfderiv_congr_point mfderiv_congr_point + +/-- A congruence lemma for `mfderiv`, (ab)using the fact that `TangentSpace I' (f x)` is +definitionally equal to `E'`. -/ +theorem mfderiv_congr {f' : M → M'} (h : f = f') : + @Eq (E →L[𝕜] E') (mfderiv I I' f x) (mfderiv I I' f' x) := by subst h; rfl +#align mfderiv_congr mfderiv_congr + +/-! ### Composition lemmas -/ + +theorem writtenInExtChartAt_comp (h : ContinuousWithinAt f s x) : + {y | writtenInExtChartAt I I'' x (g ∘ f) y = + (writtenInExtChartAt I' I'' (f x) g ∘ writtenInExtChartAt I I' x f) y} ∈ + 𝓝[(extChartAt I x).symm ⁻¹' s ∩ range I] (extChartAt I x) x := by + apply + @Filter.mem_of_superset _ _ (f ∘ (extChartAt I x).symm ⁻¹' (extChartAt I' (f x)).source) _ + (extChartAt_preimage_mem_nhdsWithin I x + (h.preimage_mem_nhdsWithin (extChartAt_source_mem_nhds _ _))) + mfld_set_tac +#align written_in_ext_chart_comp writtenInExtChartAt_comp + +variable (x) + +theorem HasMFDerivWithinAt.comp (hg : HasMFDerivWithinAt I' I'' g u (f x) g') + (hf : HasMFDerivWithinAt I I' f s x f') (hst : s ⊆ f ⁻¹' u) : + HasMFDerivWithinAt I I'' (g ∘ f) s x (g'.comp f') := by + refine' ⟨ContinuousWithinAt.comp hg.1 hf.1 hst, _⟩ + have A : + HasFDerivWithinAt (writtenInExtChartAt I' I'' (f x) g ∘ writtenInExtChartAt I I' x f) + (ContinuousLinearMap.comp g' f' : E →L[𝕜] E'') ((extChartAt I x).symm ⁻¹' s ∩ range I) + ((extChartAt I x) x) := by + have : + (extChartAt I x).symm ⁻¹' (f ⁻¹' (extChartAt I' (f x)).source) ∈ + 𝓝[(extChartAt I x).symm ⁻¹' s ∩ range I] (extChartAt I x) x := + extChartAt_preimage_mem_nhdsWithin I x + (hf.1.preimage_mem_nhdsWithin (extChartAt_source_mem_nhds _ _)) + unfold HasMFDerivWithinAt at * + rw [← hasFDerivWithinAt_inter' this, ← extChartAt_preimage_inter_eq] at hf ⊢ + have : writtenInExtChartAt I I' x f ((extChartAt I x) x) = (extChartAt I' (f x)) (f x) := by + simp only [mfld_simps] + rw [← this] at hg + apply HasFDerivWithinAt.comp ((extChartAt I x) x) hg.2 hf.2 _ + intro y hy + simp only [mfld_simps] at hy + have : f (((chartAt H x).symm : H → M) (I.symm y)) ∈ u := hst hy.1.1 + simp only [hy, this, mfld_simps] + apply A.congr_of_eventuallyEq (writtenInExtChartAt_comp hf.1) + simp only [mfld_simps] +#align has_mfderiv_within_at.comp HasMFDerivWithinAt.comp + +/-- The **chain rule for manifolds**. -/ +theorem HasMFDerivAt.comp (hg : HasMFDerivAt I' I'' g (f x) g') (hf : HasMFDerivAt I I' f x f') : + HasMFDerivAt I I'' (g ∘ f) x (g'.comp f') := by + rw [← hasMFDerivWithinAt_univ] at * + exact HasMFDerivWithinAt.comp x (hg.mono (subset_univ _)) hf subset_preimage_univ +#align has_mfderiv_at.comp HasMFDerivAt.comp + +theorem HasMFDerivAt.comp_hasMFDerivWithinAt (hg : HasMFDerivAt I' I'' g (f x) g') + (hf : HasMFDerivWithinAt I I' f s x f') : + HasMFDerivWithinAt I I'' (g ∘ f) s x (g'.comp f') := by + rw [← hasMFDerivWithinAt_univ] at * + exact HasMFDerivWithinAt.comp x (hg.mono (subset_univ _)) hf subset_preimage_univ +#align has_mfderiv_at.comp_has_mfderiv_within_at HasMFDerivAt.comp_hasMFDerivWithinAt + +theorem MDifferentiableWithinAt.comp (hg : MDifferentiableWithinAt I' I'' g u (f x)) + (hf : MDifferentiableWithinAt I I' f s x) (h : s ⊆ f ⁻¹' u) : + MDifferentiableWithinAt I I'' (g ∘ f) s x := by + rcases hf.2 with ⟨f', hf'⟩ + have F : HasMFDerivWithinAt I I' f s x f' := ⟨hf.1, hf'⟩ + rcases hg.2 with ⟨g', hg'⟩ + have G : HasMFDerivWithinAt I' I'' g u (f x) g' := ⟨hg.1, hg'⟩ + exact (HasMFDerivWithinAt.comp x G F h).mdifferentiableWithinAt +#align mdifferentiable_within_at.comp MDifferentiableWithinAt.comp + +theorem MDifferentiableAt.comp (hg : MDifferentiableAt I' I'' g (f x)) + (hf : MDifferentiableAt I I' f x) : MDifferentiableAt I I'' (g ∘ f) x := + (hg.hasMFDerivAt.comp x hf.hasMFDerivAt).mdifferentiableAt +#align mdifferentiable_at.comp MDifferentiableAt.comp + +theorem mfderivWithin_comp (hg : MDifferentiableWithinAt I' I'' g u (f x)) + (hf : MDifferentiableWithinAt I I' f s x) (h : s ⊆ f ⁻¹' u) (hxs : UniqueMDiffWithinAt I s x) : + mfderivWithin I I'' (g ∘ f) s x = + (mfderivWithin I' I'' g u (f x)).comp (mfderivWithin I I' f s x) := by + apply HasMFDerivWithinAt.mfderivWithin _ hxs + exact HasMFDerivWithinAt.comp x hg.hasMFDerivWithinAt hf.hasMFDerivWithinAt h +#align mfderiv_within_comp mfderivWithin_comp + +theorem mfderiv_comp (hg : MDifferentiableAt I' I'' g (f x)) (hf : MDifferentiableAt I I' f x) : + mfderiv I I'' (g ∘ f) x = (mfderiv I' I'' g (f x)).comp (mfderiv I I' f x) := by + apply HasMFDerivAt.mfderiv + exact HasMFDerivAt.comp x hg.hasMFDerivAt hf.hasMFDerivAt +#align mfderiv_comp mfderiv_comp + +theorem mfderiv_comp_of_eq {x : M} {y : M'} (hg : MDifferentiableAt I' I'' g y) + (hf : MDifferentiableAt I I' f x) (hy : f x = y) : + mfderiv I I'' (g ∘ f) x = (mfderiv I' I'' g (f x)).comp (mfderiv I I' f x) := by + subst hy; exact mfderiv_comp x hg hf +#align mfderiv_comp_of_eq mfderiv_comp_of_eq + +theorem MDifferentiableOn.comp (hg : MDifferentiableOn I' I'' g u) (hf : MDifferentiableOn I I' f s) + (st : s ⊆ f ⁻¹' u) : MDifferentiableOn I I'' (g ∘ f) s := fun x hx => + MDifferentiableWithinAt.comp x (hg (f x) (st hx)) (hf x hx) st +#align mdifferentiable_on.comp MDifferentiableOn.comp + +theorem MDifferentiable.comp (hg : MDifferentiable I' I'' g) (hf : MDifferentiable I I' f) : + MDifferentiable I I'' (g ∘ f) := fun x => MDifferentiableAt.comp x (hg (f x)) (hf x) +#align mdifferentiable.comp MDifferentiable.comp + +theorem tangentMapWithin_comp_at (p : TangentBundle I M) + (hg : MDifferentiableWithinAt I' I'' g u (f p.1)) (hf : MDifferentiableWithinAt I I' f s p.1) + (h : s ⊆ f ⁻¹' u) (hps : UniqueMDiffWithinAt I s p.1) : + tangentMapWithin I I'' (g ∘ f) s p = + tangentMapWithin I' I'' g u (tangentMapWithin I I' f s p) := by + simp only [tangentMapWithin, mfld_simps] + rw [mfderivWithin_comp p.1 hg hf h hps] + rfl +#align tangent_map_within_comp_at tangentMapWithin_comp_at + +theorem tangentMap_comp_at (p : TangentBundle I M) (hg : MDifferentiableAt I' I'' g (f p.1)) + (hf : MDifferentiableAt I I' f p.1) : + tangentMap I I'' (g ∘ f) p = tangentMap I' I'' g (tangentMap I I' f p) := by + simp only [tangentMap, mfld_simps] + rw [mfderiv_comp p.1 hg hf] + rfl +#align tangent_map_comp_at tangentMap_comp_at + +theorem tangentMap_comp (hg : MDifferentiable I' I'' g) (hf : MDifferentiable I I' f) : + tangentMap I I'' (g ∘ f) = tangentMap I' I'' g ∘ tangentMap I I' f := by + ext p : 1; exact tangentMap_comp_at _ (hg _) (hf _) +#align tangent_map_comp tangentMap_comp + +end DerivativesProperties diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean new file mode 100644 index 0000000000000..2b7d49aaf9d9d --- /dev/null +++ b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean @@ -0,0 +1,313 @@ +/- +Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sébastien Gouëzel, Floris van Doorn +-/ +import Mathlib.Geometry.Manifold.VectorBundle.Tangent + +#align_import geometry.manifold.mfderiv from "leanprover-community/mathlib"@"e473c3198bb41f68560cab68a0529c854b618833" + +/-! +# The derivative of functions between smooth manifolds + +Let `M` and `M'` be two smooth manifolds with corners over a field `𝕜` (with respective models with +corners `I` on `(E, H)` and `I'` on `(E', H')`), and let `f : M → M'`. We define the +derivative of the function at a point, within a set or along the whole space, mimicking the API +for (Fréchet) derivatives. It is denoted by `mfderiv I I' f x`, where "m" stands for "manifold" and +"f" for "Fréchet" (as in the usual derivative `fderiv 𝕜 f x`). + +## Main definitions + +* `UniqueMDiffOn I s` : predicate saying that, at each point of the set `s`, a function can have + at most one derivative. This technical condition is important when we define + `mfderivWithin` below, as otherwise there is an arbitrary choice in the derivative, + and many properties will fail (for instance the chain rule). This is analogous to + `UniqueDiffOn 𝕜 s` in a vector space. + +Let `f` be a map between smooth manifolds. The following definitions follow the `fderiv` API. + +* `mfderiv I I' f x` : the derivative of `f` at `x`, as a continuous linear map from the tangent + space at `x` to the tangent space at `f x`. If the map is not differentiable, this is `0`. +* `mfderivWithin I I' f s x` : the derivative of `f` at `x` within `s`, as a continuous linear map + from the tangent space at `x` to the tangent space at `f x`. If the map is not differentiable + within `s`, this is `0`. +* `MDifferentiableAt I I' f x` : Prop expressing whether `f` is differentiable at `x`. +* `MDifferentiableWithinAt 𝕜 f s x` : Prop expressing whether `f` is differentiable within `s` + at `x`. +* `HasMFDerivAt I I' f s x f'` : Prop expressing whether `f` has `f'` as a derivative at `x`. +* `HasMFDerivWithinAt I I' f s x f'` : Prop expressing whether `f` has `f'` as a derivative + within `s` at `x`. +* `MDifferentiableOn I I' f s` : Prop expressing that `f` is differentiable on the set `s`. +* `MDifferentiable I I' f` : Prop expressing that `f` is differentiable everywhere. +* `tangentMap I I' f` : the derivative of `f`, as a map from the tangent bundle of `M` to the + tangent bundle of `M'`. + +Various related results are proven in separate files: see +- `Basic.lean` for basic properties of the `mfderiv`, mimicking the API of the Fréchet derivative, +- `FDeriv.lean` for the equivalence of the manifold notions with the usual Fréchet derivative +for functions between vector spaces, +- `SpecificFunctions.lean` for results on the differential of the identity, constant functions, +products and arithmetic operators (like addition or scalar multiplication), +- `Atlas.lean` for differentiability of charts, models with corners and extended charts, +- `UniqueDifferential.lean` for various properties of unique differentiability sets in manifolds. + +## Implementation notes + +The tangent bundle is constructed using the machinery of topological fiber bundles, for which one +can define bundled morphisms and construct canonically maps from the total space of one bundle to +the total space of another one. One could use this mechanism to construct directly the derivative +of a smooth map. However, we want to define the derivative of any map (and let it be zero if the map +is not differentiable) to avoid proof arguments everywhere. This means we have to go back to the +details of the definition of the total space of a fiber bundle constructed from core, to cook up a +suitable definition of the derivative. It is the following: at each point, we have a preferred chart +(used to identify the fiber above the point with the model vector space in fiber bundles). Then one +should read the function using these preferred charts at `x` and `f x`, and take the derivative +of `f` in these charts. + +Due to the fact that we are working in a model with corners, with an additional embedding `I` of the +model space `H` in the model vector space `E`, the charts taking values in `E` are not the original +charts of the manifold, but those ones composed with `I`, called extended charts. We define +`writtenInExtChartAt I I' x f` for the function `f` written in the preferred extended charts. Then +the manifold derivative of `f`, at `x`, is just the usual derivative of +`writtenInExtChartAt I I' x f`, at the point `(extChartAt I x) x`. + +There is a subtlety with respect to continuity: if the function is not continuous, then the image +of a small open set around `x` will not be contained in the source of the preferred chart around +`f x`, which means that when reading `f` in the chart one is losing some information. To avoid this, +we include continuity in the definition of differentiablity (which is reasonable since with any +definition, differentiability implies continuity). + +*Warning*: the derivative (even within a subset) is a linear map on the whole tangent space. Suppose +that one is given a smooth submanifold `N`, and a function which is smooth on `N` (i.e., its +restriction to the subtype `N` is smooth). Then, in the whole manifold `M`, the property +`MDifferentiableOn I I' f N` holds. However, `mfderivWithin I I' f N` is not uniquely defined +(what values would one choose for vectors that are transverse to `N`?), which can create issues down +the road. The problem here is that knowing the value of `f` along `N` does not determine the +differential of `f` in all directions. This is in contrast to the case where `N` would be an open +subset, or a submanifold with boundary of maximal dimension, where this issue does not appear. +The predicate `UniqueMDiffOn I N` indicates that the derivative along `N` is unique if it exists, +and is an assumption in most statements requiring a form of uniqueness. + +On a vector space, the manifold derivative and the usual derivative are equal. This means in +particular that they live on the same space, i.e., the tangent space is defeq to the original vector +space. To get this property is a motivation for our definition of the tangent space as a single +copy of the vector space, instead of more usual definitions such as the space of derivations, or +the space of equivalence classes of smooth curves in the manifold. + +## Tags +derivative, manifold +-/ + +noncomputable section + +open scoped Classical Topology Manifold +open Set ChartedSpace + +section DerivativesDefinitions + +/-! +### Derivative of maps between manifolds + +The derivative of a smooth map `f` between smooth manifold `M` and `M'` at `x` is a bounded linear +map from the tangent space to `M` at `x`, to the tangent space to `M'` at `f x`. Since we defined +the tangent space using one specific chart, the formula for the derivative is written in terms of +this specific chart. + +We use the names `MDifferentiable` and `mfderiv`, where the prefix letter `m` means "manifold". +-/ + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] + [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M : Type*} + [TopologicalSpace M] [ChartedSpace H M] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] + {H' : Type*} [TopologicalSpace H'] (I' : ModelWithCorners 𝕜 E' H') {M' : Type*} + [TopologicalSpace M'] [ChartedSpace H' M'] + +/-- Property in the model space of a model with corners of being differentiable within at set at a +point, when read in the model vector space. This property will be lifted to manifolds to define +differentiable functions between manifolds. -/ +def DifferentiableWithinAtProp (f : H → H') (s : Set H) (x : H) : Prop := + DifferentiableWithinAt 𝕜 (I' ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ Set.range I) (I x) +#align differentiable_within_at_prop DifferentiableWithinAtProp + +/-- Being differentiable in the model space is a local property, invariant under smooth maps. +Therefore, it will lift nicely to manifolds. -/ +theorem differentiable_within_at_localInvariantProp : + (contDiffGroupoid ⊤ I).LocalInvariantProp (contDiffGroupoid ⊤ I') + (DifferentiableWithinAtProp I I') := + { is_local := by + intro s x u f u_open xu + have : I.symm ⁻¹' (s ∩ u) ∩ Set.range I = I.symm ⁻¹' s ∩ Set.range I ∩ I.symm ⁻¹' u := by + simp only [Set.inter_right_comm, Set.preimage_inter] + rw [DifferentiableWithinAtProp, DifferentiableWithinAtProp, this] + symm + apply differentiableWithinAt_inter + have : u ∈ 𝓝 (I.symm (I x)) := by + rw [ModelWithCorners.left_inv] + exact u_open.mem_nhds xu + apply I.continuous_symm.continuousAt this + right_invariance' := by + intro s x f e he hx h + rw [DifferentiableWithinAtProp] at h ⊢ + have : I x = (I ∘ e.symm ∘ I.symm) (I (e x)) := by simp only [hx, mfld_simps] + rw [this] at h + have : I (e x) ∈ I.symm ⁻¹' e.target ∩ Set.range I := by simp only [hx, mfld_simps] + have := (mem_groupoid_of_pregroupoid.2 he).2.contDiffWithinAt this + convert (h.comp' _ (this.differentiableWithinAt le_top)).mono_of_mem _ using 1 + · ext y; simp only [mfld_simps] + refine' + mem_nhdsWithin.mpr + ⟨I.symm ⁻¹' e.target, e.open_target.preimage I.continuous_symm, by + simp_rw [Set.mem_preimage, I.left_inv, e.mapsTo hx], _⟩ + mfld_set_tac + congr_of_forall := by + intro s x f g h hx hf + apply hf.congr + · intro y hy + simp only [mfld_simps] at hy + simp only [h, hy, mfld_simps] + · simp only [hx, mfld_simps] + left_invariance' := by + intro s x f e' he' hs hx h + rw [DifferentiableWithinAtProp] at h ⊢ + have A : (I' ∘ f ∘ I.symm) (I x) ∈ I'.symm ⁻¹' e'.source ∩ Set.range I' := by + simp only [hx, mfld_simps] + have := (mem_groupoid_of_pregroupoid.2 he').1.contDiffWithinAt A + convert (this.differentiableWithinAt le_top).comp _ h _ + · ext y; simp only [mfld_simps] + · intro y hy; simp only [mfld_simps] at hy; simpa only [hy, mfld_simps] using hs hy.1 } +#align differentiable_within_at_local_invariant_prop differentiable_within_at_localInvariantProp + +/-- Predicate ensuring that, at a point and within a set, a function can have at most one +derivative. This is expressed using the preferred chart at the considered point. -/ +def UniqueMDiffWithinAt (s : Set M) (x : M) := + UniqueDiffWithinAt 𝕜 ((extChartAt I x).symm ⁻¹' s ∩ range I) ((extChartAt I x) x) +#align unique_mdiff_within_at UniqueMDiffWithinAt + +/-- Predicate ensuring that, at all points of a set, a function can have at most one derivative. -/ +def UniqueMDiffOn (s : Set M) := + ∀ x ∈ s, UniqueMDiffWithinAt I s x +#align unique_mdiff_on UniqueMDiffOn + +/-- `MDifferentiableWithinAt I I' f s x` indicates that the function `f` between manifolds +has a derivative at the point `x` within the set `s`. +This is a generalization of `DifferentiableWithinAt` to manifolds. + +We require continuity in the definition, as otherwise points close to `x` in `s` could be sent by +`f` outside of the chart domain around `f x`. Then the chart could do anything to the image points, +and in particular by coincidence `writtenInExtChartAt I I' x f` could be differentiable, while +this would not mean anything relevant. -/ +def MDifferentiableWithinAt (f : M → M') (s : Set M) (x : M) := + ContinuousWithinAt f s x ∧ + DifferentiableWithinAt 𝕜 (writtenInExtChartAt I I' x f) ((extChartAt I x).symm ⁻¹' s ∩ range I) + ((extChartAt I x) x) +#align mdifferentiable_within_at MDifferentiableWithinAt + +theorem mdifferentiableWithinAt_iff_liftPropWithinAt (f : M → M') (s : Set M) (x : M) : + MDifferentiableWithinAt I I' f s x ↔ LiftPropWithinAt (DifferentiableWithinAtProp I I') f s x := + by rfl +#align mdifferentiable_within_at_iff_lift_prop_within_at mdifferentiableWithinAt_iff_liftPropWithinAt + +/-- `MDifferentiableAt I I' f x` indicates that the function `f` between manifolds +has a derivative at the point `x`. +This is a generalization of `DifferentiableAt` to manifolds. + +We require continuity in the definition, as otherwise points close to `x` could be sent by +`f` outside of the chart domain around `f x`. Then the chart could do anything to the image points, +and in particular by coincidence `writtenInExtChartAt I I' x f` could be differentiable, while +this would not mean anything relevant. -/ +def MDifferentiableAt (f : M → M') (x : M) := + ContinuousAt f x ∧ + DifferentiableWithinAt 𝕜 (writtenInExtChartAt I I' x f) (range I) ((extChartAt I x) x) +#align mdifferentiable_at MDifferentiableAt + +theorem mdifferentiableAt_iff_liftPropAt (f : M → M') (x : M) : + MDifferentiableAt I I' f x ↔ LiftPropAt (DifferentiableWithinAtProp I I') f x := by + congrm ?_ ∧ ?_ + · rw [continuousWithinAt_univ] + · -- porting note: `rfl` wasn't needed + simp [DifferentiableWithinAtProp, Set.univ_inter]; rfl +#align mdifferentiable_at_iff_lift_prop_at mdifferentiableAt_iff_liftPropAt + +/-- `MDifferentiableOn I I' f s` indicates that the function `f` between manifolds +has a derivative within `s` at all points of `s`. +This is a generalization of `DifferentiableOn` to manifolds. -/ +def MDifferentiableOn (f : M → M') (s : Set M) := + ∀ x ∈ s, MDifferentiableWithinAt I I' f s x +#align mdifferentiable_on MDifferentiableOn + +/-- `MDifferentiable I I' f` indicates that the function `f` between manifolds +has a derivative everywhere. +This is a generalization of `Differentiable` to manifolds. -/ +def MDifferentiable (f : M → M') := + ∀ x, MDifferentiableAt I I' f x +#align mdifferentiable MDifferentiable + +/-- Prop registering if a partial homeomorphism is a local diffeomorphism on its source -/ +def PartialHomeomorph.MDifferentiable (f : PartialHomeomorph M M') := + MDifferentiableOn I I' f f.source ∧ MDifferentiableOn I' I f.symm f.target +#align local_homeomorph.mdifferentiable PartialHomeomorph.MDifferentiable + +variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] + +/-- `HasMFDerivWithinAt I I' f s x f'` indicates that the function `f` between manifolds +has, at the point `x` and within the set `s`, the derivative `f'`. Here, `f'` is a continuous linear +map from the tangent space at `x` to the tangent space at `f x`. + +This is a generalization of `HasFDerivWithinAt` to manifolds (as indicated by the prefix `m`). +The order of arguments is changed as the type of the derivative `f'` depends on the choice of `x`. + +We require continuity in the definition, as otherwise points close to `x` in `s` could be sent by +`f` outside of the chart domain around `f x`. Then the chart could do anything to the image points, +and in particular by coincidence `writtenInExtChartAt I I' x f` could be differentiable, while +this would not mean anything relevant. -/ +def HasMFDerivWithinAt (f : M → M') (s : Set M) (x : M) + (f' : TangentSpace I x →L[𝕜] TangentSpace I' (f x)) := + ContinuousWithinAt f s x ∧ + HasFDerivWithinAt (writtenInExtChartAt I I' x f : E → E') f' + ((extChartAt I x).symm ⁻¹' s ∩ range I) ((extChartAt I x) x) +#align has_mfderiv_within_at HasMFDerivWithinAt + +/-- `HasMFDerivAt I I' f x f'` indicates that the function `f` between manifolds +has, at the point `x`, the derivative `f'`. Here, `f'` is a continuous linear +map from the tangent space at `x` to the tangent space at `f x`. + +We require continuity in the definition, as otherwise points close to `x` `s` could be sent by +`f` outside of the chart domain around `f x`. Then the chart could do anything to the image points, +and in particular by coincidence `writtenInExtChartAt I I' x f` could be differentiable, while +this would not mean anything relevant. -/ +def HasMFDerivAt (f : M → M') (x : M) (f' : TangentSpace I x →L[𝕜] TangentSpace I' (f x)) := + ContinuousAt f x ∧ + HasFDerivWithinAt (writtenInExtChartAt I I' x f : E → E') f' (range I) ((extChartAt I x) x) +#align has_mfderiv_at HasMFDerivAt + +/-- Let `f` be a function between two smooth manifolds. Then `mfderivWithin I I' f s x` is the +derivative of `f` at `x` within `s`, as a continuous linear map from the tangent space at `x` to the +tangent space at `f x`. -/ +def mfderivWithin (f : M → M') (s : Set M) (x : M) : TangentSpace I x →L[𝕜] TangentSpace I' (f x) := + if MDifferentiableWithinAt I I' f s x then + (fderivWithin 𝕜 (writtenInExtChartAt I I' x f) ((extChartAt I x).symm ⁻¹' s ∩ range I) + ((extChartAt I x) x) : + _) + else 0 +#align mfderiv_within mfderivWithin + +/-- Let `f` be a function between two smooth manifolds. Then `mfderiv I I' f x` is the derivative of +`f` at `x`, as a continuous linear map from the tangent space at `x` to the tangent space at +`f x`. -/ +def mfderiv (f : M → M') (x : M) : TangentSpace I x →L[𝕜] TangentSpace I' (f x) := + if MDifferentiableAt I I' f x then + (fderivWithin 𝕜 (writtenInExtChartAt I I' x f : E → E') (range I) ((extChartAt I x) x) : _) + else 0 +#align mfderiv mfderiv + +/-- The derivative within a set, as a map between the tangent bundles -/ +def tangentMapWithin (f : M → M') (s : Set M) : TangentBundle I M → TangentBundle I' M' := fun p => + ⟨f p.1, (mfderivWithin I I' f s p.1 : TangentSpace I p.1 → TangentSpace I' (f p.1)) p.2⟩ +#align tangent_map_within tangentMapWithin + +/-- The derivative, as a map between the tangent bundles -/ +def tangentMap (f : M → M') : TangentBundle I M → TangentBundle I' M' := fun p => + ⟨f p.1, (mfderiv I I' f p.1 : TangentSpace I p.1 → TangentSpace I' (f p.1)) p.2⟩ +#align tangent_map tangentMap + +end DerivativesDefinitions diff --git a/Mathlib/Geometry/Manifold/MFDeriv/FDeriv.lean b/Mathlib/Geometry/Manifold/MFDeriv/FDeriv.lean new file mode 100644 index 0000000000000..cdffd5a529578 --- /dev/null +++ b/Mathlib/Geometry/Manifold/MFDeriv/FDeriv.lean @@ -0,0 +1,136 @@ +/- +Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sébastien Gouëzel, Floris van Doorn +-/ +import Mathlib.Geometry.Manifold.MFDeriv.Basic + +/-! +### Relations between vector space derivative and manifold derivative + +The manifold derivative `mfderiv`, when considered on the model vector space with its trivial +manifold structure, coincides with the usual Frechet derivative `fderiv`. In this section, we prove +this and related statements. +-/ + +noncomputable section + +open scoped Manifold + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] + [NormedSpace 𝕜 E] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {f : E → E'} + {s : Set E} {x : E} + +section MFDerivFderiv + +theorem uniqueMDiffWithinAt_iff_uniqueDiffWithinAt : + UniqueMDiffWithinAt 𝓘(𝕜, E) s x ↔ UniqueDiffWithinAt 𝕜 s x := by + simp only [UniqueMDiffWithinAt, mfld_simps] +#align unique_mdiff_within_at_iff_unique_diff_within_at uniqueMDiffWithinAt_iff_uniqueDiffWithinAt + +alias ⟨UniqueMDiffWithinAt.uniqueDiffWithinAt, UniqueDiffWithinAt.uniqueMDiffWithinAt⟩ := + uniqueMDiffWithinAt_iff_uniqueDiffWithinAt +#align unique_mdiff_within_at.unique_diff_within_at UniqueMDiffWithinAt.uniqueDiffWithinAt +#align unique_diff_within_at.unique_mdiff_within_at UniqueDiffWithinAt.uniqueMDiffWithinAt + +theorem uniqueMDiffOn_iff_uniqueDiffOn : UniqueMDiffOn 𝓘(𝕜, E) s ↔ UniqueDiffOn 𝕜 s := by + simp [UniqueMDiffOn, UniqueDiffOn, uniqueMDiffWithinAt_iff_uniqueDiffWithinAt] +#align unique_mdiff_on_iff_unique_diff_on uniqueMDiffOn_iff_uniqueDiffOn + +alias ⟨UniqueMDiffOn.uniqueDiffOn, UniqueDiffOn.uniqueMDiffOn⟩ := uniqueMDiffOn_iff_uniqueDiffOn +#align unique_mdiff_on.unique_diff_on UniqueMDiffOn.uniqueDiffOn +#align unique_diff_on.unique_mdiff_on UniqueDiffOn.uniqueMDiffOn + +-- porting note: was `@[simp, mfld_simps]` but `simp` can prove it +theorem writtenInExtChartAt_model_space : writtenInExtChartAt 𝓘(𝕜, E) 𝓘(𝕜, E') x f = f := + rfl +#align written_in_ext_chart_model_space writtenInExtChartAt_model_space + +theorem hasMFDerivWithinAt_iff_hasFDerivWithinAt {f'} : + HasMFDerivWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x f' ↔ HasFDerivWithinAt f f' s x := by + simpa only [HasMFDerivWithinAt, and_iff_right_iff_imp, mfld_simps] using + HasFDerivWithinAt.continuousWithinAt +#align has_mfderiv_within_at_iff_has_fderiv_within_at hasMFDerivWithinAt_iff_hasFDerivWithinAt + +alias ⟨HasMFDerivWithinAt.hasFDerivWithinAt, HasFDerivWithinAt.hasMFDerivWithinAt⟩ := + hasMFDerivWithinAt_iff_hasFDerivWithinAt +#align has_mfderiv_within_at.has_fderiv_within_at HasMFDerivWithinAt.hasFDerivWithinAt +#align has_fderiv_within_at.has_mfderiv_within_at HasFDerivWithinAt.hasMFDerivWithinAt + +theorem hasMFDerivAt_iff_hasFDerivAt {f'} : + HasMFDerivAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x f' ↔ HasFDerivAt f f' x := by + rw [← hasMFDerivWithinAt_univ, hasMFDerivWithinAt_iff_hasFDerivWithinAt, hasFDerivWithinAt_univ] +#align has_mfderiv_at_iff_has_fderiv_at hasMFDerivAt_iff_hasFDerivAt + +alias ⟨HasMFDerivAt.hasFDerivAt, HasFDerivAt.hasMFDerivAt⟩ := hasMFDerivAt_iff_hasFDerivAt +#align has_mfderiv_at.has_fderiv_at HasMFDerivAt.hasFDerivAt +#align has_fderiv_at.has_mfderiv_at HasFDerivAt.hasMFDerivAt + +/-- For maps between vector spaces, `MDifferentiableWithinAt` and `DifferentiableWithinAt` +coincide -/ +theorem mdifferentiableWithinAt_iff_differentiableWithinAt : + MDifferentiableWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x ↔ DifferentiableWithinAt 𝕜 f s x := by + simp only [MDifferentiableWithinAt, mfld_simps] + exact ⟨fun H => H.2, fun H => ⟨H.continuousWithinAt, H⟩⟩ +#align mdifferentiable_within_at_iff_differentiable_within_at mdifferentiableWithinAt_iff_differentiableWithinAt + +alias ⟨MDifferentiableWithinAt.differentiableWithinAt, + DifferentiableWithinAt.mdifferentiableWithinAt⟩ := + mdifferentiableWithinAt_iff_differentiableWithinAt +#align mdifferentiable_within_at.differentiable_within_at MDifferentiableWithinAt.differentiableWithinAt +#align differentiable_within_at.mdifferentiable_within_at DifferentiableWithinAt.mdifferentiableWithinAt + +/-- For maps between vector spaces, `MDifferentiableAt` and `DifferentiableAt` coincide -/ +theorem mdifferentiableAt_iff_differentiableAt : + MDifferentiableAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x ↔ DifferentiableAt 𝕜 f x := by + simp only [MDifferentiableAt, differentiableWithinAt_univ, mfld_simps] + exact ⟨fun H => H.2, fun H => ⟨H.continuousAt, H⟩⟩ +#align mdifferentiable_at_iff_differentiable_at mdifferentiableAt_iff_differentiableAt + +alias ⟨MDifferentiableAt.differentiableAt, DifferentiableAt.mdifferentiableAt⟩ := + mdifferentiableAt_iff_differentiableAt +#align mdifferentiable_at.differentiable_at MDifferentiableAt.differentiableAt +#align differentiable_at.mdifferentiable_at DifferentiableAt.mdifferentiableAt + +/-- For maps between vector spaces, `MDifferentiableOn` and `DifferentiableOn` coincide -/ +theorem mdifferentiableOn_iff_differentiableOn : + MDifferentiableOn 𝓘(𝕜, E) 𝓘(𝕜, E') f s ↔ DifferentiableOn 𝕜 f s := by + simp only [MDifferentiableOn, DifferentiableOn, + mdifferentiableWithinAt_iff_differentiableWithinAt] +#align mdifferentiable_on_iff_differentiable_on mdifferentiableOn_iff_differentiableOn + +alias ⟨MDifferentiableOn.differentiableOn, DifferentiableOn.mdifferentiableOn⟩ := + mdifferentiableOn_iff_differentiableOn +#align mdifferentiable_on.differentiable_on MDifferentiableOn.differentiableOn +#align differentiable_on.mdifferentiable_on DifferentiableOn.mdifferentiableOn + +/-- For maps between vector spaces, `MDifferentiable` and `Differentiable` coincide -/ +theorem mdifferentiable_iff_differentiable : + MDifferentiable 𝓘(𝕜, E) 𝓘(𝕜, E') f ↔ Differentiable 𝕜 f := by + simp only [MDifferentiable, Differentiable, mdifferentiableAt_iff_differentiableAt] +#align mdifferentiable_iff_differentiable mdifferentiable_iff_differentiable + +alias ⟨MDifferentiable.differentiable, Differentiable.mdifferentiable⟩ := + mdifferentiable_iff_differentiable +#align mdifferentiable.differentiable MDifferentiable.differentiable +#align differentiable.mdifferentiable Differentiable.mdifferentiable + +/-- For maps between vector spaces, `mfderivWithin` and `fderivWithin` coincide -/ +@[simp] +theorem mfderivWithin_eq_fderivWithin : + mfderivWithin 𝓘(𝕜, E) 𝓘(𝕜, E') f s x = fderivWithin 𝕜 f s x := by + by_cases h : MDifferentiableWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x + · simp only [mfderivWithin, h, if_pos, mfld_simps] + · simp only [mfderivWithin, h, if_neg, not_false_iff] + rw [mdifferentiableWithinAt_iff_differentiableWithinAt] at h + exact (fderivWithin_zero_of_not_differentiableWithinAt h).symm +#align mfderiv_within_eq_fderiv_within mfderivWithin_eq_fderivWithin + +/-- For maps between vector spaces, `mfderiv` and `fderiv` coincide -/ +@[simp] +theorem mfderiv_eq_fderiv : mfderiv 𝓘(𝕜, E) 𝓘(𝕜, E') f x = fderiv 𝕜 f x := by + rw [← mfderivWithin_univ, ← fderivWithin_univ] + exact mfderivWithin_eq_fderivWithin +#align mfderiv_eq_fderiv mfderiv_eq_fderiv + +end MFDerivFderiv diff --git a/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean b/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean new file mode 100644 index 0000000000000..f412c63e3942d --- /dev/null +++ b/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean @@ -0,0 +1,596 @@ +/- +Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sébastien Gouëzel, Floris van Doorn +-/ +import Mathlib.Geometry.Manifold.MFDeriv.FDeriv + +/-! +# Differentiability of specific functions + +In this file, we establish differentiability results for +- continuous linear maps and continuous linear equivalences +- the identity +- constant functions +- products +- arithmetic operations (such as addition and scalar multiplication). + +-/ + +noncomputable section + +open scoped Manifold +open Bundle Set Topology + +section SpecificFunctions + +/-! ### Differentiability of specific functions -/ + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] + [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M : Type*} + [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] {E' : Type*} + [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] + (I' : ModelWithCorners 𝕜 E' H') {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] + [SmoothManifoldWithCorners I' M'] {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] + {H'' : Type*} [TopologicalSpace H''] (I'' : ModelWithCorners 𝕜 E'' H'') {M'' : Type*} + [TopologicalSpace M''] [ChartedSpace H'' M''] [SmoothManifoldWithCorners I'' M''] + +namespace ContinuousLinearMap + +variable (f : E →L[𝕜] E') {s : Set E} {x : E} + +protected theorem hasMFDerivWithinAt : HasMFDerivWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x f := + f.hasFDerivWithinAt.hasMFDerivWithinAt +#align continuous_linear_map.has_mfderiv_within_at ContinuousLinearMap.hasMFDerivWithinAt + +protected theorem hasMFDerivAt : HasMFDerivAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x f := + f.hasFDerivAt.hasMFDerivAt +#align continuous_linear_map.has_mfderiv_at ContinuousLinearMap.hasMFDerivAt + +protected theorem mdifferentiableWithinAt : MDifferentiableWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x := + f.differentiableWithinAt.mdifferentiableWithinAt +#align continuous_linear_map.mdifferentiable_within_at ContinuousLinearMap.mdifferentiableWithinAt + +protected theorem mdifferentiableOn : MDifferentiableOn 𝓘(𝕜, E) 𝓘(𝕜, E') f s := + f.differentiableOn.mdifferentiableOn +#align continuous_linear_map.mdifferentiable_on ContinuousLinearMap.mdifferentiableOn + +protected theorem mdifferentiableAt : MDifferentiableAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x := + f.differentiableAt.mdifferentiableAt +#align continuous_linear_map.mdifferentiable_at ContinuousLinearMap.mdifferentiableAt + +protected theorem mdifferentiable : MDifferentiable 𝓘(𝕜, E) 𝓘(𝕜, E') f := + f.differentiable.mdifferentiable +#align continuous_linear_map.mdifferentiable ContinuousLinearMap.mdifferentiable + +theorem mfderiv_eq : mfderiv 𝓘(𝕜, E) 𝓘(𝕜, E') f x = f := + f.hasMFDerivAt.mfderiv +#align continuous_linear_map.mfderiv_eq ContinuousLinearMap.mfderiv_eq + +theorem mfderivWithin_eq (hs : UniqueMDiffWithinAt 𝓘(𝕜, E) s x) : + mfderivWithin 𝓘(𝕜, E) 𝓘(𝕜, E') f s x = f := + f.hasMFDerivWithinAt.mfderivWithin hs +#align continuous_linear_map.mfderiv_within_eq ContinuousLinearMap.mfderivWithin_eq + +end ContinuousLinearMap + +namespace ContinuousLinearEquiv + +variable (f : E ≃L[𝕜] E') {s : Set E} {x : E} + +protected theorem hasMFDerivWithinAt : HasMFDerivWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x (f : E →L[𝕜] E') := + f.hasFDerivWithinAt.hasMFDerivWithinAt +#align continuous_linear_equiv.has_mfderiv_within_at ContinuousLinearEquiv.hasMFDerivWithinAt + +protected theorem hasMFDerivAt : HasMFDerivAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x (f : E →L[𝕜] E') := + f.hasFDerivAt.hasMFDerivAt +#align continuous_linear_equiv.has_mfderiv_at ContinuousLinearEquiv.hasMFDerivAt + +protected theorem mdifferentiableWithinAt : MDifferentiableWithinAt 𝓘(𝕜, E) 𝓘(𝕜, E') f s x := + f.differentiableWithinAt.mdifferentiableWithinAt +#align continuous_linear_equiv.mdifferentiable_within_at ContinuousLinearEquiv.mdifferentiableWithinAt + +protected theorem mdifferentiableOn : MDifferentiableOn 𝓘(𝕜, E) 𝓘(𝕜, E') f s := + f.differentiableOn.mdifferentiableOn +#align continuous_linear_equiv.mdifferentiable_on ContinuousLinearEquiv.mdifferentiableOn + +protected theorem mdifferentiableAt : MDifferentiableAt 𝓘(𝕜, E) 𝓘(𝕜, E') f x := + f.differentiableAt.mdifferentiableAt +#align continuous_linear_equiv.mdifferentiable_at ContinuousLinearEquiv.mdifferentiableAt + +protected theorem mdifferentiable : MDifferentiable 𝓘(𝕜, E) 𝓘(𝕜, E') f := + f.differentiable.mdifferentiable +#align continuous_linear_equiv.mdifferentiable ContinuousLinearEquiv.mdifferentiable + +theorem mfderiv_eq : mfderiv 𝓘(𝕜, E) 𝓘(𝕜, E') f x = (f : E →L[𝕜] E') := + f.hasMFDerivAt.mfderiv +#align continuous_linear_equiv.mfderiv_eq ContinuousLinearEquiv.mfderiv_eq + +theorem mfderivWithin_eq (hs : UniqueMDiffWithinAt 𝓘(𝕜, E) s x) : + mfderivWithin 𝓘(𝕜, E) 𝓘(𝕜, E') f s x = (f : E →L[𝕜] E') := + f.hasMFDerivWithinAt.mfderivWithin hs +#align continuous_linear_equiv.mfderiv_within_eq ContinuousLinearEquiv.mfderivWithin_eq + +end ContinuousLinearEquiv + +variable {s : Set M} {x : M} + +section id + +/-! #### Identity -/ + +theorem hasMFDerivAt_id (x : M) : + HasMFDerivAt I I (@id M) x (ContinuousLinearMap.id 𝕜 (TangentSpace I x)) := by + refine' ⟨continuousAt_id, _⟩ + have : ∀ᶠ y in 𝓝[range I] (extChartAt I x) x, (extChartAt I x ∘ (extChartAt I x).symm) y = y + · apply Filter.mem_of_superset (extChartAt_target_mem_nhdsWithin I x) + mfld_set_tac + apply HasFDerivWithinAt.congr_of_eventuallyEq (hasFDerivWithinAt_id _ _) this + simp only [mfld_simps] +#align has_mfderiv_at_id hasMFDerivAt_id + +theorem hasMFDerivWithinAt_id (s : Set M) (x : M) : + HasMFDerivWithinAt I I (@id M) s x (ContinuousLinearMap.id 𝕜 (TangentSpace I x)) := + (hasMFDerivAt_id I x).hasMFDerivWithinAt +#align has_mfderiv_within_at_id hasMFDerivWithinAt_id + +theorem mdifferentiableAt_id : MDifferentiableAt I I (@id M) x := + (hasMFDerivAt_id I x).mdifferentiableAt +#align mdifferentiable_at_id mdifferentiableAt_id + +theorem mdifferentiableWithinAt_id : MDifferentiableWithinAt I I (@id M) s x := + (mdifferentiableAt_id I).mdifferentiableWithinAt +#align mdifferentiable_within_at_id mdifferentiableWithinAt_id + +theorem mdifferentiable_id : MDifferentiable I I (@id M) := fun _ => mdifferentiableAt_id I +#align mdifferentiable_id mdifferentiable_id + +theorem mdifferentiableOn_id : MDifferentiableOn I I (@id M) s := + (mdifferentiable_id I).mdifferentiableOn +#align mdifferentiable_on_id mdifferentiableOn_id + +@[simp, mfld_simps] +theorem mfderiv_id : mfderiv I I (@id M) x = ContinuousLinearMap.id 𝕜 (TangentSpace I x) := + HasMFDerivAt.mfderiv (hasMFDerivAt_id I x) +#align mfderiv_id mfderiv_id + +theorem mfderivWithin_id (hxs : UniqueMDiffWithinAt I s x) : + mfderivWithin I I (@id M) s x = ContinuousLinearMap.id 𝕜 (TangentSpace I x) := by + rw [MDifferentiable.mfderivWithin (mdifferentiableAt_id I) hxs] + exact mfderiv_id I +#align mfderiv_within_id mfderivWithin_id + +@[simp, mfld_simps] +theorem tangentMap_id : tangentMap I I (id : M → M) = id := by ext1 ⟨x, v⟩; simp [tangentMap] +#align tangent_map_id tangentMap_id + +theorem tangentMapWithin_id {p : TangentBundle I M} (hs : UniqueMDiffWithinAt I s p.proj) : + tangentMapWithin I I (id : M → M) s p = p := by + simp only [tangentMapWithin, id.def] + rw [mfderivWithin_id] + · rcases p with ⟨⟩; rfl + · exact hs +#align tangent_map_within_id tangentMapWithin_id + +end id + +section Const + +/-! #### Constants -/ + + +variable {c : M'} + +theorem hasMFDerivAt_const (c : M') (x : M) : + HasMFDerivAt I I' (fun _ : M => c) x (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := by + refine' ⟨continuous_const.continuousAt, _⟩ + simp only [writtenInExtChartAt, (· ∘ ·), hasFDerivWithinAt_const] +#align has_mfderiv_at_const hasMFDerivAt_const + +theorem hasMFDerivWithinAt_const (c : M') (s : Set M) (x : M) : + HasMFDerivWithinAt I I' (fun _ : M => c) s x (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := + (hasMFDerivAt_const I I' c x).hasMFDerivWithinAt +#align has_mfderiv_within_at_const hasMFDerivWithinAt_const + +theorem mdifferentiableAt_const : MDifferentiableAt I I' (fun _ : M => c) x := + (hasMFDerivAt_const I I' c x).mdifferentiableAt +#align mdifferentiable_at_const mdifferentiableAt_const + +theorem mdifferentiableWithinAt_const : MDifferentiableWithinAt I I' (fun _ : M => c) s x := + (mdifferentiableAt_const I I').mdifferentiableWithinAt +#align mdifferentiable_within_at_const mdifferentiableWithinAt_const + +theorem mdifferentiable_const : MDifferentiable I I' fun _ : M => c := fun _ => + mdifferentiableAt_const I I' +#align mdifferentiable_const mdifferentiable_const + +theorem mdifferentiableOn_const : MDifferentiableOn I I' (fun _ : M => c) s := + (mdifferentiable_const I I').mdifferentiableOn +#align mdifferentiable_on_const mdifferentiableOn_const + +@[simp, mfld_simps] +theorem mfderiv_const : + mfderiv I I' (fun _ : M => c) x = (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := + HasMFDerivAt.mfderiv (hasMFDerivAt_const I I' c x) +#align mfderiv_const mfderiv_const + +theorem mfderivWithin_const (hxs : UniqueMDiffWithinAt I s x) : + mfderivWithin I I' (fun _ : M => c) s x = (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := + (hasMFDerivWithinAt_const _ _ _ _ _).mfderivWithin hxs +#align mfderiv_within_const mfderivWithin_const + +end Const + +section Prod + +/-! ### Operations on the product of two manifolds -/ + +theorem hasMFDerivAt_fst (x : M × M') : + HasMFDerivAt (I.prod I') I Prod.fst x + (ContinuousLinearMap.fst 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2)) := by + refine' ⟨continuous_fst.continuousAt, _⟩ + have : + ∀ᶠ y in 𝓝[range (I.prod I')] extChartAt (I.prod I') x x, + (extChartAt I x.1 ∘ Prod.fst ∘ (extChartAt (I.prod I') x).symm) y = y.1 := by + /- porting note: was + apply Filter.mem_of_superset (extChartAt_target_mem_nhdsWithin (I.prod I') x) + mfld_set_tac + -/ + filter_upwards [extChartAt_target_mem_nhdsWithin (I.prod I') x] with y hy + rw [extChartAt_prod] at hy + exact (extChartAt I x.1).right_inv hy.1 + apply HasFDerivWithinAt.congr_of_eventuallyEq hasFDerivWithinAt_fst this + -- porting note: next line was `simp only [mfld_simps]` + exact (extChartAt I x.1).right_inv <| (extChartAt I x.1).map_source (mem_extChartAt_source _ _) +#align has_mfderiv_at_fst hasMFDerivAt_fst + +theorem hasMFDerivWithinAt_fst (s : Set (M × M')) (x : M × M') : + HasMFDerivWithinAt (I.prod I') I Prod.fst s x + (ContinuousLinearMap.fst 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2)) := + (hasMFDerivAt_fst I I' x).hasMFDerivWithinAt +#align has_mfderiv_within_at_fst hasMFDerivWithinAt_fst + +theorem mdifferentiableAt_fst {x : M × M'} : MDifferentiableAt (I.prod I') I Prod.fst x := + (hasMFDerivAt_fst I I' x).mdifferentiableAt +#align mdifferentiable_at_fst mdifferentiableAt_fst + +theorem mdifferentiableWithinAt_fst {s : Set (M × M')} {x : M × M'} : + MDifferentiableWithinAt (I.prod I') I Prod.fst s x := + (mdifferentiableAt_fst I I').mdifferentiableWithinAt +#align mdifferentiable_within_at_fst mdifferentiableWithinAt_fst + +theorem mdifferentiable_fst : MDifferentiable (I.prod I') I (Prod.fst : M × M' → M) := fun _ => + mdifferentiableAt_fst I I' +#align mdifferentiable_fst mdifferentiable_fst + +theorem mdifferentiableOn_fst {s : Set (M × M')} : MDifferentiableOn (I.prod I') I Prod.fst s := + (mdifferentiable_fst I I').mdifferentiableOn +#align mdifferentiable_on_fst mdifferentiableOn_fst + +@[simp, mfld_simps] +theorem mfderiv_fst {x : M × M'} : + mfderiv (I.prod I') I Prod.fst x = + ContinuousLinearMap.fst 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2) := + (hasMFDerivAt_fst I I' x).mfderiv +#align mfderiv_fst mfderiv_fst + +theorem mfderivWithin_fst {s : Set (M × M')} {x : M × M'} + (hxs : UniqueMDiffWithinAt (I.prod I') s x) : + mfderivWithin (I.prod I') I Prod.fst s x = + ContinuousLinearMap.fst 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2) := + by rw [MDifferentiable.mfderivWithin (mdifferentiableAt_fst I I') hxs]; exact mfderiv_fst I I' +#align mfderiv_within_fst mfderivWithin_fst + +@[simp, mfld_simps] +theorem tangentMap_prod_fst {p : TangentBundle (I.prod I') (M × M')} : + tangentMap (I.prod I') I Prod.fst p = ⟨p.proj.1, p.2.1⟩ := by + -- porting note: `rfl` wasn't needed + simp [tangentMap]; rfl +#align tangent_map_prod_fst tangentMap_prod_fst + +theorem tangentMapWithin_prod_fst {s : Set (M × M')} {p : TangentBundle (I.prod I') (M × M')} + (hs : UniqueMDiffWithinAt (I.prod I') s p.proj) : + tangentMapWithin (I.prod I') I Prod.fst s p = ⟨p.proj.1, p.2.1⟩ := by + simp only [tangentMapWithin] + rw [mfderivWithin_fst] + · rcases p with ⟨⟩; rfl + · exact hs +#align tangent_map_within_prod_fst tangentMapWithin_prod_fst + +theorem hasMFDerivAt_snd (x : M × M') : + HasMFDerivAt (I.prod I') I' Prod.snd x + (ContinuousLinearMap.snd 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2)) := by + refine' ⟨continuous_snd.continuousAt, _⟩ + have : + ∀ᶠ y in 𝓝[range (I.prod I')] extChartAt (I.prod I') x x, + (extChartAt I' x.2 ∘ Prod.snd ∘ (extChartAt (I.prod I') x).symm) y = y.2 := by + /- porting note: was + apply Filter.mem_of_superset (extChartAt_target_mem_nhdsWithin (I.prod I') x) + mfld_set_tac + -/ + filter_upwards [extChartAt_target_mem_nhdsWithin (I.prod I') x] with y hy + rw [extChartAt_prod] at hy + exact (extChartAt I' x.2).right_inv hy.2 + apply HasFDerivWithinAt.congr_of_eventuallyEq hasFDerivWithinAt_snd this + -- porting note: the next line was `simp only [mfld_simps]` + exact (extChartAt I' x.2).right_inv <| (extChartAt I' x.2).map_source (mem_extChartAt_source _ _) +#align has_mfderiv_at_snd hasMFDerivAt_snd + +theorem hasMFDerivWithinAt_snd (s : Set (M × M')) (x : M × M') : + HasMFDerivWithinAt (I.prod I') I' Prod.snd s x + (ContinuousLinearMap.snd 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2)) := + (hasMFDerivAt_snd I I' x).hasMFDerivWithinAt +#align has_mfderiv_within_at_snd hasMFDerivWithinAt_snd + +theorem mdifferentiableAt_snd {x : M × M'} : MDifferentiableAt (I.prod I') I' Prod.snd x := + (hasMFDerivAt_snd I I' x).mdifferentiableAt +#align mdifferentiable_at_snd mdifferentiableAt_snd + +theorem mdifferentiableWithinAt_snd {s : Set (M × M')} {x : M × M'} : + MDifferentiableWithinAt (I.prod I') I' Prod.snd s x := + (mdifferentiableAt_snd I I').mdifferentiableWithinAt +#align mdifferentiable_within_at_snd mdifferentiableWithinAt_snd + +theorem mdifferentiable_snd : MDifferentiable (I.prod I') I' (Prod.snd : M × M' → M') := fun _ => + mdifferentiableAt_snd I I' +#align mdifferentiable_snd mdifferentiable_snd + +theorem mdifferentiableOn_snd {s : Set (M × M')} : MDifferentiableOn (I.prod I') I' Prod.snd s := + (mdifferentiable_snd I I').mdifferentiableOn +#align mdifferentiable_on_snd mdifferentiableOn_snd + +@[simp, mfld_simps] +theorem mfderiv_snd {x : M × M'} : + mfderiv (I.prod I') I' Prod.snd x = + ContinuousLinearMap.snd 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2) := + (hasMFDerivAt_snd I I' x).mfderiv +#align mfderiv_snd mfderiv_snd + +theorem mfderivWithin_snd {s : Set (M × M')} {x : M × M'} + (hxs : UniqueMDiffWithinAt (I.prod I') s x) : + mfderivWithin (I.prod I') I' Prod.snd s x = + ContinuousLinearMap.snd 𝕜 (TangentSpace I x.1) (TangentSpace I' x.2) := + by rw [MDifferentiable.mfderivWithin (mdifferentiableAt_snd I I') hxs]; exact mfderiv_snd I I' +#align mfderiv_within_snd mfderivWithin_snd + +@[simp, mfld_simps] +theorem tangentMap_prod_snd {p : TangentBundle (I.prod I') (M × M')} : + tangentMap (I.prod I') I' Prod.snd p = ⟨p.proj.2, p.2.2⟩ := by + -- porting note: `rfl` wasn't needed + simp [tangentMap]; rfl +#align tangent_map_prod_snd tangentMap_prod_snd + +theorem tangentMapWithin_prod_snd {s : Set (M × M')} {p : TangentBundle (I.prod I') (M × M')} + (hs : UniqueMDiffWithinAt (I.prod I') s p.proj) : + tangentMapWithin (I.prod I') I' Prod.snd s p = ⟨p.proj.2, p.2.2⟩ := by + simp only [tangentMapWithin] + rw [mfderivWithin_snd] + · rcases p with ⟨⟩; rfl + · exact hs +#align tangent_map_within_prod_snd tangentMapWithin_prod_snd + +variable {I I' I''} + +theorem MDifferentiableAt.mfderiv_prod {f : M → M'} {g : M → M''} {x : M} + (hf : MDifferentiableAt I I' f x) (hg : MDifferentiableAt I I'' g x) : + mfderiv I (I'.prod I'') (fun x => (f x, g x)) x = + (mfderiv I I' f x).prod (mfderiv I I'' g x) := by + classical + simp_rw [mfderiv, if_pos (hf.prod_mk hg), if_pos hf, if_pos hg] + exact hf.2.fderivWithin_prod hg.2 (I.unique_diff _ (mem_range_self _)) +#align mdifferentiable_at.mfderiv_prod MDifferentiableAt.mfderiv_prod + +variable (I I' I'') + +theorem mfderiv_prod_left {x₀ : M} {y₀ : M'} : + mfderiv I (I.prod I') (fun x => (x, y₀)) x₀ = + ContinuousLinearMap.inl 𝕜 (TangentSpace I x₀) (TangentSpace I' y₀) := by + refine' ((mdifferentiableAt_id I).mfderiv_prod (mdifferentiableAt_const I I')).trans _ + rw [mfderiv_id, mfderiv_const, ContinuousLinearMap.inl] +#align mfderiv_prod_left mfderiv_prod_left + +theorem mfderiv_prod_right {x₀ : M} {y₀ : M'} : + mfderiv I' (I.prod I') (fun y => (x₀, y)) y₀ = + ContinuousLinearMap.inr 𝕜 (TangentSpace I x₀) (TangentSpace I' y₀) := by + refine' ((mdifferentiableAt_const I' I).mfderiv_prod (mdifferentiableAt_id I')).trans _ + rw [mfderiv_id, mfderiv_const, ContinuousLinearMap.inr] +#align mfderiv_prod_right mfderiv_prod_right + +/-- The total derivative of a function in two variables is the sum of the partial derivatives. + Note that to state this (without casts) we need to be able to see through the definition of + `TangentSpace`. -/ +theorem mfderiv_prod_eq_add {f : M × M' → M''} {p : M × M'} + (hf : MDifferentiableAt (I.prod I') I'' f p) : + mfderiv (I.prod I') I'' f p = + show E × E' →L[𝕜] E'' from + mfderiv (I.prod I') I'' (fun z : M × M' => f (z.1, p.2)) p + + mfderiv (I.prod I') I'' (fun z : M × M' => f (p.1, z.2)) p := by + dsimp only + erw [mfderiv_comp_of_eq hf ((mdifferentiableAt_fst I I').prod_mk (mdifferentiableAt_const _ _)) + rfl, + mfderiv_comp_of_eq hf ((mdifferentiableAt_const _ _).prod_mk (mdifferentiableAt_snd I I')) rfl, + ← ContinuousLinearMap.comp_add, + (mdifferentiableAt_fst I I').mfderiv_prod (mdifferentiableAt_const (I.prod I') I'), + (mdifferentiableAt_const (I.prod I') I).mfderiv_prod (mdifferentiableAt_snd I I'), mfderiv_fst, + mfderiv_snd, mfderiv_const, mfderiv_const] + symm + convert ContinuousLinearMap.comp_id <| mfderiv (.prod I I') I'' f (p.1, p.2) + · exact ContinuousLinearMap.coprod_inl_inr +#align mfderiv_prod_eq_add mfderiv_prod_eq_add + +end Prod + +section Arithmetic + +/-! #### Arithmetic + +Note that in the `HasMFDerivAt` lemmas there is an abuse of the defeq between `E'` and +`TangentSpace 𝓘(𝕜, E') (f z)` (similarly for `g',F',p',q'`). In general this defeq is not +canonical, but in this case (the tangent space of a vector space) it is canonical. + -/ + +section Group + +variable {I} {z : M} {f g : M → E'} {f' g' : TangentSpace I z →L[𝕜] E'} + +theorem HasMFDerivAt.add (hf : HasMFDerivAt I 𝓘(𝕜, E') f z f') + (hg : HasMFDerivAt I 𝓘(𝕜, E') g z g') : HasMFDerivAt I 𝓘(𝕜, E') (f + g) z (f' + g') := + ⟨hf.1.add hg.1, hf.2.add hg.2⟩ +#align has_mfderiv_at.add HasMFDerivAt.add + +theorem MDifferentiableAt.add (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) + (hg : MDifferentiableAt I 𝓘(𝕜, E') g z) : MDifferentiableAt I 𝓘(𝕜, E') (f + g) z := + (hf.hasMFDerivAt.add hg.hasMFDerivAt).mdifferentiableAt +#align mdifferentiable_at.add MDifferentiableAt.add + +theorem MDifferentiable.add (hf : MDifferentiable I 𝓘(𝕜, E') f) + (hg : MDifferentiable I 𝓘(𝕜, E') g) : MDifferentiable I 𝓘(𝕜, E') (f + g) := fun x => + (hf x).add (hg x) +#align mdifferentiable.add MDifferentiable.add + +-- porting note: forcing types using `by exact` +theorem mfderiv_add (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) + (hg : MDifferentiableAt I 𝓘(𝕜, E') g z) : + (by exact mfderiv I 𝓘(𝕜, E') (f + g) z : TangentSpace I z →L[𝕜] E') = + (by exact mfderiv I 𝓘(𝕜, E') f z) + (by exact mfderiv I 𝓘(𝕜, E') g z) := + (hf.hasMFDerivAt.add hg.hasMFDerivAt).mfderiv +#align mfderiv_add mfderiv_add + +theorem HasMFDerivAt.const_smul (hf : HasMFDerivAt I 𝓘(𝕜, E') f z f') (s : 𝕜) : + HasMFDerivAt I 𝓘(𝕜, E') (s • f) z (s • f') := + ⟨hf.1.const_smul s, hf.2.const_smul s⟩ +#align has_mfderiv_at.const_smul HasMFDerivAt.const_smul + +theorem MDifferentiableAt.const_smul (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) (s : 𝕜) : + MDifferentiableAt I 𝓘(𝕜, E') (s • f) z := + (hf.hasMFDerivAt.const_smul s).mdifferentiableAt +#align mdifferentiable_at.const_smul MDifferentiableAt.const_smul + +theorem MDifferentiable.const_smul (s : 𝕜) (hf : MDifferentiable I 𝓘(𝕜, E') f) : + MDifferentiable I 𝓘(𝕜, E') (s • f) := fun x => (hf x).const_smul s +#align mdifferentiable.const_smul MDifferentiable.const_smul + +theorem const_smul_mfderiv (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) (s : 𝕜) : + (mfderiv I 𝓘(𝕜, E') (s • f) z : TangentSpace I z →L[𝕜] E') = + (s • mfderiv I 𝓘(𝕜, E') f z : TangentSpace I z →L[𝕜] E') := + (hf.hasMFDerivAt.const_smul s).mfderiv +#align const_smul_mfderiv const_smul_mfderiv + +theorem HasMFDerivAt.neg (hf : HasMFDerivAt I 𝓘(𝕜, E') f z f') : + HasMFDerivAt I 𝓘(𝕜, E') (-f) z (-f') := + ⟨hf.1.neg, hf.2.neg⟩ +#align has_mfderiv_at.neg HasMFDerivAt.neg + +theorem hasMFDerivAt_neg : HasMFDerivAt I 𝓘(𝕜, E') (-f) z (-f') ↔ HasMFDerivAt I 𝓘(𝕜, E') f z f' := + ⟨fun hf => by convert hf.neg <;> rw [neg_neg], fun hf => hf.neg⟩ +#align has_mfderiv_at_neg hasMFDerivAt_neg + +theorem MDifferentiableAt.neg (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) : + MDifferentiableAt I 𝓘(𝕜, E') (-f) z := + hf.hasMFDerivAt.neg.mdifferentiableAt +#align mdifferentiable_at.neg MDifferentiableAt.neg + +theorem mdifferentiableAt_neg : + MDifferentiableAt I 𝓘(𝕜, E') (-f) z ↔ MDifferentiableAt I 𝓘(𝕜, E') f z := + ⟨fun hf => by convert hf.neg; rw [neg_neg], fun hf => hf.neg⟩ +#align mdifferentiable_at_neg mdifferentiableAt_neg + +theorem MDifferentiable.neg (hf : MDifferentiable I 𝓘(𝕜, E') f) : MDifferentiable I 𝓘(𝕜, E') (-f) := + fun x => (hf x).neg +#align mdifferentiable.neg MDifferentiable.neg + +theorem mfderiv_neg (f : M → E') (x : M) : + (mfderiv I 𝓘(𝕜, E') (-f) x : TangentSpace I x →L[𝕜] E') = + (-mfderiv I 𝓘(𝕜, E') f x : TangentSpace I x →L[𝕜] E') := by + simp_rw [mfderiv] + by_cases hf : MDifferentiableAt I 𝓘(𝕜, E') f x + · exact hf.hasMFDerivAt.neg.mfderiv + · rw [if_neg hf]; rw [← mdifferentiableAt_neg] at hf; rw [if_neg hf, neg_zero] +#align mfderiv_neg mfderiv_neg + +theorem HasMFDerivAt.sub (hf : HasMFDerivAt I 𝓘(𝕜, E') f z f') + (hg : HasMFDerivAt I 𝓘(𝕜, E') g z g') : HasMFDerivAt I 𝓘(𝕜, E') (f - g) z (f' - g') := + ⟨hf.1.sub hg.1, hf.2.sub hg.2⟩ +#align has_mfderiv_at.sub HasMFDerivAt.sub + +theorem MDifferentiableAt.sub (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) + (hg : MDifferentiableAt I 𝓘(𝕜, E') g z) : MDifferentiableAt I 𝓘(𝕜, E') (f - g) z := + (hf.hasMFDerivAt.sub hg.hasMFDerivAt).mdifferentiableAt +#align mdifferentiable_at.sub MDifferentiableAt.sub + +theorem MDifferentiable.sub (hf : MDifferentiable I 𝓘(𝕜, E') f) + (hg : MDifferentiable I 𝓘(𝕜, E') g) : MDifferentiable I 𝓘(𝕜, E') (f - g) := fun x => + (hf x).sub (hg x) +#align mdifferentiable.sub MDifferentiable.sub + +theorem mfderiv_sub (hf : MDifferentiableAt I 𝓘(𝕜, E') f z) + (hg : MDifferentiableAt I 𝓘(𝕜, E') g z) : + (by exact mfderiv I 𝓘(𝕜, E') (f - g) z : TangentSpace I z →L[𝕜] E') = + (by exact mfderiv I 𝓘(𝕜, E') f z) - (by exact mfderiv I 𝓘(𝕜, E') g z) := + (hf.hasMFDerivAt.sub hg.hasMFDerivAt).mfderiv +#align mfderiv_sub mfderiv_sub + +end Group + +section AlgebraOverRing + +variable {I} {z : M} {F' : Type*} [NormedRing F'] [NormedAlgebra 𝕜 F'] {p q : M → F'} + {p' q' : TangentSpace I z →L[𝕜] F'} + +theorem HasMFDerivWithinAt.mul' (hp : HasMFDerivWithinAt I 𝓘(𝕜, F') p s z p') + (hq : HasMFDerivWithinAt I 𝓘(𝕜, F') q s z q') : + HasMFDerivWithinAt I 𝓘(𝕜, F') (p * q) s z (p z • q' + p'.smulRight (q z) : E →L[𝕜] F') := + ⟨hp.1.mul hq.1, by simpa only [mfld_simps] using hp.2.mul' hq.2⟩ +#align has_mfderiv_within_at.mul' HasMFDerivWithinAt.mul' + +theorem HasMFDerivAt.mul' (hp : HasMFDerivAt I 𝓘(𝕜, F') p z p') + (hq : HasMFDerivAt I 𝓘(𝕜, F') q z q') : + HasMFDerivAt I 𝓘(𝕜, F') (p * q) z (p z • q' + p'.smulRight (q z) : E →L[𝕜] F') := + hasMFDerivWithinAt_univ.mp <| hp.hasMFDerivWithinAt.mul' hq.hasMFDerivWithinAt +#align has_mfderiv_at.mul' HasMFDerivAt.mul' + +theorem MDifferentiableWithinAt.mul (hp : MDifferentiableWithinAt I 𝓘(𝕜, F') p s z) + (hq : MDifferentiableWithinAt I 𝓘(𝕜, F') q s z) : + MDifferentiableWithinAt I 𝓘(𝕜, F') (p * q) s z := + (hp.hasMFDerivWithinAt.mul' hq.hasMFDerivWithinAt).mdifferentiableWithinAt +#align mdifferentiable_within_at.mul MDifferentiableWithinAt.mul + +theorem MDifferentiableAt.mul (hp : MDifferentiableAt I 𝓘(𝕜, F') p z) + (hq : MDifferentiableAt I 𝓘(𝕜, F') q z) : MDifferentiableAt I 𝓘(𝕜, F') (p * q) z := + (hp.hasMFDerivAt.mul' hq.hasMFDerivAt).mdifferentiableAt +#align mdifferentiable_at.mul MDifferentiableAt.mul + +theorem MDifferentiableOn.mul (hp : MDifferentiableOn I 𝓘(𝕜, F') p s) + (hq : MDifferentiableOn I 𝓘(𝕜, F') q s) : MDifferentiableOn I 𝓘(𝕜, F') (p * q) s := fun x hx => + (hp x hx).mul <| hq x hx +#align mdifferentiable_on.mul MDifferentiableOn.mul + +theorem MDifferentiable.mul (hp : MDifferentiable I 𝓘(𝕜, F') p) + (hq : MDifferentiable I 𝓘(𝕜, F') q) : MDifferentiable I 𝓘(𝕜, F') (p * q) := fun x => + (hp x).mul (hq x) +#align mdifferentiable.mul MDifferentiable.mul + +end AlgebraOverRing + +section AlgebraOverCommRing + +variable {I} {z : M} {F' : Type*} [NormedCommRing F'] [NormedAlgebra 𝕜 F'] {p q : M → F'} + {p' q' : TangentSpace I z →L[𝕜] F'} + +theorem HasMFDerivWithinAt.mul (hp : HasMFDerivWithinAt I 𝓘(𝕜, F') p s z p') + (hq : HasMFDerivWithinAt I 𝓘(𝕜, F') q s z q') : + HasMFDerivWithinAt I 𝓘(𝕜, F') (p * q) s z (p z • q' + q z • p' : E →L[𝕜] F') := by + convert hp.mul' hq; ext _; apply mul_comm +#align has_mfderiv_within_at.mul HasMFDerivWithinAt.mul + +theorem HasMFDerivAt.mul (hp : HasMFDerivAt I 𝓘(𝕜, F') p z p') + (hq : HasMFDerivAt I 𝓘(𝕜, F') q z q') : + HasMFDerivAt I 𝓘(𝕜, F') (p * q) z (p z • q' + q z • p' : E →L[𝕜] F') := + hasMFDerivWithinAt_univ.mp <| hp.hasMFDerivWithinAt.mul hq.hasMFDerivWithinAt +#align has_mfderiv_at.mul HasMFDerivAt.mul + +end AlgebraOverCommRing + +end Arithmetic + +end SpecificFunctions diff --git a/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean b/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean new file mode 100644 index 0000000000000..b4aa88e4bd16b --- /dev/null +++ b/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean @@ -0,0 +1,153 @@ +/- +Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sébastien Gouëzel, Floris van Doorn +-/ +import Mathlib.Geometry.Manifold.MFDeriv.Atlas + +/-! +# Unique derivative sets in manifolds + +In this file, we prove various properties of unique derivative sets in manifolds. +* `image_denseRange`: suppose `f` is differentiable on `s` and its derivative at every point of `s` +has dense range. If `s` has the unique differential property, then so does `f '' s`. +* `uniqueMDiffOn_preimage`: the unique differential property is preserved by local diffeomorphisms +* `uniqueDiffOn_target_inter`: the unique differential property is preserved by + pullbacks of extended charts +* `tangentBundle_proj_preimage`: if `s` has the unique differential property, + its preimage under the tangent bundle projection also has +-/ + +noncomputable section + +open scoped Manifold +open Set + +/-! ### Unique derivative sets in manifolds -/ + +section UniqueMDiff + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] + [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {M : Type*} + [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] {E' : Type*} + [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] + {I' : ModelWithCorners 𝕜 E' H'} {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] + [SmoothManifoldWithCorners I' M'] {s : Set M} {x : M} + +/-- If `s` has the unique differential property at `x`, `f` is differentiable within `s` at x` and +its derivative has dense range, then `f '' s` has the unique differential property at `f x`. -/ +theorem UniqueMDiffWithinAt.image_denseRange (hs : UniqueMDiffWithinAt I s x) + {f : M → M'} {f' : E →L[𝕜] E'} (hf : HasMFDerivWithinAt I I' f s x f') + (hd : DenseRange f') : UniqueMDiffWithinAt I' (f '' s) (f x) := by + /- Rewrite in coordinates, apply `HasFDerivWithinAt.uniqueDiffWithinAt`. -/ + have := hs.inter' <| hf.1 (extChartAt_source_mem_nhds I' (f x)) + refine (((hf.2.mono ?sub1).uniqueDiffWithinAt this hd).mono ?sub2).congr_pt ?pt + case pt => simp only [mfld_simps] + case sub1 => mfld_set_tac + case sub2 => + rintro _ ⟨y, ⟨⟨hys, hfy⟩, -⟩, rfl⟩ + exact ⟨⟨_, hys, ((extChartAt I' (f x)).left_inv hfy).symm⟩, mem_range_self _⟩ + +/-- If `s` has the unique differential property, `f` is differentiable on `s` and its derivative +at every point of `s` has dense range, then `f '' s` has the unique differential property. +This version uses the `HasMFDerivWithinAt` predicate. -/ +theorem UniqueMDiffOn.image_denseRange' (hs : UniqueMDiffOn I s) {f : M → M'} + {f' : M → E →L[𝕜] E'} (hf : ∀ x ∈ s, HasMFDerivWithinAt I I' f s x (f' x)) + (hd : ∀ x ∈ s, DenseRange (f' x)) : + UniqueMDiffOn I' (f '' s) := + ball_image_iff.2 fun x hx ↦ (hs x hx).image_denseRange (hf x hx) (hd x hx) + +/-- If `s` has the unique differential property, `f` is differentiable on `s` and its derivative +at every point of `s` has dense range, then `f '' s` has the unique differential property. -/ +theorem UniqueMDiffOn.image_denseRange (hs : UniqueMDiffOn I s) {f : M → M'} + (hf : MDifferentiableOn I I' f s) (hd : ∀ x ∈ s, DenseRange (mfderivWithin I I' f s x)) : + UniqueMDiffOn I' (f '' s) := + hs.image_denseRange' (fun x hx ↦ (hf x hx).hasMFDerivWithinAt) hd + +protected theorem UniqueMDiffWithinAt.preimage_partialHomeomorph (hs : UniqueMDiffWithinAt I s x) + {e : PartialHomeomorph M M'} (he : e.MDifferentiable I I') (hx : x ∈ e.source) : + UniqueMDiffWithinAt I' (e.target ∩ e.symm ⁻¹' s) (e x) := by + rw [← e.image_source_inter_eq', inter_comm] + exact (hs.inter (e.open_source.mem_nhds hx)).image_denseRange + (he.mdifferentiableAt hx).hasMFDerivAt.hasMFDerivWithinAt + (he.mfderiv_surjective hx).denseRange + +/-- If a set has the unique differential property, then its image under a local +diffeomorphism also has the unique differential property. -/ +theorem UniqueMDiffOn.uniqueMDiffOn_preimage (hs : UniqueMDiffOn I s) {e : PartialHomeomorph M M'} + (he : e.MDifferentiable I I') : UniqueMDiffOn I' (e.target ∩ e.symm ⁻¹' s) := fun _x hx ↦ + e.right_inv hx.1 ▸ (hs _ hx.2).preimage_partialHomeomorph he (e.map_target hx.1) +#align unique_mdiff_on.unique_mdiff_on_preimage UniqueMDiffOn.uniqueMDiffOn_preimage + +/-- If a set in a manifold has the unique derivative property, then its pullback by any extended +chart, in the vector space, also has the unique derivative property. -/ +theorem UniqueMDiffOn.uniqueDiffOn_target_inter (hs : UniqueMDiffOn I s) (x : M) : + UniqueDiffOn 𝕜 ((extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' s) := by + -- this is just a reformulation of `UniqueMDiffOn.uniqueMDiffOn_preimage`, using as `e` + -- the local chart at `x`. + apply UniqueMDiffOn.uniqueDiffOn + rw [← PartialEquiv.image_source_inter_eq', inter_comm, extChartAt_source] + exact (hs.inter (chartAt H x).open_source).image_denseRange' + (fun y hy ↦ hasMFDerivWithinAt_extChartAt I hy.2) + fun y hy ↦ ((mdifferentiable_chart _ _).mfderiv_surjective hy.2).denseRange +#align unique_mdiff_on.unique_diff_on_target_inter UniqueMDiffOn.uniqueDiffOn_target_inter + +/-- When considering functions between manifolds, this statement shows up often. It entails +the unique differential of the pullback in extended charts of the set where the function can +be read in the charts. -/ +theorem UniqueMDiffOn.uniqueDiffOn_inter_preimage (hs : UniqueMDiffOn I s) (x : M) (y : M') + {f : M → M'} (hf : ContinuousOn f s) : + UniqueDiffOn 𝕜 + ((extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' (s ∩ f ⁻¹' (extChartAt I' y).source)) := + haveI : UniqueMDiffOn I (s ∩ f ⁻¹' (extChartAt I' y).source) := by + intro z hz + apply (hs z hz.1).inter' + apply (hf z hz.1).preimage_mem_nhdsWithin + exact (isOpen_extChartAt_source I' y).mem_nhds hz.2 + this.uniqueDiffOn_target_inter _ +#align unique_mdiff_on.unique_diff_on_inter_preimage UniqueMDiffOn.uniqueDiffOn_inter_preimage + +open Bundle + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {Z : M → Type*} + [TopologicalSpace (TotalSpace F Z)] [∀ b, TopologicalSpace (Z b)] [∀ b, AddCommMonoid (Z b)] + [∀ b, Module 𝕜 (Z b)] [FiberBundle F Z] [VectorBundle 𝕜 F Z] [SmoothVectorBundle F Z I] + +theorem Trivialization.mdifferentiable (e : Trivialization F (π F Z)) [MemTrivializationAtlas e] : + e.toPartialHomeomorph.MDifferentiable (I.prod 𝓘(𝕜, F)) (I.prod 𝓘(𝕜, F)) := + ⟨(e.smoothOn I).mdifferentiableOn, (e.smoothOn_symm I).mdifferentiableOn⟩ + +theorem UniqueMDiffWithinAt.smooth_bundle_preimage {p : TotalSpace F Z} + (hs : UniqueMDiffWithinAt I s p.proj) : + UniqueMDiffWithinAt (I.prod 𝓘(𝕜, F)) (π F Z ⁻¹' s) p := by + set e := trivializationAt F Z p.proj + have hp : p ∈ e.source := FiberBundle.mem_trivializationAt_proj_source + have : UniqueMDiffWithinAt (I.prod 𝓘(𝕜, F)) (s ×ˢ univ) (e p) + · rw [← Prod.mk.eta (p := e p), FiberBundle.trivializationAt_proj_fst] + exact hs.prod (uniqueMDiffWithinAt_univ _) + rw [← e.left_inv hp] + refine (this.preimage_partialHomeomorph e.mdifferentiable.symm (e.map_source hp)).mono ?_ + rintro y ⟨hy, hys, -⟩ + rwa [PartialHomeomorph.symm_symm, e.coe_coe, e.coe_fst hy] at hys + +variable (Z) + +theorem UniqueMDiffWithinAt.smooth_bundle_preimage' {b : M} (hs : UniqueMDiffWithinAt I s b) + (x : Z b) : UniqueMDiffWithinAt (I.prod 𝓘(𝕜, F)) (π F Z ⁻¹' s) ⟨b, x⟩ := + hs.smooth_bundle_preimage (p := ⟨b, x⟩) + +/-- In a smooth fiber bundle, the preimage under the projection of a set with +unique differential in the basis also has unique differential. -/ +theorem UniqueMDiffOn.smooth_bundle_preimage (hs : UniqueMDiffOn I s) : + UniqueMDiffOn (I.prod 𝓘(𝕜, F)) (π F Z ⁻¹' s) := fun _p hp ↦ + (hs _ hp).smooth_bundle_preimage +#align unique_mdiff_on.smooth_bundle_preimage UniqueMDiffOn.smooth_bundle_preimage + +/-- The preimage under the projection from the tangent bundle of a set with unique differential in +the basis also has unique differential. -/ +theorem UniqueMDiffOn.tangentBundle_proj_preimage (hs : UniqueMDiffOn I s) : + UniqueMDiffOn I.tangent (π E (TangentSpace I) ⁻¹' s) := + hs.smooth_bundle_preimage _ +#align unique_mdiff_on.tangent_bundle_proj_preimage UniqueMDiffOn.tangentBundle_proj_preimage + +end UniqueMDiff diff --git a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean index a9a9e4f2d9b65..0a1216e338a1e 100644 --- a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean +++ b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean @@ -82,11 +82,7 @@ partition of unity in some proofs. We prove that on a smooth finite dimensional real manifold with `σ`-compact Hausdorff topology, for any `U : M → Set M` such that `∀ x ∈ s, U x ∈ 𝓝 x` there exists a `SmoothBumpCovering ι I M s` -subordinate to `U`. Then we use this fact to prove a version of the Whitney embedding theorem: any -compact real manifold can be embedded into `ℝ^n` for large enough `n`. -/ - -set_option autoImplicit true - +subordinate to `U`. -/ variable (ι M) @@ -142,7 +138,7 @@ namespace SmoothPartitionOfUnity variable {s : Set M} (f : SmoothPartitionOfUnity ι I M s) {n : ℕ∞} -instance {s : Set M} : FunLike (SmoothPartitionOfUnity ι I M s) ι fun _ => C^∞⟮I, M; 𝓘(ℝ), ℝ⟯ where +instance {s : Set M} : FunLike (SmoothPartitionOfUnity ι I M s) ι C^∞⟮I, M; 𝓘(ℝ), ℝ⟯ where coe := toFun coe_injective' f g h := by cases f; cases g; congr @@ -188,7 +184,7 @@ theorem sum_nonneg (x : M) : 0 ≤ ∑ᶠ i, f i x := theorem contMDiff_smul {g : M → F} {i} (hg : ∀ x ∈ tsupport (f i), ContMDiffAt I 𝓘(ℝ, F) n g x) : ContMDiff I 𝓘(ℝ, F) n fun x => f i x • g x := - contMDiff_of_support fun x hx => + contMDiff_of_tsupport fun x hx => ((f i).contMDiff.contMDiffAt.of_le le_top).smul <| hg x <| tsupport_smul_subset_left _ _ hx #align smooth_partition_of_unity.cont_mdiff_smul SmoothPartitionOfUnity.contMDiff_smul @@ -483,9 +479,9 @@ variable (I) /-- Given two disjoint closed sets `s, t` in a Hausdorff σ-compact finite dimensional manifold, there exists an infinitely smooth function that is equal to `0` on `s` and to `1` on `t`. -See also `exists_smooth_zero_iff_one_iff_of_closed`, which ensures additionally that +See also `exists_msmooth_zero_iff_one_iff_of_isClosed`, which ensures additionally that `f` is equal to `0` exactly on `s` and to `1` exactly on `t`. -/ -theorem exists_smooth_zero_one_of_closed [T2Space M] [SigmaCompactSpace M] {s t : Set M} +theorem exists_smooth_zero_one_of_isClosed [T2Space M] [SigmaCompactSpace M] {s t : Set M} (hs : IsClosed s) (ht : IsClosed t) (hd : Disjoint s t) : ∃ f : C^∞⟮I, M; 𝓘(ℝ), ℝ⟯, EqOn f 0 s ∧ EqOn f 1 t ∧ ∀ x, f x ∈ Icc (0 : ℝ) 1 := by have : ∀ x ∈ t, sᶜ ∈ 𝓝 x := fun x hx => hs.isOpen_compl.mem_nhds (disjoint_right.1 hd hx) @@ -497,7 +493,7 @@ theorem exists_smooth_zero_one_of_closed [T2Space M] [SigmaCompactSpace M] {s t suffices ∀ i, g i x = 0 by simp only [this, ContMDiffMap.coeFn_mk, finsum_zero, Pi.zero_apply] refine' fun i => f.toSmoothPartitionOfUnity_zero_of_zero _ exact nmem_support.1 (subset_compl_comm.1 (hf.support_subset i) hx) -#align exists_smooth_zero_one_of_closed exists_smooth_zero_one_of_closed +#align exists_smooth_zero_one_of_closed exists_smooth_zero_one_of_isClosed namespace SmoothPartitionOfUnity @@ -527,7 +523,7 @@ theorem exists_isSubordinate {s : Set M} (hs : IsClosed s) (U : ι → Set M) (h · rcases this with ⟨f, hf, hfU⟩ exact ⟨f.toSmoothPartitionOfUnity hf, hfU.toSmoothPartitionOfUnity hf⟩ · intro s t hs ht hd - rcases exists_smooth_zero_one_of_closed I hs ht hd with ⟨f, hf⟩ + rcases exists_smooth_zero_one_of_isClosed I hs ht hd with ⟨f, hf⟩ exact ⟨f, f.smooth, hf⟩ #align smooth_partition_of_unity.exists_is_subordinate SmoothPartitionOfUnity.exists_isSubordinate @@ -634,7 +630,7 @@ lemma IsOpen.exists_msmooth_support_eq_aux {s : Set H} (hs : IsOpen s) : /-- Given an open set in a finite-dimensional real manifold, there exists a nonnegative smooth function with support equal to `s`. -/ -theorem IsOpen.exists_msmooth_support_eq (hs : IsOpen s) : +theorem IsOpen.exists_msmooth_support_eq {s : Set M} (hs : IsOpen s) : ∃ f : M → ℝ, f.support = s ∧ Smooth I 𝓘(ℝ) f ∧ ∀ x, 0 ≤ f x := by rcases SmoothPartitionOfUnity.exists_isSubordinate_chartAt_source I M with ⟨f, hf⟩ have A : ∀ (c : M), ∃ g : H → ℝ, @@ -720,8 +716,8 @@ theorem exists_msmooth_support_eq_eq_one_iff /-- Given two disjoint closed sets `s, t` in a Hausdorff σ-compact finite dimensional manifold, there exists an infinitely smooth function that is equal to `0` exactly on `s` and to `1` -exactly on `t`. See also `exists_smooth_zero_one_of_closed` for a slightly weaker version. -/ -theorem exists_msmooth_zero_iff_one_iff_of_closed {s t : Set M} +exactly on `t`. See also `exists_smooth_zero_one_of_isClosed` for a slightly weaker version. -/ +theorem exists_msmooth_zero_iff_one_iff_of_isClosed {s t : Set M} (hs : IsClosed s) (ht : IsClosed t) (hd : Disjoint s t) : ∃ f : M → ℝ, Smooth I 𝓘(ℝ) f ∧ range f ⊆ Icc 0 1 ∧ (∀ x, x ∈ s ↔ f x = 0) ∧ (∀ x, x ∈ t ↔ f x = 1) := by diff --git a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean index 55bc460838710..b64f98c656601 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean @@ -292,7 +292,7 @@ def smoothSheafCommRing.forgetStalk (x : TopCat.of M) : @[simp, reassoc, elementwise] lemma smoothSheafCommRing.ι_forgetStalk_hom (x : TopCat.of M) (U) : CategoryStruct.comp (Z := (smoothSheaf IM I M R).presheaf.stalk x) - (FunLike.coe + (DFunLike.coe (α := ((forget CommRingCat).obj ((smoothSheafCommRing IM I M R).presheaf.obj (op ((OpenNhds.inclusion x).obj U.unop))))) (colimit.ι ((OpenNhds.inclusion x).op ⋙ (smoothSheafCommRing IM I M R).presheaf) U)) @@ -343,7 +343,7 @@ def smoothSheafCommRing.eval (x : M) : (smoothSheafCommRing IM I M R).presheaf.s @[simp, reassoc, elementwise] lemma smoothSheafCommRing.forgetStalk_inv_comp_eval (x : TopCat.of M) : (smoothSheafCommRing.forgetStalk IM I M R x).inv ≫ - (FunLike.coe (smoothSheafCommRing.evalHom IM I M R x)) = + (DFunLike.coe (smoothSheafCommRing.evalHom IM I M R x)) = smoothSheaf.evalHom _ _ _ _ := by apply Limits.colimit.hom_ext intro U diff --git a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean index be615f8a99e15..b5a692212bd60 100644 --- a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean +++ b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean @@ -6,9 +6,10 @@ Authors: Sébastien Gouëzel import Mathlib.Analysis.Analytic.Basic import Mathlib.Analysis.Analytic.Composition import Mathlib.Analysis.Analytic.Linear -import Mathlib.Analysis.Calculus.ContDiff.FiniteDimension import Mathlib.Analysis.Calculus.FDeriv.Analytic import Mathlib.Geometry.Manifold.ChartedSpace +import Mathlib.Analysis.NormedSpace.FiniteDimension +import Mathlib.Analysis.Calculus.ContDiff.Basic #align_import geometry.manifold.smooth_manifold_with_corners from "leanprover-community/mathlib"@"ddec54a71a0dd025c05445d467f1a2b7d586a3ba" @@ -119,9 +120,6 @@ derivative will be `mfderiv I I' f`, instead of the more natural notations `Tang real and complex manifolds). -/ -set_option autoImplicit true - - noncomputable section universe u v w u' v' w' @@ -357,7 +355,7 @@ protected theorem locallyCompactSpace [LocallyCompactSpace E] (I : ModelWithCorn fun s => I.symm '' (s ∩ range I) := fun x ↦ by rw [← I.symm_map_nhdsWithin_range] exact ((compact_basis_nhds (I x)).inf_principal _).map _ - refine' locallyCompactSpace_of_hasBasis this _ + refine' .of_hasBasis this _ rintro x s ⟨-, hsc⟩ exact (hsc.inter_right I.closed_range).image I.continuous_symm #align model_with_corners.locally_compact ModelWithCorners.locallyCompactSpace @@ -377,9 +375,9 @@ variable (𝕜 E) /-- In the trivial model with corners, the associated `PartialEquiv` is the identity. -/ @[simp, mfld_simps] -theorem modelWithCornersSelf_localEquiv : 𝓘(𝕜, E).toPartialEquiv = PartialEquiv.refl E := +theorem modelWithCornersSelf_partialEquiv : 𝓘(𝕜, E).toPartialEquiv = PartialEquiv.refl E := rfl -#align model_with_corners_self_local_equiv modelWithCornersSelf_localEquiv +#align model_with_corners_self_local_equiv modelWithCornersSelf_partialEquiv @[simp, mfld_simps] theorem modelWithCornersSelf_coe : (𝓘(𝕜, E) : E → E) = id := @@ -532,46 +530,48 @@ variable {m n : ℕ∞} {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type* variable (n) -/-- Given a model with corners `(E, H)`, we define the groupoid of `C^n` transformations of `H` as -the maps that are `C^n` when read in `E` through `I`. -/ +/-- Given a model with corners `(E, H)`, we define the pregroupoid of `C^n` transformations of `H` +as the maps that are `C^n` when read in `E` through `I`. -/ +def contDiffPregroupoid : Pregroupoid H where + property f s := ContDiffOn 𝕜 n (I ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ range I) + comp {f g u v} hf hg _ _ _ := by + have : I ∘ (g ∘ f) ∘ I.symm = (I ∘ g ∘ I.symm) ∘ I ∘ f ∘ I.symm := by ext x; simp + simp only [this] + refine hg.comp (hf.mono fun x ⟨hx1, hx2⟩ ↦ ⟨hx1.1, hx2⟩) ?_ + rintro x ⟨hx1, _⟩ + simp only [mfld_simps] at hx1 ⊢ + exact hx1.2 + id_mem := by + apply ContDiffOn.congr contDiff_id.contDiffOn + rintro x ⟨_, hx2⟩ + rcases mem_range.1 hx2 with ⟨y, hy⟩ + rw [← hy] + simp only [mfld_simps] + locality {f u} _ H := by + apply contDiffOn_of_locally_contDiffOn + rintro y ⟨hy1, hy2⟩ + rcases mem_range.1 hy2 with ⟨x, hx⟩ + rw [← hx] at hy1 ⊢ + simp only [mfld_simps] at hy1 ⊢ + rcases H x hy1 with ⟨v, v_open, xv, hv⟩ + have : I.symm ⁻¹' (u ∩ v) ∩ range I = I.symm ⁻¹' u ∩ range I ∩ I.symm ⁻¹' v := by + rw [preimage_inter, inter_assoc, inter_assoc] + congr 1 + rw [inter_comm] + rw [this] at hv + exact ⟨I.symm ⁻¹' v, v_open.preimage I.continuous_symm, by simpa, hv⟩ + congr {f g u} _ fg hf := by + apply hf.congr + rintro y ⟨hy1, hy2⟩ + rcases mem_range.1 hy2 with ⟨x, hx⟩ + rw [← hx] at hy1 ⊢ + simp only [mfld_simps] at hy1 ⊢ + rw [fg _ hy1] + +/-- Given a model with corners `(E, H)`, we define the groupoid of invertible `C^n` transformations + of `H` as the invertible maps that are `C^n` when read in `E` through `I`. -/ def contDiffGroupoid : StructureGroupoid H := - Pregroupoid.groupoid - { property := fun f s => ContDiffOn 𝕜 n (I ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ range I) - comp := fun {f g u v} hf hg _ _ _ => by - have : I ∘ (g ∘ f) ∘ I.symm = (I ∘ g ∘ I.symm) ∘ I ∘ f ∘ I.symm := by ext x; simp - simp only [this] - refine hg.comp (hf.mono ?_) ?_ - · rintro x ⟨hx1, hx2⟩ - exact ⟨hx1.1, hx2⟩ - · rintro x ⟨hx1, _⟩ - simp only [mfld_simps] at hx1 ⊢ - exact hx1.2 - id_mem := by - apply ContDiffOn.congr contDiff_id.contDiffOn - rintro x ⟨_, hx2⟩ - rcases mem_range.1 hx2 with ⟨y, hy⟩ - rw [← hy] - simp only [mfld_simps] - locality := fun {f u} _ H => by - apply contDiffOn_of_locally_contDiffOn - rintro y ⟨hy1, hy2⟩ - rcases mem_range.1 hy2 with ⟨x, hx⟩ - rw [← hx] at hy1 ⊢ - simp only [mfld_simps] at hy1 ⊢ - rcases H x hy1 with ⟨v, v_open, xv, hv⟩ - have : I.symm ⁻¹' (u ∩ v) ∩ range I = I.symm ⁻¹' u ∩ range I ∩ I.symm ⁻¹' v := by - rw [preimage_inter, inter_assoc, inter_assoc] - congr 1 - rw [inter_comm] - rw [this] at hv - exact ⟨I.symm ⁻¹' v, v_open.preimage I.continuous_symm, by simpa, hv⟩ - congr := fun {f g u} _ fg hf => by - apply hf.congr - rintro y ⟨hy1, hy2⟩ - rcases mem_range.1 hy2 with ⟨x, hx⟩ - rw [← hx] at hy1 ⊢ - simp only [mfld_simps] at hy1 ⊢ - rw [fg _ hy1] } + Pregroupoid.groupoid (contDiffPregroupoid n I) #align cont_diff_groupoid contDiffGroupoid variable {n} @@ -593,7 +593,7 @@ theorem contDiffGroupoid_zero_eq : contDiffGroupoid 0 I = continuousGroupoid H : -- we have to check that every partial homeomorphism belongs to `contDiffGroupoid 0 I`, -- by unfolding its definition change u ∈ contDiffGroupoid 0 I - rw [contDiffGroupoid, mem_groupoid_of_pregroupoid] + rw [contDiffGroupoid, mem_groupoid_of_pregroupoid, contDiffPregroupoid] simp only [contDiffOn_zero] constructor · refine' I.continuous.comp_continuousOn (u.continuousOn.comp I.continuousOn_symm _) @@ -609,7 +609,7 @@ theorem ofSet_mem_contDiffGroupoid {s : Set H} (hs : IsOpen s) : PartialHomeomorph.ofSet s hs ∈ contDiffGroupoid n I := by rw [contDiffGroupoid, mem_groupoid_of_pregroupoid] suffices h : ContDiffOn 𝕜 n (I ∘ I.symm) (I.symm ⁻¹' s ∩ range I) - · simp [h] + · simp [h, contDiffPregroupoid] have : ContDiffOn 𝕜 n id (univ : Set E) := contDiff_id.contDiffOn exact this.congr_mono (fun x hx => I.right_inv hx.2) (subset_univ _) #align of_set_mem_cont_diff_groupoid ofSet_mem_contDiffGroupoid @@ -620,7 +620,7 @@ theorem symm_trans_mem_contDiffGroupoid (e : PartialHomeomorph M H) : e.symm.trans e ∈ contDiffGroupoid n I := haveI : e.symm.trans e ≈ PartialHomeomorph.ofSet e.target e.open_target := PartialHomeomorph.symm_trans_self _ - StructureGroupoid.eq_on_source _ (ofSet_mem_contDiffGroupoid n I e.open_target) this + StructureGroupoid.mem_of_eqOnSource _ (ofSet_mem_contDiffGroupoid n I e.open_target) this #align symm_trans_mem_cont_diff_groupoid symm_trans_mem_contDiffGroupoid variable {E' H' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] [TopologicalSpace H'] @@ -632,7 +632,8 @@ theorem contDiffGroupoid_prod {I : ModelWithCorners 𝕜 E H} {I' : ModelWithCor cases' he with he he_symm cases' he' with he' he'_symm simp only at he he_symm he' he'_symm - constructor <;> simp only [PartialEquiv.prod_source, PartialHomeomorph.prod_toPartialEquiv] + constructor <;> simp only [PartialEquiv.prod_source, PartialHomeomorph.prod_toPartialEquiv, + contDiffPregroupoid] · have h3 := ContDiffOn.prod_map he he' rw [← I.image_eq, ← I'.image_eq, prod_image_image_eq] at h3 rw [← (I.prod I').image_eq] @@ -649,7 +650,7 @@ instance : ClosedUnderRestriction (contDiffGroupoid n I) := (by apply StructureGroupoid.le_iff.mpr rintro e ⟨s, hs, hes⟩ - apply (contDiffGroupoid n I).eq_on_source' _ _ _ hes + apply (contDiffGroupoid n I).mem_of_eqOnSource' _ _ _ hes exact ofSet_mem_contDiffGroupoid n I hs) end contDiffGroupoid @@ -711,7 +712,7 @@ def analyticGroupoid : StructureGroupoid H := (f := (1 : E →L[𝕜] E)) (fun x _ => (1 : E →L[𝕜] E).analyticAt x) (fun z hz => (I.right_inv (interior_subset hz)).symm) · intro x hx - simp only [left_id, comp_apply, preimage_univ, univ_inter, mem_image] at hx + simp only [id_comp, comp_apply, preimage_univ, univ_inter, mem_image] at hx rcases hx with ⟨y, hy⟩ rw [← hy.right, I.right_inv (interior_subset hy.left)] exact hy.left @@ -755,7 +756,7 @@ theorem ofSet_mem_analyticGroupoid {s : Set H} (hs : IsOpen s) : apply mem_groupoid_of_pregroupoid.mpr suffices h : AnalyticOn 𝕜 (I ∘ I.symm) (I.symm ⁻¹' s ∩ interior (range I)) ∧ (I.symm ⁻¹' s ∩ interior (range I)).image (I ∘ I.symm) ⊆ interior (range I) - · simp only [PartialHomeomorph.ofSet_apply, left_id, PartialHomeomorph.ofSet_toPartialEquiv, + · simp only [PartialHomeomorph.ofSet_apply, id_comp, PartialHomeomorph.ofSet_toPartialEquiv, PartialEquiv.ofSet_source, h, comp_apply, mem_range, image_subset_iff, true_and, PartialHomeomorph.ofSet_symm, PartialEquiv.ofSet_target, and_self] intro x hx @@ -765,7 +766,7 @@ theorem ofSet_mem_analyticGroupoid {s : Set H} (hs : IsOpen s) : apply And.intro · have : AnalyticOn 𝕜 (1 : E →L[𝕜] E) (univ : Set E) := (fun x _ => (1 : E →L[𝕜] E).analyticAt x) exact (this.mono (subset_univ (s.preimage (I.symm) ∩ interior (range I)))).congr - (IsOpen.inter (hs.preimage I.continuous_symm) isOpen_interior) + ((hs.preimage I.continuous_symm).inter isOpen_interior) fun z hz => (I.right_inv (interior_subset hz.right)).symm · intro x hx simp only [comp_apply, mem_image] at hx @@ -779,7 +780,7 @@ theorem symm_trans_mem_analyticGroupoid (e : PartialHomeomorph M H) : e.symm.trans e ∈ analyticGroupoid I := haveI : e.symm.trans e ≈ PartialHomeomorph.ofSet e.target e.open_target := PartialHomeomorph.symm_trans_self _ - StructureGroupoid.eq_on_source _ (ofSet_mem_analyticGroupoid I e.open_target) this + StructureGroupoid.mem_of_eqOnSource _ (ofSet_mem_analyticGroupoid I e.open_target) this /-- The analytic groupoid is closed under restriction. -/ instance : ClosedUnderRestriction (analyticGroupoid I) := @@ -787,7 +788,7 @@ instance : ClosedUnderRestriction (analyticGroupoid I) := (by apply StructureGroupoid.le_iff.mpr rintro e ⟨s, hs, hes⟩ - apply (analyticGroupoid I).eq_on_source' _ _ _ hes + apply (analyticGroupoid I).mem_of_eqOnSource' _ _ _ hes exact ofSet_mem_analyticGroupoid I hs) /-- The analytic groupoid on a boundaryless charted space modeled on a complete vector space @@ -804,7 +805,7 @@ theorem mem_analyticGroupoid_of_boundaryless [CompleteSpace E] [I.Boundaryless] · intro he apply And.intro all_goals apply mem_groupoid_of_pregroupoid.mpr; simp only [I.image_eq, I.range_eq_univ, - interior_univ, subset_univ, and_true] at he ⊢ + interior_univ, subset_univ, and_true, contDiffPregroupoid] at he ⊢ · exact ⟨he.left.contDiffOn, he.right.contDiffOn⟩ · exact he @@ -1115,8 +1116,8 @@ theorem map_extend_symm_nhdsWithin_range {y : M} (hy : y ∈ f.source) : rw [← nhdsWithin_univ, ← map_extend_symm_nhdsWithin f I hy, preimage_univ, univ_inter] #align local_homeomorph.map_extend_symm_nhds_within_range PartialHomeomorph.map_extend_symm_nhdsWithin_range -theorem tendsto_extend_comp_iff {l : Filter α} {g : α → M} (hg : ∀ᶠ z in l, g z ∈ f.source) - (hy : y ∈ f.source) : +theorem tendsto_extend_comp_iff {α : Type*} {l : Filter α} {g : α → M} + (hg : ∀ᶠ z in l, g z ∈ f.source) {y : M} (hy : y ∈ f.source) : Tendsto (f.extend I ∘ g) l (𝓝 (f.extend I y)) ↔ Tendsto g l (𝓝 y) := by refine ⟨fun h u hu ↦ mem_map.2 ?_, (continuousAt_extend _ _ hy).tendsto.comp⟩ have := (f.continuousAt_extend_symm I hy).tendsto.comp h @@ -1125,7 +1126,7 @@ theorem tendsto_extend_comp_iff {l : Filter α} {g : α → M} (hg : ∀ᶠ z in simpa only [(· ∘ ·), extend_left_inv _ _ hz, mem_preimage] using hzu -- there is no definition `writtenInExtend` but we already use some made-up names in this file -theorem continuousWithinAt_writtenInExtend_iff {f' : PartialHomeomorph M' H'} {g : M → M'} +theorem continuousWithinAt_writtenInExtend_iff {f' : PartialHomeomorph M' H'} {g : M → M'} {y : M} (hy : y ∈ f.source) (hgy : g y ∈ f'.source) (hmaps : MapsTo g s f'.source) : ContinuousWithinAt (f'.extend I' ∘ g ∘ (f.extend I).symm) ((f.extend I).symm ⁻¹' s ∩ range I) (f.extend I y) ↔ ContinuousWithinAt g s y := by diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean index cc0a46cc89955..fe2a1baed3111 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean @@ -59,9 +59,6 @@ fields, they can also be C^k vector bundles, etc. bundle. -/ -set_option autoImplicit true - - assert_not_exists mfderiv open Bundle Set PartialHomeomorph @@ -328,58 +325,59 @@ theorem contMDiffOn_symm_coordChangeL : variable {e e'} -theorem contMDiffAt_coordChangeL (h : x ∈ e.baseSet) (h' : x ∈ e'.baseSet) : +theorem contMDiffAt_coordChangeL {x : B} (h : x ∈ e.baseSet) (h' : x ∈ e'.baseSet) : ContMDiffAt IB 𝓘(𝕜, F →L[𝕜] F) n (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) x := (contMDiffOn_coordChangeL IB e e').contMDiffAt <| (e.open_baseSet.inter e'.open_baseSet).mem_nhds ⟨h, h'⟩ -theorem smoothAt_coordChangeL (h : x ∈ e.baseSet) (h' : x ∈ e'.baseSet) : +theorem smoothAt_coordChangeL {x : B} (h : x ∈ e.baseSet) (h' : x ∈ e'.baseSet) : SmoothAt IB 𝓘(𝕜, F →L[𝕜] F) (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) x := contMDiffAt_coordChangeL IB h h' variable {IB} +variable {s : Set M} {f : M → B} {g : M → F} {x : M} -protected theorem ContMDiffWithinAt.coordChangeL {f : M → B} +protected theorem ContMDiffWithinAt.coordChangeL (hf : ContMDiffWithinAt IM IB n f s x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : ContMDiffWithinAt IM 𝓘(𝕜, F →L[𝕜] F) n (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) s x := (contMDiffAt_coordChangeL IB he he').comp_contMDiffWithinAt _ hf -protected nonrec theorem ContMDiffAt.coordChangeL {f : M → B} +protected nonrec theorem ContMDiffAt.coordChangeL (hf : ContMDiffAt IM IB n f x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : ContMDiffAt IM 𝓘(𝕜, F →L[𝕜] F) n (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) x := hf.coordChangeL he he' -protected theorem ContMDiffOn.coordChangeL {f : M → B} +protected theorem ContMDiffOn.coordChangeL (hf : ContMDiffOn IM IB n f s) (he : MapsTo f s e.baseSet) (he' : MapsTo f s e'.baseSet) : ContMDiffOn IM 𝓘(𝕜, F →L[𝕜] F) n (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) s := fun x hx ↦ (hf x hx).coordChangeL (he hx) (he' hx) -protected theorem ContMDiff.coordChangeL {f : M → B} +protected theorem ContMDiff.coordChangeL (hf : ContMDiff IM IB n f) (he : ∀ x, f x ∈ e.baseSet) (he' : ∀ x, f x ∈ e'.baseSet) : ContMDiff IM 𝓘(𝕜, F →L[𝕜] F) n (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) := fun x ↦ (hf x).coordChangeL (he x) (he' x) -protected nonrec theorem SmoothWithinAt.coordChangeL {f : M → B} +protected nonrec theorem SmoothWithinAt.coordChangeL (hf : SmoothWithinAt IM IB f s x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : SmoothWithinAt IM 𝓘(𝕜, F →L[𝕜] F) (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) s x := hf.coordChangeL he he' -protected nonrec theorem SmoothAt.coordChangeL {f : M → B} +protected nonrec theorem SmoothAt.coordChangeL (hf : SmoothAt IM IB f x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : SmoothAt IM 𝓘(𝕜, F →L[𝕜] F) (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) x := hf.coordChangeL he he' -protected nonrec theorem SmoothOn.coordChangeL {f : M → B} +protected nonrec theorem SmoothOn.coordChangeL (hf : SmoothOn IM IB f s) (he : MapsTo f s e.baseSet) (he' : MapsTo f s e'.baseSet) : SmoothOn IM 𝓘(𝕜, F →L[𝕜] F) (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) s := hf.coordChangeL he he' -protected nonrec theorem Smooth.coordChangeL {f : M → B} +protected nonrec theorem Smooth.coordChangeL (hf : Smooth IM IB f) (he : ∀ x, f x ∈ e.baseSet) (he' : ∀ x, f x ∈ e'.baseSet) : Smooth IM 𝓘(𝕜, F →L[𝕜] F) (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) := hf.coordChangeL he he' -protected theorem ContMDiffWithinAt.coordChange {f : M → B} {g : M → F} +protected theorem ContMDiffWithinAt.coordChange (hf : ContMDiffWithinAt IM IB n f s x) (hg : ContMDiffWithinAt IM 𝓘(𝕜, F) n g s x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : ContMDiffWithinAt IM 𝓘(𝕜, F) n (fun y ↦ e.coordChange e' (f y) (g y)) s x := by @@ -390,39 +388,39 @@ protected theorem ContMDiffWithinAt.coordChange {f : M → B} {g : M → F} exact (Trivialization.coordChangeL_apply' e e' hy (g y)).symm · exact (Trivialization.coordChangeL_apply' e e' ⟨he, he'⟩ (g x)).symm -protected nonrec theorem ContMDiffAt.coordChange {f : M → B} {g : M → F} +protected nonrec theorem ContMDiffAt.coordChange (hf : ContMDiffAt IM IB n f x) (hg : ContMDiffAt IM 𝓘(𝕜, F) n g x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : ContMDiffAt IM 𝓘(𝕜, F) n (fun y ↦ e.coordChange e' (f y) (g y)) x := hf.coordChange hg he he' -protected theorem ContMDiffOn.coordChange {f : M → B} {g : M → F} (hf : ContMDiffOn IM IB n f s) +protected theorem ContMDiffOn.coordChange (hf : ContMDiffOn IM IB n f s) (hg : ContMDiffOn IM 𝓘(𝕜, F) n g s) (he : MapsTo f s e.baseSet) (he' : MapsTo f s e'.baseSet) : ContMDiffOn IM 𝓘(𝕜, F) n (fun y ↦ e.coordChange e' (f y) (g y)) s := fun x hx ↦ (hf x hx).coordChange (hg x hx) (he hx) (he' hx) -protected theorem ContMDiff.coordChange {f : M → B} {g : M → F} (hf : ContMDiff IM IB n f) +protected theorem ContMDiff.coordChange (hf : ContMDiff IM IB n f) (hg : ContMDiff IM 𝓘(𝕜, F) n g) (he : ∀ x, f x ∈ e.baseSet) (he' : ∀ x, f x ∈ e'.baseSet) : ContMDiff IM 𝓘(𝕜, F) n (fun y ↦ e.coordChange e' (f y) (g y)) := fun x ↦ (hf x).coordChange (hg x) (he x) (he' x) -protected nonrec theorem SmoothWithinAt.coordChange {f : M → B} {g : M → F} +protected nonrec theorem SmoothWithinAt.coordChange (hf : SmoothWithinAt IM IB f s x) (hg : SmoothWithinAt IM 𝓘(𝕜, F) g s x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : SmoothWithinAt IM 𝓘(𝕜, F) (fun y ↦ e.coordChange e' (f y) (g y)) s x := hf.coordChange hg he he' -protected nonrec theorem SmoothAt.coordChange {f : M → B} {g : M → F} (hf : SmoothAt IM IB f x) +protected nonrec theorem SmoothAt.coordChange (hf : SmoothAt IM IB f x) (hg : SmoothAt IM 𝓘(𝕜, F) g x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : SmoothAt IM 𝓘(𝕜, F) (fun y ↦ e.coordChange e' (f y) (g y)) x := hf.coordChange hg he he' -protected nonrec theorem SmoothOn.coordChange {f : M → B} {g : M → F} (hf : SmoothOn IM IB f s) +protected nonrec theorem SmoothOn.coordChange (hf : SmoothOn IM IB f s) (hg : SmoothOn IM 𝓘(𝕜, F) g s) (he : MapsTo f s e.baseSet) (he' : MapsTo f s e'.baseSet) : SmoothOn IM 𝓘(𝕜, F) (fun y ↦ e.coordChange e' (f y) (g y)) s := hf.coordChange hg he he' -protected theorem Smooth.coordChange {f : M → B} {g : M → F} (hf : Smooth IM IB f) +protected theorem Smooth.coordChange (hf : Smooth IM IB f) (hg : Smooth IM 𝓘(𝕜, F) g) (he : ∀ x, f x ∈ e.baseSet) (he' : ∀ x, f x ∈ e'.baseSet) : Smooth IM 𝓘(𝕜, F) (fun y ↦ e.coordChange e' (f y) (g y)) := fun x ↦ (hf x).coordChange (hg x) (he x) (he' x) @@ -479,7 +477,7 @@ instance SmoothFiberwiseLinear.hasGroupoid : refine' ⟨_, _, e.open_baseSet.inter e'.open_baseSet, smoothOn_coordChangeL IB e e', smoothOn_symm_coordChangeL IB e e', _⟩ refine PartialHomeomorph.eqOnSourceSetoid.symm ⟨?_, ?_⟩ - · simp only [e.symm_trans_source_eq e', FiberwiseLinear.localHomeomorph, trans_toPartialEquiv, + · simp only [e.symm_trans_source_eq e', FiberwiseLinear.partialHomeomorph, trans_toPartialEquiv, symm_toPartialEquiv] · rintro ⟨b, v⟩ hb exact (e.apply_symm_apply_eq_coordChangeL e' hb.1 v).symm diff --git a/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean b/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean index affd63ea672c9..634312ae9f13f 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean @@ -31,8 +31,8 @@ namespace FiberwiseLinear variable {φ φ' : B → F ≃L[𝕜] F} {U U' : Set B} /-- For `B` a topological space and `F` a `𝕜`-normed space, a map from `U : Set B` to `F ≃L[𝕜] F` -determines a local homeomorphism from `B × F` to itself by its action fiberwise. -/ -def localHomeomorph (φ : B → F ≃L[𝕜] F) (hU : IsOpen U) +determines a partial homeomorphism from `B × F` to itself by its action fiberwise. -/ +def partialHomeomorph (φ : B → F ≃L[𝕜] F) (hU : IsOpen U) (hφ : ContinuousOn (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : ContinuousOn (fun x => (φ x).symm : B → F →L[𝕜] F) U) : PartialHomeomorph (B × F) (B × F) where @@ -54,71 +54,72 @@ def localHomeomorph (φ : B → F ≃L[𝕜] F) (hU : IsOpen U) haveI : ContinuousOn (fun p : B × F => (((φ p.1).symm : F →L[𝕜] F), p.2)) (U ×ˢ univ) := h2φ.prod_map continuousOn_id continuousOn_fst.prod (isBoundedBilinearMap_apply.continuous.comp_continuousOn this) -#align fiberwise_linear.local_homeomorph FiberwiseLinear.localHomeomorph +#align fiberwise_linear.local_homeomorph FiberwiseLinear.partialHomeomorph -/-- Compute the composition of two local homeomorphisms induced by fiberwise linear +/-- Compute the composition of two partial homeomorphisms induced by fiberwise linear equivalences. -/ -theorem trans_localHomeomorph_apply (hU : IsOpen U) +theorem trans_partialHomeomorph_apply (hU : IsOpen U) (hφ : ContinuousOn (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : ContinuousOn (fun x => (φ x).symm : B → F →L[𝕜] F) U) (hU' : IsOpen U') (hφ' : ContinuousOn (fun x => φ' x : B → F →L[𝕜] F) U') (h2φ' : ContinuousOn (fun x => (φ' x).symm : B → F →L[𝕜] F) U') (b : B) (v : F) : - (FiberwiseLinear.localHomeomorph φ hU hφ h2φ ≫ₕ FiberwiseLinear.localHomeomorph φ' hU' hφ' h2φ') + (FiberwiseLinear.partialHomeomorph φ hU hφ h2φ ≫ₕ + FiberwiseLinear.partialHomeomorph φ' hU' hφ' h2φ') ⟨b, v⟩ = ⟨b, φ' b (φ b v)⟩ := rfl -#align fiberwise_linear.trans_local_homeomorph_apply FiberwiseLinear.trans_localHomeomorph_apply +#align fiberwise_linear.trans_local_homeomorph_apply FiberwiseLinear.trans_partialHomeomorph_apply -/-- Compute the source of the composition of two local homeomorphisms induced by fiberwise linear +/-- Compute the source of the composition of two partial homeomorphisms induced by fiberwise linear equivalences. -/ -theorem source_trans_localHomeomorph (hU : IsOpen U) +theorem source_trans_partialHomeomorph (hU : IsOpen U) (hφ : ContinuousOn (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : ContinuousOn (fun x => (φ x).symm : B → F →L[𝕜] F) U) (hU' : IsOpen U') (hφ' : ContinuousOn (fun x => φ' x : B → F →L[𝕜] F) U') (h2φ' : ContinuousOn (fun x => (φ' x).symm : B → F →L[𝕜] F) U') : - (FiberwiseLinear.localHomeomorph φ hU hφ h2φ ≫ₕ - FiberwiseLinear.localHomeomorph φ' hU' hφ' h2φ').source = + (FiberwiseLinear.partialHomeomorph φ hU hφ h2φ ≫ₕ + FiberwiseLinear.partialHomeomorph φ' hU' hφ' h2φ').source = (U ∩ U') ×ˢ univ := - by dsimp only [FiberwiseLinear.localHomeomorph]; mfld_set_tac -#align fiberwise_linear.source_trans_local_homeomorph FiberwiseLinear.source_trans_localHomeomorph + by dsimp only [FiberwiseLinear.partialHomeomorph]; mfld_set_tac +#align fiberwise_linear.source_trans_local_homeomorph FiberwiseLinear.source_trans_partialHomeomorph -/-- Compute the target of the composition of two local homeomorphisms induced by fiberwise linear +/-- Compute the target of the composition of two partial homeomorphisms induced by fiberwise linear equivalences. -/ -theorem target_trans_localHomeomorph (hU : IsOpen U) +theorem target_trans_partialHomeomorph (hU : IsOpen U) (hφ : ContinuousOn (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : ContinuousOn (fun x => (φ x).symm : B → F →L[𝕜] F) U) (hU' : IsOpen U') (hφ' : ContinuousOn (fun x => φ' x : B → F →L[𝕜] F) U') (h2φ' : ContinuousOn (fun x => (φ' x).symm : B → F →L[𝕜] F) U') : - (FiberwiseLinear.localHomeomorph φ hU hφ h2φ ≫ₕ - FiberwiseLinear.localHomeomorph φ' hU' hφ' h2φ').target = + (FiberwiseLinear.partialHomeomorph φ hU hφ h2φ ≫ₕ + FiberwiseLinear.partialHomeomorph φ' hU' hφ' h2φ').target = (U ∩ U') ×ˢ univ := - by dsimp only [FiberwiseLinear.localHomeomorph]; mfld_set_tac -#align fiberwise_linear.target_trans_local_homeomorph FiberwiseLinear.target_trans_localHomeomorph + by dsimp only [FiberwiseLinear.partialHomeomorph]; mfld_set_tac +#align fiberwise_linear.target_trans_local_homeomorph FiberwiseLinear.target_trans_partialHomeomorph end FiberwiseLinear variable {EB : Type*} [NormedAddCommGroup EB] [NormedSpace 𝕜 EB] {HB : Type*} [TopologicalSpace HB] [ChartedSpace HB B] {IB : ModelWithCorners 𝕜 EB HB} -/-- Let `e` be a local homeomorphism of `B × F`. Suppose that at every point `p` in the source of +/-- Let `e` be a partial homeomorphism of `B × F`. Suppose that at every point `p` in the source of `e`, there is some neighbourhood `s` of `p` on which `e` is equal to a bi-smooth fiberwise linear -local homeomorphism. +partial homeomorphism. Then the source of `e` is of the form `U ×ˢ univ`, for some set `U` in `B`, and, at any point `x` in `U`, admits a neighbourhood `u` of `x` such that `e` is equal on `u ×ˢ univ` to some bi-smooth -fiberwise linear local homeomorphism. -/ +fiberwise linear partial homeomorphism. -/ theorem SmoothFiberwiseLinear.locality_aux₁ (e : PartialHomeomorph (B × F) (B × F)) (h : ∀ p ∈ e.source, ∃ s : Set (B × F), IsOpen s ∧ p ∈ s ∧ ∃ (φ : B → F ≃L[𝕜] F) (u : Set B) (hu : IsOpen u) (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x : F →L[𝕜] F)) u) (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr s).EqOnSource - (FiberwiseLinear.localHomeomorph φ hu hφ.continuousOn h2φ.continuousOn)) : + (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn)) : ∃ U : Set B, e.source = U ×ˢ univ ∧ ∀ x ∈ U, ∃ (φ : B → F ≃L[𝕜] F) (u : Set B) (hu : IsOpen u) (_huU : u ⊆ U) (_hux : x ∈ u), ∃ (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x : F →L[𝕜] F)) u) (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr (u ×ˢ univ)).EqOnSource - (FiberwiseLinear.localHomeomorph φ hu hφ.continuousOn h2φ.continuousOn) := by + (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn) := by rw [SetCoe.forall'] at h choose s hs hsp φ u hu hφ h2φ heφ using h have hesu : ∀ p : e.source, e.source ∩ s p = u p ×ˢ univ := by @@ -147,14 +148,14 @@ theorem SmoothFiberwiseLinear.locality_aux₁ (e : PartialHomeomorph (B × F) (B · rw [← hesu, e.restr_source_inter]; exact heφ ⟨p, hp⟩ #align smooth_fiberwise_linear.locality_aux₁ SmoothFiberwiseLinear.locality_aux₁ -/-- Let `e` be a local homeomorphism of `B × F` whose source is `U ×ˢ univ`, for some set `U` in -`B`, and which, at any point `x` in `U`, admits a neighbourhood `u` of `x` such that `e` is equal on -`u ×ˢ univ` to some bi-smooth fiberwise linear local homeomorphism. Then `e` itself is equal to -some bi-smooth fiberwise linear local homeomorphism. +/-- Let `e` be a partial homeomorphism of `B × F` whose source is `U ×ˢ univ`, for some set `U` in +`B`, and which, at any point `x` in `U`, admits a neighbourhood `u` of `x` such that `e` is equal +on `u ×ˢ univ` to some bi-smooth fiberwise linear partial homeomorphism. Then `e` itself +is equal to some bi-smooth fiberwise linear partial homeomorphism. This is the key mathematical point of the `locality` condition in the construction of the -`StructureGroupoid` of bi-smooth fiberwise linear local homeomorphisms. The proof is by gluing -together the various bi-smooth fiberwise linear local homeomorphism which exist locally. +`StructureGroupoid` of bi-smooth fiberwise linear partial homeomorphisms. The proof is by gluing +together the various bi-smooth fiberwise linear partial homeomorphism which exist locally. The `U` in the conclusion is the same `U` as in the hypothesis. We state it like this, because this is exactly what we need for `smoothFiberwiseLinear`. -/ @@ -165,11 +166,11 @@ theorem SmoothFiberwiseLinear.locality_aux₂ (e : PartialHomeomorph (B × F) (B (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x : F →L[𝕜] F)) u) (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr (u ×ˢ univ)).EqOnSource - (FiberwiseLinear.localHomeomorph φ hu hφ.continuousOn h2φ.continuousOn)) : + (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn)) : ∃ (Φ : B → F ≃L[𝕜] F) (U : Set B) (hU₀ : IsOpen U) (hΦ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (Φ x : F →L[𝕜] F)) U) (h2Φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => ((Φ x).symm : F →L[𝕜] F)) U), - e.EqOnSource (FiberwiseLinear.localHomeomorph Φ hU₀ hΦ.continuousOn h2Φ.continuousOn) := by + e.EqOnSource (FiberwiseLinear.partialHomeomorph Φ hU₀ hΦ.continuousOn h2Φ.continuousOn) := by classical rw [SetCoe.forall'] at h choose! φ u hu hUu hux hφ h2φ heφ using h @@ -227,12 +228,13 @@ private theorem mem_aux {e : PartialHomeomorph (B × F) (B × F)} : (e ∈ ⋃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x).symm : B → F →L[𝕜] F) U), - {e | e.EqOnSource (FiberwiseLinear.localHomeomorph φ hU hφ.continuousOn + {e | e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn)}) ↔ ∃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x).symm : B → F →L[𝕜] F) U), - e.EqOnSource (FiberwiseLinear.localHomeomorph φ hU hφ.continuousOn h2φ.continuousOn) := by + e.EqOnSource + (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn) := by simp only [mem_iUnion, mem_setOf_eq] variable (F B IB) @@ -246,7 +248,7 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where ⋃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x).symm : B → F →L[𝕜] F) U), - {e | e.EqOnSource (FiberwiseLinear.localHomeomorph φ hU hφ.continuousOn h2φ.continuousOn)} + {e | e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn)} trans' := by simp only [mem_aux] rintro e e' ⟨φ, U, hU, hφ, h2φ, heφ⟩ ⟨φ', U', hU', hφ', h2φ', heφ'⟩ @@ -261,8 +263,8 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where (fun x : B => (φ x).symm.toContinuousLinearMap ∘L (φ' x).symm.toContinuousLinearMap) (U ∩ U') exact (h2φ.mono <| inter_subset_left _ _).clm_comp (h2φ'.mono <| inter_subset_right _ _) - · apply FiberwiseLinear.source_trans_localHomeomorph - · rintro ⟨b, v⟩ -; apply FiberwiseLinear.trans_localHomeomorph_apply + · apply FiberwiseLinear.source_trans_partialHomeomorph + · rintro ⟨b, v⟩ -; apply FiberwiseLinear.trans_partialHomeomorph_apply -- porting note: without introducing `e` first, the first `simp only` fails symm' := fun e ↦ by simp only [mem_iUnion] @@ -277,7 +279,7 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where -/ refine mem_iUnion.2 ⟨fun _ ↦ .refl 𝕜 F, mem_iUnion.2 ⟨univ, mem_iUnion.2 ⟨isOpen_univ, ?_⟩⟩⟩ refine mem_iUnion.2 ⟨contMDiffOn_const, mem_iUnion.2 ⟨contMDiffOn_const, ?_, ?_⟩⟩ - · simp only [FiberwiseLinear.localHomeomorph, PartialHomeomorph.refl_localEquiv, + · simp only [FiberwiseLinear.partialHomeomorph, PartialHomeomorph.refl_partialEquiv, PartialEquiv.refl_source, univ_prod_univ] · exact eqOn_refl id _ locality' := by @@ -286,7 +288,7 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where intro e he obtain ⟨U, hU, h⟩ := SmoothFiberwiseLinear.locality_aux₁ e he exact SmoothFiberwiseLinear.locality_aux₂ e U hU h - eq_on_source' := by + mem_of_eqOnSource' := by simp only [mem_aux] rintro e e' ⟨φ, U, hU, hφ, h2φ, heφ⟩ hee' exact ⟨φ, U, hU, hφ, h2φ, Setoid.trans hee' heφ⟩ @@ -298,6 +300,6 @@ theorem mem_smoothFiberwiseLinear_iff (e : PartialHomeomorph (B × F) (B × F)) ∃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x).symm : B → F →L[𝕜] F) U), - e.EqOnSource (FiberwiseLinear.localHomeomorph φ hU hφ.continuousOn h2φ.continuousOn) := + e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn) := mem_aux #align mem_smooth_fiberwise_linear_iff mem_smoothFiberwiseLinear_iff diff --git a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean index 716870767ae32..d873addb7ce54 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean @@ -3,7 +3,7 @@ Copyright © 2023 Heather Macbeth. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Heather Macbeth, Floris van Doorn -/ -import Mathlib.Geometry.Manifold.MFDeriv +import Mathlib.Geometry.Manifold.MFDeriv.Basic import Mathlib.Topology.ContinuousFunction.Basic import Mathlib.Geometry.Manifold.Algebra.LieGroup @@ -59,7 +59,7 @@ namespace ContMDiffSection variable {I} {I'} {n} {F} {V} -instance : FunLike Cₛ^n⟮I; F, V⟯ M V where +instance : DFunLike Cₛ^n⟮I; F, V⟯ M V where coe := ContMDiffSection.toFun coe_injective' := by rintro ⟨⟩ ⟨⟩ h; congr @@ -98,7 +98,7 @@ protected theorem mdifferentiableAt (s : Cₛ^∞⟮I; F, V⟯) {x} : #align cont_mdiff_section.mdifferentiable_at ContMDiffSection.mdifferentiableAt theorem coe_inj ⦃s t : Cₛ^n⟮I; F, V⟯⦄ (h : (s : ∀ x, V x) = t) : s = t := - FunLike.ext' h + DFunLike.ext' h #align cont_mdiff_section.coe_inj ContMDiffSection.coe_inj theorem coe_injective : Injective ((↑) : Cₛ^n⟮I; F, V⟯ → ∀ x, V x) := @@ -106,7 +106,7 @@ theorem coe_injective : Injective ((↑) : Cₛ^n⟮I; F, V⟯ → ∀ x, V x) : #align cont_mdiff_section.coe_injective ContMDiffSection.coe_injective @[ext] -theorem ext (h : ∀ x, s x = t x) : s = t := FunLike.ext _ _ h +theorem ext (h : ∀ x, s x = t x) : s = t := DFunLike.ext _ _ h #align cont_mdiff_section.ext ContMDiffSection.ext instance instAdd : Add Cₛ^n⟮I; F, V⟯ := by diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean index 633efd4b83e70..493af01cd07a8 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean @@ -297,7 +297,6 @@ def isoOfComponents (H : X.1 ≅ Y.1) (α : H.hom _* X.2 ≅ Y.2) : X ≅ Y wher dsimp rw [H.inv_hom_id] dsimp - rw [NatTrans.comp_app] simp only [Presheaf.pushforwardObj_obj, op_obj, Opens.map_comp_obj, comp_obj, comp_c_app, unop_op, Presheaf.toPushforwardOfIso_app, whiskerRight_app, eqToHom_app, assoc, id_c_app, map_id] @@ -319,7 +318,7 @@ def sheafIsoOfIso (H : X ≅ Y) : Y.2 ≅ H.hom.base _* X.2 where inv_hom_id := by ext U dsimp - rw [NatTrans.comp_app, NatTrans.id_app] + rw [NatTrans.id_app] simp only [Presheaf.pushforwardObj_obj, op_obj, Presheaf.pushforwardToOfIso_app, Iso.symm_inv, mapIso_hom, forget_map, Iso.symm_hom, mapIso_inv, unop_op, eqToHom_map, assoc] @@ -456,15 +455,13 @@ def restrictTopIso (X : PresheafedSpace C) : X.restrict (Opens.openEmbedding ⊤ hom_inv_id := by ext · rfl - · dsimp - erw [comp_c, toRestrictTop_c, whiskerRight_id', + · erw [comp_c, toRestrictTop_c, whiskerRight_id', comp_id, ofRestrict_top_c, eqToHom_map, eqToHom_trans, eqToHom_refl] rfl inv_hom_id := by ext · rfl - · dsimp - erw [comp_c, ofRestrict_top_c, toRestrictTop_c, eqToHom_map, whiskerRight_id', comp_id, + · erw [comp_c, ofRestrict_top_c, toRestrictTop_c, eqToHom_map, whiskerRight_id', comp_id, eqToHom_trans, eqToHom_refl] rfl set_option linter.uppercaseLean3 false in diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean index 4c2508bf6ad00..9b330c43ac318 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean @@ -6,6 +6,7 @@ Authors: Scott Morrison import Mathlib.Geometry.RingedSpace.PresheafedSpace import Mathlib.Topology.Category.TopCat.Limits.Basic import Mathlib.Topology.Sheaves.Limits +import Mathlib.CategoryTheory.ConcreteCategory.Elementwise #align_import algebraic_geometry.presheafed_space.has_colimits from "leanprover-community/mathlib"@"178a32653e369dce2da68dc6b2694e385d484ef1" @@ -134,11 +135,11 @@ def pushforwardDiagramToColimit (F : J ⥤ PresheafedSpace.{_, _, v} C) : pushforwardObj_obj, op_obj, Opens.map_obj, opEquiv, Equiv.coe_fn_mk, unop_comp, Quiver.Hom.unop_op, unop_id] -- Porting note : some `simp` lemmas are not picked up - rw [NatTrans.comp_app, pushforwardMap_app, NatTrans.id_app] + rw [NatTrans.id_app] simp only [op_obj, unop_op, Opens.map_obj, map_id_c_app, Opens.map_id_obj', map_id, pushforwardEq_hom_app, eqToHom_op, id_eq, eqToHom_map, id_comp, TopCat.Presheaf.Pushforward.id_inv_app'] - rw [NatTrans.comp_app, Pushforward.comp_inv_app, id_comp] + rw [Pushforward.comp_inv_app] dsimp simp map_comp {j₁ j₂ j₃} f g := by @@ -212,13 +213,13 @@ def colimitCocone (F : J ⥤ PresheafedSpace.{_, _, v} C) : Cocone F where · ext x exact colimit.w_apply (F ⋙ PresheafedSpace.forget C) f x · ext ⟨U, hU⟩ - dsimp + dsimp [-Presheaf.comp_app] rw [PresheafedSpace.id_c_app, map_id] erw [id_comp] rw [NatTrans.comp_app, PresheafedSpace.comp_c_app, whiskerRight_app, eqToHom_app, ← congr_arg NatTrans.app (limit.w (pushforwardDiagramToColimit F).leftOp f.op), NatTrans.comp_app, Functor.leftOp_map, pushforwardDiagramToColimit_map] - dsimp + dsimp [-Presheaf.comp_app] rw [NatTrans.comp_app, NatTrans.comp_app, pushforwardEq_hom_app, id.def, eqToHom_op, Pushforward.comp_inv_app, id_comp, pushforwardMap_app, ← assoc] congr 1 } @@ -394,7 +395,7 @@ def colimitPresheafObjIsoComponentwiseLimit (F : J ⥤ PresheafedSpace.{_, _, v} simp only [Functor.op_obj, unop_op, op_inj_iff, Opens.map_coe, SetLike.ext'_iff, Set.preimage_preimage] refine congr_arg (Set.preimage . U.1) (funext fun x => ?_) - erw [← comp_app] + erw [← TopCat.comp_app] congr exact ι_preservesColimitsIso_inv (forget C) F (unop X) · intro X Y f diff --git a/Mathlib/GroupTheory/Abelianization.lean b/Mathlib/GroupTheory/Abelianization.lean index 8bd2aee2d5b81..8314f55ac87e8 100644 --- a/Mathlib/GroupTheory/Abelianization.lean +++ b/Mathlib/GroupTheory/Abelianization.lean @@ -168,7 +168,7 @@ variable {A : Type v} [Monoid A] /-- See note [partially-applied ext lemmas]. -/ @[ext] theorem hom_ext (φ ψ : Abelianization G →* A) (h : φ.comp of = ψ.comp of) : φ = ψ := - MonoidHom.ext fun x => QuotientGroup.induction_on x <| FunLike.congr_fun h + MonoidHom.ext fun x => QuotientGroup.induction_on x <| DFunLike.congr_fun h #align abelianization.hom_ext Abelianization.hom_ext section Map @@ -198,7 +198,7 @@ theorem map_comp {I : Type w} [Group I] (g : H →* I) : (map g).comp (map f) = @[simp] theorem map_map_apply {I : Type w} [Group I] {g : H →* I} {x : Abelianization G} : map g (map f x) = map (g.comp f) x := - FunLike.congr_fun (map_comp _ _) x + DFunLike.congr_fun (map_comp _ _) x #align abelianization.map_map_apply Abelianization.map_map_apply end Map diff --git a/Mathlib/GroupTheory/ClassEquation.lean b/Mathlib/GroupTheory/ClassEquation.lean index dec8cca31a06c..c3977870b7088 100644 --- a/Mathlib/GroupTheory/ClassEquation.lean +++ b/Mathlib/GroupTheory/ClassEquation.lean @@ -4,10 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Eric Rodriguez -/ -import Mathlib.GroupTheory.GroupAction.Quotient import Mathlib.Algebra.BigOperators.Finprod import Mathlib.Data.Set.Card import Mathlib.Algebra.Group.ConjFinite +import Mathlib.GroupTheory.Subgroup.Finite /-! # Class Equation @@ -24,7 +24,7 @@ This file establishes the class equation for finite groups. set_option autoImplicit true -open ConjAct MulAction ConjClasses +open MulAction ConjClasses open scoped BigOperators diff --git a/Mathlib/GroupTheory/CommutingProbability.lean b/Mathlib/GroupTheory/CommutingProbability.lean index d26941786e506..3f0d9319221e7 100644 --- a/Mathlib/GroupTheory/CommutingProbability.lean +++ b/Mathlib/GroupTheory/CommutingProbability.lean @@ -165,9 +165,7 @@ def reciprocalFactors (n : ℕ) : List ℕ := 3 :: reciprocalFactors (n / 2) else n % 4 * n :: reciprocalFactors (n / 4 + 1) -decreasing_by - simp_wf - first | exact div_two_lt h0 | exact div_four_lt h0 h1 +decreasing_by all_goals { simp_wf; omega } @[simp] lemma reciprocalFactors_zero : reciprocalFactors 0 = [0] := rfl diff --git a/Mathlib/GroupTheory/Complement.lean b/Mathlib/GroupTheory/Complement.lean index ca50d6979627c..b6aef88c20e3f 100644 --- a/Mathlib/GroupTheory/Complement.lean +++ b/Mathlib/GroupTheory/Complement.lean @@ -174,7 +174,7 @@ lemma IsComplement.mul_eq (h : IsComplement S T) : S * T = univ := @[to_additive AddSubgroup.IsComplement.card_mul_card] lemma IsComplement.card_mul_card (h : IsComplement S T) : Nat.card S * Nat.card T = Nat.card G := - (Nat.card_prod _ _).symm.trans $ Nat.card_congr $ Equiv.ofBijective _ h + (Nat.card_prod _ _).symm.trans <| Nat.card_congr <| Equiv.ofBijective _ h @[to_additive] theorem isComplement'_top_bot : IsComplement' (⊤ : Subgroup G) ⊥ := @@ -301,7 +301,7 @@ theorem range_mem_leftTransversals {f : G ⧸ H → G} (hf : ∀ q, ↑(f q) = q Set.range f ∈ leftTransversals (H : Set G) := mem_leftTransversals_iff_bijective.mpr ⟨by rintro ⟨-, q₁, rfl⟩ ⟨-, q₂, rfl⟩ h - exact Subtype.ext $ congr_arg f $ ((hf q₁).symm.trans h).trans (hf q₂), + exact Subtype.ext <| congr_arg f <| ((hf q₁).symm.trans h).trans (hf q₂), fun q => ⟨⟨f q, q, rfl⟩, hf q⟩⟩ #align subgroup.range_mem_left_transversals Subgroup.range_mem_leftTransversals #align add_subgroup.range_mem_left_transversals AddSubgroup.range_mem_leftTransversals @@ -311,7 +311,7 @@ theorem range_mem_rightTransversals {f : Quotient (QuotientGroup.rightRel H) → (hf : ∀ q, Quotient.mk'' (f q) = q) : Set.range f ∈ rightTransversals (H : Set G) := mem_rightTransversals_iff_bijective.mpr ⟨by rintro ⟨-, q₁, rfl⟩ ⟨-, q₂, rfl⟩ h - exact Subtype.ext $ congr_arg f $ ((hf q₁).symm.trans h).trans (hf q₂), + exact Subtype.ext <| congr_arg f <| ((hf q₁).symm.trans h).trans (hf q₂), fun q => ⟨⟨f q, q, rfl⟩, hf q⟩⟩ #align subgroup.range_mem_right_transversals Subgroup.range_mem_rightTransversals #align add_subgroup.range_mem_right_transversals AddSubgroup.range_mem_rightTransversals @@ -357,7 +357,7 @@ lemma exists_left_transversal_of_le {H' H : Subgroup G} (h : H' ≤ H) : simp [Set.ext_iff] · rw [← cmem.card_mul_card] refine congr_arg₂ (· * ·) ?_ ?_ <;> - exact Nat.card_congr (Equiv.Set.image _ _ $ subtype_injective H).symm + exact Nat.card_congr (Equiv.Set.image _ _ <| subtype_injective H).symm /-- Given two subgroups `H' ⊆ H`, there exists a right transversal to `H'` inside `H`. -/ @[to_additive "Given two subgroups `H' ⊆ H`, there exists a transversal to `H'` inside `H`"] @@ -374,7 +374,7 @@ lemma exists_right_transversal_of_le {H' H : Subgroup G} (h : H' ≤ H) : · have : Nat.card H'' * Nat.card S = Nat.card H := cmem.card_mul_card rw [← this] refine congr_arg₂ (· * ·) ?_ ?_ <;> - exact Nat.card_congr (Equiv.Set.image _ _ $ subtype_injective H).symm + exact Nat.card_congr (Equiv.Set.image _ _ <| subtype_injective H).symm namespace IsComplement @@ -645,7 +645,7 @@ noncomputable instance : MulAction F (leftTransversals (H : Set G)) where @[to_additive] theorem smul_toFun (f : F) (T : leftTransversals (H : Set G)) (g : G) : (f • (toFun T.2 g : G)) = toFun (f • T).2 (f • g) := - Subtype.ext_iff.mp $ @ExistsUnique.unique (↥(f • (T : Set G))) (fun s => (↑s)⁻¹ * f • g ∈ H) + Subtype.ext_iff.mp <| @ExistsUnique.unique (↥(f • (T : Set G))) (fun s => (↑s)⁻¹ * f • g ∈ H) (mem_leftTransversals_iff_existsUnique_inv_mul_mem.mp (f • T).2 (f • g)) ⟨f • (toFun T.2 g : G), Set.smul_mem_smul_set (Subtype.coe_prop _)⟩ (toFun (f • T).2 (f • g)) (QuotientAction.inv_mul_mem f (inv_toFun_mul_mem T.2 g)) (inv_toFun_mul_mem (f • T).2 (f • g)) diff --git a/Mathlib/GroupTheory/Congruence.lean b/Mathlib/GroupTheory/Congruence.lean index 19074e28d5b3d..28f8fa617973a 100644 --- a/Mathlib/GroupTheory/Congruence.lean +++ b/Mathlib/GroupTheory/Congruence.lean @@ -121,7 +121,7 @@ instance : Inhabited (Con M) := --Porting note: upgraded to FunLike /-- A coercion from a congruence relation to its underlying binary relation. -/ @[to_additive "A coercion from an additive congruence relation to its underlying binary relation."] -instance : FunLike (Con M) M (fun _ => M → Prop) where +instance : FunLike (Con M) M (M → Prop) where coe c := c.r coe_injective' := fun x y h => by rcases x with ⟨⟨x, _⟩, _⟩ @@ -178,7 +178,7 @@ variable {c} /-- The map sending a congruence relation to its underlying binary relation is injective. -/ @[to_additive "The map sending an additive congruence relation to its underlying binary relation is injective."] -theorem ext' {c d : Con M} (H : ⇑c = ⇑d) : c = d := FunLike.coe_injective H +theorem ext' {c d : Con M} (H : ⇑c = ⇑d) : c = d := DFunLike.coe_injective H #align con.ext' Con.ext' #align add_con.ext' AddCon.ext' @@ -207,7 +207,7 @@ theorem ext_iff {c d : Con M} : (∀ x y, c x y ↔ d x y) ↔ c = d := /-- Two congruence relations are equal iff their underlying binary relations are equal. -/ @[to_additive "Two additive congruence relations are equal iff their underlying binary relations are equal."] -theorem coe_inj {c d : Con M} : ⇑c = ⇑d ↔ c = d := FunLike.coe_injective.eq_iff +theorem coe_inj {c d : Con M} : ⇑c = ⇑d ↔ c = d := DFunLike.coe_injective.eq_iff #align con.ext'_iff Con.coe_inj #align add_con.ext'_iff AddCon.coe_inj @@ -606,7 +606,7 @@ variable (M) binary relations on `M`. -/ @[to_additive "There is a Galois insertion of additive congruence relations on a type with an addition `M` into binary relations on `M`."] -protected def gi : @GaloisInsertion (M → M → Prop) (Con M) _ _ conGen FunLike.coe +protected def gi : @GaloisInsertion (M → M → Prop) (Con M) _ _ conGen DFunLike.coe where choice r _ := conGen r gc _ c := ⟨fun H _ _ h => H <| ConGen.Rel.of _ _ h, @fun H => conGen_of_con c ▸ conGen_mono H⟩ @@ -950,7 +950,7 @@ are equal if they are equal on elements that are coercions from the `AddMonoid`. theorem lift_funext (f g : c.Quotient →* P) (h : ∀ a : M, f a = g a) : f = g := by rw [← lift_apply_mk' f, ← lift_apply_mk' g] congr 1 - exact FunLike.ext_iff.2 h + exact DFunLike.ext_iff.2 h #align con.lift_funext Con.lift_funext #align add_con.lift_funext AddCon.lift_funext diff --git a/Mathlib/GroupTheory/Coprod/Basic.lean b/Mathlib/GroupTheory/Coprod/Basic.lean index 27f597591adbf..c800639453d8f 100644 --- a/Mathlib/GroupTheory/Coprod/Basic.lean +++ b/Mathlib/GroupTheory/Coprod/Basic.lean @@ -242,7 +242,7 @@ theorem clift_apply_mk (f : FreeMonoid (M ⊕ N) →* P) (hM₁ hN₁ hM hN w) : @[to_additive (attr := simp)] theorem clift_comp_mk (f : FreeMonoid (M ⊕ N) →* P) (hM₁ hN₁ hM hN) : (clift f hM₁ hN₁ hM hN).comp mk = f := - FunLike.ext' rfl + DFunLike.ext' rfl @[to_additive (attr := simp)] theorem mclosure_range_inl_union_inr : @@ -275,7 +275,7 @@ then they are equal. -/ theorem hom_ext {f g : M ∗ N →* P} (h₁ : f.comp inl = g.comp inl) (h₂ : f.comp inr = g.comp inr) : f = g := MonoidHom.eq_of_eqOn_denseM mclosure_range_inl_union_inr <| eqOn_union.2 - ⟨eqOn_range.2 <| FunLike.ext'_iff.1 h₁, eqOn_range.2 <| FunLike.ext'_iff.1 h₂⟩ + ⟨eqOn_range.2 <| DFunLike.ext'_iff.1 h₁, eqOn_range.2 <| DFunLike.ext'_iff.1 h₂⟩ @[to_additive (attr := simp)] theorem clift_mk : @@ -322,7 +322,7 @@ theorem map_comp_map {M'' N''} [MulOneClass M''] [MulOneClass N''] (f' : M' →* theorem map_map {M'' N''} [MulOneClass M''] [MulOneClass N''] (f' : M' →* M'') (g' : N' →* N'') (f : M →* M') (g : N →* N') (x : M ∗ N) : map f' g' (map f g x) = map (f'.comp f) (g'.comp g) x := - FunLike.congr_fun (map_comp_map f' g' f g) x + DFunLike.congr_fun (map_comp_map f' g' f g) x variable (M N) @@ -347,7 +347,7 @@ variable {M N} @[to_additive (attr := simp)] theorem swap_swap (x : M ∗ N) : swap N M (swap M N x) = x := - FunLike.congr_fun (swap_comp_swap _ _) x + DFunLike.congr_fun (swap_comp_swap _ _) x @[to_additive] theorem swap_comp_map (f : M →* M') (g : N →* N') : @@ -357,7 +357,7 @@ theorem swap_comp_map (f : M →* M') (g : N →* N') : @[to_additive] theorem swap_map (f : M →* M') (g : N →* N') (x : M ∗ N) : swap M' N' (map f g x) = map g f (swap M N x) := - FunLike.congr_fun (swap_comp_map f g) x + DFunLike.congr_fun (swap_comp_map f g) x @[to_additive (attr := simp)] theorem swap_comp_inl : (swap M N).comp inl = inr := rfl @[to_additive (attr := simp)] theorem swap_inl (x : M) : swap M N (inl x) = inr x := rfl @@ -436,7 +436,7 @@ theorem lift_comp_swap (f : M →* P) (g : N →* P) : (lift f g).comp (swap N M @[to_additive (attr := simp)] theorem lift_swap (f : M →* P) (g : N →* P) (x : N ∗ M) : lift f g (swap N M x) = lift g f x := - FunLike.congr_fun (lift_comp_swap f g) x + DFunLike.congr_fun (lift_comp_swap f g) x @[to_additive] theorem comp_lift {P' : Type*} [Monoid P'] (f : P →* P') (g₁ : M →* P) (g₂ : N →* P) : diff --git a/Mathlib/GroupTheory/CoprodI.lean b/Mathlib/GroupTheory/CoprodI.lean index d81144d4b1d9f..20dbc97441cf5 100644 --- a/Mathlib/GroupTheory/CoprodI.lean +++ b/Mathlib/GroupTheory/CoprodI.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.FreeMonoid.Basic import Mathlib.GroupTheory.Congruence import Mathlib.GroupTheory.FreeGroup.IsFreeGroup import Mathlib.Data.List.Chain -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Basic import Mathlib.Data.Set.Pointwise.SMul #align_import group_theory.free_product from "leanprover-community/mathlib"@"9114ddffa023340c9ec86965e00cdd6fe26fcdf6" diff --git a/Mathlib/GroupTheory/Coset.lean b/Mathlib/GroupTheory/Coset.lean index 79fa7d80c42af..7937748e6567d 100644 --- a/Mathlib/GroupTheory/Coset.lean +++ b/Mathlib/GroupTheory/Coset.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Quotient import Mathlib.Data.Fintype.Prod import Mathlib.GroupTheory.GroupAction.Basic import Mathlib.GroupTheory.Subgroup.MulOpposite +import Mathlib.GroupTheory.Subgroup.Actions #align_import group_theory.coset from "leanprover-community/mathlib"@"f7fc89d5d5ff1db2d1242c7bb0e9062ce47ef47c" diff --git a/Mathlib/GroupTheory/DoubleCoset.lean b/Mathlib/GroupTheory/DoubleCoset.lean index 3d2435e0762c9..8ce528c55f618 100644 --- a/Mathlib/GroupTheory/DoubleCoset.lean +++ b/Mathlib/GroupTheory/DoubleCoset.lean @@ -178,7 +178,7 @@ theorem doset_union_rightCoset (H K : Subgroup G) (a : G) : constructor · rintro ⟨y, h_h⟩ refine' ⟨x * (y⁻¹ * a⁻¹), h_h, y, y.2, _⟩ - simp only [← mul_assoc, Subgroup.coe_mk, inv_mul_cancel_right, SubgroupClass.coe_inv] + simp only [← mul_assoc, Subgroup.coe_mk, inv_mul_cancel_right, InvMemClass.coe_inv] · rintro ⟨x, hx, y, hy, hxy⟩ refine' ⟨⟨y, hy⟩, _⟩ simp only [hxy, ← mul_assoc, hx, mul_inv_cancel_right, Subgroup.coe_mk] @@ -191,7 +191,7 @@ theorem doset_union_leftCoset (H K : Subgroup G) (a : G) : constructor · rintro ⟨y, h_h⟩ refine' ⟨y, y.2, a⁻¹ * y⁻¹ * x, h_h, _⟩ - simp only [← mul_assoc, one_mul, mul_right_inv, mul_inv_cancel_right, SubgroupClass.coe_inv] + simp only [← mul_assoc, one_mul, mul_right_inv, mul_inv_cancel_right, InvMemClass.coe_inv] · rintro ⟨x, hx, y, hy, hxy⟩ refine' ⟨⟨x, hx⟩, _⟩ simp only [hxy, ← mul_assoc, hy, one_mul, mul_left_inv, Subgroup.coe_mk, inv_mul_cancel_right] diff --git a/Mathlib/GroupTheory/EckmannHilton.lean b/Mathlib/GroupTheory/EckmannHilton.lean index d9cd17e0f947f..a986d6bd2b231 100644 --- a/Mathlib/GroupTheory/EckmannHilton.lean +++ b/Mathlib/GroupTheory/EckmannHilton.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Kenny Lau, Robert Y. Lewis -/ import Mathlib.Algebra.Group.Defs +import Mathlib.Init.Algebra.Classes #align_import group_theory.eckmann_hilton from "leanprover-community/mathlib"@"41cf0cc2f528dd40a8f2db167ea4fb37b8fde7f3" diff --git a/Mathlib/GroupTheory/Exponent.lean b/Mathlib/GroupTheory/Exponent.lean index f532888920a15..080b3db1e7deb 100644 --- a/Mathlib/GroupTheory/Exponent.lean +++ b/Mathlib/GroupTheory/Exponent.lean @@ -449,7 +449,7 @@ theorem Monoid.exponent_pi_eq_zero {ι : Type*} {M : ι → Type*} [∀ i, Monoi (hj : exponent (M j) = 0) : exponent ((i : ι) → M i) = 0 := by rw [@exponent_eq_zero_iff, ExponentExists] at hj ⊢ push_neg at hj ⊢ - peel hj with _ n hn + peel hj with n hn _ obtain ⟨m, hm⟩ := this refine ⟨Pi.mulSingle j m, fun h ↦ hm ?_⟩ simpa using congr_fun h j diff --git a/Mathlib/GroupTheory/FreeAbelianGroup.lean b/Mathlib/GroupTheory/FreeAbelianGroup.lean index e45e94d9d5b75..3c02dacb314f4 100644 --- a/Mathlib/GroupTheory/FreeAbelianGroup.lean +++ b/Mathlib/GroupTheory/FreeAbelianGroup.lean @@ -117,7 +117,7 @@ protected theorem of (x : α) : lift f (of x) = f x := by protected theorem unique (g : FreeAbelianGroup α →+ β) (hg : ∀ x, g (of x) = f x) {x} : g x = lift f x := - FunLike.congr_fun (lift.symm_apply_eq.mp (funext hg : g ∘ of = f)) _ + DFunLike.congr_fun (lift.symm_apply_eq.mp (funext hg : g ∘ of = f)) _ #align free_abelian_group.lift.unique FreeAbelianGroup.lift.unique /-- See note [partially-applied ext lemmas]. -/ diff --git a/Mathlib/GroupTheory/FreeGroup/Basic.lean b/Mathlib/GroupTheory/FreeGroup/Basic.lean index 4a10af8348449..48fcc6d42a73b 100644 --- a/Mathlib/GroupTheory/FreeGroup/Basic.lean +++ b/Mathlib/GroupTheory/FreeGroup/Basic.lean @@ -737,7 +737,7 @@ theorem lift.of {x} : lift f (of x) = f x := @[to_additive] theorem lift.unique (g : FreeGroup α →* β) (hg : ∀ x, g (FreeGroup.of x) = f x) {x} : g x = FreeGroup.lift f x := - FunLike.congr_fun (lift.symm_apply_eq.mp (funext hg : g ∘ FreeGroup.of = f)) x + DFunLike.congr_fun (lift.symm_apply_eq.mp (funext hg : g ∘ FreeGroup.of = f)) x #align free_group.lift.unique FreeGroup.lift.unique #align free_add_group.lift.unique FreeAddGroup.lift.unique @@ -754,7 +754,7 @@ theorem ext_hom {G : Type*} [Group G] (f g : FreeGroup α →* G) (h : ∀ a, f @[to_additive] theorem lift.of_eq (x : FreeGroup α) : lift FreeGroup.of x = x := - FunLike.congr_fun (lift.apply_symm_apply (MonoidHom.id _)) x + DFunLike.congr_fun (lift.apply_symm_apply (MonoidHom.id _)) x #align free_group.lift.of_eq FreeGroup.lift.of_eq #align free_add_group.lift.of_eq FreeAddGroup.lift.of_eq @@ -1363,7 +1363,7 @@ instance Red.decidableRel : DecidableRel (@Red α) if h : (x1, b1) = (x2, b2) then match Red.decidableRel tl1 tl2 with | isTrue H => isTrue <| h ▸ Red.cons_cons H - | isFalse H => isFalse fun H2 => H $ (Red.cons_cons_iff _).1 $ h.symm ▸ H2 + | isFalse H => isFalse fun H2 => H <| (Red.cons_cons_iff _).1 <| h.symm ▸ H2 else match Red.decidableRel tl1 ((x1, ! b1) :: (x2, b2) :: tl2) with | isTrue H => isTrue <| (Red.cons_cons H).tail Red.Step.cons_not diff --git a/Mathlib/GroupTheory/FreeGroup/IsFreeGroup.lean b/Mathlib/GroupTheory/FreeGroup/IsFreeGroup.lean index a26ba4bac968f..c64eff4cf797c 100644 --- a/Mathlib/GroupTheory/FreeGroup/IsFreeGroup.lean +++ b/Mathlib/GroupTheory/FreeGroup/IsFreeGroup.lean @@ -68,13 +68,13 @@ variable {ι ι' G H : Type*} [Group G] [Group H] /-- A free group basis for `G` over `ι` is associated to a map `ι → G` recording the images of the generators. -/ -instance funLike : FunLike (FreeGroupBasis ι G) ι (fun _ ↦ G) where +instance instFunLike : FunLike (FreeGroupBasis ι G) ι G where coe b := fun i ↦ b.repr.symm (FreeGroup.of i) coe_injective' := by rintro ⟨b⟩ ⟨b'⟩ hbb' have H : (b.symm : FreeGroup ι →* G) = (b'.symm : FreeGroup ι →* G) := by ext i; exact congr_fun hbb' i - have : b.symm = b'.symm := by ext x; exact FunLike.congr_fun H x + have : b.symm = b'.symm := by ext x; exact DFunLike.congr_fun H x rw [ofRepr.injEq, ← MulEquiv.symm_symm b, ← MulEquiv.symm_symm b', this] @[simp] lemma repr_apply_coe (b : FreeGroupBasis ι G) (i : ι) : b.repr (b i) = FreeGroup.of i := by diff --git a/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean b/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean index fee519dca5465..fdfafd0688214 100644 --- a/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean +++ b/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean @@ -120,7 +120,7 @@ instance actionGroupoidIsFree {G A : Type u} [Group G] [IsFreeGroup G] [MulActio refine' ⟨uncurry F' _, _, _⟩ · suffices SemidirectProduct.rightHom.comp F' = MonoidHom.id _ by -- Porting note: `MonoidHom.ext_iff` has been deprecated. - exact FunLike.ext_iff.mp this + exact DFunLike.ext_iff.mp this apply IsFreeGroup.ext_hom (fun x ↦ ?_) rw [MonoidHom.comp_apply, hF'] rfl diff --git a/Mathlib/GroupTheory/GroupAction/Basic.lean b/Mathlib/GroupTheory/GroupAction/Basic.lean index 7e0ea96048ec1..d0efa23a48d71 100644 --- a/Mathlib/GroupTheory/GroupAction/Basic.lean +++ b/Mathlib/GroupTheory/GroupAction/Basic.lean @@ -472,12 +472,12 @@ lemma stabilizer_smul_eq_left [SMul α β] [IsScalarTower G α β] (a : α) (b : @[to_additive (attr := simp)] lemma stabilizer_smul_eq_right [Group α] [MulAction α β] [SMulCommClass G α β] (a : α) (b : β) : stabilizer G (a • b) = stabilizer G b := - (le_stabilizer_smul_right _ _).antisymm' $ (le_stabilizer_smul_right a⁻¹ _).trans_eq $ by + (le_stabilizer_smul_right _ _).antisymm' <| (le_stabilizer_smul_right a⁻¹ _).trans_eq <| by rw [inv_smul_smul] @[to_additive (attr := simp)] lemma stabilizer_mul_eq_left [Group α] [IsScalarTower G α α] (a b : α) : - stabilizer G (a * b) = stabilizer G a := stabilizer_smul_eq_left a _ $ mul_left_injective _ + stabilizer G (a * b) = stabilizer G a := stabilizer_smul_eq_left a _ <| mul_left_injective _ @[to_additive (attr := simp)] lemma stabilizer_mul_eq_right [Group α] [SMulCommClass G α α] (a b : α) : diff --git a/Mathlib/GroupTheory/GroupAction/Defs.lean b/Mathlib/GroupTheory/GroupAction/Defs.lean index ca94760e61ee2..3a0b81717e9e7 100644 --- a/Mathlib/GroupTheory/GroupAction/Defs.lean +++ b/Mathlib/GroupTheory/GroupAction/Defs.lean @@ -458,24 +458,6 @@ theorem Commute.smul_left [Mul α] [SMulCommClass M α α] [IsScalarTower M α end -section ite - -variable [SMul M α] (p : Prop) [Decidable p] - -@[to_additive] -theorem ite_smul (a₁ a₂ : M) (b : α) : ite p a₁ a₂ • b = ite p (a₁ • b) (a₂ • b) := by - split_ifs <;> rfl -#align ite_smul ite_smul -#align ite_vadd ite_vadd - -@[to_additive] -theorem smul_ite (a : M) (b₁ b₂ : α) : a • ite p b₁ b₂ = ite p (a • b₁) (a • b₂) := by - split_ifs <;> rfl -#align smul_ite smul_ite -#align vadd_ite vadd_ite - -end ite - section variable [Monoid M] [MulAction M α] @@ -594,6 +576,16 @@ theorem smul_mul_smul [Mul α] (r s : M) (x y : α) [IsScalarTower M α α] [SMu #align smul_mul_smul smul_mul_smul #align vadd_add_vadd vadd_add_vadd +section Monoid +variable [Monoid N] [MulAction M N] [IsScalarTower M N N] [SMulCommClass M N N] + +lemma smul_pow (r : M) (x : N) : ∀ n, (r • x) ^ n = r ^ n • x ^ n + | 0 => by simp + | n + 1 => by rw [pow_succ', smul_pow _ _ n, smul_mul_smul, ← pow_succ', ← pow_succ'] +#align smul_pow smul_pow + +end Monoid + end namespace MulAction @@ -661,6 +653,19 @@ theorem isPretransitive_compHom obtain ⟨e, rfl⟩ : ∃ e, f e = m := hf m exact ⟨e, rfl⟩ +@[to_additive] +theorem IsPretransitive.of_smul_eq {M N α : Type*} [SMul M α] [SMul N α] + [IsPretransitive M α] (f : M → N) (hf : ∀ {c : M} {x : α}, f c • x = c • x) : + IsPretransitive N α := + ⟨fun x y ↦ (exists_smul_eq x y).elim fun m h ↦ ⟨f m, hf.trans h⟩⟩ + +@[to_additive] +theorem IsPretransitive.of_compHom + {M N α : Type*} [Monoid M] [Monoid N] [MulAction N α] + (f : M →* N) [h : letI := compHom α f; IsPretransitive M α] : + IsPretransitive N α := + letI := compHom α f; h.of_smul_eq f rfl + end MulAction end @@ -674,6 +679,12 @@ theorem smul_one_smul {M} (N) [Monoid N] [SMul M N] [MulAction N α] [SMul M α] #align smul_one_smul smul_one_smul #align vadd_zero_vadd vadd_zero_vadd +@[to_additive] +theorem MulAction.IsPretransitive.of_isScalarTower (M : Type*) {N α : Type*} [Monoid N] [SMul M N] + [MulAction N α] [SMul M α] [IsScalarTower M N α] [IsPretransitive M α] : + IsPretransitive N α := + of_smul_eq (fun x : M ↦ x • 1) (smul_one_smul N _ _) + @[to_additive (attr := simp)] theorem smul_one_mul {M N} [MulOneClass N] [SMul M N] [IsScalarTower M N N] (x : M) (y : N) : x • (1 : N) * y = x • y := by rw [smul_mul_assoc, one_mul] @@ -715,6 +726,17 @@ def MonoidHom.smulOneHom {M N} [Monoid M] [MulOneClass N] [MulAction M N] [IsSca #align smul_one_hom_apply MonoidHom.smulOneHom_apply #align vadd_zero_hom_apply AddMonoidHom.vaddZeroHom_apply +/-- A monoid homomorphism between two monoids M and N can be equivalently specified by a +multiplicative action of M on N that is compatible with the multiplication on N. -/ +@[to_additive "A monoid homomorphism between two additive monoids M and N can be equivalently + specified by an additive action of M on N that is compatible with the addition on N."] +def monoidHomEquivMulActionIsScalarTower (M N) [Monoid M] [Monoid N] : + (M →* N) ≃ {_inst : MulAction M N // IsScalarTower M N N} where + toFun f := ⟨MulAction.compHom N f, SMul.comp.isScalarTower _⟩ + invFun := fun ⟨_, _⟩ ↦ MonoidHom.smulOneHom + left_inv f := MonoidHom.ext fun m ↦ mul_one (f m) + right_inv := fun ⟨_, _⟩ ↦ Subtype.ext <| MulAction.ext _ _ <| funext₂ <| smul_one_smul N + end CompatibleScalar /-- Typeclass for scalar multiplication that preserves `0` on the right. -/ @@ -732,9 +754,8 @@ theorem smul_zero (a : M) : a • (0 : A) = 0 := SMulZeroClass.smul_zero _ #align smul_zero smul_zero -@[simp] lemma smul_ite_zero (p : Prop) [Decidable p] (a : M) (b : A) : - (a • if p then b else 0) = if p then a • b else 0 := by rw [smul_ite, smul_zero] + (a • if p then b else 0) = if p then a • b else 0 := by split_ifs <;> simp /-- Pullback a zero-preserving scalar multiplication along an injective zero-preserving map. See note [reducible non-instances]. -/ @@ -1069,6 +1090,10 @@ theorem MulDistribMulAction.toMonoidHom_apply (r : M) (x : A) : rfl #align mul_distrib_mul_action.to_monoid_hom_apply MulDistribMulAction.toMonoidHom_apply +@[simp] lemma smul_pow' (r : M) (x : A) (n : ℕ) : r • x ^ n = (r • x) ^ n := + (MulDistribMulAction.toMonoidHom _ _).map_pow _ _ +#align smul_pow' smul_pow' + variable (M A) /-- Each element of the monoid defines a monoid homomorphism. -/ diff --git a/Mathlib/GroupTheory/GroupAction/DomAct/ActionHom.lean b/Mathlib/GroupTheory/GroupAction/DomAct/ActionHom.lean index caa6ab453b23c..5746068e7ae37 100644 --- a/Mathlib/GroupTheory/GroupAction/DomAct/ActionHom.lean +++ b/Mathlib/GroupTheory/GroupAction/DomAct/ActionHom.lean @@ -33,7 +33,7 @@ instance : SMul Mᵈᵐᵃ (α →[N] β) where instance [SMul M' α] [SMulCommClass M' N α] [SMulCommClass M M' α] : SMulCommClass Mᵈᵐᵃ M'ᵈᵐᵃ (α →[N] β) := - FunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) + DFunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) theorem smul_mulActionHom_apply (c : Mᵈᵐᵃ) (f : α →[N] β) (a : α) : (c • f) a = f (mk.symm c • a) := @@ -46,7 +46,7 @@ end SMul instance [Monoid M] [MulAction M α] [SMul N α] [SMulCommClass M N α] [SMul N β] : MulAction Mᵈᵐᵃ (α →[N] β) := - FunLike.coe_injective.mulAction _ fun _ _ ↦ rfl + DFunLike.coe_injective.mulAction _ fun _ _ ↦ rfl end MulActionHom @@ -62,7 +62,7 @@ instance : SMul Mᵈᵐᵃ (A →+[N] B) where instance [DistribSMul M' A] [SMulCommClass M' N A] [SMulCommClass M M' A] : SMulCommClass Mᵈᵐᵃ M'ᵈᵐᵃ (A →+[N] B) := - FunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) + DFunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) theorem smul_mulDistribActionHom_apply (c : Mᵈᵐᵃ) (f : A →+[N] B) (a : A) : (c • f) a = f (mk.symm c • a) := @@ -77,7 +77,7 @@ end SMul instance [Monoid M] [AddMonoid A] [DistribMulAction M A] [Monoid N] [AddMonoid B] [DistribMulAction N A] [SMulCommClass M N A] [DistribMulAction N B] : MulAction Mᵈᵐᵃ (A →+[N] B) := - FunLike.coe_injective.mulAction _ fun _ _ ↦ rfl + DFunLike.coe_injective.mulAction _ fun _ _ ↦ rfl end DistribMulActionHom diff --git a/Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean b/Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean index f469c600938f6..8b943b631b2eb 100644 --- a/Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean +++ b/Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean @@ -203,7 +203,7 @@ instance : SMul Mᵈᵐᵃ (A →* B) where instance [Monoid M'] [MulDistribMulAction M' A] [SMulCommClass M M' A] : SMulCommClass Mᵈᵐᵃ M'ᵈᵐᵃ (A →* B) := - FunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) + DFunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) theorem smul_monoidHom_apply (c : Mᵈᵐᵃ) (f : A →* B) (a : A) : (c • f) a = f (mk.symm c • a) := rfl @@ -211,7 +211,7 @@ theorem smul_monoidHom_apply (c : Mᵈᵐᵃ) (f : A →* B) (a : A) : (c • f) @[simp] theorem mk_smul_monoidHom_apply (c : M) (f : A →* B) (a : A) : (mk c • f) a = f (c • a) := rfl -instance : MulAction Mᵈᵐᵃ (A →* B) := FunLike.coe_injective.mulAction (⇑) fun _ _ ↦ rfl +instance : MulAction Mᵈᵐᵃ (A →* B) := DFunLike.coe_injective.mulAction (⇑) fun _ _ ↦ rfl end MonoidHom @@ -225,10 +225,10 @@ instance : SMul Mᵈᵐᵃ (A →+ B) where smul c f := f.comp (DistribSMul.toAddMonoidHom _ (mk.symm c)) instance [DistribSMul M' A] [SMulCommClass M M' A] : SMulCommClass Mᵈᵐᵃ M'ᵈᵐᵃ (A →+ B) := - FunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) + DFunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) instance [DistribSMul M' B] : SMulCommClass Mᵈᵐᵃ M' (A →+ B) := - FunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) + DFunLike.coe_injective.smulCommClass (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) theorem smul_addMonoidHom_apply (c : Mᵈᵐᵃ) (f : A →+ B) (a : A) : (c • f) a = f (mk.symm c • a) := rfl @@ -239,10 +239,10 @@ theorem mk_smul_addMonoidHom_apply (c : M) (f : A →+ B) (a : A) : (mk c • f) end DistribSMul instance [Monoid M] [AddMonoid A] [DistribMulAction M A] [AddZeroClass B] : - MulAction Mᵈᵐᵃ (A →+ B) := FunLike.coe_injective.mulAction (⇑) fun _ _ ↦ rfl + MulAction Mᵈᵐᵃ (A →+ B) := DFunLike.coe_injective.mulAction (⇑) fun _ _ ↦ rfl instance [Monoid M] [AddMonoid A] [DistribMulAction M A] [AddCommMonoid B] : DistribMulAction Mᵈᵐᵃ (A →+ B) := - FunLike.coe_injective.distribMulAction (AddMonoidHom.coeFn A B) fun _ _ ↦ rfl + DFunLike.coe_injective.distribMulAction (AddMonoidHom.coeFn A B) fun _ _ ↦ rfl end AddMonoidHom diff --git a/Mathlib/GroupTheory/GroupAction/Embedding.lean b/Mathlib/GroupTheory/GroupAction/Embedding.lean index cf1ff2667ee11..685b68c91221b 100644 --- a/Mathlib/GroupTheory/GroupAction/Embedding.lean +++ b/Mathlib/GroupTheory/GroupAction/Embedding.lean @@ -62,6 +62,6 @@ instance [Group G] [MulAction G β] [MulAction Gᵐᵒᵖ β] [IsCentralScalar G @[to_additive] instance [Group G] [MulAction G β] : MulAction G (α ↪ β) := - FunLike.coe_injective.mulAction _ coe_smul + DFunLike.coe_injective.mulAction _ coe_smul end Function.Embedding diff --git a/Mathlib/GroupTheory/GroupAction/Group.lean b/Mathlib/GroupTheory/GroupAction/Group.lean index 4a04482a7b66c..66531b995e7e1 100644 --- a/Mathlib/GroupTheory/GroupAction/Group.lean +++ b/Mathlib/GroupTheory/GroupAction/Group.lean @@ -294,20 +294,6 @@ theorem smul_ne_zero_iff_ne (a : α) {x : β} : a • x ≠ 0 ↔ x ≠ 0 := end Group -section Gwz - -variable [GroupWithZero α] [AddMonoid β] [DistribMulAction α β] - -theorem smul_eq_zero_iff_eq' {a : α} (ha : a ≠ 0) {x : β} : a • x = 0 ↔ x = 0 := - show Units.mk0 a ha • x = 0 ↔ x = 0 from smul_eq_zero_iff_eq _ -#align smul_eq_zero_iff_eq' smul_eq_zero_iff_eq' - -theorem smul_ne_zero_iff_ne' {a : α} (ha : a ≠ 0) {x : β} : a • x ≠ 0 ↔ x ≠ 0 := - show Units.mk0 a ha • x ≠ 0 ↔ x ≠ 0 from smul_ne_zero_iff_ne _ -#align smul_ne_zero_iff_ne' smul_ne_zero_iff_ne' - -end Gwz - end DistribMulAction section MulDistribMulAction diff --git a/Mathlib/GroupTheory/GroupAction/Hom.lean b/Mathlib/GroupTheory/GroupAction/Hom.lean index ef8debb3840dc..69e39e5a86cd3 100644 --- a/Mathlib/GroupTheory/GroupAction/Hom.lean +++ b/Mathlib/GroupTheory/GroupAction/Hom.lean @@ -76,7 +76,7 @@ scalar multiplication by `M`. You should extend this class when you extend `MulActionHom`. -/ class SMulHomClass (F : Type*) (M X Y : outParam <| Type*) [SMul M X] [SMul M Y] extends - FunLike F X fun _ => Y where + DFunLike F X fun _ => Y where /-- The proposition that the function preserves the action. -/ map_smul : ∀ (f : F) (c : M) (x : X), f (c • x) = c • f x #align smul_hom_class SMulHomClass @@ -109,7 +109,7 @@ see also Algebra.Hom.Group -/ @[coe] def _root_.SMulHomClass.toMulActionHom [SMul M X] [SMul M Y] [SMulHomClass F M X Y] (f : F) : X →[M] Y where - toFun := FunLike.coe f + toFun := DFunLike.coe f map_smul' := map_smul f /-- Any type satisfying `SMulHomClass` can be cast into `MulActionHom` via @@ -117,21 +117,28 @@ def _root_.SMulHomClass.toMulActionHom [SMul M X] [SMul M Y] [SMulHomClass F M X instance [SMul M X] [SMul M Y] [SMulHomClass F M X Y] : CoeTC F (X →[M] Y) := ⟨SMulHomClass.toMulActionHom⟩ +variable (M' X Y F) in +/-- If Y/X/M forms a scalar tower, any map X → Y preserving X-action also preserves M-action. -/ +def _root_.IsScalarTower.smulHomClass [MulOneClass X] [SMul X Y] [IsScalarTower M' X Y] + [SMulHomClass F X X Y] : SMulHomClass F M' X Y where + map_smul f m x := by + rw [← mul_one (m • x), ← smul_eq_mul, map_smul, smul_assoc, ← map_smul, smul_eq_mul, mul_one] + protected theorem map_smul (f : X →[M'] Y) (m : M') (x : X) : f (m • x) = m • f x := map_smul f m x #align mul_action_hom.map_smul MulActionHom.map_smul @[ext] theorem ext {f g : X →[M'] Y} : (∀ x, f x = g x) → f = g := - FunLike.ext f g + DFunLike.ext f g #align mul_action_hom.ext MulActionHom.ext theorem ext_iff {f g : X →[M'] Y} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align mul_action_hom.ext_iff MulActionHom.ext_iff protected theorem congr_fun {f g : X →[M'] Y} (h : f = g) (x : X) : f x = g x := - FunLike.congr_fun h _ + DFunLike.congr_fun h _ #align mul_action_hom.congr_fun MulActionHom.congr_fun variable (M M') @@ -286,15 +293,15 @@ theorem coe_fn_coe' (f : A →+[M] B) : ⇑(f : A →[M] B) = f := @[ext] theorem ext {f g : A →+[M] B} : (∀ x, f x = g x) → f = g := - FunLike.ext f g + DFunLike.ext f g #align distrib_mul_action_hom.ext DistribMulActionHom.ext theorem ext_iff {f g : A →+[M] B} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align distrib_mul_action_hom.ext_iff DistribMulActionHom.ext_iff protected theorem congr_fun {f g : A →+[M] B} (h : f = g) (x : A) : f x = g x := - FunLike.congr_fun h _ + DFunLike.congr_fun h _ #align distrib_mul_action_hom.congr_fun DistribMulActionHom.congr_fun theorem toMulActionHom_injective {f g : A →+[M] B} (h : (f : A →[M] B) = (g : A →[M] B)) : @@ -305,7 +312,7 @@ theorem toMulActionHom_injective {f g : A →+[M] B} (h : (f : A →[M] B) = (g theorem toAddMonoidHom_injective {f g : A →+[M] B} (h : (f : A →+ B) = (g : A →+ B)) : f = g := by ext a - exact FunLike.congr_fun h a + exact DFunLike.congr_fun h a #align distrib_mul_action_hom.to_add_monoid_hom_injective DistribMulActionHom.toAddMonoidHom_injective protected theorem map_zero (f : A →+[M] B) : f 0 = 0 := @@ -518,11 +525,11 @@ theorem coe_fn_coe' (f : R →+*[M] S) : ⇑(f : R →+[M] S) = f := @[ext] theorem ext {f g : R →+*[M] S} : (∀ x, f x = g x) → f = g := - FunLike.ext f g + DFunLike.ext f g #align mul_semiring_action_hom.ext MulSemiringActionHom.ext theorem ext_iff {f g : R →+*[M] S} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align mul_semiring_action_hom.ext_iff MulSemiringActionHom.ext_iff protected theorem map_zero (f : R →+*[M] S) : f 0 = 0 := diff --git a/Mathlib/GroupTheory/GroupAction/Units.lean b/Mathlib/GroupTheory/GroupAction/Units.lean index 54d1e4dc7efdb..1fe32a26b9b49 100644 --- a/Mathlib/GroupTheory/GroupAction/Units.lean +++ b/Mathlib/GroupTheory/GroupAction/Units.lean @@ -5,6 +5,7 @@ Authors: Eric Wieser -/ import Mathlib.Algebra.Group.Units import Mathlib.GroupTheory.GroupAction.Defs +import Mathlib.Tactic.Common #align_import group_theory.group_action.units from "leanprover-community/mathlib"@"f1a2caaf51ef593799107fe9a8d5e411599f3996" @@ -53,25 +54,24 @@ instance [Monoid M] [SMul M α] [FaithfulSMul M α] : FaithfulSMul Mˣ α where eq_of_smul_eq_smul h := Units.ext <| eq_of_smul_eq_smul h @[to_additive] -instance [Monoid M] [MulAction M α] : - MulAction Mˣ α where +instance instMulAction [Monoid M] [MulAction M α] : MulAction Mˣ α where one_smul := (one_smul M : _) mul_smul m n := mul_smul (m : M) n -instance [Monoid M] [Zero α] [SMulZeroClass M α] : - SMulZeroClass Mˣ α where +instance instSMulZeroClass [Monoid M] [Zero α] [SMulZeroClass M α] : SMulZeroClass Mˣ α where smul := (· • ·) smul_zero m := smul_zero (m : M) instance instDistribSMulUnits [Monoid M] [AddZeroClass α] [DistribSMul M α] : DistribSMul Mˣ α where smul_add m := smul_add (m : M) -instance [Monoid M] [AddMonoid α] [DistribMulAction M α] : DistribMulAction Mˣ α := - { instDistribSMulUnits with - one_smul := fun b => one_smul M b - mul_smul := fun x y b => mul_smul (x : M) y b } +instance instDistribMulAction [Monoid M] [AddMonoid α] [DistribMulAction M α] : + DistribMulAction Mˣ α where + __ := instDistribSMulUnits + one_smul := fun b => one_smul M b + mul_smul := fun x y b => mul_smul (x : M) y b -instance [Monoid M] [Monoid α] [MulDistribMulAction M α] : +instance instMulDistribMulAction [Monoid M] [Monoid α] [MulDistribMulAction M α] : MulDistribMulAction Mˣ α where smul_mul m := smul_mul' (m : M) smul_one m := smul_one (m : M) diff --git a/Mathlib/GroupTheory/MonoidLocalization.lean b/Mathlib/GroupTheory/MonoidLocalization.lean index 62af25259b56c..0b29d229d042e 100644 --- a/Mathlib/GroupTheory/MonoidLocalization.lean +++ b/Mathlib/GroupTheory/MonoidLocalization.lean @@ -7,6 +7,7 @@ import Mathlib.Init.Data.Prod import Mathlib.GroupTheory.Congruence import Mathlib.GroupTheory.Submonoid.Membership import Mathlib.Algebra.Group.Units +import Mathlib.Algebra.Regular.Basic #align_import group_theory.monoid_localization from "leanprover-community/mathlib"@"10ee941346c27bdb5e87bb3535100c0b1f08ac41" @@ -568,7 +569,7 @@ theorem ext_iff {f g : LocalizationMap S N} : f = g ↔ ∀ x, f.toMap x = g.toM @[to_additive] theorem toMap_injective : Function.Injective (@LocalizationMap.toMap _ _ S N _) := - fun _ _ h ↦ ext <| FunLike.ext_iff.1 h + fun _ _ h ↦ ext <| DFunLike.ext_iff.1 h #align submonoid.localization_map.to_map_injective Submonoid.LocalizationMap.toMap_injective #align add_submonoid.localization_map.to_map_injective AddSubmonoid.LocalizationMap.toMap_injective @@ -584,6 +585,21 @@ theorem surj (f : LocalizationMap S N) (z : N) : ∃ x : M × S, z * f.toMap x.2 #align submonoid.localization_map.surj Submonoid.LocalizationMap.surj #align add_submonoid.localization_map.surj AddSubmonoid.LocalizationMap.surj +/-- Given a localization map `f : M →* N`, and `z w : N`, there exist `z' w' : M` and `d : S` +such that `f z' / f d = z` and `f w' / f d = w`. -/ +@[to_additive + "Given a localization map `f : M →+ N`, and `z w : N`, there exist `z' w' : M` and `d : S` +such that `f z' - f d = z` and `f w' - f d = w`."] +theorem surj₂ (f : LocalizationMap S N) (z w : N) : ∃ z' w' : M, ∃ d : S, + (z * f.toMap d = f.toMap z') ∧ (w * f.toMap d = f.toMap w') := by + let ⟨a, ha⟩ := surj f z + let ⟨b, hb⟩ := surj f w + refine ⟨a.1 * b.2, a.2 * b.1, a.2 * b.2, ?_, ?_⟩ + · simp_rw [mul_def, map_mul, ← ha] + exact (mul_assoc z _ _).symm + · simp_rw [mul_def, map_mul, ← hb] + exact mul_left_comm w _ _ + @[to_additive] theorem eq_iff_exists (f : LocalizationMap S N) {x y} : f.toMap x = f.toMap y ↔ ∃ c : S, ↑c * x = c * y := Iff.intro (f.4 x y) @@ -844,6 +860,12 @@ theorem mk'_cancel (a : M) (b c : S) : f.mk' (a * c) (b * c) = f.mk' a b := mk'_eq_of_eq' f (by rw [Submonoid.coe_mul, mul_comm (b:M), mul_assoc]) +@[to_additive] +theorem mk'_eq_of_same {a b} {d : S} : + f.mk' a d = f.mk' b d ↔ ∃ c : S, c * a = c * b := by + rw [mk'_eq_iff_eq', map_mul, map_mul, ← eq_iff_exists f] + exact (map_units f d).mul_left_inj + @[to_additive (attr := simp)] theorem mk'_self' (y : S) : f.mk' (y : M) y = 1 := show _ * _ = _ by rw [mul_inv_left, mul_one] @@ -1061,7 +1083,7 @@ theorem lift_unique {j : N →* P} (hj : ∀ x, j (f.toMap x) = g x) : f.lift hg @[to_additive (attr := simp)] theorem lift_id (x) : f.lift f.map_units x = x := - FunLike.ext_iff.1 (f.lift_of_comp <| MonoidHom.id N) x + DFunLike.ext_iff.1 (f.lift_of_comp <| MonoidHom.id N) x #align submonoid.localization_map.lift_id Submonoid.LocalizationMap.lift_id #align add_submonoid.localization_map.lift_id AddSubmonoid.LocalizationMap.lift_id @@ -1251,6 +1273,25 @@ theorem map_map {A : Type*} [CommMonoid A] {U : Submonoid A} {R} [CommMonoid R] #align submonoid.localization_map.map_map Submonoid.LocalizationMap.map_map #align add_submonoid.localization_map.map_map AddSubmonoid.LocalizationMap.map_map +/-- Given an injective `CommMonoid` homomorphism `g : M →* P`, and a submonoid `S ⊆ M`, +the induced monoid homomorphism from the localization of `M` at `S` to the +localization of `P` at `g S`, is injective. +-/ +@[to_additive "Given an injective `AddCommMonoid` homomorphism `g : M →+ P`, and a +submonoid `S ⊆ M`, the induced monoid homomorphism from the localization of `M` at `S` +to the localization of `P` at `g S`, is injective. "] +theorem map_injective_of_injective (hg : Injective g) (k : LocalizationMap (S.map g) Q) : + Injective (map f (apply_coe_mem_map g S) k) := fun z w hizw ↦ by + set i := map f (apply_coe_mem_map g S) k + have ifkg (a : M) : i (f.toMap a) = k.toMap (g a) := map_eq f (apply_coe_mem_map g S) a + let ⟨z', w', x, hxz, hxw⟩ := surj₂ f z w + have : k.toMap (g z') = k.toMap (g w') + · rw [← ifkg, ← ifkg, ← hxz, ← hxw, map_mul, map_mul, hizw] + obtain ⟨⟨_, c, hc, rfl⟩, eq⟩ := k.exists_of_eq _ _ this + simp_rw [← map_mul, hg.eq_iff] at eq + rw [← (f.map_units x).mul_left_inj, hxz, hxw, f.eq_iff_exists] + exact ⟨⟨c, hc⟩, eq⟩ + section AwayMap variable (x : M) @@ -1460,7 +1501,7 @@ theorem mulEquivOfLocalizations_right_inv_apply {k : LocalizationMap S P} {x} : @[to_additive] theorem mulEquivOfLocalizations_left_inv (k : N ≃* P) : f.mulEquivOfLocalizations (f.ofMulEquivOfLocalizations k) = k := - FunLike.ext _ _ fun x ↦ FunLike.ext_iff.1 (f.lift_of_comp k.toMonoidHom) x + DFunLike.ext _ _ fun x ↦ DFunLike.ext_iff.1 (f.lift_of_comp k.toMonoidHom) x #align submonoid.localization_map.mul_equiv_of_localizations_left_inv Submonoid.LocalizationMap.mulEquivOfLocalizations_left_inv #align add_submonoid.localization_map.add_equiv_of_localizations_left_neg AddSubmonoid.LocalizationMap.addEquivOfLocalizations_left_neg @@ -1609,6 +1650,21 @@ theorem of_mulEquivOfMulEquiv {k : LocalizationMap T Q} {j : M ≃* P} (H : S.ma #align submonoid.localization_map.of_mul_equiv_of_mul_equiv Submonoid.LocalizationMap.of_mulEquivOfMulEquiv #align add_submonoid.localization_map.of_add_equiv_of_add_equiv AddSubmonoid.LocalizationMap.of_addEquivOfAddEquiv +@[to_additive] +theorem toMap_injective_iff (f : LocalizationMap S N) : + Injective (LocalizationMap.toMap f) ↔ ∀ ⦃x⦄, x ∈ S → IsLeftRegular x := by + rw [Injective] + constructor <;> intro h + · intro x hx y z hyz + simp_rw [LocalizationMap.eq_iff_exists] at h + apply (fun y z _ => h) y z x + lift x to S using hx + use x + · intro a b hab + rw [LocalizationMap.eq_iff_exists] at hab + obtain ⟨c,hc⟩ := hab + apply (fun x a => h a) c (SetLike.coe_mem c) hc + end LocalizationMap end Submonoid @@ -1886,6 +1942,59 @@ noncomputable def lift (f : LocalizationWithZeroMap S N) (g : M →*₀ P) exact f.toMonoidWithZeroHom.map_zero.symm } #align submonoid.localization_with_zero_map.lift Submonoid.LocalizationWithZeroMap.lift +/-- Given a Localization map `f : M →*₀ N` for a Submonoid `S ⊆ M`, +if `M` is left cancellative monoid with zero, and all elements of `S` are +left regular, then N is a left cancellative monoid with zero. -/ +theorem leftCancelMulZero_of_le_isLeftRegular + (f : LocalizationWithZeroMap S N) [IsLeftCancelMulZero M] + (h : ∀ ⦃x⦄, x ∈ S → IsLeftRegular x) : IsLeftCancelMulZero N := by + let fl := f.toLocalizationMap + let g := f.toMap + constructor + intro a z w ha hazw + obtain ⟨b, hb⟩ := LocalizationMap.surj fl a + obtain ⟨x, hx⟩ := LocalizationMap.surj fl z + obtain ⟨y, hy⟩ := LocalizationMap.surj fl w + rw [(LocalizationMap.eq_mk'_iff_mul_eq fl).mpr hx, + (LocalizationMap.eq_mk'_iff_mul_eq fl).mpr hy, LocalizationMap.eq] + use 1 + rw [OneMemClass.coe_one, one_mul, one_mul] + -- The hypothesis `a ≠ 0` in `P` is equivalent to this + have b1ne0 : b.1 ≠ 0 := by + intro hb1 + have m0 : (LocalizationMap.toMap fl) 0 = 0 := f.map_zero' + have a0 : a * (LocalizationMap.toMap fl) b.2 = 0 ↔ a = 0 := + (f.toLocalizationMap.map_units' b.2).mul_left_eq_zero + rw [hb1, m0, a0] at hb + exact ha hb + have main : g (b.1 * (x.2 * y.1)) = g (b.1 * (y.2 * x.1)) := + calc + g (b.1 * (x.2 * y.1)) = g b.1 * (g x.2 * g y.1) := by rw[map_mul g,map_mul g] + _ = a * g b.2 * (g x.2 * (w * g y.2)) := by rw[hb, hy] + _ = a * w * g b.2 * (g x.2 * g y.2) := by + rw [← mul_assoc, ← mul_assoc _ w, mul_comm _ w, mul_assoc w, mul_assoc, + ← mul_assoc w, ← mul_assoc w, mul_comm w] + _ = a * z * g b.2 * (g x.2 * g y.2) := by rw [hazw] + _ = a * g b.2 * (z * g x.2 * g y.2) := by + rw [mul_assoc a, mul_comm z, ← mul_assoc a, mul_assoc, mul_assoc z] + _ = g b.1 * g (y.2 * x.1) := by rw [hx, hb, mul_comm (g x.1), ← map_mul g] + _ = g (b.1 * (y.2 * x.1)):= by rw [← map_mul g] + -- The hypothesis `h` gives that `f` (so, `g`) is injective, and we can cancel out `b.1`. + exact (IsLeftCancelMulZero.mul_left_cancel_of_ne_zero b1ne0 + ((LocalizationMap.toMap_injective_iff fl).mpr h main)).symm + +/-- Given a Localization map `f : M →*₀ N` for a Submonoid `S ⊆ M`, +if `M` is a cancellative monoid with zero, and all elements of `S` are +regular, then N is a cancellative monoid with zero. -/ +theorem isLeftRegular_of_le_isCancelMulZero (f : LocalizationWithZeroMap S N) + [IsCancelMulZero M] (h : ∀ ⦃x⦄, x ∈ S → IsRegular x) : IsCancelMulZero N := by + have : IsLeftCancelMulZero N := + leftCancelMulZero_of_le_isLeftRegular f (fun x h' => (h h').left) + exact IsLeftCancelMulZero.to_isCancelMulZero + +@[deprecated isLeftRegular_of_le_isCancelMulZero] -- 2024-01-16 +alias isLeftRegular_of_le_IsCancelMulZero := isLeftRegular_of_le_isCancelMulZero + end LocalizationWithZeroMap end Submonoid @@ -1898,16 +2007,12 @@ variable {α : Type*} [CancelCommMonoid α] {s : Submonoid α} {a₁ b₁ : α} @[to_additive] theorem mk_left_injective (b : s) : Injective fun a => mk a b := fun c d h => by - -- porting note: times out unless we add this `have`. Even `infer_instance` times out here. - have : Nonempty s := One.nonempty simpa [-mk_eq_monoidOf_mk', mk_eq_mk_iff, r_iff_exists] using h #align localization.mk_left_injective Localization.mk_left_injective #align add_localization.mk_left_injective AddLocalization.mk_left_injective @[to_additive] theorem mk_eq_mk_iff' : mk a₁ a₂ = mk b₁ b₂ ↔ ↑b₂ * a₁ = a₂ * b₁ := by - -- porting note: times out unless we add this `have`. Even `inferInstance` times out here. - have : Nonempty s := One.nonempty simp_rw [mk_eq_mk_iff, r_iff_exists, mul_left_cancel_iff, exists_const] #align localization.mk_eq_mk_iff' Localization.mk_eq_mk_iff' #align add_localization.mk_eq_mk_iff' AddLocalization.mk_eq_mk_iff' @@ -1934,7 +2039,7 @@ variable [OrderedCancelCommMonoid α] {s : Submonoid α} {a₁ b₁ : α} {a₂ instance le : LE (Localization s) := ⟨fun a b => Localization.liftOn₂ a b (fun a₁ a₂ b₁ b₂ => ↑b₂ * a₁ ≤ a₂ * b₁) - @fun a₁ b₁ a₂ b₂ c₁ d₁ c₂ d₂ hab hcd => propext $ by + @fun a₁ b₁ a₂ b₂ c₁ d₁ c₂ d₂ hab hcd => propext <| by obtain ⟨e, he⟩ := r_iff_exists.1 hab obtain ⟨f, hf⟩ := r_iff_exists.1 hcd simp only [mul_right_inj] at he hf @@ -1947,7 +2052,7 @@ instance le : LE (Localization s) := instance lt : LT (Localization s) := ⟨fun a b => Localization.liftOn₂ a b (fun a₁ a₂ b₁ b₂ => ↑b₂ * a₁ < a₂ * b₁) - @fun a₁ b₁ a₂ b₂ c₁ d₁ c₂ d₂ hab hcd => propext $ by + @fun a₁ b₁ a₂ b₂ c₁ d₁ c₂ d₂ hab hcd => propext <| by obtain ⟨e, he⟩ := r_iff_exists.1 hab obtain ⟨f, hf⟩ := r_iff_exists.1 hcd simp only [mul_right_inj] at he hf diff --git a/Mathlib/GroupTheory/Nilpotent.lean b/Mathlib/GroupTheory/Nilpotent.lean index 1c933459f59ed..78722fb41d675 100644 --- a/Mathlib/GroupTheory/Nilpotent.lean +++ b/Mathlib/GroupTheory/Nilpotent.lean @@ -662,7 +662,7 @@ the group quotiented by its center. -/ theorem nilpotent_center_quotient_ind {P : ∀ (G) [Group G] [IsNilpotent G], Prop} (G : Type*) [Group G] [IsNilpotent G] (hbase : ∀ (G) [Group G] [Subsingleton G], P G) - (hstep : ∀ (G) [Group G] [IsNilpotent G], ∀ _ih : P (G ⧸ center G), P G) : P G := by + (hstep : ∀ (G) [Group G] [IsNilpotent G], P (G ⧸ center G) → P G) : P G := by obtain ⟨n, h⟩ : ∃ n, Group.nilpotencyClass G = n := ⟨_, rfl⟩ induction' n with n ih generalizing G · haveI := nilpotencyClass_zero_iff_subsingleton.mp h @@ -865,7 +865,7 @@ theorem IsPGroup.isNilpotent [Finite G] {p : ℕ} [hp : Fact (Nat.Prime p)] (h : have hcq : Fintype.card (G ⧸ center G) < Fintype.card G := by rw [card_eq_card_quotient_mul_card_subgroup (center G)] apply lt_mul_of_one_lt_right - exact Fintype.card_pos_iff.mpr One.nonempty + exact Fintype.card_pos_iff.mpr One.instNonempty exact (Subgroup.one_lt_card_iff_ne_bot _).mpr (ne_of_gt h.bot_lt_center) have hnq : IsNilpotent (G ⧸ center G) := ih _ hcq (h.to_quotient (center G)) exact of_quotient_center_nilpotent hnq @@ -881,7 +881,7 @@ theorem isNilpotent_of_product_of_sylow_group let ps := (Fintype.card G).primeFactors have : ∀ (p : ps) (P : Sylow p G), IsNilpotent (↑P : Subgroup G) := by intro p P - haveI : Fact (Nat.Prime ↑p) := Fact.mk $ Nat.prime_of_mem_primeFactors p.2 + haveI : Fact (Nat.Prime ↑p) := Fact.mk <| Nat.prime_of_mem_primeFactors p.2 exact P.isPGroup'.isNilpotent exact nilpotent_of_mulEquiv e #align is_nilpotent_of_product_of_sylow_group isNilpotent_of_product_of_sylow_group diff --git a/Mathlib/GroupTheory/Order/Min.lean b/Mathlib/GroupTheory/Order/Min.lean index f861bed9aa738..0a605d0ade57b 100644 --- a/Mathlib/GroupTheory/Order/Min.lean +++ b/Mathlib/GroupTheory/Order/Min.lean @@ -58,8 +58,8 @@ lemma le_minOrder_iff_forall_subgroup {n : ℕ∞} : refine ⟨fun h s hs hs' ↦ ?_, fun h a ha ha' ↦ ?_⟩ · obtain ⟨a, has, ha⟩ := s.bot_or_exists_ne_one.resolve_left hs exact - (h ha $ finite_zpowers.1 $ hs'.subset $ zpowers_le.2 has).trans - (WithTop.coe_le_coe.2 $ s.orderOf_le_card hs' has) + (h ha <| finite_zpowers.1 <| hs'.subset <| zpowers_le.2 has).trans + (WithTop.coe_le_coe.2 <| s.orderOf_le_card hs' has) · simpa using h (zpowers_ne_bot.2 ha) ha'.finite_zpowers @[to_additive] @@ -81,13 +81,13 @@ protected lemma minOrder {n : ℕ} (hn : n ≠ 0) (hn₁ : n ≠ 1) : minOrder ( exact not_dvd_of_pos_of_lt (Nat.div_pos (minFac_le hn.bot_lt) n.minFac_pos) (div_lt_self hn.bot_lt (minFac_prime hn₁).one_lt) - refine ((minOrder_le_natCard (zmultiples_eq_bot.not.2 this) $ toFinite _).trans ?_).antisymm $ + refine ((minOrder_le_natCard (zmultiples_eq_bot.not.2 this) <| toFinite _).trans ?_).antisymm <| le_minOrder_iff_forall_addSubgroup.2 fun s hs _ ↦ ?_ · rw [card_eq_fintype_card, Fintype.card_zmultiples, ZMod.addOrderOf_coe _ hn, gcd_eq_right (div_dvd_of_dvd n.minFac_dvd), Nat.div_div_self n.minFac_dvd hn] · rw [card_eq_fintype_card] haveI : Nontrivial s := s.bot_or_nontrivial.resolve_left hs - exact WithTop.coe_le_coe.2 $ minFac_le_of_dvd Fintype.one_lt_card $ + exact WithTop.coe_le_coe.2 <| minFac_le_of_dvd Fintype.one_lt_card <| (card_addSubgroup_dvd_card _).trans (ZMod.card _).dvd @[simp] diff --git a/Mathlib/GroupTheory/OrderOfElement.lean b/Mathlib/GroupTheory/OrderOfElement.lean index c816151e078da..6008fa981c2e2 100644 --- a/Mathlib/GroupTheory/OrderOfElement.lean +++ b/Mathlib/GroupTheory/OrderOfElement.lean @@ -73,6 +73,16 @@ theorem isOfFinOrder_iff_pow_eq_one : IsOfFinOrder x ↔ ∃ n, 0 < n ∧ x ^ n @[to_additive] alias ⟨IsOfFinOrder.exists_pow_eq_one, _⟩ := isOfFinOrder_iff_pow_eq_one +@[to_additive] +lemma isOfFinOrder_iff_zpow_eq_one {G} [Group G] {x : G} : + IsOfFinOrder x ↔ ∃ (n : ℤ), n ≠ 0 ∧ x ^ n = 1 := by + rw [isOfFinOrder_iff_pow_eq_one] + refine ⟨fun ⟨n, hn, hn'⟩ ↦ ⟨n, Int.coe_nat_ne_zero_iff_pos.mpr hn, zpow_coe_nat x n ▸ hn'⟩, + fun ⟨n, hn, hn'⟩ ↦ ⟨n.natAbs, Int.natAbs_pos.mpr hn, ?_⟩⟩ + cases' (Int.natAbs_eq_iff (a := n)).mp rfl with h h; + · rwa [h, zpow_coe_nat] at hn' + · rwa [h, zpow_neg, inv_eq_one, zpow_coe_nat] at hn' + /-- See also `injective_pow_iff_not_isOfFinOrder`. -/ @[to_additive "See also `injective_nsmul_iff_not_isOfFinAddOrder`."] theorem not_isOfFinOrder_of_injective_pow {x : G} (h : Injective fun n : ℕ => x ^ n) : @@ -271,7 +281,7 @@ theorem orderOf_pow_dvd (n : ℕ) : orderOf (x ^ n) ∣ orderOf x := by #align add_order_of_smul_dvd addOrderOf_smul_dvd @[to_additive] -lemma pow_injOn_Iio_orderOf : (Set.Iio $ orderOf x).InjOn (x ^ ·) := by +lemma pow_injOn_Iio_orderOf : (Set.Iio <| orderOf x).InjOn (x ^ ·) := by simpa only [mul_left_iterate, mul_one] using iterate_injOn_Iio_minimalPeriod (f := (x * ·)) (x := 1) #align pow_injective_of_lt_order_of pow_injOn_Iio_orderOf @@ -281,7 +291,7 @@ lemma pow_injOn_Iio_orderOf : (Set.Iio $ orderOf x).InjOn (x ^ ·) := by protected lemma IsOfFinOrder.mem_powers_iff_mem_range_orderOf [DecidableEq G] (hx : IsOfFinOrder x) : y ∈ Submonoid.powers x ↔ y ∈ (Finset.range (orderOf x)).image (x ^ ·) := - Finset.mem_range_iff_mem_finset_range_of_mod_eq' hx.orderOf_pos $ pow_mod_orderOf _ + Finset.mem_range_iff_mem_finset_range_of_mod_eq' hx.orderOf_pos <| pow_mod_orderOf _ #align mem_powers_iff_mem_range_order_of' IsOfFinOrder.mem_powers_iff_mem_range_orderOf #align mem_multiples_iff_mem_range_add_order_of' IsOfFinAddOrder.mem_multiples_iff_mem_range_addOrderOf @@ -373,6 +383,16 @@ theorem orderOf_units {y : Gˣ} : orderOf (y : G) = orderOf y := #align order_of_units orderOf_units #align order_of_add_units addOrderOf_addUnits +/-- If the order of `x` is finite, then `x` is a unit with inverse `x ^ (orderOf x - 1)`. -/ +@[simps] +noncomputable +def IsOfFinOrder.unit {M} [Monoid M] {x : M} (hx : IsOfFinOrder x) : Mˣ := +⟨x, x ^ (orderOf x - 1), + by rw [← _root_.pow_succ, tsub_add_cancel_of_le (by exact hx.orderOf_pos), pow_orderOf_eq_one], + by rw [← _root_.pow_succ', tsub_add_cancel_of_le (by exact hx.orderOf_pos), pow_orderOf_eq_one]⟩ + +lemma IsOfFinOrder.isUnit {M} [Monoid M] {x : M} (hx : IsOfFinOrder x) : IsUnit x := ⟨hx.unit, rfl⟩ + variable (x) @[to_additive] @@ -578,7 +598,7 @@ lemma infinite_powers : (powers a : Set G).Infinite ↔ ¬ IsOfFinOrder a := fin noncomputable def finEquivPowers (x : G) (hx : IsOfFinOrder x) : Fin (orderOf x) ≃ powers x := Equiv.ofBijective (fun n ↦ ⟨x ^ (n : ℕ), ⟨n, rfl⟩⟩) ⟨fun ⟨_, h₁⟩ ⟨_, h₂⟩ ij ↦ Fin.ext (pow_injOn_Iio_orderOf h₁ h₂ (Subtype.mk_eq_mk.1 ij)), fun ⟨_, i, rfl⟩ ↦ - ⟨⟨i % orderOf x, mod_lt _ hx.orderOf_pos⟩, Subtype.eq $ pow_mod_orderOf _ _⟩⟩ + ⟨⟨i % orderOf x, mod_lt _ hx.orderOf_pos⟩, Subtype.eq <| pow_mod_orderOf _ _⟩⟩ #align fin_equiv_powers finEquivPowers #align fin_equiv_multiples finEquivMultiples @@ -602,7 +622,7 @@ lemma finEquivPowers_symm_apply (x : G) (hx) (n : ℕ) {hn : ∃ m : ℕ, x ^ m lemma Nat.card_submonoidPowers : Nat.card (powers a) = orderOf a := by classical by_cases ha : IsOfFinOrder a - · exact (Nat.card_congr (finEquivPowers _ ha).symm).trans $ by simp + · exact (Nat.card_congr (finEquivPowers _ ha).symm).trans <| by simp · have := (infinite_powers.2 ha).to_subtype rw [orderOf_eq_zero ha, Nat.card_eq_zero_of_infinite] @@ -710,7 +730,7 @@ lemma IsOfFinOrder.mem_powers_iff_mem_zpowers (hx : IsOfFinOrder x) : y ∈ powers x ↔ y ∈ zpowers x := ⟨fun ⟨n, hn⟩ ↦ ⟨n, by simp_all⟩, fun ⟨i, hi⟩ ↦ ⟨(i % orderOf x).natAbs, by dsimp only - rwa [← zpow_ofNat, Int.natAbs_of_nonneg $ Int.emod_nonneg _ $ Int.coe_nat_ne_zero_iff_pos.2 $ + rwa [← zpow_ofNat, Int.natAbs_of_nonneg <| Int.emod_nonneg _ <| Int.coe_nat_ne_zero_iff_pos.2 <| hx.orderOf_pos, zpow_mod_orderOf]⟩⟩ @[to_additive IsOfFinAddOrder.multiples_eq_zmultiples] @@ -727,7 +747,7 @@ lemma IsOfFinOrder.mem_zpowers_iff_mem_range_orderOf [DecidableEq G] (hx : IsOfF `Subgroup.zmultiples a`, sending `i` to `i • a`."] noncomputable def finEquivZPowers (x : G) (hx : IsOfFinOrder x) : Fin (orderOf x) ≃ (zpowers x : Set G) := - (finEquivPowers x hx).trans $ Equiv.Set.ofEq hx.powers_eq_zpowers + (finEquivPowers x hx).trans <| Equiv.Set.ofEq hx.powers_eq_zpowers #align fin_equiv_zpowers finEquivZPowers #align fin_equiv_zmultiples finEquivZMultiples @@ -813,7 +833,7 @@ variable [Finite G] {x y : G} {n : ℕ} -- TODO: Use this to show that a finite left cancellative monoid is a group. @[to_additive] lemma isOfFinOrder_of_finite (x : G) : IsOfFinOrder x := by - by_contra h; exact infinite_not_isOfFinOrder h $ Set.toFinite _ + by_contra h; exact infinite_not_isOfFinOrder h <| Set.toFinite _ #align exists_pow_eq_one isOfFinOrder_of_finite #align exists_nsmul_eq_zero isOfFinAddOrder_of_finite @@ -838,7 +858,7 @@ theorem orderOf_pow (x : G) : orderOf (x ^ n) = orderOf x / gcd (orderOf x) n := @[to_additive mem_multiples_iff_mem_range_addOrderOf] theorem mem_powers_iff_mem_range_orderOf [DecidableEq G] : y ∈ powers x ↔ y ∈ (Finset.range (orderOf x)).image (x ^ ·) := - Finset.mem_range_iff_mem_finset_range_of_mod_eq' (orderOf_pos x) $ pow_mod_orderOf _ + Finset.mem_range_iff_mem_finset_range_of_mod_eq' (orderOf_pos x) <| pow_mod_orderOf _ #align mem_powers_iff_mem_range_order_of mem_powers_iff_mem_range_orderOf #align mem_multiples_iff_mem_range_add_order_of mem_multiples_iff_mem_range_addOrderOf @@ -848,8 +868,8 @@ theorem mem_powers_iff_mem_range_orderOf [DecidableEq G] : "The equivalence between `Submonoid.multiples` of two elements `a, b` of the same additive order, mapping `i • a` to `i • b`."] noncomputable def powersEquivPowers (h : orderOf x = orderOf y) : powers x ≃ powers y := - (finEquivPowers x $ isOfFinOrder_of_finite _).symm.trans $ - (Fin.castIso h).toEquiv.trans $ finEquivPowers y $ isOfFinOrder_of_finite _ + (finEquivPowers x <| isOfFinOrder_of_finite _).symm.trans <| + (Fin.castIso h).toEquiv.trans <| finEquivPowers y <| isOfFinOrder_of_finite _ #align powers_equiv_powers powersEquivPowers #align multiples_equiv_multiples multiplesEquivMultiples @@ -870,8 +890,8 @@ variable [Fintype G] {x : G} @[to_additive addOrderOf_eq_card_multiples] lemma orderOf_eq_card_powers : orderOf x = Fintype.card (powers x : Set G) := - (Fintype.card_fin (orderOf x)).symm.trans $ - Fintype.card_eq.2 ⟨finEquivPowers x $ isOfFinOrder_of_finite _⟩ + (Fintype.card_fin (orderOf x)).symm.trans <| + Fintype.card_eq.2 ⟨finEquivPowers x <| isOfFinOrder_of_finite _⟩ #align order_eq_card_powers orderOf_eq_card_powers #align add_order_of_eq_card_multiples addOrderOf_eq_card_multiples @@ -941,8 +961,8 @@ theorem injective_zpow_iff_not_isOfFinOrder : (Injective fun n : ℤ => x ^ n) mapping `i • a` to `i • b`."] noncomputable def zpowersEquivZPowers (h : orderOf x = orderOf y) : (Subgroup.zpowers x : Set G) ≃ (Subgroup.zpowers y : Set G) := - (finEquivZPowers x $ isOfFinOrder_of_finite _).symm.trans $ (Fin.castIso h).toEquiv.trans $ - finEquivZPowers y $ isOfFinOrder_of_finite _ + (finEquivZPowers x <| isOfFinOrder_of_finite _).symm.trans <| (Fin.castIso h).toEquiv.trans <| + finEquivZPowers y <| isOfFinOrder_of_finite _ #align zpowers_equiv_zpowers zpowersEquivZPowers #align zmultiples_equiv_zmultiples zmultiplesEquivZMultiples @@ -964,7 +984,7 @@ variable [Fintype G] {x : G} {n : ℕ} /-- See also `Nat.card_addSubgroupZPowers`. -/ @[to_additive Fintype.card_zmultiples "See also `Nat.card_subgroup`."] theorem Fintype.card_zpowers : Fintype.card (zpowers x) = orderOf x := - (Fintype.card_eq.2 ⟨finEquivZPowers x $ isOfFinOrder_of_finite _⟩).symm.trans $ + (Fintype.card_eq.2 ⟨finEquivZPowers x <| isOfFinOrder_of_finite _⟩).symm.trans <| Fintype.card_fin (orderOf x) #align order_eq_card_zpowers Fintype.card_zpowers #align add_order_eq_card_zmultiples Fintype.card_zmultiples @@ -1019,17 +1039,17 @@ nonrec lemma Subgroup.orderOf_dvd_natCard (s : Subgroup G) (hx : x ∈ s) : @[to_additive] lemma Subgroup.orderOf_le_card (s : Subgroup G) (hs : (s : Set G).Finite) (hx : x ∈ s) : orderOf x ≤ Nat.card s := - le_of_dvd (Nat.card_pos_iff.2 $ ⟨s.coe_nonempty.to_subtype, hs.to_subtype⟩) $ + le_of_dvd (Nat.card_pos_iff.2 <| ⟨s.coe_nonempty.to_subtype, hs.to_subtype⟩) <| s.orderOf_dvd_natCard hx @[to_additive] lemma Submonoid.orderOf_le_card (s : Submonoid G) (hs : (s : Set G).Finite) (hx : x ∈ s) : orderOf x ≤ Nat.card s := by - rw [← Nat.card_submonoidPowers]; exact Nat.card_mono hs $ powers_le.2 hx + rw [← Nat.card_submonoidPowers]; exact Nat.card_mono hs <| powers_le.2 hx @[to_additive (attr := simp) card_nsmul_eq_zero'] theorem pow_card_eq_one' {G : Type*} [Group G] {x : G} : x ^ Nat.card G = 1 := - orderOf_dvd_iff_pow_eq_one.mp $ orderOf_dvd_natCard _ + orderOf_dvd_iff_pow_eq_one.mp <| orderOf_dvd_natCard _ #align pow_card_eq_one' pow_card_eq_one' #align card_nsmul_eq_zero' card_nsmul_eq_zero' @@ -1164,7 +1184,7 @@ def powCardSubgroup {G : Type*} [Group G] [Fintype G] (S : Set G) (hS : S.Nonemp obtain ⟨a, ha⟩ := hS rw [← pow_card_eq_one] exact Set.pow_mem_pow ha (Fintype.card G) - subgroupOfIdempotent (S ^ Fintype.card G) ⟨1, one_mem⟩ $ by + subgroupOfIdempotent (S ^ Fintype.card G) ⟨1, one_mem⟩ <| by classical! apply (Set.eq_of_subset_of_card_le (Set.subset_mul_left _ one_mem) (ge_of_eq _)).symm simp_rw [← pow_add, @@ -1188,7 +1208,7 @@ section LinearOrderedRing variable [LinearOrderedRing G] {a x : G} protected lemma IsOfFinOrder.eq_neg_one (ha₀ : a ≤ 0) (ha : IsOfFinOrder a) : a = -1 := - (sq_eq_one_iff.1 $ ha.pow.eq_one $ sq_nonneg a).resolve_left $ by + (sq_eq_one_iff.1 <| ha.pow.eq_one <| sq_nonneg a).resolve_left <| by rintro rfl; exact one_pos.not_le ha₀ theorem orderOf_abs_ne_one (h : |x| ≠ 1) : orderOf x = 0 := by @@ -1204,7 +1224,7 @@ theorem LinearOrderedRing.orderOf_le_two : orderOf x ≤ 2 := by cases' ne_or_eq |x| 1 with h h · simp [orderOf_abs_ne_one h] rcases eq_or_eq_neg_of_abs_eq h with (rfl | rfl) - · simp; decide + · simp apply orderOf_le_of_pow_eq_one <;> norm_num #align linear_ordered_ring.order_of_le_two LinearOrderedRing.orderOf_le_two diff --git a/Mathlib/GroupTheory/Perm/Basic.lean b/Mathlib/GroupTheory/Perm/Basic.lean index 4ac3cb1bc9490..6cb20d8d8f9ae 100644 --- a/Mathlib/GroupTheory/Perm/Basic.lean +++ b/Mathlib/GroupTheory/Perm/Basic.lean @@ -5,6 +5,7 @@ Authors: Leonardo de Moura, Mario Carneiro -/ import Mathlib.Algebra.Group.Pi import Mathlib.Algebra.Group.Prod +import Mathlib.Algebra.Group.Units.Equiv import Mathlib.Algebra.GroupPower.IterateHom import Mathlib.Logic.Equiv.Set @@ -603,7 +604,7 @@ variable [AddGroup α] (a b : α) #align equiv.add_right_zero Equiv.addRight_zero @[simp] lemma addLeft_add : Equiv.addLeft (a + b) = Equiv.addLeft a * Equiv.addLeft b := - ext $ add_assoc _ _ + ext <| add_assoc _ _ #align equiv.add_left_add Equiv.addLeft_add @[simp] lemma addRight_add : Equiv.addRight (a + b) = Equiv.addRight b * Equiv.addRight a := @@ -649,7 +650,7 @@ lemma mulRight_one : Equiv.mulRight (1 : α) = 1 := ext mul_one @[to_additive existing (attr := simp)] lemma mulLeft_mul : Equiv.mulLeft (a * b) = Equiv.mulLeft a * Equiv.mulLeft b := - ext $ mul_assoc _ _ + ext <| mul_assoc _ _ #align equiv.mul_left_mul Equiv.mulLeft_mul @[to_additive existing (attr := simp)] diff --git a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean index aacb97ec2f79f..e25e4a5d2154e 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean @@ -544,7 +544,7 @@ theorem IsCycle.sign {f : Perm α} (hf : IsCycle f) : sign f = -(-1) ^ f.support card_support_swap_mul hx.1 rw [sign_mul, sign_swap hx.1.symm, (hf.swap_mul hx.1 h1).sign, ← h] simp only [mul_neg, neg_mul, one_mul, neg_neg, pow_add, pow_one, mul_one] -termination_by _ => f.support.card +termination_by f.support.card #align equiv.perm.is_cycle.sign Equiv.Perm.IsCycle.sign theorem IsCycle.of_pow {n : ℕ} (h1 : IsCycle (f ^ n)) (h2 : f.support ⊆ (f ^ n).support) : @@ -678,7 +678,7 @@ theorem IsCycle.pow_eq_one_iff [Finite β] {f : Perm β} (hf : IsCycle f) {n : -- TODO: Define a `Set`-valued support to get rid of the `Finite β` assumption theorem IsCycle.pow_eq_one_iff' [Finite β] {f : Perm β} (hf : IsCycle f) {n : ℕ} {x : β} (hx : f x ≠ x) : f ^ n = 1 ↔ (f ^ n) x = x := - ⟨fun h => FunLike.congr_fun h x, fun h => hf.pow_eq_one_iff.2 ⟨x, hx, h⟩⟩ + ⟨fun h => DFunLike.congr_fun h x, fun h => hf.pow_eq_one_iff.2 ⟨x, hx, h⟩⟩ #align equiv.perm.is_cycle.pow_eq_one_iff' Equiv.Perm.IsCycle.pow_eq_one_iff' -- TODO: Define a `Set`-valued support to get rid of the `Finite β` assumption @@ -1793,9 +1793,9 @@ theorem Disjoint.isConj_mul {α : Type*} [Finite α] {σ τ π ρ : Perm α} (hc · rw [mul_apply, mul_apply] at h rw [h, inv_apply_self, (hd1 x).resolve_left hxσ] · rwa [mul_apply, mul_apply, inv_apply_self, apply_eq_iff_eq] + · rwa [Subtype.coe_mk, mem_coe, mem_support] · rwa [Subtype.coe_mk, Perm.mul_apply, (hd1 x).resolve_left hxσ, mem_coe, apply_mem_support, mem_support] - · rwa [Subtype.coe_mk, mem_coe, mem_support] · rw [mem_coe, ← apply_mem_support, mem_support] at hxτ rw [Set.union_apply_right hd1''.le_bot _, Set.union_apply_right hd1''.le_bot _] simp only [subtypeEquiv_apply, Perm.coe_mul, Sum.map_inr, comp_apply, @@ -1804,9 +1804,9 @@ theorem Disjoint.isConj_mul {α : Type*} [Finite α] {σ τ π ρ : Perm α} (hc · rw [mul_apply, mul_apply] at h rw [inv_apply_self, h, (hd1 (τ x)).resolve_right hxτ] · rwa [mul_apply, mul_apply, inv_apply_self, apply_eq_iff_eq] + · rwa [Subtype.coe_mk, mem_coe, ← apply_mem_support, mem_support] · rwa [Subtype.coe_mk, Perm.mul_apply, (hd1 (τ x)).resolve_right hxτ, mem_coe, mem_support] - · rwa [Subtype.coe_mk, mem_coe, ← apply_mem_support, mem_support] #align equiv.perm.disjoint.is_conj_mul Equiv.Perm.Disjoint.isConj_mul section FixedPoints diff --git a/Mathlib/GroupTheory/Perm/Cycle/Type.lean b/Mathlib/GroupTheory/Perm/Cycle/Type.lean index 86064bffa2f56..829c36285e1f1 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Type.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Type.lean @@ -340,7 +340,7 @@ theorem card_fixedPoints_modEq [DecidableEq α] {f : Function.End α} {p n : ℕ leftInverse_iff_comp.mpr ((pow_sub_mul_pow f (Nat.one_le_pow n p hp.out.pos)).trans hf), leftInverse_iff_comp.mpr ((pow_mul_pow_sub f (Nat.one_le_pow n p hp.out.pos)).trans hf)⟩ have hσ : σ ^ p ^ n = 1 - · rw [FunLike.ext'_iff, coe_pow] + · rw [DFunLike.ext'_iff, coe_pow] exact (hom_coe_pow (fun g : Function.End α ↦ g) rfl (fun g h ↦ rfl) f (p ^ n)).symm.trans hf suffices : Fintype.card f.fixedPoints = (support σ)ᶜ.card · exact this ▸ (card_compl_support_modEq hσ).symm diff --git a/Mathlib/GroupTheory/Perm/DomMulAct.lean b/Mathlib/GroupTheory/Perm/DomMulAct.lean new file mode 100644 index 0000000000000..4f996e0b7ec1a --- /dev/null +++ b/Mathlib/GroupTheory/Perm/DomMulAct.lean @@ -0,0 +1,109 @@ +/- +Copyright (c) 2023 Junyan Xu, Antoine Chambert-Loir. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Junyan Xu, Antoine Chambert-Loir +-/ + +import Mathlib.GroupTheory.GroupAction.DomAct.Basic +import Mathlib.GroupTheory.Subgroup.Basic +import Mathlib.GroupTheory.GroupAction.Basic + +import Mathlib.Data.Fintype.Basic +import Mathlib.Data.Fintype.Perm +import Mathlib.SetTheory.Cardinal.Finite + + +/-! Subgroup of `Equiv.Perm α` preserving a function + +Let `α` and `ι` by types and let `f : α → ι` + +* `DomMulAct.mem_stabilizer_iff` proves that the stabilizer of `f : α → ι` + in `(Equiv.Perm α)ᵈᵐᵃ` is the set of `g : (Equiv.Perm α)ᵈᵐᵃ` such that `f ∘ (mk.symm g) = f`. + + The natural equivalence from `stabilizer (Perm α)ᵈᵐᵃ f` to `{ g : Perm α // p ∘ g = f }` + can be obtained as `subtypeEquiv mk.symm (fun _ => mem_stabilizer_iff)` + +* `DomMulAct.stabilizerMulEquiv` is the `MulEquiv` from + the MulOpposite of this stabilizer to the product, + for `i : ι`, of `Equiv.Perm {a // f a = i}`. + +* Under `Fintype α` and `Fintype ι`, `DomMulAct.stabilizer_card p` computes + the cardinality of the type of permutations preserving `p` : + `Fintype.card {g : Perm α // f ∘ g = f} = ∏ i, (Fintype.card {a // f a = i})!`. + +-/ + +variable {α ι : Type*} {f : α → ι} + +open Equiv MulAction + +namespace DomMulAct + +lemma mem_stabilizer_iff {g : (Perm α)ᵈᵐᵃ} : + g ∈ stabilizer (Perm α)ᵈᵐᵃ f ↔ f ∘ (mk.symm g :) = f := by + simp only [MulAction.mem_stabilizer_iff]; rfl + +/-- The `invFun` component of `MulEquiv` from `MulAction.stabilizer (Perm α) f` + to the product of the `Equiv.Perm {a // f a = i} -/ +def stabilizerEquiv_invFun (g : ∀ i, Perm {a // f a = i}) (a : α) : α := g (f a) ⟨a, rfl⟩ + +lemma stabilizerEquiv_invFun_eq (g : ∀ i, Perm {a // f a = i}) {a : α} {i : ι} (h : f a = i) : + stabilizerEquiv_invFun g a = g i ⟨a, h⟩ := by subst h; rfl + +lemma comp_stabilizerEquiv_invFun (g : ∀ i, Perm {a // f a = i}) (a : α) : + f (stabilizerEquiv_invFun g a) = f a := + (g (f a) ⟨a, rfl⟩).prop + +/-- The `invFun` component of `MulEquiv` from `MulAction.stabilizer (Perm α) p` + to the product of the `Equiv.Perm {a | f a = i} (as an `Equiv.Perm α`) -/ +def stabilizerEquiv_invFun_aux (g : ∀ i, Perm {a // f a = i}) : Perm α where + toFun := stabilizerEquiv_invFun g + invFun := stabilizerEquiv_invFun (fun i ↦ (g i).symm) + left_inv a := by + rw [stabilizerEquiv_invFun_eq _ (comp_stabilizerEquiv_invFun g a)] + exact congr_arg Subtype.val ((g <| f a).left_inv _) + right_inv a := by + rw [stabilizerEquiv_invFun_eq _ (comp_stabilizerEquiv_invFun _ a)] + exact congr_arg Subtype.val ((g <| f a).right_inv _) + +variable (f) + +/-- The `MulEquiv` from the `MulOpposite` of `MulAction.stabilizer (Perm α)ᵈᵐᵃ f` + to the product of the `Equiv.Perm {a // f a = i}` -/ +def stabilizerMulEquiv : (stabilizer (Perm α)ᵈᵐᵃ f)ᵐᵒᵖ ≃* (∀ i, Perm {a // f a = i}) where + toFun g i := Perm.subtypePerm (mk.symm g.unop) fun a ↦ by + rw [← Function.comp_apply (f := f), mem_stabilizer_iff.mp g.unop.prop] + invFun g := ⟨mk (stabilizerEquiv_invFun_aux g), by + ext a + rw [smul_apply, symm_apply_apply, Perm.smul_def] + apply comp_stabilizerEquiv_invFun⟩ + left_inv g := rfl + right_inv g := by ext i a; apply stabilizerEquiv_invFun_eq + map_mul' g h := rfl + +variable {f} + +lemma stabilizerMulEquiv_apply (g : (stabilizer (Perm α)ᵈᵐᵃ f)ᵐᵒᵖ) {a : α} {i : ι} (h : f a = i) : + ((stabilizerMulEquiv f)) g i ⟨a, h⟩ = (mk.symm g.unop : Equiv.Perm α) a := rfl + +section Fintype + +variable [Fintype α] [Fintype ι] [DecidableEq α] [DecidableEq ι] + +open BigOperators Nat + +variable (f) + +/-- The cardinality of the type of permutations preserving a function -/ +theorem stabilizer_card: + Fintype.card {g : Perm α // f ∘ g = f} = ∏ i, (Fintype.card {a // f a = i})! := by + -- rewriting via Nat.card because Fintype instance is not found + rw [← Nat.card_eq_fintype_card, Nat.card_congr (subtypeEquiv mk fun _ ↦ ?_), + Nat.card_congr MulOpposite.opEquiv, + Nat.card_congr (DomMulAct.stabilizerMulEquiv f).toEquiv, Nat.card_pi] + · exact Finset.prod_congr rfl fun i _ ↦ by rw [Nat.card_eq_fintype_card, Fintype.card_perm] + · rfl + +end Fintype + +end DomMulAct diff --git a/Mathlib/GroupTheory/Perm/Subgroup.lean b/Mathlib/GroupTheory/Perm/Subgroup.lean index 50c85aaae9c89..2139ee529b44c 100644 --- a/Mathlib/GroupTheory/Perm/Subgroup.lean +++ b/Mathlib/GroupTheory/Perm/Subgroup.lean @@ -6,6 +6,7 @@ Authors: Eric Wieser import Mathlib.GroupTheory.Perm.Basic import Mathlib.Data.Fintype.Perm import Mathlib.GroupTheory.Subgroup.Finite +import Mathlib.GroupTheory.GroupAction.Group #align_import group_theory.perm.subgroup from "leanprover-community/mathlib"@"4c19a16e4b705bf135cf9a80ac18fcc99c438514" diff --git a/Mathlib/GroupTheory/PresentedGroup.lean b/Mathlib/GroupTheory/PresentedGroup.lean index f4234d557363d..e185c28bb0d68 100644 --- a/Mathlib/GroupTheory/PresentedGroup.lean +++ b/Mathlib/GroupTheory/PresentedGroup.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Michael Howes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Michael Howes +Authors: Michael Howes, Newell Jensen -/ import Mathlib.GroupTheory.FreeGroup.Basic import Mathlib.GroupTheory.QuotientGroup @@ -94,6 +94,24 @@ theorem ext {φ ψ : PresentedGroup rels →* G} (hx : ∀ (x : α), φ (.of x) ext apply hx +variable {β : Type*} + +/-- Presented groups of isomorphic types are isomorphic. -/ +def equivPresentedGroup (rels : Set (FreeGroup α)) (e : α ≃ β) : + PresentedGroup rels ≃* PresentedGroup (FreeGroup.freeGroupCongr e '' rels) := + QuotientGroup.congr (Subgroup.normalClosure rels) + (Subgroup.normalClosure ((FreeGroup.freeGroupCongr e) '' rels)) (FreeGroup.freeGroupCongr e) + (Subgroup.map_normalClosure rels (FreeGroup.freeGroupCongr e).toMonoidHom + (FreeGroup.freeGroupCongr e).surjective) + +theorem equivPresentedGroup_apply_of (x : α) (rels : Set (FreeGroup α)) (e : α ≃ β) : + equivPresentedGroup rels e (PresentedGroup.of x) = + PresentedGroup.of (rels := FreeGroup.freeGroupCongr e '' rels) (e x) := rfl + +theorem equivPresentedGroup_symm_apply_of (x : β) (rels : Set (FreeGroup α)) (e : α ≃ β) : + (equivPresentedGroup rels e).symm (PresentedGroup.of x) = + PresentedGroup.of (rels := rels) (e.symm x) := rfl + end ToGroup instance (rels : Set (FreeGroup α)) : Inhabited (PresentedGroup rels) := diff --git a/Mathlib/GroupTheory/PushoutI.lean b/Mathlib/GroupTheory/PushoutI.lean index 70f378df31c31..51b2e20105649 100644 --- a/Mathlib/GroupTheory/PushoutI.lean +++ b/Mathlib/GroupTheory/PushoutI.lean @@ -104,7 +104,7 @@ def lift (f : ∀ i, G i →* K) (k : H →* K) Con.lift _ (Coprod.lift (CoprodI.lift f) k) <| by apply Con.conGen_le fun x y => ?_ rintro ⟨i, x', rfl, rfl⟩ - simp only [FunLike.ext_iff, MonoidHom.coe_comp, comp_apply] at hf + simp only [DFunLike.ext_iff, MonoidHom.coe_comp, comp_apply] at hf simp [hf] @[simp] @@ -151,9 +151,9 @@ def homEquiv : { toFun := fun f => ⟨(fun i => f.comp (of i), f.comp (base φ)), fun i => by rw [MonoidHom.comp_assoc, of_comp_eq_base]⟩ invFun := fun f => lift f.1.1 f.1.2 f.2, - left_inv := fun _ => hom_ext (by simp [FunLike.ext_iff]) - (by simp [FunLike.ext_iff]) - right_inv := fun ⟨⟨_, _⟩, _⟩ => by simp [FunLike.ext_iff, Function.funext_iff] } + left_inv := fun _ => hom_ext (by simp [DFunLike.ext_iff]) + (by simp [DFunLike.ext_iff]) + right_inv := fun ⟨⟨_, _⟩, _⟩ => by simp [DFunLike.ext_iff, Function.funext_iff] } /-- The map from the coproduct into the pushout -/ def ofCoprodI : CoprodI G →* PushoutI φ := @@ -442,7 +442,7 @@ noncomputable instance mulAction [DecidableEq ι] [∀ i, DecidableEq (G i)] : (fun i => MulAction.toEndHom) MulAction.toEndHom <| by intro i - simp only [MulAction.toEndHom, FunLike.ext_iff, MonoidHom.coe_comp, MonoidHom.coe_mk, + simp only [MulAction.toEndHom, DFunLike.ext_iff, MonoidHom.coe_comp, MonoidHom.coe_mk, OneHom.coe_mk, comp_apply] intro h funext w diff --git a/Mathlib/GroupTheory/QuotientGroup.lean b/Mathlib/GroupTheory/QuotientGroup.lean index 944dba4dea68d..26814c036c243 100644 --- a/Mathlib/GroupTheory/QuotientGroup.lean +++ b/Mathlib/GroupTheory/QuotientGroup.lean @@ -112,7 +112,7 @@ See note [partially-applied ext lemmas]. -/ See note [partially-applied ext lemmas]. "] theorem monoidHom_ext ⦃f g : G ⧸ N →* M⦄ (h : f.comp (mk' N) = g.comp (mk' N)) : f = g := - MonoidHom.ext fun x => QuotientGroup.induction_on x <| (FunLike.congr_fun h : _) + MonoidHom.ext fun x => QuotientGroup.induction_on x <| (DFunLike.congr_fun h : _) #align quotient_group.monoid_hom_ext QuotientGroup.monoidHom_ext #align quotient_add_group.add_monoid_hom_ext QuotientAddGroup.addMonoidHom_ext @@ -127,7 +127,7 @@ theorem eq_one_iff {N : Subgroup G} [nN : N.Normal] (x : G) : (x : G ⧸ N) = 1 theorem ker_le_range_iff {I : Type w} [Group I] (f : G →* H) [f.range.Normal] (g : H →* I) : g.ker ≤ f.range ↔ (mk' f.range).comp g.ker.subtype = 1 := ⟨fun h => MonoidHom.ext fun ⟨_, hx⟩ => (eq_one_iff _).mpr <| h hx, - fun h x hx => (eq_one_iff _).mp <| by exact FunLike.congr_fun h ⟨x, hx⟩⟩ + fun h x hx => (eq_one_iff _).mp <| by exact DFunLike.congr_fun h ⟨x, hx⟩⟩ @[to_additive (attr := simp)] theorem ker_mk' : MonoidHom.ker (QuotientGroup.mk' N : G →* G ⧸ N) = N := @@ -297,7 +297,7 @@ section Pointwise open Set @[to_additive (attr := simp)] lemma image_coe : ((↑) : G → Q) '' N = 1 := - congr_arg ((↑) : Subgroup Q → Set Q) $ map_mk'_self N + congr_arg ((↑) : Subgroup Q → Set Q) <| map_mk'_self N @[to_additive] lemma preimage_image_coe (s : Set G) : ((↑) : G → Q) ⁻¹' ((↑) '' s) = N * s := by diff --git a/Mathlib/GroupTheory/SemidirectProduct.lean b/Mathlib/GroupTheory/SemidirectProduct.lean index a9e412baca896..2cf317efcb1cd 100644 --- a/Mathlib/GroupTheory/SemidirectProduct.lean +++ b/Mathlib/GroupTheory/SemidirectProduct.lean @@ -219,7 +219,7 @@ def lift (f₁ : N →* H) (f₂ : G →* H) toFun a := f₁ a.1 * f₂ a.2 map_one' := by simp map_mul' a b := by - have := fun n g ↦ FunLike.ext_iff.1 (h n) g + have := fun n g ↦ DFunLike.ext_iff.1 (h n) g simp only [MulAut.conj_apply, MonoidHom.comp_apply, MulEquiv.coe_toMonoidHom] at this simp only [mul_left, mul_right, map_mul, this, mul_assoc, inv_mul_cancel_left] #align semidirect_product.lift SemidirectProduct.lift @@ -242,7 +242,7 @@ theorem lift_comp_inr : (lift f₁ f₂ h).comp inr = f₂ := by ext; simp theorem lift_unique (F : N ⋊[φ] G →* H) : F = lift (F.comp inl) (F.comp inr) fun _ ↦ by ext; simp [inl_aut] := by - rw [FunLike.ext_iff] + rw [DFunLike.ext_iff] simp only [lift, MonoidHom.comp_apply, MonoidHom.coe_mk, OneHom.coe_mk, ← map_mul, inl_left_mul_inr_right, forall_const] #align semidirect_product.lift_unique SemidirectProduct.lift_unique @@ -269,7 +269,7 @@ def map (f₁ : N →* N₁) (f₂ : G →* G₁) toFun x := ⟨f₁ x.1, f₂ x.2⟩ map_one' := by simp map_mul' x y := by - replace h := FunLike.ext_iff.1 (h x.right) y.left + replace h := DFunLike.ext_iff.1 (h x.right) y.left ext <;> simp_all #align semidirect_product.map SemidirectProduct.map diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index b63941b7ea2f7..ff130f40771a4 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -670,8 +670,8 @@ lemma not_isCyclic_iff_exponent_eq_prime [Group α] {p : ℕ} (hp : p.Prime) orders of `g` are `1`, `p`, or `p ^ 2`. It can't be the former because `g ≠ 1`, and it can't the latter because the group isn't cyclic. -/ have := (Nat.mem_divisors (m := p ^ 2)).mpr ⟨hα' ▸ orderOf_dvd_card (x := g), by aesop⟩ - simp? [Nat.divisors_prime_pow hp 2] at this says - simp only [Nat.divisors_prime_pow hp 2, Finset.mem_map, Finset.mem_range, + simp? [Nat.divisors_prime_pow hp 2] at this says + simp only [Nat.divisors_prime_pow hp 2, Nat.reduceAdd, Finset.mem_map, Finset.mem_range, Function.Embedding.coeFn_mk] at this obtain ⟨a, ha, ha'⟩ := this interval_cases a diff --git a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean index 89f7d4bb81a27..d59dca0893786 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean @@ -241,7 +241,7 @@ def OddCommuteEquiv (hn : Odd n) : { p : DihedralGroup n × DihedralGroup n // C | .inl i => rfl | .inr (.inl j) => rfl | .inr (.inr (.inl k)) => - congrArg (Sum.inr ∘ Sum.inr ∘ Sum.inl) $ two_mul (u⁻¹ * k) ▸ u.mul_inv_cancel_left k + congrArg (Sum.inr ∘ Sum.inr ∘ Sum.inl) <| two_mul (u⁻¹ * k) ▸ u.mul_inv_cancel_left k | .inr (.inr (.inr ⟨i, j⟩)) => rfl } /-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs of commuting elements. -/ diff --git a/Mathlib/GroupTheory/Subgroup/Basic.lean b/Mathlib/GroupTheory/Subgroup/Basic.lean index 9c7b655d1f690..2181cd5907cd4 100644 --- a/Mathlib/GroupTheory/Subgroup/Basic.lean +++ b/Mathlib/GroupTheory/Subgroup/Basic.lean @@ -4,11 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kexing Ying -/ import Mathlib.Algebra.Group.Conj -import Mathlib.Algebra.Module.Basic import Mathlib.Algebra.Order.Group.InjSurj -import Mathlib.Data.Countable.Basic +import Mathlib.Data.Set.Image import Mathlib.GroupTheory.Submonoid.Centralizer -import Mathlib.Logic.Encodable.Basic import Mathlib.Order.Atoms import Mathlib.Tactic.ApplyFun @@ -133,7 +131,7 @@ theorem inv_mem_iff {S G} [InvolutiveInv G] {_ : SetLike S G} [InvMemClass S G] #align inv_mem_iff inv_mem_iff #align neg_mem_iff neg_mem_iff -@[simp] theorem abs_mem_iff {S G} [InvolutiveNeg G] [LinearOrder G] {_ : SetLike S G} +@[simp] theorem abs_mem_iff {S G} [AddGroup G] [LinearOrder G] {_ : SetLike S G} [NegMemClass S G] {H : S} {x : G} : |x| ∈ H ↔ x ∈ H := by cases abs_choice x <;> simp [*] @@ -187,8 +185,29 @@ theorem mul_mem_cancel_left {x y : G} (h : x ∈ H) : x * y ∈ H ↔ y ∈ H := #align mul_mem_cancel_left mul_mem_cancel_left #align add_mem_cancel_left add_mem_cancel_left +namespace InvMemClass + +/-- A subgroup of a group inherits an inverse. -/ +@[to_additive "An additive subgroup of an `AddGroup` inherits an inverse."] +instance inv {G : Type u_1} {S : Type u_2} [Inv G] [SetLike S G] + [InvMemClass S G] {H : S} : Inv H := + ⟨fun a => ⟨a⁻¹, inv_mem a.2⟩⟩ +#align subgroup_class.has_inv InvMemClass.inv +#align add_subgroup_class.has_neg NegMemClass.neg + +@[to_additive (attr := simp, norm_cast)] +theorem coe_inv (x : H) : (x⁻¹).1 = x.1⁻¹ := + rfl +#align subgroup_class.coe_inv InvMemClass.coe_inv +#align add_subgroup_class.coe_neg NegMemClass.coe_neg + +end InvMemClass + namespace SubgroupClass +-- deprecated since 15 January 2024 +@[to_additive (attr := deprecated)] alias coe_inv := InvMemClass.coe_inv + -- Here we assume H, K, and L are subgroups, but in fact any one of them -- could be allowed to be a subsemigroup. -- Counterexample where K and L are submonoids: H = ℤ, K = ℕ, L = -ℕ @@ -201,14 +220,6 @@ theorem subset_union {H K L : S} : (H : Set G) ⊆ K ∪ L ↔ H ≤ K ∨ H ≤ ((h yH).resolve_left fun yK ↦ xK <| (mul_mem_cancel_right yK).mp ·) (mul_mem_cancel_left <| (h xH).resolve_left xK).mp -/-- A subgroup of a group inherits an inverse. -/ -@[to_additive "An additive subgroup of an `AddGroup` inherits an inverse."] -instance inv {G : Type u_1} {S : Type u_2} [DivInvMonoid G] [SetLike S G] - [SubgroupClass S G] {H : S} : Inv H := - ⟨fun a => ⟨a⁻¹, inv_mem a.2⟩⟩ -#align subgroup_class.has_inv SubgroupClass.inv -#align add_subgroup_class.has_neg AddSubgroupClass.neg - /-- A subgroup of a group inherits a division -/ @[to_additive "An additive subgroup of an `AddGroup` inherits a subtraction."] instance div {G : Type u_1} {S : Type u_2} [DivInvMonoid G] [SetLike S G] @@ -230,12 +241,6 @@ instance zpow {M S} [DivInvMonoid M] [SetLike S M] [SubgroupClass S M] {H : S} : #align subgroup_class.has_zpow SubgroupClass.zpow -- Porting note: additive align statement is given above -@[to_additive (attr := simp, norm_cast)] -theorem coe_inv (x : H) : (x⁻¹).1 = x.1⁻¹ := - rfl -#align subgroup_class.coe_inv SubgroupClass.coe_inv -#align add_subgroup_class.coe_neg AddSubgroupClass.coe_neg - @[to_additive (attr := simp, norm_cast)] theorem coe_div (x y : H) : (x / y).1 = x.1 / y.1 := rfl @@ -1286,7 +1291,7 @@ theorem closure_iUnion {ι} (s : ι → Set G) : closure (⋃ i, s i) = ⨆ i, c #align add_subgroup.closure_Union AddSubgroup.closure_iUnion @[to_additive (attr := simp)] -theorem closure_eq_bot_iff : closure k = ⊥ ↔ k ⊆ {1} := le_bot_iff.symm.trans $ closure_le _ +theorem closure_eq_bot_iff : closure k = ⊥ ↔ k ⊆ {1} := le_bot_iff.symm.trans <| closure_le _ #align subgroup.closure_eq_bot_iff Subgroup.closure_eq_bot_iff #align add_subgroup.closure_eq_bot_iff AddSubgroup.closure_eq_bot_iff @@ -2963,7 +2968,7 @@ theorem ker_prodMap {G' : Type*} {N' : Type*} [Group G'] [Group N'] (f : G →* @[to_additive] theorem range_le_ker_iff (f : G →* G') (g : G' →* G'') : f.range ≤ g.ker ↔ g.comp f = 1 := - ⟨fun h => ext fun x => h ⟨x, rfl⟩, by rintro h _ ⟨y, rfl⟩; exact FunLike.congr_fun h y⟩ + ⟨fun h => ext fun x => h ⟨x, rfl⟩, by rintro h _ ⟨y, rfl⟩; exact DFunLike.congr_fun h y⟩ @[to_additive] instance (priority := 100) normal_ker (f : G →* M) : f.ker.Normal := @@ -3213,7 +3218,7 @@ theorem map_le_map_iff_of_injective {f : G →* N} (hf : Function.Injective f) { @[to_additive (attr := simp)] theorem map_subtype_le_map_subtype {G' : Subgroup G} {H K : Subgroup G'} : H.map G'.subtype ≤ K.map G'.subtype ↔ H ≤ K := - map_le_map_iff_of_injective $ by apply Subtype.coe_injective + map_le_map_iff_of_injective <| by apply Subtype.coe_injective #align subgroup.map_subtype_le_map_subtype Subgroup.map_subtype_le_map_subtype #align add_subgroup.map_subtype_le_map_subtype AddSubgroup.map_subtype_le_map_subtype @@ -3697,7 +3702,7 @@ instance prod_normal (H : Subgroup G) (K : Subgroup N) [hH : H.Normal] [hK : K.N theorem inf_subgroupOf_inf_normal_of_right (A B' B : Subgroup G) (hB : B' ≤ B) [hN : (B'.subgroupOf B).Normal] : ((A ⊓ B').subgroupOf (A ⊓ B)).Normal := { conj_mem := fun {n} hn g => - ⟨mul_mem (mul_mem (mem_inf.1 g.2).1 (mem_inf.1 n.2).1) $ + ⟨mul_mem (mul_mem (mem_inf.1 g.2).1 (mem_inf.1 n.2).1) <| show ↑g⁻¹ ∈ A from (inv_mem (mem_inf.1 g.2).1), (normal_subgroupOf_iff hB).mp hN n g hn.2 (mem_inf.mp g.2).2⟩ } #align subgroup.inf_subgroup_of_inf_normal_of_right Subgroup.inf_subgroupOf_inf_normal_of_right @@ -3708,7 +3713,7 @@ theorem inf_subgroupOf_inf_normal_of_left {A' A : Subgroup G} (B : Subgroup G) ( [hN : (A'.subgroupOf A).Normal] : ((A' ⊓ B).subgroupOf (A ⊓ B)).Normal := { conj_mem := fun n hn g => ⟨(normal_subgroupOf_iff hA).mp hN n g hn.1 (mem_inf.mp g.2).1, - mul_mem (mul_mem (mem_inf.1 g.2).2 (mem_inf.1 n.2).2) $ + mul_mem (mul_mem (mem_inf.1 g.2).2 (mem_inf.1 n.2).2) <| show ↑g⁻¹ ∈ B from (inv_mem (mem_inf.1 g.2).2)⟩ } #align subgroup.inf_subgroup_of_inf_normal_of_left Subgroup.inf_subgroupOf_inf_normal_of_left #align add_subgroup.inf_add_subgroup_of_inf_normal_of_left AddSubgroup.inf_addSubgroupOf_inf_normal_of_left diff --git a/Mathlib/GroupTheory/Subgroup/MulOpposite.lean b/Mathlib/GroupTheory/Subgroup/MulOpposite.lean index 36871378efb86..5465d8ead4083 100644 --- a/Mathlib/GroupTheory/Subgroup/MulOpposite.lean +++ b/Mathlib/GroupTheory/Subgroup/MulOpposite.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Alex Kontorovich. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Alex Kontorovich -/ -import Mathlib.GroupTheory.Subgroup.Actions +import Mathlib.Logic.Encodable.Basic +import Mathlib.GroupTheory.Subgroup.Basic import Mathlib.GroupTheory.Submonoid.MulOpposite #align_import group_theory.subgroup.mul_opposite from "leanprover-community/mathlib"@"f93c11933efbc3c2f0299e47b8ff83e9b539cbf6" diff --git a/Mathlib/GroupTheory/Subgroup/Saturated.lean b/Mathlib/GroupTheory/Subgroup/Saturated.lean index 6b802b881f48f..2869daa94f436 100644 --- a/Mathlib/GroupTheory/Subgroup/Saturated.lean +++ b/Mathlib/GroupTheory/Subgroup/Saturated.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ import Mathlib.GroupTheory.Subgroup.Basic +import Mathlib.Algebra.Module.Basic #align_import group_theory.subgroup.saturated from "leanprover-community/mathlib"@"f7fc89d5d5ff1db2d1242c7bb0e9062ce47ef47c" diff --git a/Mathlib/GroupTheory/Subgroup/Simple.lean b/Mathlib/GroupTheory/Subgroup/Simple.lean index 5a41b061fcbb4..991bb41b7601c 100644 --- a/Mathlib/GroupTheory/Subgroup/Simple.lean +++ b/Mathlib/GroupTheory/Subgroup/Simple.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Aaron Anderson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ -import Mathlib.GroupTheory.Subgroup.Actions +import Mathlib.GroupTheory.Subgroup.Basic #align_import group_theory.subgroup.simple from "leanprover-community/mathlib"@"f93c11933efbc3c2f0299e47b8ff83e9b539cbf6" diff --git a/Mathlib/GroupTheory/Subgroup/ZPowers.lean b/Mathlib/GroupTheory/Subgroup/ZPowers.lean index bb1dc47dafcb9..d9fb32558be73 100644 --- a/Mathlib/GroupTheory/Subgroup/ZPowers.lean +++ b/Mathlib/GroupTheory/Subgroup/ZPowers.lean @@ -3,7 +3,10 @@ Copyright (c) 2020 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ +import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.GroupTheory.Subgroup.Basic +import Mathlib.Data.Countable.Basic +import Mathlib.Data.Set.Image #align_import group_theory.subgroup.zpowers from "leanprover-community/mathlib"@"4be589053caf347b899a494da75410deb55fb3ef" diff --git a/Mathlib/GroupTheory/Submonoid/Membership.lean b/Mathlib/GroupTheory/Submonoid/Membership.lean index c815ce3f0b156..6f61f2b1ebadc 100644 --- a/Mathlib/GroupTheory/Submonoid/Membership.lean +++ b/Mathlib/GroupTheory/Submonoid/Membership.lean @@ -4,10 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Kenny Lau, Johan Commelin, Mario Carneiro, Kevin Buzzard, Amelia Livingston, Yury Kudryashov -/ -import Mathlib.GroupTheory.Submonoid.Operations -import Mathlib.Algebra.BigOperators.Basic import Mathlib.Algebra.FreeMonoid.Basic import Mathlib.Data.Finset.NoncommProd +import Mathlib.Data.Int.Order.Lemmas +import Mathlib.GroupTheory.Submonoid.Operations #align_import group_theory.submonoid.membership from "leanprover-community/mathlib"@"e655e4ea5c6d02854696f97494997ba4c31be802" @@ -398,8 +398,8 @@ theorem closure_eq_image_prod (s : Set M) : @[to_additive] theorem exists_list_of_mem_closure {s : Set M} {x : M} (hx : x ∈ closure s) : - ∃ (l : List M) (_ : ∀ y ∈ l, y ∈ s), l.prod = x := by - rwa [← SetLike.mem_coe, closure_eq_image_prod, Set.mem_image_iff_bex] at hx + ∃ l : List M, (∀ y ∈ l, y ∈ s) ∧ l.prod = x := by + rwa [← SetLike.mem_coe, closure_eq_image_prod, Set.mem_image] at hx #align submonoid.exists_list_of_mem_closure Submonoid.exists_list_of_mem_closure #align add_submonoid.exists_list_of_mem_closure AddSubmonoid.exists_list_of_mem_closure @@ -477,7 +477,7 @@ noncomputable instance decidableMemPowers : DecidablePred (· ∈ Submonoid.powe -- Porting note: TODO the following instance should follow from a more general principle -- See also mathlib4#2417 noncomputable instance fintypePowers [Fintype M] : Fintype (powers a) := - inferInstanceAs $ Fintype {y // y ∈ powers a} + inferInstanceAs <| Fintype {y // y ∈ powers a} theorem powers_eq_closure (n : M) : powers n = closure {n} := by ext @@ -487,7 +487,7 @@ theorem powers_eq_closure (n : M) : powers n = closure {n} := by lemma powers_le {n : M} {P : Submonoid M} : powers n ≤ P ↔ n ∈ P := by simp [powers_eq_closure] #align submonoid.powers_subset Submonoid.powers_le -lemma powers_one : powers (1 : M) = ⊥ := bot_unique <| powers_le.2 $ one_mem _ +lemma powers_one : powers (1 : M) = ⊥ := bot_unique <| powers_le.2 <| one_mem _ #align submonoid.powers_one Submonoid.powers_one /-- The submonoid generated by an element is a group if that element has finite order. -/ diff --git a/Mathlib/GroupTheory/Submonoid/Pointwise.lean b/Mathlib/GroupTheory/Submonoid/Pointwise.lean index 4edc0bf5cea8e..c649ff459c048 100644 --- a/Mathlib/GroupTheory/Submonoid/Pointwise.lean +++ b/Mathlib/GroupTheory/Submonoid/Pointwise.lean @@ -689,17 +689,17 @@ end Semiring end AddSubmonoid -namespace Set.IsPwo +namespace Set.IsPWO variable [OrderedCancelCommMonoid α] {s : Set α} @[to_additive] -theorem submonoid_closure (hpos : ∀ x : α, x ∈ s → 1 ≤ x) (h : s.IsPwo) : - IsPwo (Submonoid.closure s : Set α) := by +theorem submonoid_closure (hpos : ∀ x : α, x ∈ s → 1 ≤ x) (h : s.IsPWO) : + IsPWO (Submonoid.closure s : Set α) := by rw [Submonoid.closure_eq_image_prod] refine' (h.partiallyWellOrderedOn_sublistForall₂ (· ≤ ·)).image_of_monotone_on _ exact fun l1 _ l2 hl2 h12 => h12.prod_le_prod' fun x hx => hpos x <| hl2 x hx -#align set.is_pwo.submonoid_closure Set.IsPwo.submonoid_closure -#align set.is_pwo.add_submonoid_closure Set.IsPwo.addSubmonoid_closure +#align set.is_pwo.submonoid_closure Set.IsPWO.submonoid_closure +#align set.is_pwo.add_submonoid_closure Set.IsPWO.addSubmonoid_closure -end Set.IsPwo +end Set.IsPWO diff --git a/Mathlib/GroupTheory/Subsemigroup/Center.lean b/Mathlib/GroupTheory/Subsemigroup/Center.lean index 555e6dcfd3760..1373de3505fe2 100644 --- a/Mathlib/GroupTheory/Subsemigroup/Center.lean +++ b/Mathlib/GroupTheory/Subsemigroup/Center.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.Group.Commute.Units import Mathlib.Algebra.Invertible.Basic import Mathlib.GroupTheory.Subsemigroup.Operations import Mathlib.Data.Int.Cast.Lemmas +import Mathlib.Logic.Basic #align_import group_theory.subsemigroup.center from "leanprover-community/mathlib"@"1ac8d4304efba9d03fa720d06516fac845aa5353" @@ -63,12 +64,12 @@ namespace IsMulCentral variable {a b c : M} [Mul M] --- c.f. Commute.left_comm +-- cf. `Commute.left_comm` @[to_additive] protected theorem left_comm (h : IsMulCentral a) (b c) : a * (b * c) = b * (a * c) := by simp only [h.comm, h.right_assoc] --- c.f. Commute.right_comm +-- cf. `Commute.right_comm` @[to_additive] protected theorem right_comm (h : IsMulCentral c) (a b) : a * b * c = a * c * b := by simp only [h.right_assoc, h.mid_assoc, h.comm] diff --git a/Mathlib/GroupTheory/Subsemigroup/Operations.lean b/Mathlib/GroupTheory/Subsemigroup/Operations.lean index 3eedc8c373bf2..68a8721c9eb90 100644 --- a/Mathlib/GroupTheory/Subsemigroup/Operations.lean +++ b/Mathlib/GroupTheory/Subsemigroup/Operations.lean @@ -109,11 +109,11 @@ theorem Subsemigroup.toAddSubsemigroup_closure (S : Set M) : theorem AddSubsemigroup.toSubsemigroup'_closure (S : Set (Additive M)) : AddSubsemigroup.toSubsemigroup' (AddSubsemigroup.closure S) = - Subsemigroup.closure (Multiplicative.ofAdd ⁻¹' S) := + Subsemigroup.closure (Additive.ofMul ⁻¹' S) := le_antisymm (AddSubsemigroup.toSubsemigroup'.le_symm_apply.1 <| AddSubsemigroup.closure_le.2 (Subsemigroup.subset_closure (M := M))) - (Subsemigroup.closure_le.2 $ AddSubsemigroup.subset_closure (M := Additive M)) + (Subsemigroup.closure_le.2 <| AddSubsemigroup.subset_closure (M := Additive M)) #align add_subsemigroup.to_subsemigroup'_closure AddSubsemigroup.toSubsemigroup'_closure end @@ -150,17 +150,17 @@ theorem AddSubsemigroup.toSubsemigroup_closure (S : Set A) : Subsemigroup.closure (Multiplicative.toAdd ⁻¹' S) := le_antisymm (AddSubsemigroup.toSubsemigroup.to_galoisConnection.l_le <| - AddSubsemigroup.closure_le.2 $ Subsemigroup.subset_closure (M := Multiplicative A)) - (Subsemigroup.closure_le.2 $ AddSubsemigroup.subset_closure (M := A)) + AddSubsemigroup.closure_le.2 <| Subsemigroup.subset_closure (M := Multiplicative A)) + (Subsemigroup.closure_le.2 <| AddSubsemigroup.subset_closure (M := A)) #align add_subsemigroup.to_subsemigroup_closure AddSubsemigroup.toSubsemigroup_closure theorem Subsemigroup.toAddSubsemigroup'_closure (S : Set (Multiplicative A)) : Subsemigroup.toAddSubsemigroup' (Subsemigroup.closure S) = - AddSubsemigroup.closure (Additive.ofMul ⁻¹' S) := + AddSubsemigroup.closure (Multiplicative.ofAdd ⁻¹' S) := le_antisymm (Subsemigroup.toAddSubsemigroup'.to_galoisConnection.l_le <| - Subsemigroup.closure_le.2 $ AddSubsemigroup.subset_closure (M := A)) - (AddSubsemigroup.closure_le.2 $ Subsemigroup.subset_closure (M := Multiplicative A)) + Subsemigroup.closure_le.2 <| AddSubsemigroup.subset_closure (M := A)) + (AddSubsemigroup.closure_le.2 <| Subsemigroup.subset_closure (M := Multiplicative A)) #align subsemigroup.to_add_subsemigroup'_closure Subsemigroup.toAddSubsemigroup'_closure end diff --git a/Mathlib/GroupTheory/Sylow.lean b/Mathlib/GroupTheory/Sylow.lean index ce8e024089543..7c2a9db4c1a04 100644 --- a/Mathlib/GroupTheory/Sylow.lean +++ b/Mathlib/GroupTheory/Sylow.lean @@ -658,13 +658,13 @@ then there is a subgroup of cardinality `p ^ n`. -/ lemma exists_subgroup_card_pow_prime_of_le_card {n p : ℕ} (hp : p.Prime) (h : IsPGroup p G) (hn : p ^ n ≤ Nat.card G) : ∃ H : Subgroup G, Nat.card H = p ^ n := by have : Fact p.Prime := ⟨hp⟩ - have : Finite G := Nat.finite_of_card_ne_zero $ by linarith [Nat.one_le_pow n p hp.pos] + have : Finite G := Nat.finite_of_card_ne_zero <| by linarith [Nat.one_le_pow n p hp.pos] cases nonempty_fintype G obtain ⟨m, hm⟩ := h.exists_card_eq simp_rw [Nat.card_eq_fintype_card] at hm hn ⊢ refine exists_subgroup_card_pow_prime _ ?_ rw [hm] at hn ⊢ - exact pow_dvd_pow _ $ (pow_le_pow_iff_right hp.one_lt).1 hn + exact pow_dvd_pow _ <| (pow_le_pow_iff_right hp.one_lt).1 hn /-- A special case of **Sylow's first theorem**. If `G` is a `p`-group and `H` a subgroup of size at least `p ^ n` then there is a subgroup of `H` of cardinality `p ^ n`. -/ diff --git a/Mathlib/GroupTheory/Torsion.lean b/Mathlib/GroupTheory/Torsion.lean index 348357074807b..82831b0528813 100644 --- a/Mathlib/GroupTheory/Torsion.lean +++ b/Mathlib/GroupTheory/Torsion.lean @@ -373,6 +373,12 @@ theorem not_isTorsionFree_iff : ¬IsTorsionFree G ↔ ∃ g : G, g ≠ 1 ∧ IsO lemma isTorsionFree_of_subsingleton [Subsingleton G] : IsTorsionFree G := fun _a ha _ => ha <| Subsingleton.elim _ _ +@[to_additive] +lemma isTorsionFree_iff_torsion_eq_bot {G} [CommGroup G] : + IsTorsionFree G ↔ CommGroup.torsion G = ⊥ := by + rw [IsTorsionFree, eq_bot_iff, SetLike.le_def] + simp [not_imp_not, CommGroup.mem_torsion] + end Monoid section Group diff --git a/Mathlib/Init/Align.lean b/Mathlib/Init/Align.lean index 183424c0bef39..c6a0c5efede6b 100644 --- a/Mathlib/Init/Align.lean +++ b/Mathlib/Init/Align.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Daniel Selsam, Mario Carneiro -/ +import Std.Data.Option.Lemmas import Mathlib.Mathport.Rename import Mathlib.Init.Logic import Mathlib.Tactic.Relation.Symm diff --git a/Mathlib/Init/Classical.lean b/Mathlib/Init/Classical.lean index 0d308dd7a094b..b2bdec9e082d1 100644 --- a/Mathlib/Init/Classical.lean +++ b/Mathlib/Init/Classical.lean @@ -5,7 +5,6 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Tactic.IrreducibleDef import Mathlib.Mathport.Rename -import Mathlib.Init.Logic /-! ### alignments from lean 3 `init.classical` -/ diff --git a/Mathlib/Init/Control/Lawful.lean b/Mathlib/Init/Control/Lawful.lean index d724cf80fa92e..4d5140830be1c 100644 --- a/Mathlib/Init/Control/Lawful.lean +++ b/Mathlib/Init/Control/Lawful.lean @@ -189,7 +189,7 @@ namespace OptionT variable {α β : Type u} {m : Type u → Type v} (x : OptionT m α) -theorem ext {x x' : OptionT m α} (h : x.run = x'.run) : x = x' := +@[ext] theorem ext {x x' : OptionT m α} (h : x.run = x'.run) : x = x' := h #align option_t.ext OptionTₓ.ext diff --git a/Mathlib/Init/Data/Bool/Lemmas.lean b/Mathlib/Init/Data/Bool/Lemmas.lean index ced7ce8edc03e..88fae582d58b7 100644 --- a/Mathlib/Init/Data/Bool/Lemmas.lean +++ b/Mathlib/Init/Data/Bool/Lemmas.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -import Mathlib.Init.Data.Bool.Basic +import Std.Data.Bool import Mathlib.Init.Logic import Mathlib.Tactic.Coe @@ -107,10 +107,10 @@ theorem coe_false : ↑false = False := by simp theorem coe_true : ↑true = True := by simp #align coe_tt Bool.coe_true -theorem coe_sort_false : (↥false : Prop) = False := by simp +theorem coe_sort_false : (false : Prop) = False := by simp #align coe_sort_ff Bool.coe_sort_false -theorem coe_sort_true : (↥true : Prop) = True := by simp +theorem coe_sort_true : (true : Prop) = True := by simp #align coe_sort_tt Bool.coe_sort_true theorem decide_iff (p : Prop) [d : Decidable p] : decide p = true ↔ p := by simp diff --git a/Mathlib/Init/Data/Int/Basic.lean b/Mathlib/Init/Data/Int/Basic.lean index c4cf7cb0c694a..64e97441b1ea8 100644 --- a/Mathlib/Init/Data/Int/Basic.lean +++ b/Mathlib/Init/Data/Int/Basic.lean @@ -7,8 +7,7 @@ The integers, with addition, multiplication, and subtraction. -/ import Mathlib.Mathport.Rename import Mathlib.Init.Data.Nat.Notation -import Mathlib.Init.ZeroOne -import Std.Data.Int.Lemmas +import Std.Data.Int.Order open Nat diff --git a/Mathlib/Init/Data/Int/Bitwise.lean b/Mathlib/Init/Data/Int/Bitwise.lean index 2b866c2806de0..adeb94a46c221 100644 --- a/Mathlib/Init/Data/Int/Bitwise.lean +++ b/Mathlib/Init/Data/Int/Bitwise.lean @@ -6,6 +6,7 @@ Authors: Mario Carneiro import Mathlib.Init.Data.Int.Basic import Mathlib.Init.Data.Nat.Bitwise +import Mathlib.Init.ZeroOne #align_import init.data.int.bitwise from "leanprover-community/lean"@"855e5b74e3a52a40552e8f067169d747d48743fd" diff --git a/Mathlib/Init/Data/Int/CompLemmas.lean b/Mathlib/Init/Data/Int/CompLemmas.lean index 7fb5a1885379c..80a836204ad31 100644 --- a/Mathlib/Init/Data/Int/CompLemmas.lean +++ b/Mathlib/Init/Data/Int/CompLemmas.lean @@ -5,6 +5,7 @@ Authors: Leonardo de Moura -/ import Mathlib.Init.Data.Int.Order +import Mathlib.Init.ZeroOne #align_import init.data.int.comp_lemmas from "leanprover-community/lean"@"4a03bdeb31b3688c31d02d7ff8e0ff2e5d6174db" diff --git a/Mathlib/Init/Data/Int/Lemmas.lean b/Mathlib/Init/Data/Int/Lemmas.lean index 31803bd249387..d19ff4b4b307e 100644 --- a/Mathlib/Init/Data/Int/Lemmas.lean +++ b/Mathlib/Init/Data/Int/Lemmas.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Std.Data.Int.Lemmas +import Std.Data.Int.Order import Mathlib.Mathport.Rename /-! diff --git a/Mathlib/Init/Data/List/Basic.lean b/Mathlib/Init/Data/List/Basic.lean index 845220ec45808..c029e080b9f5d 100644 --- a/Mathlib/Init/Data/List/Basic.lean +++ b/Mathlib/Init/Data/List/Basic.lean @@ -5,7 +5,6 @@ Authors: Leonardo de Moura -/ import Mathlib.Mathport.Rename import Mathlib.Init.Data.Nat.Notation -import Std.Data.Nat.Lemmas import Std.Data.List.Basic /-! Definitions for `List` not (yet) in `Std` diff --git a/Mathlib/Init/Data/List/Instances.lean b/Mathlib/Init/Data/List/Instances.lean index 17815db2c5dee..427ade9eb5d77 100644 --- a/Mathlib/Init/Data/List/Instances.lean +++ b/Mathlib/Init/Data/List/Instances.lean @@ -3,7 +3,9 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -import Mathlib.Init.Data.List.Lemmas +import Std.Data.List.Lemmas +import Mathlib.Init.Data.List.Basic +import Mathlib.Tactic.Cases #align_import init.data.list.instances from "leanprover-community/lean"@"9af482290ef68e8aaa5ead01aa7b09b7be7019fd" @@ -80,7 +82,7 @@ instance decidableBall (l : List α) : Decidable (∀ x ∈ l, p x) := match (inferInstance : Decidable <| ∃ x ∈ l, ¬ p x) with | isFalse h => isTrue fun x hx => match ‹DecidablePred p› x with | isTrue h' => h' - | isFalse h' => False.elim $ h ⟨x, hx, h'⟩ + | isFalse h' => False.elim <| h ⟨x, hx, h'⟩ | isTrue h => isFalse <| let ⟨x, h, np⟩ := h; fun al => np (al x h) #align list.decidable_ball List.decidableBall diff --git a/Mathlib/Init/Data/List/Lemmas.lean b/Mathlib/Init/Data/List/Lemmas.lean index 58423c8980808..2b7f40d7ca428 100644 --- a/Mathlib/Init/Data/List/Lemmas.lean +++ b/Mathlib/Init/Data/List/Lemmas.lean @@ -3,9 +3,8 @@ Copyright (c) 2014 Parikshit Khanna. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn -/ -import Mathlib.Init.Data.List.Basic -import Mathlib.Init.Function -import Mathlib.Init.Data.Nat.Lemmas +import Std.Data.List.Lemmas +import Mathlib.Mathport.Rename import Mathlib.Tactic.Cases /-! diff --git a/Mathlib/Init/Data/Nat/Bitwise.lean b/Mathlib/Init/Data/Nat/Bitwise.lean index 4c90b75b8f2df..da829a3673f05 100644 --- a/Mathlib/Init/Data/Nat/Bitwise.lean +++ b/Mathlib/Init/Data/Nat/Bitwise.lean @@ -6,7 +6,6 @@ Authors: Mario Carneiro import Mathlib.Init.Data.Nat.Lemmas import Init.WFTactics import Mathlib.Data.Bool.Basic -import Mathlib.Init.Data.Bool.Lemmas import Mathlib.Init.ZeroOne import Mathlib.Tactic.Cases import Mathlib.Tactic.Says diff --git a/Mathlib/Init/Data/Nat/GCD.lean b/Mathlib/Init/Data/Nat/GCD.lean index 76cafc5a2e8e2..83e958705c4c8 100644 --- a/Mathlib/Init/Data/Nat/GCD.lean +++ b/Mathlib/Init/Data/Nat/GCD.lean @@ -5,8 +5,9 @@ Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro -/ -import Mathlib.Init.Data.Nat.Lemmas -import Mathlib.Init.Meta.WellFoundedTactics +import Std.Data.Nat.Gcd +import Mathlib.Init.Data.Nat.Notation +import Mathlib.Mathport.Rename #align_import init.data.nat.gcd from "leanprover-community/lean"@"855e5b74e3a52a40552e8f067169d747d48743fd" diff --git a/Mathlib/Init/Data/Nat/Lemmas.lean b/Mathlib/Init/Data/Nat/Lemmas.lean index 25a14c70fd10b..0dd6e55337748 100644 --- a/Mathlib/Init/Data/Nat/Lemmas.lean +++ b/Mathlib/Init/Data/Nat/Lemmas.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad -/ import Std.Data.Nat.Lemmas +import Std.WF import Mathlib.Init.Data.Nat.Basic -import Mathlib.Init.Order.LinearOrder +import Mathlib.Init.Order.Defs #align_import init.data.nat.lemmas from "leanprover-community/lean"@"38b59111b2b4e6c572582b27e8937e92fc70ac02" @@ -462,7 +463,7 @@ Many lemmas are proven more generally in mathlib `algebra/order/sub` -/ #align nat.mul_self_sub_mul_self_eq Nat.mul_self_sub_mul_self_eq -#align nat.succ_mul_succ_eq Nat.succ_mul_succ_eq +#align nat.succ_mul_succ_eq Nat.succ_mul_succ /-! min -/ @@ -780,7 +781,7 @@ lemma to_digits_core_length (b : Nat) (h : 2 <= b) (f n e : Nat) simp only [hdiv_ten]; exact Nat.le.step h_pred_pos else simp only [hdiv_ten, - to_digits_core_lens_eq b f (n / b) (Nat.digitChar $ n % b), if_false] + to_digits_core_lens_eq b f (n / b) (Nat.digitChar <| n % b), if_false] exact Nat.succ_le_succ ih else obtain rfl : e = 0 := Nat.eq_zero_of_not_pos h_pred_pos diff --git a/Mathlib/Init/Data/Quot.lean b/Mathlib/Init/Data/Quot.lean index 25b17b7e9eee2..6bc2fbec70f0d 100644 --- a/Mathlib/Init/Data/Quot.lean +++ b/Mathlib/Init/Data/Quot.lean @@ -3,8 +3,8 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ - -import Mathlib.Init.Logic +import Std.Logic +import Mathlib.Mathport.Rename /-! # Quotient types diff --git a/Mathlib/Init/Data/Sigma/Basic.lean b/Mathlib/Init/Data/Sigma/Basic.lean index 2a4ea417b7758..f5de39ccc1319 100644 --- a/Mathlib/Init/Data/Sigma/Basic.lean +++ b/Mathlib/Init/Data/Sigma/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2014 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad, Floris van Doorn -/ -import Mathlib.Init.Logic /-! # Lemmas about `Sigma` from Lean 3 core. diff --git a/Mathlib/Init/Data/Sigma/Lex.lean b/Mathlib/Init/Data/Sigma/Lex.lean index 9ad5ad0ea143a..8c91724d1ae44 100644 --- a/Mathlib/Init/Data/Sigma/Lex.lean +++ b/Mathlib/Init/Data/Sigma/Lex.lean @@ -3,7 +3,7 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -import Mathlib.Init.Data.Sigma.Basic +import Mathlib.Mathport.Rename #align_import init.data.sigma.lex from "leanprover-community/lean"@"9af482290ef68e8aaa5ead01aa7b09b7be7019fd" diff --git a/Mathlib/Init/Data/Subtype/Basic.lean b/Mathlib/Init/Data/Subtype/Basic.lean index 964f96368aa57..42b4c2d32cee5 100644 --- a/Mathlib/Init/Data/Subtype/Basic.lean +++ b/Mathlib/Init/Data/Subtype/Basic.lean @@ -3,7 +3,8 @@ Copyright (c) 2014 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad -/ -import Mathlib.Init.Logic +import Std.Logic +import Mathlib.Mathport.Rename #align_import init.data.subtype.basic from "leanprover-community/lean"@"855e5b74e3a52a40552e8f067169d747d48743fd" diff --git a/Mathlib/Init/Function.lean b/Mathlib/Init/Function.lean index 6ca9bd07a87e1..8432a72c9adac 100644 --- a/Mathlib/Init/Function.lean +++ b/Mathlib/Init/Function.lean @@ -3,10 +3,11 @@ Copyright (c) 2014 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad, Haitao Zhang -/ -import Mathlib.Init.Logic +import Mathlib.Tactic.Basic import Mathlib.Mathport.Rename import Mathlib.Tactic.Attr.Register import Mathlib.Tactic.Eqns +import Mathlib.Tactic.TypeStar #align_import init.function from "leanprover-community/lean"@"03a6a6015c0b12dce7b36b4a1f7205a92dfaa592" @@ -14,7 +15,6 @@ import Mathlib.Tactic.Eqns # General operations on functions -/ - universe u₁ u₂ u₃ u₄ u₅ namespace Function @@ -39,11 +39,11 @@ def dcomp {β : α → Sort u₂} {φ : ∀ {x : α}, β x → Sort u₃} (f : infixr:80 " ∘' " => Function.dcomp -@[reducible] +@[reducible, deprecated] -- Deprecated since 13 January 2024 def compRight (f : β → β → β) (g : α → β) : β → α → β := fun b a => f b (g a) #align function.comp_right Function.compRight -@[reducible] +@[reducible, deprecated] -- Deprecated since 13 January 2024 def compLeft (f : β → β → β) (g : α → β) : α → β → β := fun a b => f (g a) b #align function.comp_left Function.compLeft @@ -54,13 +54,16 @@ from `β` to `α`. -/ def onFun (f : β → β → φ) (g : α → β) : α → α → φ := fun x y => f (g x) (g y) #align function.on_fun Function.onFun +@[inherit_doc onFun] +infixl:2 " on " => onFun + /-- Given functions `f : α → β → φ`, `g : α → β → δ` and a binary operator `op : φ → δ → ζ`, produce a function `α → β → ζ` that applies `f` and `g` on each argument and then applies `op` to the results. -/ -- Porting note: the ζ variable was originally constrained to `Sort u₁`, but this seems to -- have been an oversight. -@[reducible] +@[reducible, deprecated] -- Deprecated since 13 January 2024 def combine (f : α → β → φ) (op : φ → δ → ζ) (g : α → β → δ) : α → β → ζ := fun x y => op (f x y) (g x y) #align function.combine Function.combine @@ -71,24 +74,29 @@ def combine (f : α → β → φ) (op : φ → δ → ζ) (g : α → β → δ def swap {φ : α → β → Sort u₃} (f : ∀ x y, φ x y) : ∀ y x, φ x y := fun y x => f x y #align function.swap Function.swap -@[reducible] +@[reducible, deprecated] -- Deprecated since 13 January 2024 def app {β : α → Sort u₂} (f : ∀ x, β x) (x : α) : β x := f x #align function.app Function.app -@[inherit_doc onFun] -infixl:2 " on " => onFun - -- porting note: removed, it was never used -- notation f " -[" op "]- " g => combine f op g -theorem left_id (f : α → β) : id ∘ f = f := - rfl -#align function.left_id Function.left_id +@[simp, mfld_simps] +theorem id_comp (f : α → β) : id ∘ f = f := rfl +#align function.left_id Function.id_comp +#align function.comp.left_id Function.id_comp -theorem right_id (f : α → β) : f ∘ id = f := - rfl -#align function.right_id Function.right_id +@[deprecated] alias left_id := id_comp -- Deprecated since 14 January 2014 +@[deprecated] alias comp.left_id := id_comp -- Deprecated since 14 January 2014 + +@[simp, mfld_simps] +theorem comp_id (f : α → β) : f ∘ id = f := rfl +#align function.right_id Function.comp_id +#align function.comp.right_id Function.comp_id + +@[deprecated] alias right_id := comp_id -- Deprecated since 14 January 2014 +@[deprecated] alias comp.right_id := comp_id -- Deprecated since 14 January 2014 #align function.comp_app Function.comp_apply @@ -96,19 +104,13 @@ theorem comp.assoc (f : φ → δ) (g : β → φ) (h : α → β) : (f ∘ g) rfl #align function.comp.assoc Function.comp.assoc -@[simp, mfld_simps] -theorem comp.left_id (f : α → β) : id ∘ f = f := - rfl -#align function.comp.left_id Function.comp.left_id +@[simp] theorem const_comp {γ : Sort*} (f : α → β) (c : γ) : const β c ∘ f = const α c := rfl +#align function.const_comp Function.const_comp -@[simp, mfld_simps] -theorem comp.right_id (f : α → β) : f ∘ id = f := - rfl -#align function.comp.right_id Function.comp.right_id +@[simp] theorem comp_const (f : β → φ) (b : β) : f ∘ const α b = const α (f b) := rfl +#align function.comp_const_right Function.comp_const -theorem comp_const_right (f : β → φ) (b : β) : f ∘ const α b = const α (f b) := - rfl -#align function.comp_const_right Function.comp_const_right +@[deprecated] alias comp_const_right := comp_const -- Deprecated since 14 January 2014 /-- A function `f : α → β` is called injective if `f x = f y` implies `x = y`. -/ def Injective (f : α → β) : Prop := diff --git a/Mathlib/Init/IteSimp.lean b/Mathlib/Init/IteSimp.lean index 255f277e8b1de..d525bca7773c4 100644 --- a/Mathlib/Init/IteSimp.lean +++ b/Mathlib/Init/IteSimp.lean @@ -4,8 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -import Mathlib.Init.Data.Bool.Basic -import Mathlib.Init.Data.Bool.Lemmas +import Mathlib.Mathport.Rename #align_import init.ite_simp from "leanprover-community/lean"@"4a03bdeb31b3688c31d02d7ff8e0ff2e5d6174db" diff --git a/Mathlib/Init/Logic.lean b/Mathlib/Init/Logic.lean index 4885c34d8c9eb..a40b700a2bf6a 100644 --- a/Mathlib/Init/Logic.lean +++ b/Mathlib/Init/Logic.lean @@ -7,13 +7,11 @@ import Std.Tactic.Ext import Std.Tactic.Lint.Basic import Std.Tactic.Relation.Rfl import Std.Logic -import Std.WF -import Mathlib.Tactic.Basic +import Mathlib.Tactic.Lemma import Mathlib.Tactic.Relation.Symm import Mathlib.Mathport.Attributes import Mathlib.Mathport.Rename import Mathlib.Tactic.Relation.Trans -import Mathlib.Util.Imports import Mathlib.Tactic.ProjectionNotation set_option autoImplicit true @@ -39,8 +37,6 @@ set_option autoImplicit true /- Eq -/ alias proof_irrel := proofIrrel -alias congr_fun := congrFun -alias congr_arg := congrArg @[deprecated] theorem trans_rel_left {α : Sort u} {a b c : α} (r : α → α → Prop) (h₁ : r a b) (h₂ : b = c) : r a c := h₂ ▸ h₁ @@ -268,7 +264,7 @@ theorem ExistsUnique.unique {α : Sort u} {p : α → Prop} -- @[congr] theorem exists_unique_congr {p q : α → Prop} (h : ∀ a, p a ↔ q a) : (∃! a, p a) ↔ ∃! a, q a := - exists_congr fun _ ↦ and_congr (h _) $ forall_congr' fun _ ↦ imp_congr_left (h _) + exists_congr fun _ ↦ and_congr (h _) <| forall_congr' fun _ ↦ imp_congr_left (h _) /- decidable -/ diff --git a/Mathlib/Init/Meta/WellFoundedTactics.lean b/Mathlib/Init/Meta/WellFoundedTactics.lean index b86e8eb4979db..22e4a343ba987 100644 --- a/Mathlib/Init/Meta/WellFoundedTactics.lean +++ b/Mathlib/Init/Meta/WellFoundedTactics.lean @@ -3,8 +3,8 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -prelude -import Mathlib.Init.Data.Nat.Lemmas +import Std.Data.Nat.Lemmas +import Mathlib.Mathport.Rename #align_import init.meta.well_founded_tactics from "leanprover-community/lean"@"855e5b74e3a52a40552e8f067169d747d48743fd" diff --git a/Mathlib/Init/Order/Defs.lean b/Mathlib/Init/Order/Defs.lean index c0f97b9393654..719b8ff63b533 100644 --- a/Mathlib/Init/Order/Defs.lean +++ b/Mathlib/Init/Order/Defs.lean @@ -7,6 +7,7 @@ import Mathlib.Mathport.Rename import Mathlib.Init.Algebra.Classes import Mathlib.Init.Data.Ordering.Basic import Mathlib.Tactic.SplitIfs +import Mathlib.Tactic.TypeStar #align_import init.algebra.order from "leanprover-community/lean"@"c2bcdbcbe741ed37c361a30d38e179182b989f76" diff --git a/Mathlib/Init/Propext.lean b/Mathlib/Init/Propext.lean index bd9c27e7f7e94..28dcf63eacc6f 100644 --- a/Mathlib/Init/Propext.lean +++ b/Mathlib/Init/Propext.lean @@ -3,7 +3,7 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -import Mathlib.Init.Logic +import Std.Logic import Mathlib.Mathport.Rename /-! Additional congruence lemmas. -/ diff --git a/Mathlib/Init/Set.lean b/Mathlib/Init/Set.lean index 1a5838c67f927..ffeefe5d78d39 100644 --- a/Mathlib/Init/Set.lean +++ b/Mathlib/Init/Set.lean @@ -175,7 +175,7 @@ instance : Functor Set where map := @Set.image instance : LawfulFunctor Set where id_map _ := funext fun _ ↦ propext ⟨λ ⟨_, sb, rfl⟩ => sb, λ sb => ⟨_, sb, rfl⟩⟩ - comp_map g h _ := funext $ λ c => propext + comp_map g h _ := funext <| λ c => propext ⟨λ ⟨a, ⟨h₁, h₂⟩⟩ => ⟨g a, ⟨⟨a, ⟨h₁, rfl⟩⟩, h₂⟩⟩, λ ⟨_, ⟨⟨a, ⟨h₁, h₂⟩⟩, h₃⟩⟩ => ⟨a, ⟨h₁, show h (g a) = c from h₂ ▸ h₃⟩⟩⟩ map_const := rfl diff --git a/Mathlib/Lean/CoreM.lean b/Mathlib/Lean/CoreM.lean index 5c33e15999c4c..747b38c8f3222 100644 --- a/Mathlib/Lean/CoreM.lean +++ b/Mathlib/Lean/CoreM.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Lean import Mathlib.Tactic.ToExpr /-! diff --git a/Mathlib/Lean/Elab/Term.lean b/Mathlib/Lean/Elab/Term.lean index 97faafafde5f3..6a0efa334d1ed 100644 --- a/Mathlib/Lean/Elab/Term.lean +++ b/Mathlib/Lean/Elab/Term.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Lean.Elab +import Lean.Elab.SyntheticMVars /-! # Additions to `Lean.Elab.Term` diff --git a/Mathlib/Lean/EnvExtension.lean b/Mathlib/Lean/EnvExtension.lean index 41d341faf97da..f590aa29ff4bd 100644 --- a/Mathlib/Lean/EnvExtension.lean +++ b/Mathlib/Lean/EnvExtension.lean @@ -3,7 +3,8 @@ Copyright (c) 2023 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ -import Lean +import Lean.ScopedEnvExtension + /-! # Helper function for environment extensions and attributes. -/ diff --git a/Mathlib/Lean/Exception.lean b/Mathlib/Lean/Exception.lean index 3433a64a748c1..47a7a9f747be6 100644 --- a/Mathlib/Lean/Exception.lean +++ b/Mathlib/Lean/Exception.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 E.W.Ayers. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: E.W.Ayers -/ -import Lean +import Lean.Exception set_option autoImplicit true diff --git a/Mathlib/Lean/Expr/Basic.lean b/Mathlib/Lean/Expr/Basic.lean index eaab712e9ff82..c20aac70e85b8 100644 --- a/Mathlib/Lean/Expr/Basic.lean +++ b/Mathlib/Lean/Expr/Basic.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Simon Hudon, Scott Morrison, Keeley Hoek, Robert Y. Lewis, Floris van Doorn, E.W.Ayers, Arthur Paulino -/ -import Lean +import Lean.Meta.Tactic.Rewrite import Std.Lean.Expr +import Std.Data.Rat.Basic import Std.Data.List.Basic /-! @@ -93,7 +94,7 @@ def isBlackListed {m} [Monad m] [MonadEnv m] (declName : Name) : m Bool := do if declName matches .str _ "inj" then return true if declName matches .str _ "noConfusionType" then return true let env ← getEnv - pure $ declName.isInternalDetail + pure <| declName.isInternalDetail || isAuxRecursor env declName || isNoConfusion env declName <||> isRec declName <||> isMatcher declName @@ -490,50 +491,4 @@ def getFieldsToParents (env : Environment) (structName : Name) : Array Name := getStructureFields env structName |>.filter fun fieldName => isSubobjectField? env structName fieldName |>.isSome -/-- Return the name of the module in which a declaration was defined. -/ -def Environment.getModuleFor? (env : Environment) (declName : Name) : Option Name := - match env.getModuleIdxFor? declName with - | none => - if env.constants.map₂.contains declName then - env.header.mainModule - else - none - | some idx => env.header.moduleNames[idx.toNat]! - -/-- -Return the names of the modules in which constants used in the specified declaration were defined. - -Note that this will *not* account for tactics and syntax used in the declaration, -so the results may not suffice as imports. --/ -def Name.requiredModules (n : Name) : CoreM NameSet := do - let env ← getEnv - let mut requiredModules : NameSet := {} - let ci ← getConstInfo n - for n in ci.getUsedConstantsAsSet do - match env.getModuleFor? n with - | some m => - if ¬ (`Init).isPrefixOf m then - requiredModules := requiredModules.insert m - | none => pure () - return requiredModules - -/-- -Return the names of the modules in which constants used in the current file were defined. - -Note that this will *not* account for tactics and syntax used in the file, -so the results may not suffice as imports. --/ -def Environment.requiredModules (env : Environment) : NameSet := Id.run do - let localConstantInfos := env.constants.map₂ - let mut requiredModules : NameSet := {} - for (_, ci) in localConstantInfos do - for n in ci.getUsedConstantsAsSet do - match env.getModuleFor? n with - | some m => - if ¬ (`Init).isPrefixOf m then - requiredModules := requiredModules.insert m - | none => pure () - return requiredModules - end Lean diff --git a/Mathlib/Lean/Expr/ExtraRecognizers.lean b/Mathlib/Lean/Expr/ExtraRecognizers.lean index 0bf2ba6df23d1..84ba47b6aeed5 100644 --- a/Mathlib/Lean/Expr/ExtraRecognizers.lean +++ b/Mathlib/Lean/Expr/ExtraRecognizers.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Mathlib.Lean.Expr.Basic import Mathlib.Data.Set.Basic /-! diff --git a/Mathlib/Lean/Expr/ReplaceRec.lean b/Mathlib/Lean/Expr/ReplaceRec.lean index 3e51b4be73e4c..a7250368d91c7 100644 --- a/Mathlib/Lean/Expr/ReplaceRec.lean +++ b/Mathlib/Lean/Expr/ReplaceRec.lean @@ -4,11 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Simon Hudon, Scott Morrison, Keeley Hoek, Robert Y. Lewis, Floris van Doorn, E.W.Ayers -/ -import Lean -import Lean.Meta import Std.Util.TermUnsafe import Mathlib.Lean.Expr.Traverse import Mathlib.Util.MemoFix + namespace Lean.Expr /-! # ReplaceRec diff --git a/Mathlib/Lean/Expr/Traverse.lean b/Mathlib/Lean/Expr/Traverse.lean index 0a01a77851920..f2c6bdf82aec3 100644 --- a/Mathlib/Lean/Expr/Traverse.lean +++ b/Mathlib/Lean/Expr/Traverse.lean @@ -3,9 +3,7 @@ Copyright (c) 2022 E.W.Ayers. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: E.W.Ayers -/ - -import Lean -import Mathlib.Lean.Expr.Basic +import Lean.Expr /-! # Traversal functions for expressions. diff --git a/Mathlib/Lean/Json.lean b/Mathlib/Lean/Json.lean index e71bc62c61bf3..0b7a56fd66b3d 100644 --- a/Mathlib/Lean/Json.lean +++ b/Mathlib/Lean/Json.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Lean import Mathlib.Mathport.Rename #align_import data.json from "leanprover-community/mathlib"@"b93a64dac6f7e8f10164b867ac329dda0747e075" diff --git a/Mathlib/Lean/LocalContext.lean b/Mathlib/Lean/LocalContext.lean index 7ee2f578e4884..bbe5dfb511a34 100644 --- a/Mathlib/Lean/LocalContext.lean +++ b/Mathlib/Lean/LocalContext.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Lean.Meta.Tactic.Apply +import Lean.LocalContext namespace Lean.LocalContext diff --git a/Mathlib/Lean/Meta.lean b/Mathlib/Lean/Meta.lean index 1e2f89dca7792..602e6ccf9375b 100644 --- a/Mathlib/Lean/Meta.lean +++ b/Mathlib/Lean/Meta.lean @@ -3,11 +3,10 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Lean.Elab import Lean.Meta.Tactic.Assert import Lean.Meta.Tactic.Clear import Std.Data.Option.Basic -import Std.Data.List.Count +import Std.Data.List.Basic /-! ## Additional utilities in `Lean.MVarId` -/ @@ -26,7 +25,7 @@ def «let» (g : MVarId) (h : Name) (v : Expr) (t : Option Expr := .none) : -/ def existsi (mvar : MVarId) (es : List Expr) : MetaM MVarId := do es.foldlM (λ mv e => do - let (subgoals,_) ← Elab.Term.TermElabM.run $ Elab.Tactic.run mv do + let (subgoals,_) ← Elab.Term.TermElabM.run <| Elab.Tactic.run mv do Elab.Tactic.evalTactic (← `(tactic| refine ⟨?_,?_⟩)) let [sg1, sg2] := subgoals | throwError "expected two subgoals" sg1.assign e @@ -121,24 +120,6 @@ def countLocalHypsUsed [Monad m] [MonadLCtx m] [MonadMCtx m] (e : Expr) : m Nat let e' ← instantiateMVars e return (← getLocalHyps).toList.countP fun h => h.occurs e' -/-- -Given a monadic function `F` that takes a type and a term of that type and produces a new term, -lifts this to the monadic function that opens a `∀` telescope, applies `F` to the body, -and then builds the lambda telescope term for the new term. --/ -def mapForallTelescope' (F : Expr → Expr → MetaM Expr) (forallTerm : Expr) : MetaM Expr := do - forallTelescope (← Meta.inferType forallTerm) fun xs ty => do - Meta.mkLambdaFVars xs (← F ty (mkAppN forallTerm xs)) - -/-- -Given a monadic function `F` that takes a term and produces a new term, -lifts this to the monadic function that opens a `∀` telescope, applies `F` to the body, -and then builds the lambda telescope term for the new term. --/ -def mapForallTelescope (F : Expr → MetaM Expr) (forallTerm : Expr) : MetaM Expr := do - mapForallTelescope' (fun _ e => F e) forallTerm - - /-- Get the type the given metavariable after instantiating metavariables and cleaning up annotations. -/ def _root_.Lean.MVarId.getType'' (mvarId : MVarId) : MetaM Expr := diff --git a/Mathlib/Lean/Meta/CongrTheorems.lean b/Mathlib/Lean/Meta/CongrTheorems.lean index a0aefdf6a6251..d867ea7377527 100644 --- a/Mathlib/Lean/Meta/CongrTheorems.lean +++ b/Mathlib/Lean/Meta/CongrTheorems.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ +import Lean.Meta.Tactic.Cleanup import Mathlib.Lean.Meta /-! diff --git a/Mathlib/Lean/Meta/DiscrTree.lean b/Mathlib/Lean/Meta/DiscrTree.lean index 41d79afb61159..6113e9e64e338 100644 --- a/Mathlib/Lean/Meta/DiscrTree.lean +++ b/Mathlib/Lean/Meta/DiscrTree.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Lean.Meta.DiscrTree -import Std.Lean.Meta.DiscrTree import Mathlib.Lean.Expr.Traverse /-! diff --git a/Mathlib/Lean/Meta/Simp.lean b/Mathlib/Lean/Meta/Simp.lean index a7fd62c98f59e..89be05bfeac2d 100644 --- a/Mathlib/Lean/Meta/Simp.lean +++ b/Mathlib/Lean/Meta/Simp.lean @@ -3,10 +3,8 @@ Copyright (c) 2022 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Gabriel Ebner, Floris van Doorn -/ -import Lean import Std.Tactic.OpenPrivate import Std.Lean.Meta.DiscrTree -import Std.Lean.Meta.Simp /-! # Helper functions for using the simplifier. diff --git a/Mathlib/Lean/Name.lean b/Mathlib/Lean/Name.lean index f91356d298801..2458d52d10fa2 100644 --- a/Mathlib/Lean/Name.lean +++ b/Mathlib/Lean/Name.lean @@ -5,13 +5,11 @@ Authors: Scott Morrison -/ import Std.Data.HashMap.Basic import Std.Lean.SMap -import Mathlib.Lean.Expr.Basic /-! # Additional functions on `Lean.Name`. -We provide `Name.getModule`, -and `allNames` and `allNamesByModule`. +We provide `allNames` and `allNamesByModule`. -/ open Lean Meta Elab @@ -19,7 +17,7 @@ open Lean Meta Elab private def isBlackListed (declName : Name) : CoreM Bool := do if declName.toString.startsWith "Lean" then return true let env ← getEnv - pure $ declName.isInternalDetail + pure <| declName.isInternalDetail || isAuxRecursor env declName || isNoConfusion env declName <||> isRec declName <||> isMatcher declName @@ -49,13 +47,6 @@ def allNamesByModule (p : Name → Bool) : CoreM (Std.HashMap Name (Array Name)) else return names -/-- Returns the very first part of a name: for `Mathlib.Data.Set.Basic` it returns `Mathlib`. -/ -def getModule (name : Name) (s := "") : Name := - match name with - | .anonymous => s - | .num _ _ => panic s!"panic in `getModule`: did not expect numerical name: {name}." - | .str pre s => getModule pre s - /-- Decapitalize the last component of a name. -/ def Lean.Name.decapitalize (n : Name) : Name := n.modifyBase fun diff --git a/Mathlib/Lean/PrettyPrinter/Delaborator.lean b/Mathlib/Lean/PrettyPrinter/Delaborator.lean index 1cae05ba0a25e..34f664c3bf2c2 100644 --- a/Mathlib/Lean/PrettyPrinter/Delaborator.lean +++ b/Mathlib/Lean/PrettyPrinter/Delaborator.lean @@ -45,7 +45,7 @@ See also `Lean.PrettyPrinter.Delaborator.withBindingBodyUnusedName`. -/ def withBindingBodyUnusedName' {α} (d : Syntax → Expr → DelabM α) : DelabM α := do let n ← getUnusedName (← getExpr).bindingName! (← getExpr).bindingBody! let stxN ← annotateCurPos (mkIdent n) - withBindingBody' n $ d stxN + withBindingBody' n <| d stxN /-- Update `OptionsPerPos` at the given position, setting the key `n` to have the boolean value `v`. -/ diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean index 84c5fb3b9186f..64b15371b1008 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean @@ -93,11 +93,11 @@ instance equivLike : EquivLike (P₁ ≃ᵃ[k] P₂) P₁ P₂ where inv f := f.invFun left_inv f := f.left_inv right_inv f := f.right_inv - coe_injective' _ _ h _ := toAffineMap_injective (FunLike.coe_injective h) + coe_injective' _ _ h _ := toAffineMap_injective (DFunLike.coe_injective h) #align affine_equiv.equiv_like AffineEquiv.equivLike instance : CoeFun (P₁ ≃ᵃ[k] P₂) fun _ => P₁ → P₂ := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun instance : CoeOut (P₁ ≃ᵃ[k] P₂) (P₁ ≃ P₂) := ⟨AffineEquiv.toEquiv⟩ @@ -132,15 +132,15 @@ theorem coe_linear (e : P₁ ≃ᵃ[k] P₂) : (e : P₁ →ᵃ[k] P₂).linear @[ext] theorem ext {e e' : P₁ ≃ᵃ[k] P₂} (h : ∀ x, e x = e' x) : e = e' := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align affine_equiv.ext AffineEquiv.ext theorem coeFn_injective : @Injective (P₁ ≃ᵃ[k] P₂) (P₁ → P₂) (⇑) := - FunLike.coe_injective + DFunLike.coe_injective #align affine_equiv.coe_fn_injective AffineEquiv.coeFn_injective @[norm_cast] --- Porting note: removed `simp`: proof is `simp only [FunLike.coe_fn_eq]` +-- Porting note: removed `simp`: proof is `simp only [DFunLike.coe_fn_eq]` theorem coeFn_inj {e e' : P₁ ≃ᵃ[k] P₂} : (e : P₁ → P₂) = e' ↔ e = e' := coeFn_injective.eq_iff #align affine_equiv.coe_fn_inj AffineEquiv.coeFn_inj diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean index 47c7a6e92ba48..0affa217d951e 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean @@ -59,9 +59,9 @@ structure AffineMap (k : Type*) {V1 : Type*} (P1 : Type*) {V2 : Type*} (P2 : Typ induces a corresponding linear map from `V1` to `V2`. -/ notation:25 P1 " →ᵃ[" k:25 "] " P2:0 => AffineMap k P1 P2 -instance AffineMap.funLike (k : Type*) {V1 : Type*} (P1 : Type*) {V2 : Type*} (P2 : Type*) +instance AffineMap.instFunLike (k : Type*) {V1 : Type*} (P1 : Type*) {V2 : Type*} (P2 : Type*) [Ring k] [AddCommGroup V1] [Module k V1] [AffineSpace V1 P1] [AddCommGroup V2] [Module k V2] - [AffineSpace V2 P2] : FunLike (P1 →ᵃ[k] P2) P1 fun _ => P2 + [AffineSpace V2 P2] : FunLike (P1 →ᵃ[k] P2) P1 P2 where coe := AffineMap.toFun coe_injective' := fun ⟨f, f_linear, f_add⟩ ⟨g, g_linear, g_add⟩ => fun (h : f = g) => by @@ -69,12 +69,12 @@ instance AffineMap.funLike (k : Type*) {V1 : Type*} (P1 : Type*) {V2 : Type*} (P congr with v apply vadd_right_cancel (f p) erw [← f_add, h, ← g_add] -#align affine_map.fun_like AffineMap.funLike +#align affine_map.fun_like AffineMap.instFunLike instance AffineMap.hasCoeToFun (k : Type*) {V1 : Type*} (P1 : Type*) {V2 : Type*} (P2 : Type*) [Ring k] [AddCommGroup V1] [Module k V1] [AffineSpace V1 P1] [AddCommGroup V2] [Module k V2] [AffineSpace V2 P2] : CoeFun (P1 →ᵃ[k] P2) fun _ => P1 → P2 := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun #align affine_map.has_coe_to_fun AffineMap.hasCoeToFun namespace LinearMap @@ -140,7 +140,7 @@ theorem linearMap_vsub (f : P1 →ᵃ[k] P2) (p1 p2 : P1) : f.linear (p1 -ᵥ p2 /-- Two affine maps are equal if they coerce to the same function. -/ @[ext] theorem ext {f g : P1 →ᵃ[k] P2} (h : ∀ p, f p = g p) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align affine_map.ext AffineMap.ext theorem ext_iff {f g : P1 →ᵃ[k] P2} : f = g ↔ ∀ p, f p = g p := @@ -148,7 +148,7 @@ theorem ext_iff {f g : P1 →ᵃ[k] P2} : f = g ↔ ∀ p, f p = g p := #align affine_map.ext_iff AffineMap.ext_iff theorem coeFn_injective : @Function.Injective (P1 →ᵃ[k] P2) (P1 → P2) (⇑) := - FunLike.coe_injective + DFunLike.coe_injective #align affine_map.coe_fn_injective AffineMap.coeFn_injective protected theorem congr_arg (f : P1 →ᵃ[k] P2) {x y : P1} (h : x = y) : f x = f y := @@ -673,7 +673,7 @@ theorem image_uIcc {k : Type*} [LinearOrderedField k] (f : k →ᵃ[k] k) (a b : section -variable {ι : Type*} {V : ∀ _ : ι, Type*} {P : ∀ _ : ι, Type*} [∀ i, AddCommGroup (V i)] +variable {ι : Type*} {V : ι → Type*} {P : ι → Type*} [∀ i, AddCommGroup (V i)] [∀ i, Module k (V i)] [∀ i, AddTorsor (V i) (P i)] /-- Evaluation at a point as an affine map. -/ diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean index 445981c716895..5b5061e2b527a 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean @@ -1493,7 +1493,7 @@ theorem direction_affineSpan_insert {s : AffineSubspace k P} {p1 p2 : P} (hp1 : `s` with `p2` added if and only if it is a multiple of `p2 -ᵥ p1` added to a point in `s`. -/ theorem mem_affineSpan_insert_iff {s : AffineSubspace k P} {p1 : P} (hp1 : p1 ∈ s) (p2 p : P) : p ∈ affineSpan k (insert p2 (s : Set P)) ↔ - ∃ (r : k) (p0 : P) (_hp0 : p0 ∈ s), p = r • (p2 -ᵥ p1 : V) +ᵥ p0 := by + ∃ r : k, ∃ p0 ∈ s, p = r • (p2 -ᵥ p1 : V) +ᵥ p0 := by rw [← mem_coe] at hp1 rw [← vsub_right_mem_direction_iff_mem (mem_affineSpan k (Set.mem_insert_of_mem _ hp1)), direction_affineSpan_insert hp1, Submodule.mem_sup] diff --git a/Mathlib/LinearAlgebra/AffineSpace/Basis.lean b/Mathlib/LinearAlgebra/AffineSpace/Basis.lean index 65ddc86b8d1ed..ed87422d7ac76 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Basis.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Basis.lean @@ -67,14 +67,14 @@ variable [Ring k] [Module k V] (b : AffineBasis ι k P) {s : Finset ι} {i j : instance : Inhabited (AffineBasis PUnit k PUnit) := ⟨⟨id, affineIndependent_of_subsingleton k id, by simp⟩⟩ -instance funLike : FunLike (AffineBasis ι k P) ι fun _ => P where +instance instFunLike : FunLike (AffineBasis ι k P) ι P where coe := AffineBasis.toFun coe_injective' f g h := by cases f; cases g; congr -#align affine_basis.fun_like AffineBasis.funLike +#align affine_basis.fun_like AffineBasis.instFunLike @[ext] theorem ext {b₁ b₂ : AffineBasis ι k P} (h : (b₁ : ι → P) = b₂) : b₁ = b₂ := - FunLike.coe_injective h + DFunLike.coe_injective h #align affine_basis.ext AffineBasis.ext theorem ind : AffineIndependent k b := @@ -309,7 +309,7 @@ theorem coord_apply_centroid [CharZero k] (b : AffineBasis ι k P) {s : Finset #align affine_basis.coord_apply_centroid AffineBasis.coord_apply_centroid theorem exists_affine_subbasis {t : Set P} (ht : affineSpan k t = ⊤) : - ∃ (s : _) (_ : s ⊆ t) (b : AffineBasis (↥s) k P), ⇑b = ((↑) : s → P) := by + ∃ s ⊆ t, ∃ b : AffineBasis s k P, ⇑b = ((↑) : s → P) := by obtain ⟨s, hst, h_tot, h_ind⟩ := exists_affineIndependent k V t refine' ⟨s, hst, ⟨(↑), h_ind, _⟩, rfl⟩ rw [Subtype.range_coe, h_tot, ht] diff --git a/Mathlib/LinearAlgebra/AffineSpace/Combination.lean b/Mathlib/LinearAlgebra/AffineSpace/Combination.lean index 8708ce5c517a6..a48adf47dfdc2 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Combination.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Combination.lean @@ -164,7 +164,7 @@ theorem weightedVSubOfPoint_indicator_subset (w : ι → k) (p : ι → P) (b : (h : s₁ ⊆ s₂) : s₁.weightedVSubOfPoint p b w = s₂.weightedVSubOfPoint p b (Set.indicator (↑s₁) w) := by rw [weightedVSubOfPoint_apply, weightedVSubOfPoint_apply] - exact Eq.symm $ + exact Eq.symm <| sum_indicator_subset_of_eq_zero w (fun i wi => wi • (p i -ᵥ b : V)) h fun i => zero_smul k _ #align finset.weighted_vsub_of_point_indicator_subset Finset.weightedVSubOfPoint_indicator_subset diff --git a/Mathlib/LinearAlgebra/AffineSpace/FiniteDimensional.lean b/Mathlib/LinearAlgebra/AffineSpace/FiniteDimensional.lean index 40af94e3ad5ee..616ce0dfdf203 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/FiniteDimensional.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Joseph Myers. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Myers -/ +import Mathlib.Init.Core import Mathlib.LinearAlgebra.AffineSpace.Basis import Mathlib.LinearAlgebra.FiniteDimensional @@ -125,6 +126,13 @@ theorem AffineIndependent.finrank_vectorSpan [Fintype ι] {p : ι → P} (hi : A exact hi.finrank_vectorSpan_image_finset hc #align affine_independent.finrank_vector_span AffineIndependent.finrank_vectorSpan +/-- The `vectorSpan` of a finite affinely independent family has dimension one less than its +cardinality. -/ +lemma AffineIndependent.finrank_vectorSpan_add_one [Fintype ι] [Nonempty ι] {p : ι → P} + (hi : AffineIndependent k p) : finrank k (vectorSpan k (Set.range p)) + 1 = Fintype.card ι := by + rw [hi.finrank_vectorSpan (tsub_add_cancel_of_le _).symm, tsub_add_cancel_of_le] <;> + exact Fintype.card_pos + /-- The `vectorSpan` of a finite affinely independent family whose cardinality is one more than that of the finite-dimensional space is `⊤`. -/ @@ -142,7 +150,7 @@ theorem finrank_vectorSpan_image_finset_le [DecidableEq P] (p : ι → P) (s : F (hc : Finset.card s = n + 1) : finrank k (vectorSpan k (s.image p : Set P)) ≤ n := by classical have hn : (s.image p).Nonempty := by - rw [Finset.Nonempty.image_iff, ← Finset.card_pos, hc] + rw [Finset.image_nonempty, ← Finset.card_pos, hc] apply Nat.succ_pos rcases hn with ⟨p₁, hp₁⟩ rw [vectorSpan_eq_span_vsub_finset_right_ne k hp₁] @@ -162,6 +170,12 @@ theorem finrank_vectorSpan_range_le [Fintype ι] (p : ι → P) {n : ℕ} (hc : exact finrank_vectorSpan_image_finset_le _ _ _ hc #align finrank_vector_span_range_le finrank_vectorSpan_range_le +/-- The `vectorSpan` of an indexed family of `n + 1` points has dimension at most `n`. -/ +lemma finrank_vectorSpan_range_add_one_le [Fintype ι] [Nonempty ι] (p : ι → P) : + finrank k (vectorSpan k (Set.range p)) + 1 ≤ Fintype.card ι := + (le_tsub_iff_right $ Nat.succ_le_iff.2 Fintype.card_pos).1 $ finrank_vectorSpan_range_le _ _ + (tsub_add_cancel_of_le $ Nat.succ_le_iff.2 Fintype.card_pos).symm + /-- `n + 1` points are affinely independent if and only if their `vectorSpan` has dimension `n`. -/ theorem affineIndependent_iff_finrank_vectorSpan_eq [Fintype ι] (p : ι → P) {n : ℕ} @@ -217,6 +231,46 @@ lemma AffineIndependent.card_le_finrank_succ [Fintype ι] {p : ι → P} (hp : A exact (affineIndependent_iff_le_finrank_vectorSpan _ _ (tsub_add_cancel_of_le <| Nat.one_le_iff_ne_zero.2 Fintype.card_ne_zero).symm).1 hp +open Finset in +/-- If an affine independent finset is contained in the affine span of another finset, then its +cardinality is at most the cardinality of that finset. -/ +lemma AffineIndependent.card_le_card_of_subset_affineSpan {s t : Finset V} + (hs : AffineIndependent k ((↑) : s → V)) (hst : (s : Set V) ⊆ affineSpan k (t : Set V)) : + s.card ≤ t.card := by + obtain rfl | hs' := s.eq_empty_or_nonempty + · simp + obtain rfl | ht' := t.eq_empty_or_nonempty + · simpa [Set.subset_empty_iff] using hst + have := hs'.to_subtype + have := ht'.to_set.to_subtype + have direction_le := AffineSubspace.direction_le (affineSpan_mono k hst) + rw [AffineSubspace.affineSpan_coe, direction_affineSpan, direction_affineSpan, + ← @Subtype.range_coe _ (s : Set V), ← @Subtype.range_coe _ (t : Set V)] at direction_le + have finrank_le := add_le_add_right (Submodule.finrank_le_finrank_of_le direction_le) 1 + -- We use `erw` to elide the difference between `↥s` and `↥(s : Set V)}` + erw [hs.finrank_vectorSpan_add_one] at finrank_le + simpa using finrank_le.trans <| finrank_vectorSpan_range_add_one_le _ _ + +open Finset in +/-- If the affine span of an affine independent finset is strictly contained in the affine span of +another finset, then its cardinality is strictly less than the cardinality of that finset. -/ +lemma AffineIndependent.card_lt_card_of_affineSpan_lt_affineSpan {s t : Finset V} + (hs : AffineIndependent k ((↑) : s → V)) + (hst : affineSpan k (s : Set V) < affineSpan k (t : Set V)) : s.card < t.card := by + obtain rfl | hs' := s.eq_empty_or_nonempty + · simpa [card_pos] using hst + obtain rfl | ht' := t.eq_empty_or_nonempty + · simp [Set.subset_empty_iff] at hst + have := hs'.to_subtype + have := ht'.to_set.to_subtype + have dir_lt := AffineSubspace.direction_lt_of_nonempty (k := k) hst $ hs'.to_set.affineSpan k + rw [direction_affineSpan, direction_affineSpan, + ← @Subtype.range_coe _ (s : Set V), ← @Subtype.range_coe _ (t : Set V)] at dir_lt + have finrank_lt := add_lt_add_right (Submodule.finrank_lt_finrank_of_lt dir_lt) 1 + -- We use `erw` to elide the difference between `↥s` and `↥(s : Set V)}` + erw [hs.finrank_vectorSpan_add_one] at finrank_lt + simpa using finrank_lt.trans_le <| finrank_vectorSpan_range_add_one_le _ _ + /-- If the `vectorSpan` of a finite subset of an affinely independent family lies in a submodule with dimension one less than its cardinality, it equals that submodule. -/ diff --git a/Mathlib/LinearAlgebra/AffineSpace/Independent.lean b/Mathlib/LinearAlgebra/AffineSpace/Independent.lean index 2d3609c22ab62..c3fae90cba6f0 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Independent.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Independent.lean @@ -606,7 +606,7 @@ theorem exists_subset_affineIndependent_affineSpan_eq_top {s : Set P} variable (k V) theorem exists_affineIndependent (s : Set P) : - ∃ (t : _) (_ : t ⊆ s), affineSpan k t = affineSpan k s ∧ AffineIndependent k ((↑) : t → P) := by + ∃ t ⊆ s, affineSpan k t = affineSpan k s ∧ AffineIndependent k ((↑) : t → P) := by rcases s.eq_empty_or_nonempty with (rfl | ⟨p, hp⟩) · exact ⟨∅, Set.empty_subset ∅, rfl, affineIndependent_of_subsingleton k _⟩ obtain ⟨b, hb₁, hb₂, hb₃⟩ := exists_linearIndependent k ((Equiv.vaddConst p).symm '' s) @@ -614,7 +614,7 @@ theorem exists_affineIndependent (s : Set P) : rw [linearIndependent_set_iff_affineIndependent_vadd_union_singleton k hb₀ p] at hb₃ refine' ⟨{p} ∪ Equiv.vaddConst p '' b, _, _, hb₃⟩ · apply Set.union_subset (Set.singleton_subset_iff.mpr hp) - rwa [← (Equiv.vaddConst p).subset_image' b s] + rwa [← (Equiv.vaddConst p).subset_symm_image b s] · rw [Equiv.coe_vaddConst_symm, ← vectorSpan_eq_span_vsub_set_right k hp] at hb₂ apply AffineSubspace.ext_of_direction_eq · have : Submodule.span k b = Submodule.span k (insert 0 b) := by simp diff --git a/Mathlib/LinearAlgebra/AffineSpace/Matrix.lean b/Mathlib/LinearAlgebra/AffineSpace/Matrix.lean index d0312a7d3496e..db448ff89f3f1 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Matrix.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Matrix.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ import Mathlib.LinearAlgebra.AffineSpace.Basis -import Mathlib.LinearAlgebra.Determinant +import Mathlib.LinearAlgebra.Matrix.NonsingularInverse #align_import linear_algebra.affine_space.matrix from "leanprover-community/mathlib"@"2de9c37fa71dde2f1c6feff19876dd6a7b1519f0" diff --git a/Mathlib/LinearAlgebra/AffineSpace/MidpointZero.lean b/Mathlib/LinearAlgebra/AffineSpace/MidpointZero.lean index fa0a158eb3312..14d57532a859a 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/MidpointZero.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/MidpointZero.lean @@ -48,7 +48,7 @@ theorem homothety_one_half {k : Type*} {V P : Type*} [Field k] [CharZero k] [Add #align homothety_one_half homothety_one_half @[simp] -theorem pi_midpoint_apply {k ι : Type*} {V : ∀ _ : ι, Type*} {P : ∀ _ : ι, Type*} [Field k] +theorem pi_midpoint_apply {k ι : Type*} {V : ι → Type*} {P : ι → Type*} [Field k] [Invertible (2 : k)] [∀ i, AddCommGroup (V i)] [∀ i, Module k (V i)] [∀ i, AddTorsor (V i) (P i)] (f g : ∀ i, P i) (i : ι) : midpoint k f g i = midpoint k (f i) (g i) := diff --git a/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean b/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean index fd7653f7081ba..ba64898fe7aec 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean @@ -3,10 +3,12 @@ Copyright (c) 2020 Yury G. Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury G. Kudryashov -/ +import Mathlib.Algebra.CharP.Invertible import Mathlib.Algebra.Order.Invertible import Mathlib.Algebra.Order.Module.OrderedSMul -import Mathlib.LinearAlgebra.AffineSpace.MidpointZero +import Mathlib.Algebra.Order.Group.Instances import Mathlib.LinearAlgebra.AffineSpace.Slope +import Mathlib.LinearAlgebra.AffineSpace.Midpoint import Mathlib.Tactic.FieldSimp #align_import linear_algebra.affine_space.ordered from "leanprover-community/mathlib"@"78261225eb5cedc61c5c74ecb44e5b385d13b733" diff --git a/Mathlib/LinearAlgebra/Alternating/Basic.lean b/Mathlib/LinearAlgebra/Alternating/Basic.lean index 2d0dd2c9f8864..029af4544d4d8 100644 --- a/Mathlib/LinearAlgebra/Alternating/Basic.lean +++ b/Mathlib/LinearAlgebra/Alternating/Basic.lean @@ -96,17 +96,17 @@ open Function section Coercions -instance funLike : FunLike (M [Λ^ι]→ₗ[R] N) (ι → M) (fun _ => N) where +instance instFunLike : FunLike (M [Λ^ι]→ₗ[R] N) (ι → M) N where coe f := f.toFun coe_injective' := fun f g h ↦ by rcases f with ⟨⟨_, _, _⟩, _⟩ rcases g with ⟨⟨_, _, _⟩, _⟩ congr -#align alternating_map.fun_like AlternatingMap.funLike +#align alternating_map.fun_like AlternatingMap.instFunLike -- shortcut instance instance coeFun : CoeFun (M [Λ^ι]→ₗ[R] N) fun _ => (ι → M) → N := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ #align alternating_map.has_coe_to_fun AlternatingMap.coeFun initialize_simps_projections AlternatingMap (toFun → apply) @@ -132,7 +132,7 @@ theorem congr_arg (f : M [Λ^ι]→ₗ[R] N) {x y : ι → M} (h : x = y) : f x #align alternating_map.congr_arg AlternatingMap.congr_arg theorem coe_injective : Injective ((↑) : M [Λ^ι]→ₗ[R] N → (ι → M) → N) := - FunLike.coe_injective + DFunLike.coe_injective #align alternating_map.coe_injective AlternatingMap.coe_injective @[norm_cast] -- @[simp] -- Porting note: simp can prove this @@ -142,7 +142,7 @@ theorem coe_inj {f g : M [Λ^ι]→ₗ[R] N} : (f : (ι → M) → N) = g ↔ f @[ext] theorem ext {f f' : M [Λ^ι]→ₗ[R] N} (H : ∀ x, f x = f' x) : f = f' := - FunLike.ext _ _ H + DFunLike.ext _ _ H #align alternating_map.ext AlternatingMap.ext theorem ext_iff {f g : M [Λ^ι]→ₗ[R] N} : f = g ↔ ∀ x, f x = g x := diff --git a/Mathlib/LinearAlgebra/Basic.lean b/Mathlib/LinearAlgebra/Basic.lean index edc7d3ec3ecdc..7421593a23ce6 100644 --- a/Mathlib/LinearAlgebra/Basic.lean +++ b/Mathlib/LinearAlgebra/Basic.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Frédéric Dupuis, Heather Macbeth -/ -import Mathlib.Algebra.BigOperators.Pi import Mathlib.Algebra.Module.Hom import Mathlib.Algebra.Module.Prod import Mathlib.Algebra.Module.Submodule.Map @@ -233,7 +232,7 @@ theorem eqLocus_toAddSubmonoid (f g : F) : @[simp] theorem eqLocus_eq_top {f g : F} : eqLocus f g = ⊤ ↔ f = g := by - simp [SetLike.ext_iff, FunLike.ext_iff] + simp [SetLike.ext_iff, DFunLike.ext_iff] @[simp] theorem eqLocus_same (f : F) : eqLocus f f = ⊤ := eqLocus_eq_top.2 rfl @@ -248,7 +247,7 @@ theorem eqOn_sup {f g : F} {S T : Submodule R M} (hS : Set.EqOn f g S) (hT : Set theorem ext_on_codisjoint {f g : F} {S T : Submodule R M} (hST : Codisjoint S T) (hS : Set.EqOn f g S) (hT : Set.EqOn f g T) : f = g := - FunLike.ext _ _ fun _ ↦ eqOn_sup hS hT <| hST.eq_top.symm ▸ trivial + DFunLike.ext _ _ fun _ ↦ eqOn_sup hS hT <| hST.eq_top.symm ▸ trivial end @@ -658,7 +657,7 @@ theorem range_inclusion (p q : Submodule R M) (h : p ≤ q) : @[simp] theorem map_subtype_range_inclusion {p p' : Submodule R M} (h : p ≤ p') : - map p'.subtype (range $ inclusion h) = p := by simp [range_inclusion, map_comap_eq, h] + map p'.subtype (range <| inclusion h) = p := by simp [range_inclusion, map_comap_eq, h] #align submodule.map_subtype_range_of_le Submodule.map_subtype_range_inclusion theorem disjoint_iff_comap_eq_bot {p q : Submodule R M} : Disjoint p q ↔ comap p.subtype q = ⊥ := by @@ -672,7 +671,7 @@ def MapSubtype.relIso : Submodule R p ≃o { p' : Submodule R M // p' ≤ p } wh invFun q := comap p.subtype q left_inv p' := comap_map_eq_of_injective (by exact Subtype.val_injective) p' right_inv := fun ⟨q, hq⟩ => Subtype.ext_val <| by simp [map_comap_subtype p, inf_of_le_right hq] - map_rel_iff' {p₁ p₂} := Subtype.coe_le_coe.symm.trans $ by + map_rel_iff' {p₁ p₂} := Subtype.coe_le_coe.symm.trans <| by dsimp rw [map_le_iff_le_comap, comap_map_eq_of_injective (show Injective p.subtype from Subtype.coe_injective) p₂] @@ -681,7 +680,7 @@ def MapSubtype.relIso : Submodule R p ≃o { p' : Submodule R M // p' ≤ p } wh /-- If `p ⊆ M` is a submodule, the ordering of submodules of `p` is embedded in the ordering of submodules of `M`. -/ def MapSubtype.orderEmbedding : Submodule R p ↪o Submodule R M := - (RelIso.toRelEmbedding <| MapSubtype.relIso p).trans $ + (RelIso.toRelEmbedding <| MapSubtype.relIso p).trans <| Subtype.relEmbedding (X := Submodule R M) (fun p p' ↦ p ≤ p') _ #align submodule.map_subtype.order_embedding Submodule.MapSubtype.orderEmbedding @@ -739,7 +738,7 @@ def submoduleImage {M' : Type*} [AddCommMonoid M'] [Module R M'] {O : Submodule @[simp] theorem mem_submoduleImage {M' : Type*} [AddCommMonoid M'] [Module R M'] {O : Submodule R M} {ϕ : O →ₗ[R] M'} {N : Submodule R M} {x : M'} : - x ∈ ϕ.submoduleImage N ↔ ∃ (y : _) (yO : y ∈ O) (_ : y ∈ N), ϕ ⟨y, yO⟩ = x := by + x ∈ ϕ.submoduleImage N ↔ ∃ (y : _) (yO : y ∈ O), y ∈ N ∧ ϕ ⟨y, yO⟩ = x := by refine' Submodule.mem_map.trans ⟨_, _⟩ <;> simp_rw [Submodule.mem_comap] · rintro ⟨⟨y, yO⟩, yN : y ∈ N, h⟩ exact ⟨y, yO, yN, h⟩ @@ -1346,6 +1345,19 @@ theorem conj_id (e : M ≃ₗ[R] M₂) : e.conj LinearMap.id = LinearMap.id := b simp [conj_apply] #align linear_equiv.conj_id LinearEquiv.conj_id +variable (M) in +/-- An `R`-linear isomorphism between two `R`-modules `M₂` and `M₃` induces an `S`-linear +isomorphism between `M₂ →ₗ[R] M` and `M₃ →ₗ[R] M`, if `M` is both an `R`-module and an +`S`-module and their actions commute. -/ +def congrLeft {R} (S) [Semiring R] [Semiring S] [Module R M₂] [Module R M₃] [Module R M] + [Module S M] [SMulCommClass R S M] (e : M₂ ≃ₗ[R] M₃) : (M₂ →ₗ[R] M) ≃ₗ[S] (M₃ →ₗ[R] M) where + toFun f := f.comp e.symm.toLinearMap + invFun f := f.comp e.toLinearMap + map_add' _ _ := rfl + map_smul' _ _ := rfl + left_inv f := by dsimp only; apply DFunLike.ext; exact (congr_arg f <| e.left_inv ·) + right_inv f := by dsimp only; apply DFunLike.ext; exact (congr_arg f <| e.right_inv ·) + end CommSemiring section Field diff --git a/Mathlib/LinearAlgebra/Basis.lean b/Mathlib/LinearAlgebra/Basis.lean index 82ce4f3fdf46b..7423f8018b2e7 100644 --- a/Mathlib/LinearAlgebra/Basis.lean +++ b/Mathlib/LinearAlgebra/Basis.lean @@ -8,8 +8,6 @@ import Mathlib.Algebra.BigOperators.Finprod import Mathlib.Data.Fintype.BigOperators import Mathlib.LinearAlgebra.Finsupp import Mathlib.LinearAlgebra.LinearIndependent -import Mathlib.LinearAlgebra.LinearPMap -import Mathlib.LinearAlgebra.Projection import Mathlib.SetTheory.Cardinal.Cofinality #align_import linear_algebra.basis from "leanprover-community/mathlib"@"13bce9a6b6c44f6b4c91ac1c1d2a816e2533d395" @@ -84,7 +82,7 @@ variable (ι R M) /-- A `Basis ι R M` for a module `M` is the type of `ι`-indexed `R`-bases of `M`. -The basis vectors are available as `FunLike.coe (b : Basis ι R M) : ι → M`. +The basis vectors are available as `DFunLike.coe (b : Basis ι R M) : ι → M`. To turn a linear independent family of vectors spanning `M` into a basis, use `Basis.mk`. They are internally represented as linear equivs `M ≃ₗ[R] (ι →₀ R)`, available as `Basis.repr`. @@ -119,11 +117,11 @@ theorem repr_injective : Injective (repr : Basis ι R M → M ≃ₗ[R] ι → #align basis.repr_injective Basis.repr_injective /-- `b i` is the `i`th basis vector. -/ -instance funLike : FunLike (Basis ι R M) ι fun _ => M where +instance instFunLike : FunLike (Basis ι R M) ι M where coe b i := b.repr.symm (Finsupp.single i 1) coe_injective' f g h := repr_injective <| LinearEquiv.symm_bijective.injective <| LinearEquiv.toLinearMap_injective <| by ext; exact congr_fun h _ -#align basis.fun_like Basis.funLike +#align basis.fun_like Basis.instFunLike @[simp] theorem coe_ofRepr (e : M ≃ₗ[R] ι →₀ R) : ⇑(ofRepr e) = fun i => e.symm (Finsupp.single i 1) := @@ -218,7 +216,7 @@ def coord : M →ₗ[R] R := #align basis.coord Basis.coord theorem forall_coord_eq_zero_iff {x : M} : (∀ i, b.coord i x = 0) ↔ x = 0 := - Iff.trans (by simp only [b.coord_apply, FunLike.ext_iff, Finsupp.zero_apply]) + Iff.trans (by simp only [b.coord_apply, DFunLike.ext_iff, Finsupp.zero_apply]) b.repr.map_eq_zero_iff #align basis.forall_coord_eq_zero_iff Basis.forall_coord_eq_zero_iff @@ -289,7 +287,7 @@ theorem ext' {f₁ f₂ : M ≃ₛₗ[σ] M₁} (h : ∀ i, f₁ (b i) = f₂ (b /-- Two elements are equal iff their coordinates are equal. -/ theorem ext_elem_iff {x y : M} : x = y ↔ ∀ i, b.repr x i = b.repr y i := by - simp only [← FunLike.ext_iff, EmbeddingLike.apply_eq_iff_eq] + simp only [← DFunLike.ext_iff, EmbeddingLike.apply_eq_iff_eq] #align basis.ext_elem_iff Basis.ext_elem_iff alias ⟨_, _root_.Basis.ext_elem⟩ := ext_elem_iff @@ -337,7 +335,7 @@ theorem eq_ofRepr_eq_repr {b₁ b₂ : Basis ι R M} (h : ∀ x i, b₁.repr x i /-- Two bases are equal if their basis vectors are the same. -/ @[ext] theorem eq_of_apply_eq {b₁ b₂ : Basis ι R M} : (∀ i, b₁ i = b₂ i) → b₁ = b₂ := - FunLike.ext _ _ + DFunLike.ext _ _ #align basis.eq_of_apply_eq Basis.eq_of_apply_eq end Ext @@ -436,7 +434,7 @@ theorem repr_reindex_apply (i' : ι') : (b.reindex e).repr x i' = b.repr x (e.sy @[simp] theorem repr_reindex : (b.reindex e).repr x = (b.repr x).mapDomain e := - FunLike.ext _ _ <| by simp [repr_reindex_apply] + DFunLike.ext _ _ <| by simp [repr_reindex_apply] #align basis.repr_reindex Basis.repr_reindex @[simp] @@ -835,7 +833,7 @@ theorem singleton_repr (ι R : Type*) [Unique ι] [Semiring R] (x i) : theorem basis_singleton_iff {R M : Type*} [Ring R] [Nontrivial R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M] (ι : Type*) [Unique ι] : - Nonempty (Basis ι R M) ↔ ∃ (x : _) (_ : x ≠ 0), ∀ y : M, ∃ r : R, r • x = y := by + Nonempty (Basis ι R M) ↔ ∃ x ≠ 0, ∀ y : M, ∃ r : R, r • x = y := by constructor · rintro ⟨b⟩ refine' ⟨b default, b.linearIndependent.ne_zero _, _⟩ @@ -1407,7 +1405,7 @@ lemma Basis.mem_center_iff {A} ∧ (b i * z) * b j = b i * (z * b j) ∧ (b i * b j) * z = b i * (b j * z) := by constructor - · intro h; + · intro h constructor · intro i apply (h.1 (b i)).symm @@ -1470,7 +1468,7 @@ theorem Basis.restrictScalars_repr_apply (m : span R (Set.range b)) (i : ι) : suffices Finsupp.mapRange.linearMap (Algebra.linearMap R S) ∘ₗ (b.restrictScalars R).repr.toLinearMap = ((b.repr : M →ₗ[S] ι →₀ S).restrictScalars R).domRestrict _ - by exact FunLike.congr_fun (LinearMap.congr_fun this m) i + by exact DFunLike.congr_fun (LinearMap.congr_fun this m) i refine Basis.ext (b.restrictScalars R) fun _ => ?_ simp only [LinearMap.coe_comp, LinearEquiv.coe_toLinearMap, Function.comp_apply, map_one, Basis.repr_self, Finsupp.mapRange.linearMap_apply, Finsupp.mapRange_single, @@ -1601,7 +1599,7 @@ theorem union_support_maximal_linearIndependent_eq_range_basis {ι : Type w} (b apply_fun fun x => b.repr x b' at z simp only [repr_self, LinearEquiv.map_smul, mul_one, Finsupp.single_eq_same, Pi.neg_apply, Finsupp.smul_single', LinearEquiv.map_neg, Finsupp.coe_neg] at z - erw [FunLike.congr_fun (Finsupp.apply_total R (b.repr : M →ₗ[R] ι →₀ R) v l.some) b'] at z + erw [DFunLike.congr_fun (Finsupp.apply_total R (b.repr : M →ₗ[R] ι →₀ R) v l.some) b'] at z simpa [Finsupp.total_apply, w] using z -- Then all the other coefficients are zero, because `v` is linear independent. have l₁ : l.some = 0 := by @@ -1610,7 +1608,7 @@ theorem union_support_maximal_linearIndependent_eq_range_basis {ι : Type w} (b -- Finally we put those facts together to show the linear combination is trivial. ext (_ | a) · simp only [l₀, Finsupp.coe_zero, Pi.zero_apply] - · erw [FunLike.congr_fun l₁ a] + · erw [DFunLike.congr_fun l₁ a] simp only [Finsupp.coe_zero, Pi.zero_apply] rw [LinearIndependent.Maximal] at m specialize m (range v') i' r diff --git a/Mathlib/LinearAlgebra/Basis/Bilinear.lean b/Mathlib/LinearAlgebra/Basis/Bilinear.lean index 04ddaa2e9fded..22ec729ca1df9 100644 --- a/Mathlib/LinearAlgebra/Basis/Bilinear.lean +++ b/Mathlib/LinearAlgebra/Basis/Bilinear.lean @@ -17,11 +17,12 @@ namespace LinearMap variable {ι₁ ι₂ : Type*} -variable {R R₂ S S₂ M N P : Type*} +variable {R R₂ S S₂ M N P Rₗ : Type*} variable {Mₗ Nₗ Pₗ : Type*} -variable [CommSemiring R] [CommSemiring S] [CommSemiring R₂] [CommSemiring S₂] +-- Could weaken [CommSemiring Rₗ] to [SMulCommClass Rₗ Rₗ Pₗ], but might impact performance +variable [Semiring R] [Semiring S] [Semiring R₂] [Semiring S₂] [CommSemiring Rₗ] section AddCommMonoid @@ -31,13 +32,13 @@ variable [AddCommMonoid Mₗ] [AddCommMonoid Nₗ] [AddCommMonoid Pₗ] variable [Module R M] [Module S N] [Module R₂ P] [Module S₂ P] -variable [Module R Mₗ] [Module R Nₗ] [Module R Pₗ] +variable [Module Rₗ Mₗ] [Module Rₗ Nₗ] [Module Rₗ Pₗ] variable [SMulCommClass S₂ R₂ P] variable {ρ₁₂ : R →+* R₂} {σ₁₂ : S →+* S₂} -variable (b₁ : Basis ι₁ R M) (b₂ : Basis ι₂ S N) (b₁' : Basis ι₁ R Mₗ) (b₂' : Basis ι₂ R Nₗ) +variable (b₁ : Basis ι₁ R M) (b₂ : Basis ι₂ S N) (b₁' : Basis ι₁ Rₗ Mₗ) (b₂' : Basis ι₂ Rₗ Nₗ) /-- Two bilinear maps are equal when they are equal on all basis vectors. -/ theorem ext_basis {B B' : M →ₛₗ[ρ₁₂] N →ₛₗ[σ₁₂] P} (h : ∀ i j, B (b₁ i) (b₂ j) = B' (b₁ i) (b₂ j)) : @@ -59,7 +60,7 @@ theorem sum_repr_mul_repr_mulₛₗ {B : M →ₛₗ[ρ₁₂] N →ₛₗ[σ₁ /-- Write out `B x y` as a sum over `B (b i) (b j)` if `b` is a basis. Version for bilinear maps, see `sum_repr_mul_repr_mulₛₗ` for the semi-bilinear version. -/ -theorem sum_repr_mul_repr_mul {B : Mₗ →ₗ[R] Nₗ →ₗ[R] Pₗ} (x y) : +theorem sum_repr_mul_repr_mul {B : Mₗ →ₗ[Rₗ] Nₗ →ₗ[Rₗ] Pₗ} (x y) : ((b₁'.repr x).sum fun i xi => (b₂'.repr y).sum fun j yj => xi • yj • B (b₁' i) (b₂' j)) = B x y := by conv_rhs => rw [← b₁'.total_repr x, ← b₂'.total_repr y] @@ -70,4 +71,3 @@ theorem sum_repr_mul_repr_mul {B : Mₗ →ₗ[R] Nₗ →ₗ[R] Pₗ} (x y) : end AddCommMonoid end LinearMap - diff --git a/Mathlib/LinearAlgebra/Basis/Flag.lean b/Mathlib/LinearAlgebra/Basis/Flag.lean index 646ed7fa109b7..6ae87d009929c 100644 --- a/Mathlib/LinearAlgebra/Basis/Flag.lean +++ b/Mathlib/LinearAlgebra/Basis/Flag.lean @@ -85,20 +85,20 @@ section DivisionRing variable {K V : Type*} [DivisionRing K] [AddCommGroup V] [Module K V] {n : ℕ} -theorem flag_covby (b : Basis (Fin n) K V) (i : Fin n) : +theorem flag_covBy (b : Basis (Fin n) K V) (i : Fin n) : b.flag i.castSucc ⋖ b.flag i.succ := by rw [flag_succ] - apply covby_span_singleton_sup + apply covBy_span_singleton_sup simp -theorem flag_wcovby (b : Basis (Fin n) K V) (i : Fin n) : +theorem flag_wcovBy (b : Basis (Fin n) K V) (i : Fin n) : b.flag i.castSucc ⩿ b.flag i.succ := - (b.flag_covby i).wcovby + (b.flag_covBy i).wcovBy /-- Range of `Basis.flag` as a `Flag`. -/ @[simps!] def toFlag (b : Basis (Fin n) K V) : Flag (Submodule K V) := - .rangeFin b.flag b.flag_zero b.flag_last b.flag_wcovby + .rangeFin b.flag b.flag_zero b.flag_last b.flag_wcovBy @[simp] theorem mem_toFlag (b : Basis (Fin n) K V) {p : Submodule K V} : p ∈ b.toFlag ↔ ∃ k, b.flag k = p := diff --git a/Mathlib/LinearAlgebra/Basis/VectorSpace.lean b/Mathlib/LinearAlgebra/Basis/VectorSpace.lean index be85df2d5f2b4..6cb19bb4ec890 100644 --- a/Mathlib/LinearAlgebra/Basis/VectorSpace.lean +++ b/Mathlib/LinearAlgebra/Basis/VectorSpace.lean @@ -5,6 +5,8 @@ Authors: Johannes Hölzl, Mario Carneiro, Alexander Bentkamp -/ import Mathlib.LinearAlgebra.Basis import Mathlib.LinearAlgebra.FreeModule.Basic +import Mathlib.LinearAlgebra.LinearPMap +import Mathlib.LinearAlgebra.Projection #align_import linear_algebra.basis from "leanprover-community/mathlib"@"13bce9a6b6c44f6b4c91ac1c1d2a816e2533d395" @@ -180,7 +182,7 @@ theorem nonzero_span_atom (v : V) (hv : v ≠ 0) : IsAtom (span K {v} : Submodul /-- The atoms of the lattice of submodules of a module over a division ring are the submodules equal to the span of a nonzero element of the module. -/ theorem atom_iff_nonzero_span (W : Submodule K V) : - IsAtom W ↔ ∃ (v : V) (_ : v ≠ 0), W = span K {v} := by + IsAtom W ↔ ∃ v ≠ 0, W = span K {v} := by refine' ⟨fun h => _, fun h => _⟩ · cases' h with hbot h rcases (Submodule.ne_bot_iff W).1 hbot with ⟨v, ⟨hW, hv⟩⟩ diff --git a/Mathlib/LinearAlgebra/BilinearForm/Basic.lean b/Mathlib/LinearAlgebra/BilinearForm/Basic.lean index d7313f3286aa3..0efb9a9254108 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Basic.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Andreas Swerdlow. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andreas Swerdlow, Kexing Ying -/ -import Mathlib.LinearAlgebra.Dual +import Mathlib.Algebra.Algebra.Tower #align_import linear_algebra.bilinear_form from "leanprover-community/mathlib"@"f0c8bf9245297a541f468be517f1bde6195105e9" diff --git a/Mathlib/LinearAlgebra/BilinearForm/Hom.lean b/Mathlib/LinearAlgebra/BilinearForm/Hom.lean index 1d4c7edc191d2..5e7bb034733b9 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Hom.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Hom.lean @@ -3,7 +3,9 @@ Copyright (c) 2018 Andreas Swerdlow. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andreas Swerdlow, Kexing Ying -/ +import Mathlib.LinearAlgebra.BilinearMap import Mathlib.LinearAlgebra.BilinearForm.Basic +import Mathlib.LinearAlgebra.Basis /-! # Bilinear form and linear maps diff --git a/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean b/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean index d89af45216db9..f9ffb45f7154e 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Andreas Swerdlow. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andreas Swerdlow, Kexing Ying -/ +import Mathlib.Algebra.GroupWithZero.NonZeroDivisors import Mathlib.LinearAlgebra.BilinearForm.Properties /-! diff --git a/Mathlib/LinearAlgebra/BilinearForm/Properties.lean b/Mathlib/LinearAlgebra/BilinearForm/Properties.lean index 8cb79c1718ba2..e35d9531783a2 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Properties.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Properties.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andreas Swerdlow, Kexing Ying -/ import Mathlib.LinearAlgebra.BilinearForm.Hom +import Mathlib.LinearAlgebra.Dual /-! # Bilinear form @@ -297,7 +298,7 @@ def isPairSelfAdjointSubmodule : Submodule R₂ (Module.End R₂ M₂) where @[simp] theorem mem_isPairSelfAdjointSubmodule (f : Module.End R₂ M₂) : - f ∈ isPairSelfAdjointSubmodule B₂ F₂ ↔ IsPairSelfAdjoint B₂ F₂ f := by rfl + f ∈ isPairSelfAdjointSubmodule B₂ F₂ ↔ IsPairSelfAdjoint B₂ F₂ f := Iff.rfl #align bilin_form.mem_is_pair_self_adjoint_submodule BilinForm.mem_isPairSelfAdjointSubmodule theorem isPairSelfAdjoint_equiv (e : M₂' ≃ₗ[R₂] M₂) (f : Module.End R₂ M₂) : diff --git a/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean b/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean index 7acb2ca42b11e..1eab203decd3b 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean @@ -144,7 +144,7 @@ theorem tensorDistribEquiv_toLinearMap : @[simp] theorem tensorDistribEquiv_apply (B : BilinForm R M₁ ⊗ BilinForm R M₂) : tensorDistribEquiv R (M₁ := M₁) (M₂ := M₂) B = tensorDistrib R R B := - FunLike.congr_fun (tensorDistribEquiv_toLinearMap R M₁ M₂) B + DFunLike.congr_fun (tensorDistribEquiv_toLinearMap R M₁ M₂) B #align bilin_form.tensor_distrib_equiv_apply BilinForm.tensorDistribEquiv_apply end CommRing diff --git a/Mathlib/LinearAlgebra/Charpoly/ToMatrix.lean b/Mathlib/LinearAlgebra/Charpoly/ToMatrix.lean index e1ee558c5b153..86f7e52825920 100644 --- a/Mathlib/LinearAlgebra/Charpoly/ToMatrix.lean +++ b/Mathlib/LinearAlgebra/Charpoly/ToMatrix.lean @@ -39,7 +39,7 @@ section Basic attribute [-instance] instCoeOut attribute [local instance 2000] RingHomClass.toNonUnitalRingHomClass -attribute [local instance 2000] NonUnitalRingHomClass.toMulHomClass MulHomClass.toFunLike +attribute [local instance 2000] NonUnitalRingHomClass.toMulHomClass MulHomClass.toDFunLike /-- `charpoly f` is the characteristic polynomial of the matrix of `f` in any basis. -/ @[simp] diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean index c7a4dce5ee57f..ea17710ed8bac 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Data.Complex.Module import Mathlib.LinearAlgebra.QuadraticForm.TensorProduct import Mathlib.LinearAlgebra.CliffordAlgebra.Conjugation import Mathlib.LinearAlgebra.TensorProduct.Opposite @@ -117,7 +116,7 @@ theorem toBaseChange_comp_involute (Q : QuadraticForm R V) : theorem toBaseChange_involute (Q : QuadraticForm R V) (x : CliffordAlgebra (Q.baseChange A)) : toBaseChange A Q (involute x) = TensorProduct.map LinearMap.id (involute.toLinearMap) (toBaseChange A Q x) := - FunLike.congr_fun (toBaseChange_comp_involute A Q) x + DFunLike.congr_fun (toBaseChange_comp_involute A Q) x open MulOpposite @@ -141,7 +140,7 @@ theorem toBaseChange_comp_reverseOp (Q : QuadraticForm R V) : theorem toBaseChange_reverse (Q : QuadraticForm R V) (x : CliffordAlgebra (Q.baseChange A)) : toBaseChange A Q (reverse x) = TensorProduct.map LinearMap.id reverse (toBaseChange A Q x) := by - have := FunLike.congr_fun (toBaseChange_comp_reverseOp A Q) x + have := DFunLike.congr_fun (toBaseChange_comp_reverseOp A Q) x refine (congr_arg unop this).trans ?_; clear this refine (LinearMap.congr_fun (TensorProduct.AlgebraTensorModule.map_comp _ _ _ _).symm _).trans ?_ rw [reverse, ← AlgEquiv.toLinearMap, ← AlgEquiv.toLinearEquiv_toLinearMap, diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean index d789db8ce06e1..d285b9cf308a5 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean @@ -250,7 +250,7 @@ theorem forall_mul_self_eq_iff {A : Type*} [Ring A] [Algebra R A] (h2 : IsUnit ( (∀ x, f x * f x = algebraMap _ _ (Q x)) ↔ (LinearMap.mul R A).compl₂ f ∘ₗ f + (LinearMap.mul R A).flip.compl₂ f ∘ₗ f = Q.polarBilin.toLin.compr₂ (Algebra.linearMap R A) := by - simp_rw [FunLike.ext_iff] + simp_rw [DFunLike.ext_iff] refine ⟨mul_add_swap_eq_polar_of_forall_mul_self_eq _, fun h x => ?_⟩ change ∀ x y : M, f x * f y + f y * f x = algebraMap R A (QuadraticForm.polar Q x y) at h apply h2.mul_left_cancel diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/CategoryTheory.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/CategoryTheory.lean index adf30ab8c442c..508a7c231fc96 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/CategoryTheory.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/CategoryTheory.lean @@ -5,6 +5,7 @@ Authors: Eric Wieser -/ import Mathlib.LinearAlgebra.CliffordAlgebra.Basic import Mathlib.LinearAlgebra.QuadraticForm.QuadraticModuleCat +import Mathlib.Algebra.Category.AlgebraCat.Basic /-! # Category-theoretic interpretations of `clifford_algebra` diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Even.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Even.lean index 8fa5dfcf22422..3237f6134468b 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Even.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Even.lean @@ -149,7 +149,7 @@ private def fFold : M →ₗ[R] A × S f →ₗ[R] A × S f := /- We could write this `snd` term in a point-free style as follows, but it wouldn't help as we don't have any prod or subtype combinators to deal with n-linear maps of this degree. ```lean - (LinearMap.lcomp R _ (Algebra.lmul R A).to_linear_map.flip).comp $ + (LinearMap.lcomp R _ (Algebra.lmul R A).to_linear_map.flip).comp <| (LinearMap.llcomp R M A A).flip.comp f.flip : M →ₗ[R] A →ₗ[R] M →ₗ[R] A) ``` -/ diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Fold.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Fold.lean index 38df9d962ff6b..2bf1c626a2868 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Fold.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Fold.lean @@ -100,7 +100,7 @@ def foldl (f : M →ₗ[R] N →ₗ[R] N) (hf : ∀ m x, f m (f m x) = Q m • x @[simp] theorem foldl_reverse (f : M →ₗ[R] N →ₗ[R] N) (hf) (n : N) (x : CliffordAlgebra Q) : foldl Q f hf n (reverse x) = foldr Q f hf n x := - FunLike.congr_arg (foldr Q f hf n) <| reverse_reverse _ + DFunLike.congr_arg (foldr Q f hf n) <| reverse_reverse _ #align clifford_algebra.foldl_reverse CliffordAlgebra.foldl_reverse @[simp] diff --git a/Mathlib/LinearAlgebra/DFinsupp.lean b/Mathlib/LinearAlgebra/DFinsupp.lean index 53432a58a766b..c44481084e4a5 100644 --- a/Mathlib/LinearAlgebra/DFinsupp.lean +++ b/Mathlib/LinearAlgebra/DFinsupp.lean @@ -449,7 +449,7 @@ theorem independent_of_dfinsupp_lsum_injective (p : ι → Submodule R N) lsum ℕ (M := fun i ↦ ↥(p i)) (fun i => (p i).subtype) (erase i v) = lsum ℕ (M := fun i ↦ ↥(p i)) (fun i => (p i).subtype) (single i x) · simpa only [lsum_single] using hv - have := FunLike.ext_iff.mp (h hv) i + have := DFunLike.ext_iff.mp (h hv) i simpa [eq_comm] using this #align complete_lattice.independent_of_dfinsupp_lsum_injective CompleteLattice.independent_of_dfinsupp_lsum_injective diff --git a/Mathlib/LinearAlgebra/Determinant.lean b/Mathlib/LinearAlgebra/Determinant.lean index 486a450c61a9d..6e035d7b2fb8c 100644 --- a/Mathlib/LinearAlgebra/Determinant.lean +++ b/Mathlib/LinearAlgebra/Determinant.lean @@ -623,7 +623,7 @@ theorem Basis.det_reindex' {ι' : Type*} [Fintype ι'] [DecidableEq ι'] (b : Ba theorem Basis.det_reindex_symm {ι' : Type*} [Fintype ι'] [DecidableEq ι'] (b : Basis ι R M) (v : ι → M) (e : ι' ≃ ι) : (b.reindex e.symm).det (v ∘ e) = b.det v := by - rw [Basis.det_reindex, Function.comp.assoc, e.self_comp_symm, Function.comp.right_id] + rw [Basis.det_reindex, Function.comp.assoc, e.self_comp_symm, Function.comp_id] #align basis.det_reindex_symm Basis.det_reindex_symm @[simp] diff --git a/Mathlib/LinearAlgebra/Dimension/Basic.lean b/Mathlib/LinearAlgebra/Dimension/Basic.lean index b5d29c77c519f..45cda19b20e6d 100644 --- a/Mathlib/LinearAlgebra/Dimension/Basic.lean +++ b/Mathlib/LinearAlgebra/Dimension/Basic.lean @@ -3,9 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Scott Morrison -/ -import Mathlib.LinearAlgebra.DFinsupp -import Mathlib.LinearAlgebra.Quotient -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.LinearAlgebra.LinearIndependent #align_import linear_algebra.dimension from "leanprover-community/mathlib"@"47a5f8186becdbc826190ced4312f8199f9db6a5" diff --git a/Mathlib/LinearAlgebra/Dimension/Constructions.lean b/Mathlib/LinearAlgebra/Dimension/Constructions.lean index 6fb253c151ca6..0a73b8ba75414 100644 --- a/Mathlib/LinearAlgebra/Dimension/Constructions.lean +++ b/Mathlib/LinearAlgebra/Dimension/Constructions.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Scott Morrison, Chris Hughes, Anne Baanen -/ -import Mathlib.LinearAlgebra.Dimension.Finite +import Mathlib.LinearAlgebra.Dimension.Free import Mathlib.Algebra.Module.Torsion #align_import linear_algebra.dimension from "leanprover-community/mathlib"@"47a5f8186becdbc826190ced4312f8199f9db6a5" @@ -374,27 +374,6 @@ theorem FiniteDimensional.finrank_tensorProduct : end TensorProduct -section Span - -variable [StrongRankCondition R] - -theorem rank_span_le_of_finite {s : Set M} (hs : s.Finite) : Module.rank R (span R s) ≤ #s := by - rw [Module.rank_def] - apply ciSup_le' - rintro ⟨t, ht⟩ - letI := hs.fintype - simpa [Cardinal.mk_image_eq Subtype.val_injective] using linearIndependent_le_span' _ - (ht.map (f := Submodule.subtype _) (by simp)).image s (fun x ↦ by aesop) - -theorem rank_span_finset_le (s : Finset M) : Module.rank R (span R (s : Set M)) ≤ s.card := by - simpa using rank_span_le_of_finite s.finite_toSet - -theorem rank_span_of_finset (s : Finset M) : Module.rank R (span R (s : Set M)) < ℵ₀ := - (rank_span_finset_le s).trans_lt (Cardinal.nat_lt_aleph0 _) -#align rank_span_of_finset rank_span_of_finset - -end Span - section SubmoduleRank section @@ -449,9 +428,93 @@ theorem Submodule.finrank_le_finrank_of_le {s t : Submodule R M} [Module.Finite end - end SubmoduleRank +section Span + +variable [StrongRankCondition R] + +theorem rank_span_le (s : Set M) : Module.rank R (span R s) ≤ #s := by + rw [Finsupp.span_eq_range_total, ← lift_strictMono.le_iff_le] + refine (lift_rank_range_le _).trans ?_ + rw [rank_finsupp_self] + simp only [lift_lift, ge_iff_le, le_refl] +#align rank_span_le rank_span_le + +theorem rank_span_finset_le (s : Finset M) : Module.rank R (span R (s : Set M)) ≤ s.card := by + simpa using rank_span_le s.toSet + +theorem rank_span_of_finset (s : Finset M) : Module.rank R (span R (s : Set M)) < ℵ₀ := + (rank_span_finset_le s).trans_lt (Cardinal.nat_lt_aleph0 _) +#align rank_span_of_finset rank_span_of_finset + +open Submodule FiniteDimensional + +variable (R) + +/-- The rank of a set of vectors as a natural number. -/ +protected noncomputable def Set.finrank (s : Set M) : ℕ := + finrank R (span R s) +#align set.finrank Set.finrank + +variable {R} + +theorem finrank_span_le_card (s : Set M) [Fintype s] : finrank R (span R s) ≤ s.toFinset.card := + finrank_le_of_rank_le (by simpa using rank_span_le (R := R) s) +#align finrank_span_le_card finrank_span_le_card + +theorem finrank_span_finset_le_card (s : Finset M) : (s : Set M).finrank R ≤ s.card := + calc + (s : Set M).finrank R ≤ (s : Set M).toFinset.card := finrank_span_le_card (M := M) s + _ = s.card := by simp +#align finrank_span_finset_le_card finrank_span_finset_le_card + +theorem finrank_range_le_card {ι : Type*} [Fintype ι] (b : ι → M) : + (Set.range b).finrank R ≤ Fintype.card ι := by + classical + refine (finrank_span_le_card _).trans ?_ + rw [Set.toFinset_range] + exact Finset.card_image_le +#align finrank_range_le_card finrank_range_le_card + +theorem finrank_span_eq_card [Nontrivial R] {ι : Type*} [Fintype ι] {b : ι → M} + (hb : LinearIndependent R b) : + finrank R (span R (Set.range b)) = Fintype.card ι := + finrank_eq_of_rank_eq + (by + have : Module.rank R (span R (Set.range b)) = #(Set.range b) := rank_span hb + rwa [← lift_inj, mk_range_eq_of_injective hb.injective, Cardinal.mk_fintype, lift_natCast, + lift_eq_nat_iff] at this) +#align finrank_span_eq_card finrank_span_eq_card + +theorem finrank_span_set_eq_card {s : Set M} [Fintype s] (hs : LinearIndependent R ((↑) : s → M)) : + finrank R (span R s) = s.toFinset.card := + finrank_eq_of_rank_eq + (by + have : Module.rank R (span R s) = #s := rank_span_set hs + rwa [Cardinal.mk_fintype, ← Set.toFinset_card] at this) +#align finrank_span_set_eq_card finrank_span_set_eq_card + +theorem finrank_span_finset_eq_card {s : Finset M} (hs : LinearIndependent R ((↑) : s → M)) : + finrank R (span R (s : Set M)) = s.card := by + convert finrank_span_set_eq_card (s := (s : Set M)) hs + ext + simp +#align finrank_span_finset_eq_card finrank_span_finset_eq_card + +theorem span_lt_of_subset_of_card_lt_finrank {s : Set M} [Fintype s] {t : Submodule R M} + (subset : s ⊆ t) (card_lt : s.toFinset.card < finrank R t) : span R s < t := + lt_of_le_of_finrank_lt_finrank (span_le.mpr subset) + (lt_of_le_of_lt (finrank_span_le_card _) card_lt) +#align span_lt_of_subset_of_card_lt_finrank span_lt_of_subset_of_card_lt_finrank + +theorem span_lt_top_of_card_lt_finrank {s : Set M} [Fintype s] + (card_lt : s.toFinset.card < finrank R M) : span R s < ⊤ := + lt_top_of_finrank_lt_finrank (lt_of_le_of_lt (finrank_span_le_card _) card_lt) +#align span_lt_top_of_card_lt_finrank span_lt_top_of_card_lt_finrank + +end Span + section SubalgebraRank open Module diff --git a/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean b/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean index ceaced347eef7..cb97afd90168a 100644 --- a/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean +++ b/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean @@ -59,13 +59,6 @@ theorem Basis.finite_ofVectorSpaceIndex_of_rank_lt_aleph0 (h : Module.rank K V < finite_def.2 <| (Basis.ofVectorSpace K V).nonempty_fintype_index_of_rank_lt_aleph0 h #align basis.finite_of_vector_space_index_of_rank_lt_aleph_0 Basis.finite_ofVectorSpaceIndex_of_rank_lt_aleph0 --- TODO how far can we generalise this? -theorem rank_span_le (s : Set V) : Module.rank K (span K s) ≤ #s := by - obtain ⟨b, hb, hsab, hlib⟩ := exists_linearIndependent K s - convert Cardinal.mk_le_mk_of_subset hb - rw [← hsab, rank_span_set hlib] -#align rank_span_le rank_span_le - theorem rank_quotient_add_rank (p : Submodule K V) : Module.rank K (V ⧸ p) + Module.rank K p = Module.rank K V := by classical @@ -326,68 +319,6 @@ open Submodule FiniteDimensional variable [DivisionRing K] [AddCommGroup V] [Module K V] -variable (K) - -/-- The rank of a set of vectors as a natural number. -/ -protected noncomputable def Set.finrank (s : Set V) : ℕ := - finrank K (span K s) -#align set.finrank Set.finrank - -variable {K} - -theorem finrank_span_le_card (s : Set V) [Fintype s] : finrank K (span K s) ≤ s.toFinset.card := - finrank_le_of_rank_le (by simpa using rank_span_le (K := K) s) -#align finrank_span_le_card finrank_span_le_card - -theorem finrank_span_finset_le_card (s : Finset V) : (s : Set V).finrank K ≤ s.card := - calc - (s : Set V).finrank K ≤ (s : Set V).toFinset.card := finrank_span_le_card (V := V) s - _ = s.card := by simp -#align finrank_span_finset_le_card finrank_span_finset_le_card - -theorem finrank_range_le_card {ι : Type*} [Fintype ι] {b : ι → V} : - (Set.range b).finrank K ≤ Fintype.card ι := by - classical - refine (finrank_span_le_card _).trans ?_ - rw [Set.toFinset_range] - exact Finset.card_image_le -#align finrank_range_le_card finrank_range_le_card - -theorem finrank_span_eq_card {ι : Type*} [Fintype ι] {b : ι → V} (hb : LinearIndependent K b) : - finrank K (span K (Set.range b)) = Fintype.card ι := - finrank_eq_of_rank_eq - (by - have : Module.rank K (span K (Set.range b)) = #(Set.range b) := rank_span hb - rwa [← lift_inj, mk_range_eq_of_injective hb.injective, Cardinal.mk_fintype, lift_natCast, - lift_eq_nat_iff] at this) -#align finrank_span_eq_card finrank_span_eq_card - -theorem finrank_span_set_eq_card (s : Set V) [Fintype s] (hs : LinearIndependent K ((↑) : s → V)) : - finrank K (span K s) = s.toFinset.card := - finrank_eq_of_rank_eq - (by - have : Module.rank K (span K s) = #s := rank_span_set hs - rwa [Cardinal.mk_fintype, ← Set.toFinset_card] at this) -#align finrank_span_set_eq_card finrank_span_set_eq_card - -theorem finrank_span_finset_eq_card (s : Finset V) (hs : LinearIndependent K ((↑) : s → V)) : - finrank K (span K (s : Set V)) = s.card := by - convert finrank_span_set_eq_card (s : Set V) hs - ext - simp -#align finrank_span_finset_eq_card finrank_span_finset_eq_card - -theorem span_lt_of_subset_of_card_lt_finrank {s : Set V} [Fintype s] {t : Submodule K V} - (subset : s ⊆ t) (card_lt : s.toFinset.card < finrank K t) : span K s < t := - lt_of_le_of_finrank_lt_finrank (span_le.mpr subset) - (lt_of_le_of_lt (finrank_span_le_card _) card_lt) -#align span_lt_of_subset_of_card_lt_finrank span_lt_of_subset_of_card_lt_finrank - -theorem span_lt_top_of_card_lt_finrank {s : Set V} [Fintype s] - (card_lt : s.toFinset.card < finrank K V) : span K s < ⊤ := - lt_top_of_finrank_lt_finrank (lt_of_le_of_lt (finrank_span_le_card _) card_lt) -#align span_lt_top_of_card_lt_finrank span_lt_top_of_card_lt_finrank - /-- Given a family of `n` linearly independent vectors in a finite-dimensional space of dimension `> n`, one may extend the family by another vector while retaining linear independence. -/ theorem exists_linearIndependent_snoc_of_lt_finrank {n : ℕ} {v : Fin n → V} @@ -492,7 +423,7 @@ theorem linearIndependent_iff_card_eq_finrank_span {ι : Type*} [Fintype ι] {b theorem linearIndependent_iff_card_le_finrank_span {ι : Type*} [Fintype ι] {b : ι → V} : LinearIndependent K b ↔ Fintype.card ι ≤ (Set.range b).finrank K := by - rw [linearIndependent_iff_card_eq_finrank_span, finrank_range_le_card.le_iff_eq] + rw [linearIndependent_iff_card_eq_finrank_span, (finrank_range_le_card _).le_iff_eq] #align linear_independent_iff_card_le_finrank_span linearIndependent_iff_card_le_finrank_span /-- A family of `finrank K V` vectors forms a basis if they span the whole space. -/ @@ -536,7 +467,7 @@ variable [DivisionRing K] /-- Key lemma towards the Erdős-Kaplansky theorem from https://mathoverflow.net/a/168624 -/ theorem max_aleph0_card_le_rank_fun_nat : max ℵ₀ #K ≤ Module.rank K (ℕ → K) := by have aleph0_le : ℵ₀ ≤ Module.rank K (ℕ → K) := (rank_finsupp_self K ℕ).symm.trans_le - (Finsupp.lcoeFun.rank_le_of_injective <| by exact FunLike.coe_injective) + (Finsupp.lcoeFun.rank_le_of_injective <| by exact DFunLike.coe_injective) refine max_le aleph0_le ?_ obtain card_K | card_K := le_or_lt #K ℵ₀ · exact card_K.trans aleph0_le diff --git a/Mathlib/LinearAlgebra/Dimension/Finite.lean b/Mathlib/LinearAlgebra/Dimension/Finite.lean index dfd6dbd4c9189..1bb8e6f94bd39 100644 --- a/Mathlib/LinearAlgebra/Dimension/Finite.lean +++ b/Mathlib/LinearAlgebra/Dimension/Finite.lean @@ -3,10 +3,10 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Scott Morrison -/ -import Mathlib.LinearAlgebra.Dimension.Free import Mathlib.Algebra.Module.Torsion import Mathlib.SetTheory.Cardinal.Cofinality import Mathlib.LinearAlgebra.FreeModule.Finite.Basic +import Mathlib.LinearAlgebra.Dimension.StrongRankCondition #align_import linear_algebra.dimension from "leanprover-community/mathlib"@"47a5f8186becdbc826190ced4312f8199f9db6a5" @@ -64,7 +64,7 @@ lemma rank_eq_zero_iff : rintro ⟨i : s⟩ obtain ⟨a, ha, ha'⟩ := h i apply ha - simpa using FunLike.congr_fun (linearIndependent_iff.mp hs (Finsupp.single i a) (by simpa)) i + simpa using DFunLike.congr_fun (linearIndependent_iff.mp hs (Finsupp.single i a) (by simpa)) i variable [Nontrivial R] @@ -190,9 +190,9 @@ theorem lt_aleph0_of_finite {ι : Type w} [Module.Finite R M] {v : ι → M} (h : LinearIndependent R v) : #ι < ℵ₀ := by apply Cardinal.lift_lt.1 apply lt_of_le_of_lt - apply h.cardinal_lift_le_rank - rw [← finrank_eq_rank, Cardinal.lift_aleph0, Cardinal.lift_natCast] - apply Cardinal.nat_lt_aleph0 + · apply h.cardinal_lift_le_rank + · rw [← finrank_eq_rank, Cardinal.lift_aleph0, Cardinal.lift_natCast] + apply Cardinal.nat_lt_aleph0 theorem finite [Module.Finite R M] {ι : Type*} {f : ι → M} (h : LinearIndependent R f) : Finite ι := @@ -364,20 +364,16 @@ variable [StrongRankCondition R] [Module.Finite R M] /-- A finite rank torsion-free module has positive `finrank` iff it has a nonzero element. -/ theorem FiniteDimensional.finrank_pos_iff_exists_ne_zero [NoZeroSMulDivisors R M] : - 0 < finrank R M ↔ ∃ x : M, x ≠ 0 := - Iff.trans - (by - rw [← finrank_eq_rank] - norm_cast) - (@rank_pos_iff_exists_ne_zero R M _ _ _ _ _) + 0 < finrank R M ↔ ∃ x : M, x ≠ 0 := by + rw [← @rank_pos_iff_exists_ne_zero R M, ← finrank_eq_rank] + norm_cast #align finite_dimensional.finrank_pos_iff_exists_ne_zero FiniteDimensional.finrank_pos_iff_exists_ne_zero /-- An `R`-finite torsion-free module has positive `finrank` iff it is nontrivial. -/ theorem FiniteDimensional.finrank_pos_iff [NoZeroSMulDivisors R M] : - 0 < finrank R M ↔ Nontrivial M := - Iff.trans - (by rw [← finrank_eq_rank]; norm_cast) - (rank_pos_iff_nontrivial (R := R)) + 0 < finrank R M ↔ Nontrivial M := by + rw [← rank_pos_iff_nontrivial (R := R), ← finrank_eq_rank] + norm_cast #align finite_dimensional.finrank_pos_iff FiniteDimensional.finrank_pos_iff /-- A nontrivial finite dimensional space has positive `finrank`. -/ @@ -389,26 +385,23 @@ theorem FiniteDimensional.finrank_pos [NoZeroSMulDivisors R M] [h : Nontrivial M /-- See `FiniteDimensional.finrank_zero_iff` for the stronger version with `NoZeroSMulDivisors R M`. -/ theorem FiniteDimensional.finrank_eq_zero_iff [Module.Finite R M] : - finrank R M = 0 ↔ ∀ x : M, ∃ a : R, a ≠ 0 ∧ a • x = 0 := - Iff.trans - (by rw [← finrank_eq_rank]; norm_cast) - (rank_eq_zero_iff (R := R)) + finrank R M = 0 ↔ ∀ x : M, ∃ a : R, a ≠ 0 ∧ a • x = 0 := by + rw [← rank_eq_zero_iff (R := R), ← finrank_eq_rank] + norm_cast /-- The `StrongRankCondition` is automatic. See `commRing_strongRankCondition`. -/ theorem FiniteDimensional.finrank_eq_zero_iff_isTorsion {R} [CommRing R] [StrongRankCondition R] [IsDomain R] [Module R M] [Module.Finite R M] : - finrank R M = 0 ↔ Module.IsTorsion R M := - Iff.trans - (by rw [← finrank_eq_rank]; norm_cast) - (rank_eq_zero_iff_isTorsion (R := R)) + finrank R M = 0 ↔ Module.IsTorsion R M := by + rw [← rank_eq_zero_iff_isTorsion (R := R), ← finrank_eq_rank] + norm_cast /-- A finite dimensional space has zero `finrank` iff it is a subsingleton. This is the `finrank` version of `rank_zero_iff`. -/ theorem FiniteDimensional.finrank_zero_iff [NoZeroSMulDivisors R M] : - finrank R M = 0 ↔ Subsingleton M := - Iff.trans - (by rw [← finrank_eq_rank]; norm_cast) - (rank_zero_iff (R := R)) + finrank R M = 0 ↔ Subsingleton M := by + rw [← rank_zero_iff (R := R), ← finrank_eq_rank] + norm_cast #align finite_dimensional.finrank_zero_iff FiniteDimensional.finrank_zero_iff end StrongRankCondition diff --git a/Mathlib/LinearAlgebra/Dimension/Free.lean b/Mathlib/LinearAlgebra/Dimension/Free.lean index 661215d32a310..1a7aa1c15205d 100644 --- a/Mathlib/LinearAlgebra/Dimension/Free.lean +++ b/Mathlib/LinearAlgebra/Dimension/Free.lean @@ -23,12 +23,57 @@ import Mathlib.LinearAlgebra.FreeModule.Finite.Basic noncomputable section -universe u v v' - -variable {R : Type u} {M M₁ : Type v} {M' : Type v'} +universe u v v' w open BigOperators Cardinal Basis Submodule Function Set DirectSum FiniteDimensional +section Tower + +variable (F : Type u) (K : Type v) (A : Type w) + +variable [Ring F] [Ring K] [AddCommGroup A] + +variable [Module F K] [Module K A] [Module F A] [IsScalarTower F K A] + +variable [StrongRankCondition F] [StrongRankCondition K] [Module.Free F K] [Module.Free K A] + +/-- Tower law: if `A` is a `K`-module and `K` is an extension of `F` then +$\operatorname{rank}_F(A) = \operatorname{rank}_F(K) * \operatorname{rank}_K(A)$. + +The universe polymorphic version of `rank_mul_rank` below. -/ +theorem lift_rank_mul_lift_rank : + Cardinal.lift.{w} (Module.rank F K) * Cardinal.lift.{v} (Module.rank K A) = + Cardinal.lift.{v} (Module.rank F A) := by + let b := Module.Free.chooseBasis F K + let c := Module.Free.chooseBasis K A + rw [← (Module.rank F K).lift_id, ← b.mk_eq_rank, ← (Module.rank K A).lift_id, ← c.mk_eq_rank, + ← lift_umax.{w, v}, ← (b.smul c).mk_eq_rank, mk_prod, lift_mul, lift_lift, lift_lift, lift_lift, + lift_lift, lift_umax.{v, w}] +#align lift_rank_mul_lift_rank lift_rank_mul_lift_rank + +/-- Tower law: if `A` is a `K`-module and `K` is an extension of `F` then +$\operatorname{rank}_F(A) = \operatorname{rank}_F(K) * \operatorname{rank}_K(A)$. + +This is a simpler version of `lift_rank_mul_lift_rank` with `K` and `A` in the same universe. -/ +theorem rank_mul_rank (A : Type v) [AddCommGroup A] + [Module K A] [Module F A] [IsScalarTower F K A] [Module.Free K A] : + Module.rank F K * Module.rank K A = Module.rank F A := by + convert lift_rank_mul_lift_rank F K A <;> rw [lift_id] +#align rank_mul_rank rank_mul_rank + +/-- Tower law: if `A` is a `K`-module and `K` is an extension of `F` then +$\operatorname{rank}_F(A) = \operatorname{rank}_F(K) * \operatorname{rank}_K(A)$. -/ +theorem FiniteDimensional.finrank_mul_finrank : finrank F K * finrank K A = finrank F A := by + simp_rw [finrank] + rw [← toNat_lift.{w} (Module.rank F K), ← toNat_lift.{v} (Module.rank K A), ← toNat_mul, + lift_rank_mul_lift_rank, toNat_lift] +#align finite_dimensional.finrank_mul_finrank FiniteDimensional.finrank_mul_finrank +#align finite_dimensional.finrank_mul_finrank' FiniteDimensional.finrank_mul_finrank + +end Tower + +variable {R : Type u} {M M₁ : Type v} {M' : Type v'} + variable [Ring R] [StrongRankCondition R] variable [AddCommGroup M] [Module R M] [Module.Free R M] diff --git a/Mathlib/LinearAlgebra/Dimension/Localization.lean b/Mathlib/LinearAlgebra/Dimension/Localization.lean new file mode 100644 index 0000000000000..b839ca7c30aad --- /dev/null +++ b/Mathlib/LinearAlgebra/Dimension/Localization.lean @@ -0,0 +1,87 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.Algebra.Module.Submodule.Localization +import Mathlib.LinearAlgebra.Dimension.DivisionRing +import Mathlib.RingTheory.Localization.FractionRing + +/-! +# Rank of localization + +## Main statements + +- `IsLocalizedModule.lift_rank_eq`: `rank_Rₚ Mₚ = rank R M`. +- `rank_quotient_add_rank_of_isDomain`: The **rank-nullity theorem** for commutative domains. + +-/ +open Cardinal nonZeroDivisors + +section CommRing + +universe u u' v v' + +variable {R : Type u} (S : Type u') {M : Type v} {N : Type v'} +variable [CommRing R] [CommRing S] [AddCommGroup M] [AddCommGroup N] [Module R M] +variable [Module R M] [Module R N] [Algebra R S] [Module S N] [IsScalarTower R S N] +variable (p : Submonoid R) [IsLocalization p S] (f : M →ₗ[R] N) [IsLocalizedModule p f] +variable (hp : p ≤ R⁰) + +lemma IsLocalizedModule.lift_rank_eq : + Cardinal.lift.{v} (Module.rank S N) = Cardinal.lift.{v'} (Module.rank R M) := by + cases' subsingleton_or_nontrivial R + · have := (algebraMap R S).codomain_trivial; simp only [rank_subsingleton, lift_one] + have := (IsLocalization.injective S hp).nontrivial + apply le_antisymm + · rw [Module.rank_def, lift_iSup (bddAbove_range.{v', v'} _)] + apply ciSup_le' + intro ⟨s, hs⟩ + choose sec hsec using IsLocalizedModule.surj p f + refine LinearIndependent.cardinal_lift_le_rank (ι := s) (v := fun i ↦ (sec i).1) ?_ + rw [linearIndependent_iff'] at hs ⊢ + intro t g hg i hit + apply hp (sec i).2.prop + apply IsLocalization.injective S hp + rw [map_zero] + refine hs t (fun i ↦ algebraMap R S (g i * (sec i).2)) ?_ _ hit + simp only [map_mul, mul_smul, algebraMap_smul, ← Submonoid.smul_def, + hsec, ← map_smul, ← map_sum, hg, map_zero] + · rw [Module.rank_def, lift_iSup (bddAbove_range.{v, v} _)] + apply ciSup_le' + intro ⟨s, hs⟩ + choose sec hsec using IsLocalization.surj p (S := S) + refine LinearIndependent.cardinal_lift_le_rank (ι := s) (v := fun i ↦ f i) ?_ + rw [linearIndependent_iff'] at hs ⊢ + intro t g hg i hit + apply (IsLocalization.map_units S (sec (g i)).2).mul_left_injective + classical + let u := fun (i : s) ↦ (t.erase i).prod (fun j ↦ (sec (g j)).2) + have : f (t.sum fun i ↦ u i • (sec (g i)).1 • i) = f 0 + · convert congr_arg (t.prod (fun j ↦ (sec (g j)).2) • ·) hg + · simp only [map_sum, map_smul, Submonoid.smul_def, Finset.smul_sum] + apply Finset.sum_congr rfl + intro j hj + simp only [← @IsScalarTower.algebraMap_smul R S N, Submonoid.coe_finset_prod, map_prod] + rw [← hsec, mul_comm (g j), mul_smul, ← mul_smul, Finset.prod_erase_mul (h := hj)] + rw [map_zero, smul_zero] + obtain ⟨c, hc⟩ := IsLocalizedModule.exists_of_eq (S := p) this + simp_rw [smul_zero, Finset.smul_sum, ← mul_smul, Submonoid.smul_def, ← mul_smul, mul_comm] at hc + simp only [hsec, zero_mul, map_eq_zero_iff (algebraMap R S) (IsLocalization.injective S hp)] + apply hp (c * u i).prop + exact hs t _ hc _ hit + +lemma IsLocalizedModule.rank_eq {N : Type v} [AddCommGroup N] + [Module R N] [Module S N] [IsScalarTower R S N] (f : M →ₗ[R] N) [IsLocalizedModule p f] : + Module.rank S N = Module.rank R M := by simpa using IsLocalizedModule.lift_rank_eq S p f hp + +/-- The **rank-nullity theorem** for commutative domains. -/ +theorem rank_quotient_add_rank_of_isDomain [IsDomain R] (M' : Submodule R M) : + Module.rank R (M ⧸ M') + Module.rank R M' = Module.rank R M := by + apply lift_injective.{max u v} + rw [lift_add, ← IsLocalizedModule.lift_rank_eq (FractionRing R) R⁰ (M'.toLocalized R⁰) le_rfl, + ← IsLocalizedModule.lift_rank_eq (FractionRing R) R⁰ (LocalizedModule.mkLinearMap R⁰ M) le_rfl, + ← IsLocalizedModule.lift_rank_eq (FractionRing R) R⁰ (M'.toLocalizedQuotient R⁰) le_rfl, + ← lift_add, rank_quotient_add_rank] + +end CommRing diff --git a/Mathlib/LinearAlgebra/Dual.lean b/Mathlib/LinearAlgebra/Dual.lean index b83dcc91a128d..5fffc6570a527 100644 --- a/Mathlib/LinearAlgebra/Dual.lean +++ b/Mathlib/LinearAlgebra/Dual.lean @@ -345,7 +345,7 @@ theorem toDual_eq_equivFun [Fintype ι] (m : M) (i : ι) : b.toDual m (b i) = b. #align basis.to_dual_eq_equiv_fun Basis.toDual_eq_equivFun theorem toDual_injective : Injective b.toDual := fun x y h ↦ b.ext_elem_iff.mpr fun i ↦ by - simp_rw [← toDual_eq_repr]; exact FunLike.congr_fun h _ + simp_rw [← toDual_eq_repr]; exact DFunLike.congr_fun h _ theorem toDual_inj (m : M) (a : b.toDual m = 0) : m = 0 := b.toDual_injective (by rwa [_root_.map_zero]) @@ -687,7 +687,7 @@ lemma equiv [IsReflexive R M] (e : M ≃ₗ[R] N) : IsReflexive R N where let ed : Dual R (Dual R N) ≃ₗ[R] Dual R (Dual R M) := e.symm.dualMap.dualMap have : Dual.eval R N = ed.symm.comp ((Dual.eval R M).comp e.symm.toLinearMap) := by ext m f - exact FunLike.congr_arg f (e.apply_symm_apply m).symm + exact DFunLike.congr_arg f (e.apply_symm_apply m).symm simp only [this, LinearEquiv.trans_symm, LinearEquiv.symm_symm, LinearEquiv.dualMap_symm, coe_comp, LinearEquiv.coe_coe, EquivLike.comp_bijective] exact Bijective.comp (bijective_dual_eval R M) (LinearEquiv.bijective _) @@ -1106,7 +1106,7 @@ variable {W : Subspace K V} @[simp] theorem dualLift_of_subtype {φ : Module.Dual K W} (w : W) : W.dualLift φ (w : V) = φ w := - congr_arg φ <| FunLike.congr_fun + congr_arg φ <| DFunLike.congr_fun (Classical.choose_spec <| W.subtype.exists_leftInverse_of_injective W.ker_subtype) w #align subspace.dual_lift_of_subtype Subspace.dualLift_of_subtype @@ -1295,7 +1295,7 @@ def dualCopairing (W : Submodule R M) : W.dualAnnihilator →ₗ[R] M ⧸ W → #align submodule.dual_copairing Submodule.dualCopairing -- Porting note: helper instance -instance (W : Submodule R M) : FunLike (W.dualAnnihilator) M fun _ => R := +instance (W : Submodule R M) : FunLike (W.dualAnnihilator) M R := { coe := fun φ => φ.val, coe_injective' := fun φ ψ h => by ext @@ -1390,7 +1390,7 @@ theorem quotDualCoannihilatorToDual_injective (W : Submodule R (Dual R M)) : theorem flip_quotDualCoannihilatorToDual_injective (W : Submodule R (Dual R M)) : Function.Injective W.quotDualCoannihilatorToDual.flip := - fun _ _ he ↦ Subtype.ext <| LinearMap.ext fun m ↦ FunLike.congr_fun he ⟦m⟧ + fun _ _ he ↦ Subtype.ext <| LinearMap.ext fun m ↦ DFunLike.congr_fun he ⟦m⟧ open LinearMap in theorem quotDualCoannihilatorToDual_nondegenerate (W : Submodule R (Dual R M)) : @@ -1422,7 +1422,9 @@ theorem range_dualMap_eq_dualAnnihilator_ker_of_subtype_range_surjective (f : M have := range_dualMap_eq_dualAnnihilator_ker_of_surjective f.rangeRestrict rr_surj convert this using 1 -- Porting note: broken dot notation lean4#1910 - · change range ((range f).subtype.comp f.rangeRestrict).dualMap = _ + · calc + _ = range ((range f).subtype.comp f.rangeRestrict).dualMap := by simp + _ = _ := ?_ rw [← dualMap_comp_dualMap, range_comp_of_range_eq_top] rwa [range_eq_top] · apply congr_arg diff --git a/Mathlib/LinearAlgebra/Eigenspace/Basic.lean b/Mathlib/LinearAlgebra/Eigenspace/Basic.lean index dc41f54cd5260..00819dca5d9ac 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Basic.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Basic.lean @@ -109,6 +109,10 @@ theorem HasEigenvector.apply_eq_smul {f : End R M} {μ : R} {x : M} (hx : f.HasE mem_eigenspace_iff.mp hx.1 #align module.End.has_eigenvector.apply_eq_smul Module.End.HasEigenvector.apply_eq_smul +theorem HasEigenvector.pow_apply {f : End R M} {μ : R} {v : M} (hv : f.HasEigenvector μ v) (n : ℕ) : + (f ^ n) v = μ ^ n • v := by + induction n <;> simp [*, pow_succ f, hv.apply_eq_smul, smul_smul, pow_succ' μ] + theorem HasEigenvalue.exists_hasEigenvector {f : End R M} {μ : R} (hμ : f.HasEigenvalue μ) : ∃ v, f.HasEigenvector μ v := Submodule.exists_mem_ne_zero_of_ne_bot hμ diff --git a/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean b/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean index 8783494ac3016..e338e347517f5 100644 --- a/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean +++ b/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean @@ -263,7 +263,7 @@ theorem ι_mul_prod_list {n : ℕ} (f : Fin n → M) (i : Fin n) : by_cases h : i = 0 · rw [h, ι_sq_zero, zero_mul] · replace hn := - congr_arg (ι R (f 0) * ·) $ hn (fun i => f <| Fin.succ i) (i.pred h) + congr_arg (ι R (f 0) * ·) <| hn (fun i => f <| Fin.succ i) (i.pred h) simp only at hn rw [Fin.succ_pred, ← mul_assoc, mul_zero] at hn refine' (eq_zero_iff_eq_zero_of_add_eq_zero _).mp hn diff --git a/Mathlib/LinearAlgebra/FiniteDimensional.lean b/Mathlib/LinearAlgebra/FiniteDimensional.lean index cb0bc96d39f12..c07c30bb999dd 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ import Mathlib.FieldTheory.Finiteness +import Mathlib.LinearAlgebra.Dimension.DivisionRing #align_import linear_algebra.finite_dimensional from "leanprover-community/mathlib"@"e95e4f92c8f8da3c7f693c3ec948bcf9b6683f51" @@ -1033,8 +1034,7 @@ theorem finrank_eq_one_iff (ι : Type*) [Unique ι] : finrank K V = 1 ↔ Nonemp /-- A module has dimension 1 iff there is some nonzero `v : V` so every vector is a multiple of `v`. -/ -theorem finrank_eq_one_iff' : finrank K V = 1 ↔ ∃ (v : V) (_n : v ≠ 0), - ∀ w : V, ∃ c : K, c • v = w := by +theorem finrank_eq_one_iff' : finrank K V = 1 ↔ ∃ v ≠ 0, ∀ w : V, ∃ c : K, c • v = w := by -- porting note: was a messy `convert` proof rw [finrank_eq_one_iff PUnit.{u+1}, Basis.basis_singleton_iff PUnit] #align finrank_eq_one_iff' finrank_eq_one_iff' @@ -1079,7 +1079,7 @@ theorem surjective_of_nonzero_of_finrank_eq_one {W A : Type*} [Semiring A] [Modu [AddCommGroup W] [Module K W] [Module A W] [LinearMap.CompatibleSMul V W K A] (h : finrank K W = 1) {f : V →ₗ[A] W} (w : f ≠ 0) : Surjective f := by change Surjective (f.restrictScalars K) - obtain ⟨v, n⟩ := FunLike.ne_iff.mp w + obtain ⟨v, n⟩ := DFunLike.ne_iff.mp w intro z obtain ⟨c, rfl⟩ := (finrank_eq_one_iff_of_nonzero' (f v) n).mp h z exact ⟨c • v, by simp⟩ diff --git a/Mathlib/LinearAlgebra/Finsupp.lean b/Mathlib/LinearAlgebra/Finsupp.lean index 49de2c6a75bfb..602e8fdfba234 100644 --- a/Mathlib/LinearAlgebra/Finsupp.lean +++ b/Mathlib/LinearAlgebra/Finsupp.lean @@ -6,6 +6,7 @@ Authors: Johannes Hölzl import Mathlib.Data.Finsupp.Encodable import Mathlib.LinearAlgebra.Pi import Mathlib.LinearAlgebra.Span +import Mathlib.Data.Set.Countable #align_import linear_algebra.finsupp from "leanprover-community/mathlib"@"9d684a893c52e1d6692a504a118bfccbae04feeb" @@ -170,6 +171,24 @@ def lapply (a : α) : (α →₀ M) →ₗ[R] M := { Finsupp.applyAddHom a with map_smul' := fun _ _ => rfl } #align finsupp.lapply Finsupp.lapply +section CompatibleSMul + +variable (R S M N ι : Type*) +variable [Semiring S] [AddCommMonoid M] [AddCommMonoid N] [Module S M] [Module S N] + +instance _root_.LinearMap.CompatibleSMul.finsupp_dom [SMulZeroClass R M] [DistribSMul R N] + [LinearMap.CompatibleSMul M N R S] : LinearMap.CompatibleSMul (ι →₀ M) N R S where + map_smul f r m := by + conv_rhs => rw [← sum_single m, map_finsupp_sum, smul_sum] + erw [← sum_single (r • m), sum_mapRange_index single_zero, map_finsupp_sum] + congr; ext i m; exact (f.comp <| lsingle i).map_smul_of_tower r m + +instance _root_.LinearMap.CompatibleSMul.finsupp_cod [SMul R M] [SMulZeroClass R N] + [LinearMap.CompatibleSMul M N R S] : LinearMap.CompatibleSMul M (ι →₀ N) R S where + map_smul f r m := by ext i; apply ((lapply i).comp f).map_smul_of_tower + +end CompatibleSMul + /-- Forget that a function is finitely supported. This is the linear version of `Finsupp.toFun`. -/ diff --git a/Mathlib/LinearAlgebra/FinsuppVectorSpace.lean b/Mathlib/LinearAlgebra/FinsuppVectorSpace.lean index 8982feab1c641..64c7e549b67a1 100644 --- a/Mathlib/LinearAlgebra/FinsuppVectorSpace.lean +++ b/Mathlib/LinearAlgebra/FinsuppVectorSpace.lean @@ -79,7 +79,8 @@ protected def basis {φ : ι → Type*} (b : ∀ i, Basis (φ i) R M) : Basis ( (b i).repr.symm (g.comapDomain _ (Set.injOn_of_injective sigma_mk_injective _)) support := g.support.image Sigma.fst mem_support_toFun := fun i => by - rw [Ne.def, ← (b i).repr.injective.eq_iff, (b i).repr.apply_symm_apply, FunLike.ext_iff] + rw [Ne.def, ← (b i).repr.injective.eq_iff, (b i).repr.apply_symm_apply, + DFunLike.ext_iff] simp only [exists_prop, LinearEquiv.map_zero, comapDomain_apply, zero_apply, exists_and_right, mem_support_iff, exists_eq_right, Sigma.exists, Finset.mem_image, not_forall] } diff --git a/Mathlib/LinearAlgebra/FreeModule/Basic.lean b/Mathlib/LinearAlgebra/FreeModule/Basic.lean index d2236c84b3a6c..fc5a6b55a3033 100644 --- a/Mathlib/LinearAlgebra/FreeModule/Basic.lean +++ b/Mathlib/LinearAlgebra/FreeModule/Basic.lean @@ -3,10 +3,7 @@ Copyright (c) 2021 Riccardo Brasca. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Riccardo Brasca -/ -import Mathlib.LinearAlgebra.DirectSum.Finsupp -import Mathlib.Logic.Small.Basic -import Mathlib.LinearAlgebra.StdBasis -import Mathlib.LinearAlgebra.FinsuppVectorSpace +import Mathlib.Data.Finsupp.Fintype import Mathlib.LinearAlgebra.TensorProductBasis #align_import linear_algebra.free_module.basic from "leanprover-community/mathlib"@"4e7e7009099d4a88a750de710909b95487bf0124" @@ -118,6 +115,9 @@ instance (priority := 100) noZeroSMulDivisors [NoZeroDivisors R] : NoZeroSMulDiv instance [Nontrivial M] : Nonempty (Module.Free.ChooseBasisIndex R M) := (Module.Free.chooseBasis R M).index_nonempty +theorem infinite [Infinite R] [Nontrivial M] : Infinite M := + (Equiv.infinite_iff (chooseBasis R M).repr.toEquiv).mpr Finsupp.infinite_of_right + variable {R M N} theorem of_equiv (e : M ≃ₗ[R] N) : Module.Free R N := diff --git a/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean b/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean index e4d7267b05ff3..76a13af9ee51a 100644 --- a/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean +++ b/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Riccardo Brasca -/ import Mathlib.LinearAlgebra.Dimension.LinearMap +import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition #align_import linear_algebra.free_module.finite.matrix from "leanprover-community/mathlib"@"b1c23399f01266afe392a0d8f71f599a0dad4f7b" @@ -21,80 +22,97 @@ We provide some instances for finite and free modules involving matrices. -/ -universe u v w +universe u u' v w -variable (R : Type u) (M : Type v) (N : Type w) +variable (R : Type u) (S : Type u') (M : Type v) (N : Type w) -open Module.Free (chooseBasis) +open Module.Free (chooseBasis ChooseBasisIndex) open FiniteDimensional (finrank) -section CommRing +section Ring -variable [CommRing R] [AddCommGroup M] [Module R M] [Module.Free R M] +variable [Ring R] [Ring S] [AddCommGroup M] [Module R M] [Module.Free R M] [Module.Finite R M] +variable [AddCommGroup N] [Module R N] [Module S N] [SMulCommClass R S N] -variable [AddCommGroup N] [Module R N] [Module.Free R N] +private noncomputable def linearMapEquivFun : (M →ₗ[R] N) ≃ₗ[S] ChooseBasisIndex R M → N := + (chooseBasis R M).repr.congrLeft N S ≪≫ₗ (Finsupp.lsum S).symm ≪≫ₗ + LinearEquiv.piCongrRight fun _ ↦ LinearMap.ringLmapEquivSelf R S N -instance Module.Free.linearMap [Module.Finite R M] [Module.Finite R N] : - Module.Free R (M →ₗ[R] N) := by - cases subsingleton_or_nontrivial R - · apply Module.Free.of_subsingleton' - classical exact - Module.Free.of_equiv (LinearMap.toMatrix (chooseBasis R M) (chooseBasis R N)).symm +instance Module.Free.linearMap [Module.Free S N] : Module.Free S (M →ₗ[R] N) := + Module.Free.of_equiv (linearMapEquivFun R S M N).symm #align module.free.linear_map Module.Free.linearMap -variable {R} - -instance Module.Finite.linearMap [Module.Finite R M] [Module.Finite R N] : - Module.Finite R (M →ₗ[R] N) := by - cases subsingleton_or_nontrivial R - · infer_instance - classical - have f := (LinearMap.toMatrix (chooseBasis R M) (chooseBasis R N)).symm - exact Module.Finite.of_surjective f.toLinearMap (LinearEquiv.surjective f) +instance Module.Finite.linearMap [Module.Finite S N] : Module.Finite S (M →ₗ[R] N) := + Module.Finite.equiv (linearMapEquivFun R S M N).symm #align module.finite.linear_map Module.Finite.linearMap -end CommRing +variable [StrongRankCondition R] [StrongRankCondition S] [Module.Free S N] -section Integer +open Cardinal +theorem FiniteDimensional.rank_linearMap : + Module.rank S (M →ₗ[R] N) = lift.{w} (Module.rank R M) * lift.{v} (Module.rank S N) := by + rw [(linearMapEquivFun R S M N).rank_eq, rank_fun_eq_lift_mul, + ← finrank_eq_card_chooseBasisIndex, ← finrank_eq_rank R, lift_natCast] -variable [AddCommGroup M] [Module.Finite ℤ M] [Module.Free ℤ M] +/-- The finrank of `M →ₗ[R] N` as an `S`-module is `(finrank R M) * (finrank S N)`. -/ +theorem FiniteDimensional.finrank_linearMap : + finrank S (M →ₗ[R] N) = finrank R M * finrank S N := by + simp_rw [finrank, rank_linearMap, toNat_mul, toNat_lift] +#align finite_dimensional.finrank_linear_map FiniteDimensional.finrank_linearMap -variable [AddCommGroup N] [Module.Finite ℤ N] [Module.Free ℤ N] +variable [Module R S] [SMulCommClass R S S] -instance Module.Finite.addMonoidHom : Module.Finite ℤ (M →+ N) := - Module.Finite.equiv (addMonoidHomLequivInt ℤ).symm -#align module.finite.add_monoid_hom Module.Finite.addMonoidHom +theorem FiniteDimensional.rank_linearMap_self : + Module.rank S (M →ₗ[R] S) = lift.{u'} (Module.rank R M) := by + rw [rank_linearMap, rank_self, lift_one, mul_one] -instance Module.Free.addMonoidHom : Module.Free ℤ (M →+ N) := - letI : Module.Free ℤ (M →ₗ[ℤ] N) := Module.Free.linearMap _ _ _ - Module.Free.of_equiv (addMonoidHomLequivInt ℤ).symm -#align module.free.add_monoid_hom Module.Free.addMonoidHom +theorem FiniteDimensional.finrank_linearMap_self : finrank S (M →ₗ[R] S) = finrank R M := by + rw [finrank_linearMap, finrank_self, mul_one] -end Integer +end Ring -section CommRing +section AlgHom -variable [CommRing R] [StrongRankCondition R] +variable (K M : Type*) (L : Type v) [CommRing K] [Ring M] [Algebra K M] + [Module.Free K M] [Module.Finite K M] [CommRing L] [IsDomain L] [Algebra K L] -variable [AddCommGroup M] [Module R M] [Module.Free R M] [Module.Finite R M] +instance Finite.algHom : Finite (M →ₐ[K] L) := + (linearIndependent_algHom_toLinearMap K M L).finite -variable [AddCommGroup N] [Module R N] [Module.Free R N] [Module.Finite R N] +open Cardinal -/-- The finrank of `M →ₗ[R] N` is `(finrank R M) * (finrank R N)`. -/ -theorem FiniteDimensional.finrank_linearMap : - finrank R (M →ₗ[R] N) = finrank R M * finrank R N := by - classical - letI := nontrivial_of_invariantBasisNumber R - have h := LinearMap.toMatrix (chooseBasis R M) (chooseBasis R N) - simp_rw [h.finrank_eq, FiniteDimensional.finrank_matrix, - FiniteDimensional.finrank_eq_card_chooseBasisIndex, mul_comm] -#align finite_dimensional.finrank_linear_map FiniteDimensional.finrank_linearMap +theorem cardinal_mk_algHom_le_rank : #(M →ₐ[K] L) ≤ lift.{v} (Module.rank K M) := by + convert (linearIndependent_algHom_toLinearMap K M L).cardinal_lift_le_rank + · rw [lift_id] + · have := Module.nontrivial K L + rw [lift_id, FiniteDimensional.rank_linearMap_self] + +theorem card_algHom_le_finrank : Nat.card (M →ₐ[K] L) ≤ finrank K M := by + convert toNat_le_of_le_of_lt_aleph0 ?_ (cardinal_mk_algHom_le_rank K M L) + · rw [toNat_lift, finrank] + · rw [lift_lt_aleph0]; have := Module.nontrivial K L; apply rank_lt_aleph0 -end CommRing +end AlgHom + +section Integer + +variable [AddCommGroup M] [Module.Finite ℤ M] [Module.Free ℤ M] [AddCommGroup N] + +instance Module.Finite.addMonoidHom [Module.Finite ℤ N] : Module.Finite ℤ (M →+ N) := + Module.Finite.equiv (addMonoidHomLequivInt ℤ).symm +#align module.finite.add_monoid_hom Module.Finite.addMonoidHom + +instance Module.Free.addMonoidHom [Module.Free ℤ N] : Module.Free ℤ (M →+ N) := + letI : Module.Free ℤ (M →ₗ[ℤ] N) := Module.Free.linearMap _ _ _ _ + Module.Free.of_equiv (addMonoidHomLequivInt ℤ).symm +#align module.free.add_monoid_hom Module.Free.addMonoidHom + +end Integer -theorem Matrix.rank_vecMulVec {K m n : Type u} [CommRing K] [StrongRankCondition K] [Fintype n] +theorem Matrix.rank_vecMulVec {K m n : Type u} [CommRing K] [Fintype n] [DecidableEq n] (w : m → K) (v : n → K) : (Matrix.vecMulVec w v).toLin'.rank ≤ 1 := by + nontriviality K rw [Matrix.vecMulVec_eq, Matrix.toLin'_mul] refine' le_trans (LinearMap.rank_comp_le_left _ _) _ refine' (LinearMap.rank_le_domain _).trans_eq _ diff --git a/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean b/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean index c660b3009e1b4..d51717fb2e96c 100644 --- a/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean +++ b/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Anne Baanen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ +import Mathlib.LinearAlgebra.FreeModule.Finite.Basic import Mathlib.LinearAlgebra.FreeModule.PID import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition import Mathlib.LinearAlgebra.QuotientPi @@ -76,7 +77,7 @@ noncomputable def quotientEquivPiSpan (I : Ideal S) (b : Basis ι R S) (hI : I · infer_instance classical let this := - Submodule.quotientPi (show ∀ _, Submodule R R from fun i => span ({a i} : Set R)) + Submodule.quotientPi (show _ → Submodule R R from fun i => span ({a i} : Set R)) exact this #align ideal.quotient_equiv_pi_span Ideal.quotientEquivPiSpan diff --git a/Mathlib/LinearAlgebra/FreeModule/PID.lean b/Mathlib/LinearAlgebra/FreeModule/PID.lean index 33b9639e6cbcc..a5cfbcb40c0fc 100644 --- a/Mathlib/LinearAlgebra/FreeModule/PID.lean +++ b/Mathlib/LinearAlgebra/FreeModule/PID.lean @@ -160,21 +160,17 @@ but must also feed in a basis for `M` using `basis_of_pid` to keep the induction -/ theorem Submodule.basis_of_pid_aux [Finite ι] {O : Type*} [AddCommGroup O] [Module R O] (M N : Submodule R O) (b'M : Basis ι R M) (N_bot : N ≠ ⊥) (N_le_M : N ≤ M) : - ∃ y ∈ M, - ∃ (a : R) (_ : a • y ∈ N), - ∃ M' ≤ M, - ∃ N' ≤ N, - ∃ (_N'_le_M' : N' ≤ M') (_y_ortho_M' : - ∀ (c : R) (z : O), z ∈ M' → c • y + z = 0 → c = 0) (_ay_ortho_N' : - ∀ (c : R) (z : O), z ∈ N' → c • a • y + z = 0 → c = 0), - ∀ (n') (bN' : Basis (Fin n') R N'), - ∃ bN : Basis (Fin (n' + 1)) R N, - ∀ (m') (hn'm' : n' ≤ m') (bM' : Basis (Fin m') R M'), - ∃ (hnm : n' + 1 ≤ m' + 1) (bM : Basis (Fin (m' + 1)) R M), - ∀ (as : Fin n' → R) - (_h : ∀ i : Fin n', (bN' i : O) = as i • (bM' (Fin.castLE hn'm' i) : O)), - ∃ as' : Fin (n' + 1) → R, - ∀ i : Fin (n' + 1), (bN i : O) = as' i • (bM (Fin.castLE hnm i) : O) := by + ∃ y ∈ M, ∃ a : R, a • y ∈ N ∧ ∃ M' ≤ M, ∃ N' ≤ N, + N' ≤ M' ∧ (∀ (c : R) (z : O), z ∈ M' → c • y + z = 0 → c = 0) ∧ + (∀ (c : R) (z : O), z ∈ N' → c • a • y + z = 0 → c = 0) ∧ + ∀ (n') (bN' : Basis (Fin n') R N'), + ∃ bN : Basis (Fin (n' + 1)) R N, + ∀ (m') (hn'm' : n' ≤ m') (bM' : Basis (Fin m') R M'), + ∃ (hnm : n' + 1 ≤ m' + 1) (bM : Basis (Fin (m' + 1)) R M), + ∀ as : Fin n' → R, + (∀ i : Fin n', (bN' i : O) = as i • (bM' (Fin.castLE hn'm' i) : O)) → + ∃ as' : Fin (n' + 1) → R, + ∀ i : Fin (n' + 1), (bN i : O) = as' i • (bM (Fin.castLE hnm i) : O) := by -- Let `ϕ` be a maximal projection of `M` onto `R`, in the sense that there is -- no `ψ` whose image of `N` is larger than `ϕ`'s image of `N`. have : ∃ ϕ : M →ₗ[R] R, ∀ ψ : M →ₗ[R] R, ¬ϕ.submoduleImage N < ψ.submoduleImage N := by @@ -411,14 +407,23 @@ noncomputable def Module.basisOfFiniteTypeTorsionFree' [Module.Finite R M] Module.basisOfFiniteTypeTorsionFree Module.Finite.exists_fin.choose_spec.choose_spec #align module.basis_of_finite_type_torsion_free' Module.basisOfFiniteTypeTorsionFree' --- It would be nice to make this an instance but it is empirically problematic, possibly because --- of the loop that it causes with `Module.Free.noZeroSMulDivisors` -theorem Module.free_of_finite_type_torsion_free' [Module.Finite R M] [NoZeroSMulDivisors R M] : +instance Module.free_of_finite_type_torsion_free' [Module.Finite R M] [NoZeroSMulDivisors R M] : Module.Free R M := by obtain ⟨n, b⟩ : Σn, Basis (Fin n) R M := Module.basisOfFiniteTypeTorsionFree' exact Module.Free.of_basis b #align module.free_of_finite_type_torsion_free' Module.free_of_finite_type_torsion_free' +instance {S : Type*} [CommRing S] [Algebra R S] {I : Ideal S} [hI₁ : Module.Finite R I] + [hI₂ : NoZeroSMulDivisors R I] : Module.Free R I := by + have : Module.Finite R (restrictScalars R I) := hI₁ + have : NoZeroSMulDivisors R (restrictScalars R I) := hI₂ + change Module.Free R (restrictScalars R I) + exact Module.free_of_finite_type_torsion_free' + +theorem Module.free_iff_noZeroSMulDivisors [Module.Finite R M] : + Module.Free R M ↔ NoZeroSMulDivisors R M := + ⟨fun _ ↦ inferInstance, fun _ ↦ inferInstance⟩ + section SmithNormal /-- A Smith normal form basis for a submodule `N` of a module `M` consists of diff --git a/Mathlib/LinearAlgebra/Isomorphisms.lean b/Mathlib/LinearAlgebra/Isomorphisms.lean index 92062d2f6c92a..de327aa716e66 100644 --- a/Mathlib/LinearAlgebra/Isomorphisms.lean +++ b/Mathlib/LinearAlgebra/Isomorphisms.lean @@ -106,7 +106,7 @@ noncomputable def quotientInfEquivSupQuotient (p p' : Submodule R M) : #align linear_map.quotient_inf_equiv_sup_quotient LinearMap.quotientInfEquivSupQuotient -- @[simp] --- Porting note: `simp` affects the type arguments of `FunLike.coe`, so this theorem can't be +-- Porting note: `simp` affects the type arguments of `DFunLike.coe`, so this theorem can't be -- a simp theorem anymore, even if it has high priority. theorem coe_quotientInfToSupQuotient (p p' : Submodule R M) : ⇑(quotientInfToSupQuotient p p') = quotientInfEquivSupQuotient p p' := diff --git a/Mathlib/LinearAlgebra/LinearIndependent.lean b/Mathlib/LinearAlgebra/LinearIndependent.lean index b10ca9e4c9e33..7c2969d15d050 100644 --- a/Mathlib/LinearAlgebra/LinearIndependent.lean +++ b/Mathlib/LinearAlgebra/LinearIndependent.lean @@ -144,7 +144,7 @@ theorem linearIndependent_iff' : (fun j _hjs hji => by rw [Finsupp.lapply_apply, Finsupp.single_eq_of_ne hji]) fun hnis => hnis.elim his _ = (∑ j in s, Finsupp.single j (g j)) i := (map_sum ..).symm - _ = 0 := FunLike.ext_iff.1 h i, + _ = 0 := DFunLike.ext_iff.1 h i, fun hf l hl => Finsupp.ext fun i => _root_.by_contradiction fun hni => hni <| hf _ _ hl _ <| Finsupp.mem_support_iff.2 hni⟩ @@ -238,6 +238,14 @@ theorem LinearIndependent.comp (h : LinearIndependent R v) (f : ι' → ι) (hf rw [Finsupp.mapDomain_apply hf] #align linear_independent.comp LinearIndependent.comp +/-- A family is linearly independent if and only if all of its finite subfamily is +linearly independent. -/ +theorem linearIndependent_iff_finset_linearIndependent : + LinearIndependent R v ↔ ∀ (s : Finset ι), LinearIndependent R (v ∘ (Subtype.val : s → ι)) := + ⟨fun H _ ↦ H.comp _ Subtype.val_injective, fun H ↦ linearIndependent_iff'.2 fun s g hg i hi ↦ + Fintype.linearIndependent_iff.1 (H s) (g ∘ Subtype.val) + (hg ▸ Finset.sum_attach s fun j ↦ g j • v j) ⟨i, hi⟩⟩ + theorem LinearIndependent.coe_range (i : LinearIndependent R v) : LinearIndependent R ((↑) : range v → M) := by simpa using i.comp _ (rangeSplitting_injective v) #align linear_independent.coe_range LinearIndependent.coe_range @@ -328,7 +336,7 @@ theorem linearIndependent_of_subsingleton [Subsingleton R] : LinearIndependent R theorem linearIndependent_equiv (e : ι ≃ ι') {f : ι' → M} : LinearIndependent R (f ∘ e) ↔ LinearIndependent R f := - ⟨fun h => Function.comp.right_id f ▸ e.self_comp_symm ▸ h.comp _ e.symm.injective, fun h => + ⟨fun h => Function.comp_id f ▸ e.self_comp_symm ▸ h.comp _ e.symm.injective, fun h => h.comp _ e.injective⟩ #align linear_independent_equiv linearIndependent_equiv @@ -461,19 +469,19 @@ theorem linearIndependent_subtype {s : Set M} : theorem linearIndependent_comp_subtype_disjoint {s : Set ι} : LinearIndependent R (v ∘ (↑) : s → M) ↔ - Disjoint (Finsupp.supported R R s) (LinearMap.ker $ Finsupp.total ι M R v) := + Disjoint (Finsupp.supported R R s) (LinearMap.ker <| Finsupp.total ι M R v) := by rw [linearIndependent_comp_subtype, LinearMap.disjoint_ker] #align linear_independent_comp_subtype_disjoint linearIndependent_comp_subtype_disjoint theorem linearIndependent_subtype_disjoint {s : Set M} : LinearIndependent R (fun x => x : s → M) ↔ - Disjoint (Finsupp.supported R R s) (LinearMap.ker $ Finsupp.total M M R id) := + Disjoint (Finsupp.supported R R s) (LinearMap.ker <| Finsupp.total M M R id) := by apply linearIndependent_comp_subtype_disjoint (v := id) #align linear_independent_subtype_disjoint linearIndependent_subtype_disjoint theorem linearIndependent_iff_totalOn {s : Set M} : LinearIndependent R (fun x => x : s → M) ↔ - (LinearMap.ker $ Finsupp.totalOn M M R id s) = ⊥ := by + (LinearMap.ker <| Finsupp.totalOn M M R id s) = ⊥ := by rw [Finsupp.totalOn, LinearMap.ker, LinearMap.comap_codRestrict, Submodule.map_bot, comap_bot, LinearMap.ker_comp, linearIndependent_subtype_disjoint, disjoint_iff_inf_le, ← map_comap_subtype, map_le_iff_le_comap, comap_bot, ker_subtype, le_bot_iff] @@ -1198,6 +1206,21 @@ theorem linearIndependent_monoidHom (G : Type*) [Monoid G] (L : Type*) [CommRing (Finset.forall_mem_insert ..).2 ⟨h4, h3⟩ #align linear_independent_monoid_hom linearIndependent_monoidHom +lemma linearIndependent_algHom_toLinearMap + (K M L) [CommSemiring K] [Semiring M] [Algebra K M] [CommRing L] [IsDomain L] [Algebra K L] : + LinearIndependent L (AlgHom.toLinearMap : (M →ₐ[K] L) → M →ₗ[K] L) := by + apply LinearIndependent.of_comp (LinearMap.ltoFun K M L) + exact (linearIndependent_monoidHom M L).comp + (RingHom.toMonoidHom ∘ AlgHom.toRingHom) + (fun _ _ e ↦ AlgHom.ext (DFunLike.congr_fun e : _)) + +lemma linearIndependent_algHom_toLinearMap' (K M L) [CommRing K] + [Semiring M] [Algebra K M] [CommRing L] [IsDomain L] [Algebra K L] [NoZeroSMulDivisors K L] : + LinearIndependent K (AlgHom.toLinearMap : (M →ₐ[K] L) → M →ₗ[K] L) := by + apply (linearIndependent_algHom_toLinearMap K M L).restrict_scalars + simp_rw [Algebra.smul_def, mul_one] + exact NoZeroSMulDivisors.algebraMap_injective K L + theorem le_of_span_le_span [Nontrivial R] {s t u : Set M} (hl : LinearIndependent R ((↑) : u → M)) (hsu : s ⊆ u) (htu : t ⊆ u) (hst : span R s ≤ span R t) : s ⊆ t := by have := @@ -1381,7 +1404,7 @@ theorem linearIndependent_fin2 {f : Fin 2 → V} : #align linear_independent_fin2 linearIndependent_fin2 theorem exists_linearIndependent_extension (hs : LinearIndependent K ((↑) : s → V)) (hst : s ⊆ t) : - ∃ (b : _) (_ : b ⊆ t), s ⊆ b ∧ t ⊆ span K b ∧ LinearIndependent K ((↑) : b → V) := by + ∃ b ⊆ t, s ⊆ b ∧ t ⊆ span K b ∧ LinearIndependent K ((↑) : b → V) := by -- Porting note: The placeholder should be solved before `rcases`. have := by refine zorn_subset_nonempty { b | b ⊆ t ∧ LinearIndependent K ((↑) : b → V) } ?_ _ ⟨hst, hs⟩ @@ -1401,7 +1424,7 @@ theorem exists_linearIndependent_extension (hs : LinearIndependent K ((↑) : s variable (K t) theorem exists_linearIndependent : - ∃ (b : _) (_ : b ⊆ t), span K b = span K t ∧ LinearIndependent K ((↑) : b → V) := by + ∃ b ⊆ t, span K b = span K t ∧ LinearIndependent K ((↑) : b → V) := by obtain ⟨b, hb₁, -, hb₂, hb₃⟩ := exists_linearIndependent_extension (linearIndependent_empty K V) (Set.empty_subset t) exact ⟨b, hb₁, (span_eq_of_le _ hb₂ (Submodule.span_mono hb₁)).symm, hb₃⟩ diff --git a/Mathlib/LinearAlgebra/Matrix/Basis.lean b/Mathlib/LinearAlgebra/Matrix/Basis.lean index c1e6af877eaf1..e3aef3ab68d9c 100644 --- a/Mathlib/LinearAlgebra/Matrix/Basis.lean +++ b/Mathlib/LinearAlgebra/Matrix/Basis.lean @@ -118,6 +118,13 @@ theorem sum_toMatrix_smul_self [Fintype ι] : ∑ i : ι, e.toMatrix v i j • e simp_rw [e.toMatrix_apply, e.sum_repr] #align basis.sum_to_matrix_smul_self Basis.sum_toMatrix_smul_self +theorem toMatrix_smul {R₁ S : Type*} [CommRing R₁] [Ring S] [Algebra R₁ S] [Fintype ι] + [DecidableEq ι] (x : S) (b : Basis ι R₁ S) (w : ι → S) : + (b.toMatrix (x • w)) = (Algebra.leftMulMatrix b x) * (b.toMatrix w) := by + ext + rw [Basis.toMatrix_apply, Pi.smul_apply, smul_eq_mul, ← Algebra.leftMulMatrix_mulVec_repr] + rfl + theorem toMatrix_map_vecMul {S : Type*} [Ring S] [Algebra R S] [Fintype ι] (b : Basis ι R S) (v : ι' → S) : ((b.toMatrix v).map <| algebraMap R S).vecMul b = v := by ext i @@ -177,10 +184,9 @@ variable [Fintype ι'] [Fintype κ] [Fintype κ'] @[simp] theorem basis_toMatrix_mul_linearMap_toMatrix [DecidableEq ι'] : c.toMatrix c' * LinearMap.toMatrix b' c' f = LinearMap.toMatrix b' c f := - (Matrix.toLin b' c).injective - (by - haveI := Classical.decEq κ' - rw [toLin_toMatrix, toLin_mul b' c' c, toLin_toMatrix, c.toLin_toMatrix, id_comp]) + (Matrix.toLin b' c).injective <| by + haveI := Classical.decEq κ' + rw [toLin_toMatrix, toLin_mul b' c' c, toLin_toMatrix, c.toLin_toMatrix, LinearMap.id_comp] #align basis_to_matrix_mul_linear_map_to_matrix basis_toMatrix_mul_linearMap_toMatrix variable [Fintype ι] @@ -188,8 +194,8 @@ variable [Fintype ι] @[simp] theorem linearMap_toMatrix_mul_basis_toMatrix [DecidableEq ι] [DecidableEq ι'] : LinearMap.toMatrix b' c' f * b'.toMatrix b = LinearMap.toMatrix b c' f := - (Matrix.toLin b c').injective - (by rw [toLin_toMatrix, toLin_mul b b' c', toLin_toMatrix, b'.toLin_toMatrix, comp_id]) + (Matrix.toLin b c').injective <| by + rw [toLin_toMatrix, toLin_mul b b' c', toLin_toMatrix, b'.toLin_toMatrix, LinearMap.comp_id] #align linear_map_to_matrix_mul_basis_to_matrix linearMap_toMatrix_mul_basis_toMatrix theorem basis_toMatrix_mul_linearMap_toMatrix_mul_basis_toMatrix [DecidableEq ι] [DecidableEq ι'] : diff --git a/Mathlib/LinearAlgebra/Matrix/BilinearForm.lean b/Mathlib/LinearAlgebra/Matrix/BilinearForm.lean index 0459aff303ab3..a3df969451a62 100644 --- a/Mathlib/LinearAlgebra/Matrix/BilinearForm.lean +++ b/Mathlib/LinearAlgebra/Matrix/BilinearForm.lean @@ -65,52 +65,28 @@ open Matrix /-- The map from `Matrix n n R` to bilinear forms on `n → R`. This is an auxiliary definition for the equivalence `Matrix.toBilin'`. -/ -def Matrix.toBilin'Aux [Fintype n] (M : Matrix n n R₂) : BilinForm R₂ (n → R₂) where - bilin v w := ∑ i, ∑ j, v i * M i j * w j - bilin_add_left x y z := by simp only [Pi.add_apply, add_mul, sum_add_distrib] - bilin_smul_left a x y := by simp only [Pi.smul_apply, smul_eq_mul, mul_assoc, mul_sum] - bilin_add_right x y z := by simp only [Pi.add_apply, mul_add, sum_add_distrib] - bilin_smul_right a x y := by - simp only [Pi.smul_apply, smul_eq_mul, mul_assoc, mul_left_comm, mul_sum] +def Matrix.toBilin'Aux [Fintype n] (M : Matrix n n R₂) : BilinForm R₂ (n → R₂) := + LinearMap.toBilin (Matrix.toLinearMap₂'Aux _ _ M) #align matrix.to_bilin'_aux Matrix.toBilin'Aux theorem Matrix.toBilin'Aux_stdBasis [Fintype n] [DecidableEq n] (M : Matrix n n R₂) (i j : n) : M.toBilin'Aux (LinearMap.stdBasis R₂ (fun _ => R₂) i 1) - (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := by - rw [Matrix.toBilin'Aux] - dsimp only -- Porting note: had to add `dsimp only` to get rid of the projections - rw [sum_eq_single i, sum_eq_single j] - · simp only [stdBasis_same, stdBasis_same, one_mul, mul_one] - · rintro j' - hj' - apply mul_eq_zero_of_right - exact stdBasis_ne R₂ (fun _ => R₂) _ _ hj' 1 - · intros - have := Finset.mem_univ j - contradiction - · rintro i' - hi' - refine' Finset.sum_eq_zero fun j _ => _ - apply mul_eq_zero_of_left - apply mul_eq_zero_of_left - exact stdBasis_ne R₂ (fun _ => R₂) _ _ hi' 1 - · intros - have := Finset.mem_univ i - contradiction + (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := + Matrix.toLinearMap₂'Aux_stdBasis _ _ _ _ _ #align matrix.to_bilin'_aux_std_basis Matrix.toBilin'Aux_stdBasis /-- The linear map from bilinear forms to `Matrix n n R` given an `n`-indexed basis. This is an auxiliary definition for the equivalence `Matrix.toBilin'`. -/ -def BilinForm.toMatrixAux (b : n → M₂) : BilinForm R₂ M₂ →ₗ[R₂] Matrix n n R₂ where - toFun B := of fun i j => B (b i) (b j) - map_add' _ _ := rfl - map_smul' _ _ := rfl +def BilinForm.toMatrixAux (b : n → M₂) : BilinForm R₂ M₂ →ₗ[R₂] Matrix n n R₂ := + (LinearMap.toMatrix₂Aux b b) ∘ₗ BilinForm.toLinHom (R₂ := R₂) #align bilin_form.to_matrix_aux BilinForm.toMatrixAux @[simp] theorem BilinForm.toMatrixAux_apply (B : BilinForm R₂ M₂) (b : n → M₂) (i j : n) : -- porting note: had to hint the base ring even though it should be clear from context... BilinForm.toMatrixAux (R₂ := R₂) b B i j = B (b i) (b j) := - rfl + LinearMap.toMatrix₂Aux_apply (toLin B) _ _ _ _ #align bilin_form.to_matrix_aux_apply BilinForm.toMatrixAux_apply variable [Fintype n] [Fintype o] @@ -119,9 +95,10 @@ theorem toBilin'Aux_toMatrixAux [DecidableEq n] (B₂ : BilinForm R₂ (n → R -- porting note: had to hint the base ring even though it should be clear from context... Matrix.toBilin'Aux (BilinForm.toMatrixAux (R₂ := R₂) (fun j => stdBasis R₂ (fun _ => R₂) j 1) B₂) = B₂ := by - refine' ext_basis (Pi.basisFun R₂ n) fun i j => _ - rw [Pi.basisFun_apply, Pi.basisFun_apply, Matrix.toBilin'Aux_stdBasis, - BilinForm.toMatrixAux_apply] + rw [BilinForm.toMatrixAux, Matrix.toBilin'Aux, coe_comp, Function.comp_apply, + toLinearMap₂'Aux_toMatrix₂Aux] + ext x y + simp only [toBilin_apply, BilinForm.toLin'_apply] #align to_bilin'_aux_to_matrix_aux toBilin'Aux_toMatrixAux section ToMatrix' @@ -136,14 +113,7 @@ variable [DecidableEq n] [DecidableEq o] /-- The linear equivalence between bilinear forms on `n → R` and `n × n` matrices -/ def BilinForm.toMatrix' : BilinForm R₂ (n → R₂) ≃ₗ[R₂] Matrix n n R₂ := - { BilinForm.toMatrixAux fun j => - stdBasis R₂ (fun _ => R₂) j - 1 with - invFun := Matrix.toBilin'Aux - left_inv := fun B ↦ by convert toBilin'Aux_toMatrixAux B - right_inv := fun M => by - ext i j - simp only [toFun_eq_coe, BilinForm.toMatrixAux_apply, Matrix.toBilin'Aux_stdBasis] } + BilinForm.toLin ≪≫ₗ LinearMap.toMatrix₂' #align bilin_form.to_matrix' BilinForm.toMatrix' @[simp] @@ -165,25 +135,18 @@ theorem Matrix.toBilin'Aux_eq (M : Matrix n n R₂) : Matrix.toBilin'Aux M = Mat #align matrix.to_bilin'_aux_eq Matrix.toBilin'Aux_eq theorem Matrix.toBilin'_apply (M : Matrix n n R₂) (x y : n → R₂) : - Matrix.toBilin' M x y = ∑ i, ∑ j, x i * M i j * y j := - rfl + Matrix.toBilin' M x y = ∑ i, ∑ j, x i * M i j * y j := Matrix.toLinearMap₂'_apply _ _ _ #align matrix.to_bilin'_apply Matrix.toBilin'_apply theorem Matrix.toBilin'_apply' (M : Matrix n n R₂) (v w : n → R₂) : - Matrix.toBilin' M v w = Matrix.dotProduct v (M.mulVec w) := by - simp_rw [Matrix.toBilin'_apply, Matrix.dotProduct, Matrix.mulVec, Matrix.dotProduct] - refine' Finset.sum_congr rfl fun _ _ => _ - rw [Finset.mul_sum] - refine' Finset.sum_congr rfl fun _ _ => _ - rw [← mul_assoc] + Matrix.toBilin' M v w = Matrix.dotProduct v (M.mulVec w) := Matrix.toLinearMap₂'_apply' _ _ _ #align matrix.to_bilin'_apply' Matrix.toBilin'_apply' @[simp] theorem Matrix.toBilin'_stdBasis (M : Matrix n n R₂) (i j : n) : Matrix.toBilin' M (LinearMap.stdBasis R₂ (fun _ => R₂) i 1) - (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := - Matrix.toBilin'Aux_stdBasis M i j + (LinearMap.stdBasis R₂ (fun _ => R₂) j 1) = M i j := Matrix.toLinearMap₂'_stdBasis _ _ _ #align matrix.to_bilin'_std_basis Matrix.toBilin'_stdBasis @[simp] @@ -207,64 +170,47 @@ theorem Matrix.toBilin'_toMatrix' (B : BilinForm R₂ (n → R₂)) : @[simp] theorem BilinForm.toMatrix'_toBilin' (M : Matrix n n R₂) : BilinForm.toMatrix' (Matrix.toBilin' M) = M := - BilinForm.toMatrix'.apply_symm_apply M + LinearMap.toMatrix₂'.apply_symm_apply M #align bilin_form.to_matrix'_to_bilin' BilinForm.toMatrix'_toBilin' @[simp] theorem BilinForm.toMatrix'_apply (B : BilinForm R₂ (n → R₂)) (i j : n) : BilinForm.toMatrix' B i j = B (stdBasis R₂ (fun _ => R₂) i 1) (stdBasis R₂ (fun _ => R₂) j 1) := - rfl + LinearMap.toMatrix₂'_apply _ _ _ #align bilin_form.to_matrix'_apply BilinForm.toMatrix'_apply -- Porting note: dot notation for bundled maps doesn't work in the rest of this section @[simp] theorem BilinForm.toMatrix'_comp (B : BilinForm R₂ (n → R₂)) (l r : (o → R₂) →ₗ[R₂] n → R₂) : BilinForm.toMatrix' (B.comp l r) = - (LinearMap.toMatrix' l)ᵀ * BilinForm.toMatrix' B * LinearMap.toMatrix' r := by - ext i j - simp only [BilinForm.toMatrix'_apply, BilinForm.comp_apply, transpose_apply, Matrix.mul_apply, - LinearMap.toMatrix', LinearEquiv.coe_mk, sum_mul] - rw [sum_comm] - conv_lhs => rw [← BilinForm.sum_repr_mul_repr_mul (Pi.basisFun R₂ n) (l _) (r _)] - rw [Finsupp.sum_fintype] - · apply sum_congr rfl - rintro i' - - rw [Finsupp.sum_fintype] - · apply sum_congr rfl - rintro j' - - simp only [smul_eq_mul, Pi.basisFun_repr, mul_assoc, mul_comm, mul_left_comm, - Pi.basisFun_apply, of_apply] - · intros - simp only [zero_smul, smul_zero] - · intros - simp only [zero_smul, Finsupp.sum_zero] + (LinearMap.toMatrix' l)ᵀ * BilinForm.toMatrix' B * LinearMap.toMatrix' r := + LinearMap.toMatrix₂'_compl₁₂ (toLin B) _ _ #align bilin_form.to_matrix'_comp BilinForm.toMatrix'_comp theorem BilinForm.toMatrix'_compLeft (B : BilinForm R₂ (n → R₂)) (f : (n → R₂) →ₗ[R₂] n → R₂) : - BilinForm.toMatrix' (B.compLeft f) = (LinearMap.toMatrix' f)ᵀ * BilinForm.toMatrix' B := by - simp only [BilinForm.compLeft, BilinForm.toMatrix'_comp, toMatrix'_id, Matrix.mul_one] + BilinForm.toMatrix' (B.compLeft f) = (LinearMap.toMatrix' f)ᵀ * BilinForm.toMatrix' B := + LinearMap.toMatrix₂'_comp (toLin B) _ #align bilin_form.to_matrix'_comp_left BilinForm.toMatrix'_compLeft theorem BilinForm.toMatrix'_compRight (B : BilinForm R₂ (n → R₂)) (f : (n → R₂) →ₗ[R₂] n → R₂) : - BilinForm.toMatrix' (B.compRight f) = BilinForm.toMatrix' B * LinearMap.toMatrix' f := by - simp only [BilinForm.compRight, BilinForm.toMatrix'_comp, toMatrix'_id, transpose_one, - Matrix.one_mul] + BilinForm.toMatrix' (B.compRight f) = BilinForm.toMatrix' B * LinearMap.toMatrix' f := + LinearMap.toMatrix₂'_compl₂ (toLin B) _ #align bilin_form.to_matrix'_comp_right BilinForm.toMatrix'_compRight theorem BilinForm.mul_toMatrix'_mul (B : BilinForm R₂ (n → R₂)) (M : Matrix o n R₂) (N : Matrix n o R₂) : M * BilinForm.toMatrix' B * N = - BilinForm.toMatrix' (B.comp (Matrix.toLin' Mᵀ) (Matrix.toLin' N)) := by - simp only [B.toMatrix'_comp, transpose_transpose, toMatrix'_toLin'] + BilinForm.toMatrix' (B.comp (Matrix.toLin' Mᵀ) (Matrix.toLin' N)) := + LinearMap.mul_toMatrix₂'_mul (toLin B) _ _ #align bilin_form.mul_to_matrix'_mul BilinForm.mul_toMatrix'_mul theorem BilinForm.mul_toMatrix' (B : BilinForm R₂ (n → R₂)) (M : Matrix n n R₂) : - M * BilinForm.toMatrix' B = BilinForm.toMatrix' (B.compLeft (Matrix.toLin' Mᵀ)) := by - simp only [toMatrix'_compLeft, transpose_transpose, toMatrix'_toLin'] + M * BilinForm.toMatrix' B = BilinForm.toMatrix' (B.compLeft (Matrix.toLin' Mᵀ)) := + LinearMap.mul_toMatrix' (toLin B) _ #align bilin_form.mul_to_matrix' BilinForm.mul_toMatrix' theorem BilinForm.toMatrix'_mul (B : BilinForm R₂ (n → R₂)) (M : Matrix n n R₂) : - BilinForm.toMatrix' B * M = BilinForm.toMatrix' (B.compRight (Matrix.toLin' M)) := by - simp only [toMatrix'_compRight, toMatrix'_toLin'] + BilinForm.toMatrix' B * M = BilinForm.toMatrix' (B.compRight (Matrix.toLin' M)) := + LinearMap.toMatrix₂'_mul (toLin B) _ #align bilin_form.to_matrix'_mul BilinForm.toMatrix'_mul theorem Matrix.toBilin'_comp (M : Matrix n n R₂) (P Q : Matrix n o R₂) : @@ -289,7 +235,7 @@ variable [DecidableEq n] (b : Basis n R₂ M₂) /-- `BilinForm.toMatrix b` is the equivalence between `R`-bilinear forms on `M` and `n`-by-`n` matrices with entries in `R`, if `b` is an `R`-basis for `M`. -/ noncomputable def BilinForm.toMatrix : BilinForm R₂ M₂ ≃ₗ[R₂] Matrix n n R₂ := - (BilinForm.congr b.equivFun).trans BilinForm.toMatrix' + BilinForm.toLin ≪≫ₗ (LinearMap.toMatrix₂ b b) #align bilin_form.to_matrix BilinForm.toMatrix /-- `BilinForm.toMatrix b` is the equivalence between `R`-bilinear forms on `M` and @@ -300,23 +246,20 @@ noncomputable def Matrix.toBilin : Matrix n n R₂ ≃ₗ[R₂] BilinForm R₂ M @[simp] theorem BilinForm.toMatrix_apply (B : BilinForm R₂ M₂) (i j : n) : - BilinForm.toMatrix b B i j = B (b i) (b j) := by - rw [BilinForm.toMatrix, LinearEquiv.trans_apply, BilinForm.toMatrix'_apply, congr_apply, - b.equivFun_symm_stdBasis, b.equivFun_symm_stdBasis] + BilinForm.toMatrix b B i j = B (b i) (b j) := + LinearMap.toMatrix₂_apply _ _ (toLin B) _ _ #align bilin_form.to_matrix_apply BilinForm.toMatrix_apply @[simp] theorem Matrix.toBilin_apply (M : Matrix n n R₂) (x y : M₂) : - Matrix.toBilin b M x y = ∑ i, ∑ j, b.repr x i * M i j * b.repr y j := by - rw [Matrix.toBilin, BilinForm.toMatrix, LinearEquiv.symm_trans_apply, ← Matrix.toBilin'] - simp only [congr_symm, congr_apply, LinearEquiv.symm_symm, Matrix.toBilin'_apply, - Basis.equivFun_apply] + Matrix.toBilin b M x y = ∑ i, ∑ j, b.repr x i * M i j * b.repr y j := + Matrix.toLinearMap₂_apply _ _ _ _ _ #align matrix.to_bilin_apply Matrix.toBilin_apply -- Not a `simp` lemma since `BilinForm.toMatrix` needs an extra argument theorem BilinearForm.toMatrixAux_eq (B : BilinForm R₂ M₂) : BilinForm.toMatrixAux (R₂ := R₂) b B = BilinForm.toMatrix b B := - ext fun i j => by rw [BilinForm.toMatrix_apply, BilinForm.toMatrixAux_apply] + LinearMap.toMatrix₂Aux_eq _ _ (toLin B) #align bilinear_form.to_matrix_aux_eq BilinearForm.toMatrixAux_eq @[simp] @@ -336,8 +279,7 @@ theorem Matrix.toBilin_basisFun : Matrix.toBilin (Pi.basisFun R₂ n) = Matrix.t theorem BilinForm.toMatrix_basisFun : BilinForm.toMatrix (Pi.basisFun R₂ n) = BilinForm.toMatrix' := by - ext B - rw [BilinForm.toMatrix_apply, BilinForm.toMatrix'_apply, Pi.basisFun_apply, Pi.basisFun_apply] + rw [BilinForm.toMatrix, BilinForm.toMatrix', LinearMap.toMatrix₂_basisFun] #align bilin_form.to_matrix_basis_fun BilinForm.toMatrix_basisFun @[simp] @@ -361,63 +303,51 @@ variable [DecidableEq o] -- Cannot be a `simp` lemma because `b` must be inferred. theorem BilinForm.toMatrix_comp (B : BilinForm R₂ M₂) (l r : M₂' →ₗ[R₂] M₂) : BilinForm.toMatrix c (B.comp l r) = - (LinearMap.toMatrix c b l)ᵀ * BilinForm.toMatrix b B * LinearMap.toMatrix c b r := by - ext i j - simp only [BilinForm.toMatrix_apply, BilinForm.comp_apply, transpose_apply, Matrix.mul_apply, - LinearMap.toMatrix', LinearEquiv.coe_mk, sum_mul] - rw [sum_comm] - conv_lhs => rw [← BilinForm.sum_repr_mul_repr_mul b] - rw [Finsupp.sum_fintype] - · apply sum_congr rfl - rintro i' - - rw [Finsupp.sum_fintype] - · apply sum_congr rfl - rintro j' - - simp only [smul_eq_mul, LinearMap.toMatrix_apply, Basis.equivFun_apply, mul_assoc, mul_comm, - mul_left_comm] - · intros - simp only [zero_smul, smul_zero] - · intros - simp only [zero_smul, Finsupp.sum_zero] + (LinearMap.toMatrix c b l)ᵀ * BilinForm.toMatrix b B * LinearMap.toMatrix c b r := + LinearMap.toMatrix₂_compl₁₂ _ _ _ _ (toLin B) _ _ #align bilin_form.to_matrix_comp BilinForm.toMatrix_comp theorem BilinForm.toMatrix_compLeft (B : BilinForm R₂ M₂) (f : M₂ →ₗ[R₂] M₂) : - BilinForm.toMatrix b (B.compLeft f) = (LinearMap.toMatrix b b f)ᵀ * BilinForm.toMatrix b B := by - simp only [compLeft, BilinForm.toMatrix_comp b b, toMatrix_id, Matrix.mul_one] + BilinForm.toMatrix b (B.compLeft f) = (LinearMap.toMatrix b b f)ᵀ * BilinForm.toMatrix b B := + LinearMap.toMatrix₂_comp _ _ _ (toLin B) _ #align bilin_form.to_matrix_comp_left BilinForm.toMatrix_compLeft theorem BilinForm.toMatrix_compRight (B : BilinForm R₂ M₂) (f : M₂ →ₗ[R₂] M₂) : - BilinForm.toMatrix b (B.compRight f) = BilinForm.toMatrix b B * LinearMap.toMatrix b b f := by - simp only [BilinForm.compRight, BilinForm.toMatrix_comp b b, toMatrix_id, transpose_one, - Matrix.one_mul] + BilinForm.toMatrix b (B.compRight f) = BilinForm.toMatrix b B * LinearMap.toMatrix b b f := + LinearMap.toMatrix₂_compl₂ _ _ _ (toLin B) _ #align bilin_form.to_matrix_comp_right BilinForm.toMatrix_compRight @[simp] theorem BilinForm.toMatrix_mul_basis_toMatrix (c : Basis o R₂ M₂) (B : BilinForm R₂ M₂) : - (b.toMatrix c)ᵀ * BilinForm.toMatrix b B * b.toMatrix c = BilinForm.toMatrix c B := by - rw [← LinearMap.toMatrix_id_eq_basis_toMatrix, ← BilinForm.toMatrix_comp, BilinForm.comp_id_id] + (b.toMatrix c)ᵀ * BilinForm.toMatrix b B * b.toMatrix c = BilinForm.toMatrix c B := + LinearMap.toMatrix₂_mul_basis_toMatrix _ _ _ _ (toLin B) #align bilin_form.to_matrix_mul_basis_to_matrix BilinForm.toMatrix_mul_basis_toMatrix theorem BilinForm.mul_toMatrix_mul (B : BilinForm R₂ M₂) (M : Matrix o n R₂) (N : Matrix n o R₂) : M * BilinForm.toMatrix b B * N = BilinForm.toMatrix c (B.comp (Matrix.toLin c b Mᵀ) (Matrix.toLin c b N)) := - by simp only [B.toMatrix_comp b c, toMatrix_toLin, transpose_transpose] + LinearMap.mul_toMatrix₂_mul _ _ _ _ (toLin B) _ _ #align bilin_form.mul_to_matrix_mul BilinForm.mul_toMatrix_mul theorem BilinForm.mul_toMatrix (B : BilinForm R₂ M₂) (M : Matrix n n R₂) : - M * BilinForm.toMatrix b B = BilinForm.toMatrix b (B.compLeft (Matrix.toLin b b Mᵀ)) := by - rw [B.toMatrix_compLeft b, toMatrix_toLin, transpose_transpose] + M * BilinForm.toMatrix b B = BilinForm.toMatrix b (B.compLeft (Matrix.toLin b b Mᵀ)) := + LinearMap.mul_toMatrix₂ _ _ _ (toLin B) _ #align bilin_form.mul_to_matrix BilinForm.mul_toMatrix theorem BilinForm.toMatrix_mul (B : BilinForm R₂ M₂) (M : Matrix n n R₂) : - BilinForm.toMatrix b B * M = BilinForm.toMatrix b (B.compRight (Matrix.toLin b b M)) := by - rw [B.toMatrix_compRight b, toMatrix_toLin] + BilinForm.toMatrix b B * M = BilinForm.toMatrix b (B.compRight (Matrix.toLin b b M)) := + LinearMap.toMatrix₂_mul _ _ _ (toLin B) _ #align bilin_form.to_matrix_mul BilinForm.toMatrix_mul theorem Matrix.toBilin_comp (M : Matrix n n R₂) (P Q : Matrix n o R₂) : - (Matrix.toBilin b M).comp (toLin c b P) (toLin c b Q) = Matrix.toBilin c (Pᵀ * M * Q) := - (BilinForm.toMatrix c).injective - (by simp only [BilinForm.toMatrix_comp b c, BilinForm.toMatrix_toBilin, toMatrix_toLin]) + (Matrix.toBilin b M).comp (toLin c b P) (toLin c b Q) = Matrix.toBilin c (Pᵀ * M * Q) := by + ext x y + rw [Matrix.toBilin, + BilinForm.toMatrix, Matrix.toBilin, BilinForm.toMatrix, LinearEquiv.trans_symm, + LinearEquiv.trans_symm, toMatrix₂_symm, BilinForm.toLin_symm, LinearEquiv.trans_apply, + toMatrix₂_symm, BilinForm.toLin_symm, LinearEquiv.trans_apply, + ← Matrix.toLinearMap₂_compl₁₂ b b c c] + simp #align matrix.to_bilin_comp Matrix.toBilin_comp end ToMatrix @@ -438,57 +368,22 @@ variable (J J₃ A A' : Matrix n n R₃) theorem isAdjointPair_toBilin' [DecidableEq n] : BilinForm.IsAdjointPair (Matrix.toBilin' J) (Matrix.toBilin' J₃) (Matrix.toLin' A) (Matrix.toLin' A') ↔ - Matrix.IsAdjointPair J J₃ A A' := by - rw [BilinForm.isAdjointPair_iff_compLeft_eq_compRight] - have h : - ∀ B B' : BilinForm R₃ (n → R₃), B = B' ↔ BilinForm.toMatrix' B = BilinForm.toMatrix' B' := by - intro B B' - constructor <;> intro h - · rw [h] - · exact BilinForm.toMatrix'.injective h - rw [h, BilinForm.toMatrix'_compLeft, BilinForm.toMatrix'_compRight, LinearMap.toMatrix'_toLin', - LinearMap.toMatrix'_toLin', BilinForm.toMatrix'_toBilin', BilinForm.toMatrix'_toBilin'] - rfl + Matrix.IsAdjointPair J J₃ A A' := + isAdjointPair_toLinearMap₂' _ _ _ _ #align is_adjoint_pair_to_bilin' isAdjointPair_toBilin' @[simp] theorem isAdjointPair_toBilin [DecidableEq n] : BilinForm.IsAdjointPair (Matrix.toBilin b J) (Matrix.toBilin b J₃) (Matrix.toLin b b A) (Matrix.toLin b b A') ↔ - Matrix.IsAdjointPair J J₃ A A' := by - rw [BilinForm.isAdjointPair_iff_compLeft_eq_compRight] - have h : ∀ B B' : BilinForm R₃ M₃, B = B' ↔ BilinForm.toMatrix b B = BilinForm.toMatrix b B' := by - intro B B' - constructor <;> intro h - · rw [h] - · exact (BilinForm.toMatrix b).injective h - rw [h, BilinForm.toMatrix_compLeft, BilinForm.toMatrix_compRight, LinearMap.toMatrix_toLin, - LinearMap.toMatrix_toLin, BilinForm.toMatrix_toBilin, BilinForm.toMatrix_toBilin] - rfl + Matrix.IsAdjointPair J J₃ A A' := + isAdjointPair_toLinearMap₂ _ _ _ _ _ _ #align is_adjoint_pair_to_bilin isAdjointPair_toBilin theorem Matrix.isAdjointPair_equiv' [DecidableEq n] (P : Matrix n n R₃) (h : IsUnit P) : (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A A' ↔ - J.IsAdjointPair J (P * A * P⁻¹) (P * A' * P⁻¹) := by - have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h - -- Porting note: the original proof used a complicated conv and timed out - let u := P.nonsingInvUnit h' - have coe_u : (u : Matrix n n R₃) = P := rfl - have coe_u_inv : (↑u⁻¹ : Matrix n n R₃) = P⁻¹ := rfl - let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h') - have coe_v : (v : Matrix n n R₃) = Pᵀ := rfl - have coe_v_inv : (↑v⁻¹ : Matrix n n R₃) = P⁻¹ᵀ := P.transpose_nonsing_inv.symm - set x := Aᵀ * Pᵀ * J with x_def - set y := J * P * A' with y_def - simp only [Matrix.IsAdjointPair] - calc (Aᵀ * (Pᵀ * J * P) = Pᵀ * J * P * A') - ↔ (x * ↑u = ↑v * y) := ?_ - _ ↔ (↑v⁻¹ * x = y * ↑u⁻¹) := ?_ - _ ↔ ((P * A * P⁻¹)ᵀ * J = J * (P * A' * P⁻¹)) := ?_ - · simp only [mul_assoc, x_def, y_def, coe_u, coe_v] - · rw [Units.eq_mul_inv_iff_mul_eq, mul_assoc ↑v⁻¹ x, Units.inv_mul_eq_iff_eq_mul] - · rw [x_def, y_def, coe_u_inv, coe_v_inv] - simp only [Matrix.mul_assoc, Matrix.transpose_mul] + J.IsAdjointPair J (P * A * P⁻¹) (P * A' * P⁻¹) := + Matrix.isAdjointPair_equiv _ _ _ _ h #align matrix.is_adjoint_pair_equiv' Matrix.isAdjointPair_equiv' variable [DecidableEq n] diff --git a/Mathlib/LinearAlgebra/Matrix/Block.lean b/Mathlib/LinearAlgebra/Matrix/Block.lean index 1e13c7a1481db..7087255623bc1 100644 --- a/Mathlib/LinearAlgebra/Matrix/Block.lean +++ b/Mathlib/LinearAlgebra/Matrix/Block.lean @@ -67,7 +67,7 @@ theorem blockTriangular_reindex_iff {b : n → α} {e : m ≃ n} : · convert h.submatrix simp only [reindex_apply, submatrix_submatrix, submatrix_id_id, Equiv.symm_comp_self] · convert h.submatrix - simp only [comp.assoc b e e.symm, Equiv.self_comp_symm, comp.right_id] + simp only [comp.assoc b e e.symm, Equiv.self_comp_symm, comp_id] #align matrix.block_triangular_reindex_iff Matrix.blockTriangular_reindex_iff protected theorem BlockTriangular.transpose : diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean index e9a77c9c386dc..a4a5ab33a04e0 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean @@ -163,7 +163,7 @@ theorem matPolyEquiv_symm_map_eval (M : (Matrix n n R)[X]) (r : R) : suffices ((aeval r).mapMatrix.comp matPolyEquiv.symm.toAlgHom : (Matrix n n R)[X] →ₐ[R] _) = (eval₂AlgHom' (AlgHom.id R _) (scalar n r) fun x => (scalar_commute _ (Commute.all _) _).symm) from - FunLike.congr_fun this M + DFunLike.congr_fun this M ext : 1 · ext M : 1 simp [Function.comp] diff --git a/Mathlib/LinearAlgebra/Matrix/Determinant.lean b/Mathlib/LinearAlgebra/Matrix/Determinant.lean index 30018656a2541..cd08d23c41c2d 100644 --- a/Mathlib/LinearAlgebra/Matrix/Determinant.lean +++ b/Mathlib/LinearAlgebra/Matrix/Determinant.lean @@ -13,6 +13,7 @@ import Mathlib.Algebra.Algebra.Basic import Mathlib.Tactic.Ring import Mathlib.LinearAlgebra.Alternating.Basic import Mathlib.LinearAlgebra.Pi +import Mathlib.GroupTheory.GroupAction.Ring #align_import linear_algebra.matrix.determinant from "leanprover-community/mathlib"@"c3019c79074b0619edb4b27553a91b2e82242395" @@ -647,8 +648,7 @@ theorem det_fromBlocks_zero₂₁ (A : Matrix m m R) (B : Matrix m n R) (D : Mat simp_rw [det_apply'] convert Eq.symm <| sum_subset (β := R) (subset_univ ((sumCongrHom m n).range : Set (Perm (Sum m n))).toFinset) ?_ - rw [sum_mul_sum] - simp_rw [univ_product_univ] + simp_rw [sum_mul_sum, ← sum_product', univ_product_univ] refine sum_nbij (fun σ ↦ σ.fst.sumCongr σ.snd) ?_ ?_ ?_ ?_ · intro σ₁₂ _ simp only @@ -659,7 +659,7 @@ theorem det_fromBlocks_zero₂₁ (A : Matrix m m R) (B : Matrix m n R) (D : Mat dsimp only intro h have h2 : ∀ x, Perm.sumCongr σ₁.fst σ₁.snd x = Perm.sumCongr σ₂.fst σ₂.snd x := - FunLike.congr_fun h + DFunLike.congr_fun h simp only [Sum.map_inr, Sum.map_inl, Perm.sumCongr_apply, Sum.forall, Sum.inl.injEq, Sum.inr.injEq] at h2 ext x diff --git a/Mathlib/LinearAlgebra/Matrix/DotProduct.lean b/Mathlib/LinearAlgebra/Matrix/DotProduct.lean index 3a0f8d7a88ee2..79e0829864147 100644 --- a/Mathlib/LinearAlgebra/Matrix/DotProduct.lean +++ b/Mathlib/LinearAlgebra/Matrix/DotProduct.lean @@ -70,6 +70,23 @@ theorem dotProduct_eq_zero_iff {v : n → R} : (∀ w, dotProduct v w = 0) ↔ v end Semiring +section OrderedSemiring + +variable [OrderedSemiring R] [Fintype n] + +lemma dotProduct_nonneg_of_nonneg {v w : n → R} (hv : 0 ≤ v) (hw : 0 ≤ w) : 0 ≤ dotProduct v w := + Finset.sum_nonneg (fun i _ => mul_nonneg (hv i) (hw i)) + +lemma dotProduct_le_dotProduct_of_nonneg_right {u v w : n → R} (huv : u ≤ v) (hw : 0 ≤ w) : + dotProduct u w ≤ dotProduct v w := + Finset.sum_le_sum (fun i _ => mul_le_mul_of_nonneg_right (huv i) (hw i)) + +lemma dotProduct_le_dotProduct_of_nonneg_left {u v w : n → R} (huv : u ≤ v) (hw : 0 ≤ w) : + dotProduct w u ≤ dotProduct w v := + Finset.sum_le_sum (fun i _ => mul_le_mul_of_nonneg_left (huv i) (hw i)) + +end OrderedSemiring + section Self variable [Fintype m] [Fintype n] [Fintype p] diff --git a/Mathlib/LinearAlgebra/Matrix/FiniteDimensional.lean b/Mathlib/LinearAlgebra/Matrix/FiniteDimensional.lean index 32d6ece657692..4e719fd745b73 100644 --- a/Mathlib/LinearAlgebra/Matrix/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/Matrix/FiniteDimensional.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Matrix.Basic import Mathlib.LinearAlgebra.FiniteDimensional import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix import Mathlib.LinearAlgebra.Matrix.ToLin +import Mathlib.Algebra.Module.Algebra #align_import linear_algebra.matrix.finite_dimensional from "leanprover-community/mathlib"@"b1c23399f01266afe392a0d8f71f599a0dad4f7b" @@ -53,7 +54,7 @@ variable {V : Type*} [AddCommGroup V] [Module K V] [FiniteDimensional K V] variable {W : Type*} [AddCommGroup W] [Module K W] [FiniteDimensional K W] instance finiteDimensional : FiniteDimensional K (V →ₗ[K] W) := - Module.Finite.linearMap _ _ + Module.Finite.linearMap _ _ _ _ #align linear_map.finite_dimensional LinearMap.finiteDimensional variable {A : Type*} [Ring A] [Algebra K A] [Module A V] [IsScalarTower K A V] [Module A W] diff --git a/Mathlib/LinearAlgebra/Matrix/Hermitian.lean b/Mathlib/LinearAlgebra/Matrix/Hermitian.lean index 0c81e187da734..f67f94879cb61 100644 --- a/Mathlib/LinearAlgebra/Matrix/Hermitian.lean +++ b/Mathlib/LinearAlgebra/Matrix/Hermitian.lean @@ -139,7 +139,7 @@ theorem isHermitian_diagonal_of_self_adjoint [DecidableEq n] (v : n → α) (h : #align matrix.is_hermitian_diagonal_of_self_adjoint Matrix.isHermitian_diagonal_of_self_adjoint /-- A diagonal matrix is hermitian if each diagonal entry is self-adjoint -/ -lemma isHermitian_diagonal_iff [DecidableEq n]{d : n → α} : +lemma isHermitian_diagonal_iff [DecidableEq n] {d : n → α} : IsHermitian (diagonal d) ↔ (∀ i : n, IsSelfAdjoint (d i)) := by simp [isSelfAdjoint_iff, IsHermitian, conjTranspose, diagonal_transpose, diagonal_map] diff --git a/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean b/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean index 74a6c6c02351a..118ed4872458c 100644 --- a/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean @@ -9,6 +9,7 @@ import Mathlib.LinearAlgebra.Matrix.Nondegenerate import Mathlib.LinearAlgebra.Matrix.NonsingularInverse import Mathlib.LinearAlgebra.Matrix.ToLinearEquiv import Mathlib.LinearAlgebra.SesquilinearForm +import Mathlib.LinearAlgebra.Basis.Bilinear #align_import linear_algebra.matrix.sesquilinear_form from "leanprover-community/mathlib"@"84582d2872fb47c0c17eec7382dc097c9ec7137a" @@ -46,7 +47,7 @@ open Matrix section AuxToLinearMap -variable [CommSemiring R] [CommSemiring R₁] [CommSemiring R₂] +variable [CommSemiring R] [Semiring R₁] [Semiring R₂] variable [Fintype n] [Fintype m] @@ -83,7 +84,7 @@ section AuxToMatrix section CommSemiring -variable [CommSemiring R] [CommSemiring R₁] [CommSemiring R₂] +variable [CommSemiring R] [Semiring R₁] [Semiring R₂] variable [AddCommMonoid M₁] [Module R₁ M₁] [AddCommMonoid M₂] [Module R₂ M₂] @@ -110,7 +111,7 @@ end CommSemiring section CommRing -variable [CommRing R] [CommRing R₁] [CommRing R₂] +variable [CommSemiring R] [Semiring R₁] [Semiring R₂] variable [AddCommMonoid M₁] [Module R₁ M₁] [AddCommMonoid M₂] [Module R₂ M₂] @@ -149,7 +150,7 @@ This section deals with the conversion between matrices and sesquilinear forms o -/ -variable [CommRing R] [CommRing R₁] [CommRing R₂] +variable [CommSemiring R] [Semiring R₁] [Semiring R₂] variable [Fintype n] [Fintype m] @@ -345,7 +346,7 @@ a module with a fixed basis. -/ -variable [CommRing R] +variable [CommSemiring R] variable [AddCommMonoid M₁] [Module R M₁] [AddCommMonoid M₂] [Module R M₂] @@ -530,7 +531,7 @@ variable (J J₂ : Matrix n n R) (J' : Matrix n' n' R) variable (A : Matrix n' n R) (A' : Matrix n n' R) -variable (A₁ : Matrix n n R) +variable (A₁ A₂ : Matrix n n R) /-- The condition for the matrices `A`, `A'` to be an adjoint pair with respect to the square matrices `J`, `J₃`. -/ @@ -589,13 +590,13 @@ theorem isAdjointPair_toLinearMap₂ : #align is_adjoint_pair_to_linear_map₂ isAdjointPair_toLinearMap₂ theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) : - (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔ - J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by + (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₂ ↔ + J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₂ * P⁻¹) := by have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h let u := P.nonsingInvUnit h' let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h') let x := A₁ᵀ * Pᵀ * J - let y := J * P * A₁ + let y := J * P * A₂ -- TODO(mathlib4#6607): fix elaboration so `val` isn't needed suffices x * u.val = v.val * y ↔ (v⁻¹).val * x = y * (u⁻¹).val by dsimp only [Matrix.IsAdjointPair] diff --git a/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean b/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean index 9beef8ed4ede1..ad1e80d36de7a 100644 --- a/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean +++ b/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean @@ -124,6 +124,13 @@ instance : Pow (SpecialLinearGroup n R) ℕ where instance : Inhabited (SpecialLinearGroup n R) := ⟨1⟩ +/-- The transpose of a matrix in `SL(n, R)` -/ +def transpose (A : SpecialLinearGroup n R) : SpecialLinearGroup n R := + ⟨A.1.transpose, A.1.det_transpose ▸ A.2⟩ + +@[inherit_doc] +scoped postfix:1024 "ᵀ" => SpecialLinearGroup.transpose + section CoeLemmas variable (A B : SpecialLinearGroup n R) @@ -158,6 +165,10 @@ theorem coe_pow (m : ℕ) : ↑ₘ(A ^ m) = ↑ₘA ^ m := rfl #align matrix.special_linear_group.coe_pow Matrix.SpecialLinearGroup.coe_pow +@[simp] +lemma coe_transpose (A : SpecialLinearGroup n R) : ↑ₘAᵀ = (↑ₘA)ᵀ := + rfl + theorem det_ne_zero [Nontrivial R] (g : SpecialLinearGroup n R) : det ↑ₘg ≠ 0 := by rw [g.det_coe] norm_num @@ -319,12 +330,70 @@ theorem fin_two_exists_eq_mk_of_apply_zero_one_eq_zero {R : Type*} [Field R] (g simp_rw [eq_inv_of_mul_eq_one_right had, hg] #align matrix.special_linear_group.fin_two_exists_eq_mk_of_apply_zero_one_eq_zero Matrix.SpecialLinearGroup.fin_two_exists_eq_mk_of_apply_zero_one_eq_zero +lemma isCoprime_row (A : SL(2, R)) (i : Fin 2): IsCoprime (A i 0) (A i 1) := by + refine match i with + | 0 => ⟨A 1 1, -(A 1 0), ?_⟩ + | 1 => ⟨-(A 0 1), A 0 0, ?_⟩ <;> + · simp_rw [det_coe A ▸ det_fin_two A.1] + ring + +lemma isCoprime_col (A : SL(2, R)) (j : Fin 2): IsCoprime (A 0 j) (A 1 j) := by + refine match j with + | 0 => ⟨A 1 1, -(A 0 1), ?_⟩ + | 1 => ⟨-(A 1 0), A 0 0, ?_⟩ <;> + · simp_rw [det_coe A ▸ det_fin_two A.1] + ring + end SpecialCases end SpecialLinearGroup end Matrix +namespace IsCoprime + +open Matrix MatrixGroups SpecialLinearGroup + +variable {R : Type*} [CommRing R] + +/-- Given any pair of coprime elements of `R`, there exists a matrix in `SL(2, R)` having those +entries as its left or right column. -/ +lemma exists_SL2_col {a b : R} (hab : IsCoprime a b) (j : Fin 2): + ∃ g : SL(2, R), g 0 j = a ∧ g 1 j = b := by + obtain ⟨u, v, h⟩ := hab + refine match j with + | 0 => ⟨⟨!![a, -v; b, u], ?_⟩, rfl, rfl⟩ + | 1 => ⟨⟨!![v, a; -u, b], ?_⟩, rfl, rfl⟩ <;> + · rw [Matrix.det_fin_two_of, ← h] + ring + +/-- Given any pair of coprime elements of `R`, there exists a matrix in `SL(2, R)` having those +entries as its top or bottom row. -/ +lemma exists_SL2_row {a b : R} (hab : IsCoprime a b) (i : Fin 2): + ∃ g : SL(2, R), g i 0 = a ∧ g i 1 = b := by + obtain ⟨u, v, h⟩ := hab + refine match i with + | 0 => ⟨⟨!![a, b; -v, u], ?_⟩, rfl, rfl⟩ + | 1 => ⟨⟨!![v, -u; a, b], ?_⟩, rfl, rfl⟩ <;> + · rw [Matrix.det_fin_two_of, ← h] + ring + +/-- A vector with coprime entries, right-multiplied by a matrix in `SL(2, R)`, has +coprime entries. -/ +lemma vecMulSL {v : Fin 2 → R} (hab : IsCoprime (v 0) (v 1)) (A : SL(2, R)) : + IsCoprime (vecMul v A.1 0) (vecMul v A.1 1) := by + obtain ⟨g, hg⟩ := hab.exists_SL2_row 0 + have : v = g 0 := funext fun t ↦ by { fin_cases t <;> tauto } + simpa only [this] using isCoprime_row (g * A) 0 + +/-- A vector with coprime entries, left-multiplied by a matrix in `SL(2, R)`, has +coprime entries. -/ +lemma mulVecSL {v : Fin 2 → R} (hab : IsCoprime (v 0) (v 1)) (A : SL(2, R)) : + IsCoprime (mulVec A.1 v 0) (mulVec A.1 v 1) := by + simpa only [← vecMul_transpose] using hab.vecMulSL A.transpose + +end IsCoprime + namespace ModularGroup open MatrixGroups diff --git a/Mathlib/LinearAlgebra/Matrix/Spectrum.lean b/Mathlib/LinearAlgebra/Matrix/Spectrum.lean index 4d38c25ccaa4c..b9ae79079ebba 100644 --- a/Mathlib/LinearAlgebra/Matrix/Spectrum.lean +++ b/Mathlib/LinearAlgebra/Matrix/Spectrum.lean @@ -142,7 +142,7 @@ theorem det_eq_prod_eigenvalues : det A = ∏ i, (hA.eigenvalues i : 𝕜) := by /-- *spectral theorem* (Alternate form for convenience) A hermitian matrix can be can be replaced by a diagonal matrix sandwiched between the eigenvector matrices. This alternate form -allows direct rewriting of A since: $ A = V D V⁻¹$ -/ +allows direct rewriting of A since: <| A = V D V⁻¹$ -/ lemma spectral_theorem' : A = hA.eigenvectorMatrix * diagonal ((↑) ∘ hA.eigenvalues) * hA.eigenvectorMatrixInv := by simpa [ ← Matrix.mul_assoc, hA.eigenvectorMatrix_mul_inv, Matrix.one_mul] using diff --git a/Mathlib/LinearAlgebra/Matrix/ToLin.lean b/Mathlib/LinearAlgebra/Matrix/ToLin.lean index 1006a13c7bd07..93d38bdb8fb2f 100644 --- a/Mathlib/LinearAlgebra/Matrix/ToLin.lean +++ b/Mathlib/LinearAlgebra/Matrix/ToLin.lean @@ -7,7 +7,6 @@ import Mathlib.Data.Matrix.Block import Mathlib.Data.Matrix.Notation import Mathlib.LinearAlgebra.StdBasis import Mathlib.RingTheory.AlgebraTower -import Mathlib.Algebra.Module.Algebra import Mathlib.Algebra.Algebra.Subalgebra.Tower #align_import linear_algebra.matrix.to_lin from "leanprover-community/mathlib"@"0e2aab2b0d521f060f62a14d2cf2e2c54e8491d6" diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index 6fb14148bba21..ffef14b558256 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.BigOperators.Order import Mathlib.Data.Fintype.BigOperators import Mathlib.Data.Fintype.Sort import Mathlib.Data.List.FinRange +import Mathlib.LinearAlgebra.Pi #align_import linear_algebra.multilinear.basic from "leanprover-community/mathlib"@"78fdf68dcd2fdb3fe64c0dd6f88926a49418a6ea" @@ -107,7 +108,7 @@ variable [Semiring R] [∀ i, AddCommMonoid (M i)] [∀ i, AddCommMonoid (M₁ i [Module R M₃] [Module R M'] (f f' : MultilinearMap R M₁ M₂) -- Porting note: Replaced CoeFun with FunLike instance -instance : FunLike (MultilinearMap R M₁ M₂) (∀ i, M₁ i) (fun _ ↦ M₂) where +instance : FunLike (MultilinearMap R M₁ M₂) (∀ i, M₁ i) M₂ where coe f := f.toFun coe_injective' := fun f g h ↦ by cases f; cases g; cases h; rfl @@ -124,29 +125,29 @@ theorem coe_mk (f : (∀ i, M₁ i) → M₂) (h₁ h₂) : ⇑(⟨f, h₁, h₂ #align multilinear_map.coe_mk MultilinearMap.coe_mk theorem congr_fun {f g : MultilinearMap R M₁ M₂} (h : f = g) (x : ∀ i, M₁ i) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align multilinear_map.congr_fun MultilinearMap.congr_fun nonrec theorem congr_arg (f : MultilinearMap R M₁ M₂) {x y : ∀ i, M₁ i} (h : x = y) : f x = f y := - FunLike.congr_arg f h + DFunLike.congr_arg f h #align multilinear_map.congr_arg MultilinearMap.congr_arg theorem coe_injective : Injective ((↑) : MultilinearMap R M₁ M₂ → (∀ i, M₁ i) → M₂) := - FunLike.coe_injective + DFunLike.coe_injective #align multilinear_map.coe_injective MultilinearMap.coe_injective @[norm_cast] -- Porting note: Removed simp attribute, simp can prove this theorem coe_inj {f g : MultilinearMap R M₁ M₂} : (f : (∀ i, M₁ i) → M₂) = g ↔ f = g := - FunLike.coe_fn_eq + DFunLike.coe_fn_eq #align multilinear_map.coe_inj MultilinearMap.coe_inj @[ext] theorem ext {f f' : MultilinearMap R M₁ M₂} (H : ∀ x, f x = f' x) : f = f' := - FunLike.ext _ _ H + DFunLike.ext _ _ H #align multilinear_map.ext MultilinearMap.ext theorem ext_iff {f g : MultilinearMap R M₁ M₂} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align multilinear_map.ext_iff MultilinearMap.ext_iff @[simp] @@ -231,7 +232,7 @@ instance addCommMonoid : AddCommMonoid (MultilinearMap R M₁ M₂) := /-- Coercion of a multilinear map to a function as an additive monoid homomorphism. -/ @[simps] def coeAddMonoidHom : MultilinearMap R M₁ M₂ →+ (((i : ι) → M₁ i) → M₂) where - toFun := FunLike.coe; map_zero' := rfl; map_add' _ _ := rfl + toFun := DFunLike.coe; map_zero' := rfl; map_add' _ _ := rfl @[simp] theorem coe_sum {α : Type*} (f : α → MultilinearMap R M₁ M₂) (s : Finset α) : @@ -308,7 +309,7 @@ def constOfIsEmpty [IsEmpty ι] (m : M₂) : MultilinearMap R M₁ M₂ where end --- Porting note: Included `FunLike.coe` to avoid strange CoeFun instance for Equiv +-- Porting note: Included `DFunLike.coe` to avoid strange CoeFun instance for Equiv /-- Given a multilinear map `f` on `n` variables (parameterized by `Fin n`) and a subset `s` of `k` of these variables, one gets a new multilinear map on `Fin k` by varying these variables, and fixing the other ones equal to a given value `z`. It is denoted by `f.restr s hk z`, where `hk` is a @@ -316,18 +317,18 @@ proof that the cardinality of `s` is `k`. The implicit identification between `F we use is the canonical (increasing) bijection. -/ def restr {k n : ℕ} (f : MultilinearMap R (fun _ : Fin n => M') M₂) (s : Finset (Fin n)) (hk : s.card = k) (z : M') : MultilinearMap R (fun _ : Fin k => M') M₂ where - toFun v := f fun j => if h : j ∈ s then v ((FunLike.coe (s.orderIsoOfFin hk).symm) ⟨j, h⟩) else z + toFun v := f fun j => if h : j ∈ s then v ((DFunLike.coe (s.orderIsoOfFin hk).symm) ⟨j, h⟩) else z /- Porting note: The proofs of the following two lemmas used to only use `erw` followed by `simp`, but it seems `erw` no longer unfolds or unifies well enough to work without more help. -/ map_add' v i x y := by - have : FunLike.coe (s.orderIsoOfFin hk).symm = (s.orderIsoOfFin hk).toEquiv.symm := rfl + have : DFunLike.coe (s.orderIsoOfFin hk).symm = (s.orderIsoOfFin hk).toEquiv.symm := rfl simp only [this] erw [dite_comp_equiv_update (s.orderIsoOfFin hk).toEquiv, dite_comp_equiv_update (s.orderIsoOfFin hk).toEquiv, dite_comp_equiv_update (s.orderIsoOfFin hk).toEquiv] simp map_smul' v i c x := by - have : FunLike.coe (s.orderIsoOfFin hk).symm = (s.orderIsoOfFin hk).toEquiv.symm := rfl + have : DFunLike.coe (s.orderIsoOfFin hk).symm = (s.orderIsoOfFin hk).toEquiv.symm := rfl simp only [this] erw [dite_comp_equiv_update (s.orderIsoOfFin hk).toEquiv, dite_comp_equiv_update (s.orderIsoOfFin hk).toEquiv] @@ -760,6 +761,68 @@ theorem domDomCongr_eq_iff (σ : ι₁ ≃ ι₂) (f g : MultilinearMap R (fun _ end +/-! If `{a // P a}` is a subtype of `ι` and if we fix an element `z` of `(i : {a // ¬ P a}) → M₁ i`, +then a multilinear map on `M₁` defines a multilinear map on the restriction of `M₁` to +`{a // P a}`, by fixing the arguments out of `{a // P a}` equal to the values of `z`.-/ + +lemma domDomRestrict_aux [DecidableEq ι] (P : ι → Prop) [DecidablePred P] + [DecidableEq {a // P a}] + (x : (i : {a // P a}) → M₁ i) (z : (i : {a // ¬ P a}) → M₁ i) (i : {a : ι // P a}) + (c : M₁ i) : (fun j ↦ if h : P j then Function.update x i c ⟨j, h⟩ else z ⟨j, h⟩) = + Function.update (fun j => if h : P j then x ⟨j, h⟩ else z ⟨j, h⟩) i c := by + ext j + by_cases h : j = i + · rw [h, Function.update_same] + simp only [i.2, update_same, dite_true] + · rw [Function.update_noteq h] + by_cases h' : P j + · simp only [h', ne_eq, Subtype.mk.injEq, dite_true] + have h'' : ¬ ⟨j, h'⟩ = i := + fun he => by apply_fun (fun x => x.1) at he; exact h he + rw [Function.update_noteq h''] + · simp only [h', ne_eq, Subtype.mk.injEq, dite_false] + +/-- Given a multilinear map `f` on `(i : ι) → M i`, a (decidable) predicate `P` on `ι` and +an element `z` of `(i : {a // ¬ P a}) → M₁ i`, construct a multilinear map on +`(i : {a // P a}) → M₁ i)` whose value at `x` is `f` evaluated at the vector with `i`th coordinate +`x i` if `P i` and `z i` otherwise. + +The naming is similar to `MultilinearMap.domDomCongr`: here we are applying the restriction to the +domain of the domain. +-/ +def domDomRestrict [DecidableEq ι] (f : MultilinearMap R M₁ M₂) (P : ι → Prop) [DecidablePred P] + (z : (i : {a : ι // ¬ P a}) → M₁ i) : + MultilinearMap R (fun (i : {a : ι // P a}) => M₁ i) M₂ where + toFun x := f (fun j ↦ if h : P j then x ⟨j, h⟩ else z ⟨j, h⟩) + map_add' x i a b := by + simp only + repeat (rw [domDomRestrict_aux]) + simp only [MultilinearMap.map_add] + map_smul' z i c a := by + simp only + repeat (rw [domDomRestrict_aux]) + simp only [MultilinearMap.map_smul] + +@[simp] +lemma domDomRestrict_apply [DecidableEq ι] (f : MultilinearMap R M₁ M₂) (P : ι → Prop) + [DecidablePred P] (x : (i : {a // P a}) → M₁ i) (z : (i : {a // ¬ P a}) → M₁ i) : + f.domDomRestrict P z x = f (fun j => if h : P j then x ⟨j, h⟩ else z ⟨j, h⟩) := rfl + +-- TODO: Should add a ref here when available. +/-- The "derivative" of a multilinear map, as a linear map from `(i : ι) → M₁ i` to `M₂`. +For continuous multilinear maps, this will indeed be the derivative.-/ +def linearDeriv [DecidableEq ι] [Fintype ι] (f : MultilinearMap R M₁ M₂) + (x : (i : ι) → M₁ i) : ((i : ι) → M₁ i) →ₗ[R] M₂ := + ∑ i : ι, (f.toLinearMap x i).comp (LinearMap.proj i) + +@[simp] +lemma linearDeriv_apply [DecidableEq ι] [Fintype ι] (f : MultilinearMap R M₁ M₂) + (x y : (i : ι) → M₁ i) : + f.linearDeriv x y = ∑ i, f (update x i (y i)) := by + unfold linearDeriv + simp only [LinearMap.coeFn_sum, LinearMap.coe_comp, LinearMap.coe_proj, Finset.sum_apply, + Function.comp_apply, Function.eval, toLinearMap_apply] + end Semiring end MultilinearMap @@ -1194,6 +1257,70 @@ theorem map_sub [DecidableEq ι] (m : ∀ i, M₁ i) (i : ι) (x y : M₁ i) : rw [sub_eq_add_neg, sub_eq_add_neg, MultilinearMap.map_add, map_neg] #align multilinear_map.map_sub MultilinearMap.map_sub +lemma map_update [DecidableEq ι] (x : (i : ι) → M₁ i) (i : ι) (v : M₁ i) : + f (update x i v) = f x - f (update x i (x i - v)) := by + rw [map_sub, update_eq_self, sub_sub_cancel] + +open Finset in +lemma map_sub_map_piecewise [LinearOrder ι] (a b : (i : ι) → M₁ i) (s : Finset ι) : + f a - f (s.piecewise b a) = + ∑ i in s, f (fun j ↦ if j ∈ s → j < i then a j else if i = j then a j - b j else b j) := by + refine s.induction_on_min ?_ fun k s hk ih ↦ ?_ + · rw [Finset.piecewise_empty, sum_empty, sub_self] + rw [Finset.piecewise_insert, map_update, ← sub_add, ih, + add_comm, sum_insert (lt_irrefl _ <| hk k ·)] + simp_rw [s.mem_insert] + congr 1 + · congr; ext i; split_ifs with h₁ h₂ + · rw [update_noteq, Finset.piecewise_eq_of_not_mem] + · exact fun h ↦ (hk i h).not_lt (h₁ <| .inr h) + · exact fun h ↦ (h₁ <| .inl h).ne h + · cases h₂ + rw [update_same, s.piecewise_eq_of_not_mem _ _ (lt_irrefl _ <| hk k ·)] + · push_neg at h₁ + rw [update_noteq (Ne.symm h₂), s.piecewise_eq_of_mem _ _ (h₁.1.resolve_left <| Ne.symm h₂)] + · apply sum_congr rfl; intro i hi; congr; ext j; congr 1; apply propext + simp_rw [imp_iff_not_or, not_or]; apply or_congr_left' + intro h; rw [and_iff_right]; rintro rfl; exact h (hk i hi) + +/-- This calculates the differences between the values of a multilinear map at +two arguments that differ on a finset `s` of `ι`. It requires a +linear order on `ι` in order to express the result.-/ +lemma map_piecewise_sub_map_piecewise [LinearOrder ι] (a b v : (i : ι) → M₁ i) (s : Finset ι) : + f (s.piecewise a v) - f (s.piecewise b v) = ∑ i in s, f + fun j ↦ if j ∈ s then if j < i then a j else if j = i then a j - b j else b j else v j := by + rw [← s.piecewise_idem_right b a, map_sub_map_piecewise] + refine Finset.sum_congr rfl fun i hi ↦ congr_arg f <| funext fun j ↦ ?_ + by_cases hjs : j ∈ s + · rw [if_pos hjs]; by_cases hji : j < i + · rw [if_pos fun _ ↦ hji, if_pos hji, s.piecewise_eq_of_mem _ _ hjs] + rw [if_neg (not_imp.mpr ⟨hjs, hji⟩), if_neg hji] + obtain rfl | hij := eq_or_ne i j + · rw [if_pos rfl, if_pos rfl, s.piecewise_eq_of_mem _ _ hi] + · rw [if_neg hij, if_neg hij.symm] + · rw [if_neg hjs, if_pos fun h ↦ (hjs h).elim, s.piecewise_eq_of_not_mem _ _ hjs] + +open Finset in +lemma map_add_eq_map_add_linearDeriv_add [DecidableEq ι] [Fintype ι] (x h : (i : ι) → M₁ i) : + f (x + h) = f x + f.linearDeriv x h + + ∑ s in univ.powerset.filter (2 ≤ ·.card), f (s.piecewise h x) := by + rw [add_comm, map_add_univ, ← Finset.powerset_univ, + ← sum_filter_add_sum_filter_not _ (2 ≤ ·.card)] + simp_rw [not_le, Nat.lt_succ, le_iff_lt_or_eq (b := 1), Nat.lt_one_iff, filter_or, + ← powersetCard_eq_filter, sum_union (univ.pairwise_disjoint_powersetCard zero_ne_one), + powersetCard_zero, powersetCard_one, sum_singleton, Finset.piecewise_empty, sum_map, + Function.Embedding.coeFn_mk, Finset.piecewise_singleton, linearDeriv_apply, add_comm] + +open Finset in +/-- This expresses the difference between the values of a multilinear map +at two points "close to `x`" in terms of the "derivative" of the multilinear map at `x` +and of "second-order" terms.-/ +lemma map_add_sub_map_add_sub_linearDeriv [DecidableEq ι] [Fintype ι] (x h h' : (i : ι) → M₁ i) : + f (x + h) - f (x + h') - f.linearDeriv x (h - h') = + ∑ s in univ.powerset.filter (2 ≤ ·.card), (f (s.piecewise h x) - f (s.piecewise h' x)) := by + simp_rw [map_add_eq_map_add_linearDeriv_add, add_assoc, add_sub_add_comm, sub_self, zero_add, + ← LinearMap.map_sub, add_sub_cancel', sum_sub_distrib] + end AddCommGroup section CommSemiring diff --git a/Mathlib/LinearAlgebra/Multilinear/FiniteDimensional.lean b/Mathlib/LinearAlgebra/Multilinear/FiniteDimensional.lean index a86cd0ca681b9..834945661cca7 100644 --- a/Mathlib/LinearAlgebra/Multilinear/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/Multilinear/FiniteDimensional.lean @@ -48,7 +48,7 @@ private theorem free_and_finite_fin (n : ℕ) (N : Fin n → Type*) [∀ i, AddC ⟨Module.Free.of_equiv (multilinearCurryLeftEquiv R N M₂), Module.Finite.equiv (multilinearCurryLeftEquiv R N M₂)⟩ cases ih fun i => N i.succ - exact ⟨Module.Free.linearMap _ _ _, Module.Finite.linearMap _ _⟩ + exact ⟨Module.Free.linearMap _ _ _ _, Module.Finite.linearMap _ _ _ _⟩ variable [∀ i, AddCommGroup (M₁ i)] [∀ i, Module R (M₁ i)] diff --git a/Mathlib/LinearAlgebra/PID.lean b/Mathlib/LinearAlgebra/PID.lean index e4d8487cff978..74a6cd3a603d8 100644 --- a/Mathlib/LinearAlgebra/PID.lean +++ b/Mathlib/LinearAlgebra/PID.lean @@ -5,6 +5,7 @@ Authors: Oliver Nash -/ import Mathlib.LinearAlgebra.Trace import Mathlib.LinearAlgebra.FreeModule.PID +import Mathlib.LinearAlgebra.FreeModule.Finite.Basic /-! # Linear maps of modules with coefficients in a principal ideal domain diff --git a/Mathlib/LinearAlgebra/PerfectPairing.lean b/Mathlib/LinearAlgebra/PerfectPairing.lean index 873d72447c238..f7660bd1ef639 100644 --- a/Mathlib/LinearAlgebra/PerfectPairing.lean +++ b/Mathlib/LinearAlgebra/PerfectPairing.lean @@ -43,7 +43,7 @@ variable {R M N} namespace PerfectPairing -instance instFunLike : FunLike (PerfectPairing R M N) M (fun _ ↦ N →ₗ[R] R) where +instance instFunLike : FunLike (PerfectPairing R M N) M (N →ₗ[R] R) where coe f := f.toLin coe_injective' x y h := by cases x; cases y; simpa using h diff --git a/Mathlib/LinearAlgebra/Pi.lean b/Mathlib/LinearAlgebra/Pi.lean index 551e0c0806e92..13e8aa5f46a28 100644 --- a/Mathlib/LinearAlgebra/Pi.lean +++ b/Mathlib/LinearAlgebra/Pi.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Eric Wieser -/ import Mathlib.GroupTheory.GroupAction.BigOperators +import Mathlib.Logic.Equiv.Fin import Mathlib.LinearAlgebra.Basic +import Mathlib.Algebra.BigOperators.Pi #align_import linear_algebra.pi from "leanprover-community/mathlib"@"dc6c365e751e34d100e80fe6e314c3c3e0fd2988" @@ -105,6 +107,11 @@ theorem iInf_ker_proj : (⨅ i, ker (proj i : ((i : ι) → φ i) →ₗ[R] φ i exact (mem_bot _).2 (funext fun i => h i) #align linear_map.infi_ker_proj LinearMap.iInf_ker_proj +instance CompatibleSMul.pi (R S M N ι : Type*) [Semiring S] + [AddCommMonoid M] [AddCommMonoid N] [SMul R M] [SMul R N] [Module S M] [Module S N] + [LinearMap.CompatibleSMul M N R S] : LinearMap.CompatibleSMul M (ι → N) R S where + map_smul f r m := by ext i; apply ((LinearMap.proj i).comp f).map_smul_of_tower + /-- Linear map between the function spaces `I → M₂` and `I → M₃`, induced by a linear map `f` between `M₂` and `M₃`. -/ @[simps] @@ -535,7 +542,7 @@ end Extend /-! ### Bundled versions of `Matrix.vecCons` and `Matrix.vecEmpty` The idea of these definitions is to be able to define a map as `x ↦ ![f₁ x, f₂ x, f₃ x]`, where -`f₁ f₂ f₃` are already linear maps, as `f₁.vecCons $ f₂.vecCons $ f₃.vecCons $ vecEmpty`. +`f₁ f₂ f₃` are already linear maps, as `f₁.vecCons <| f₂.vecCons <| f₃.vecCons <| vecEmpty`. While the same thing could be achieved using `LinearMap.pi ![f₁, f₂, f₃]`, this is not definitionally equal to the result using `LinearMap.vecCons`, as `Fin.cases` and function diff --git a/Mathlib/LinearAlgebra/PiTensorProduct.lean b/Mathlib/LinearAlgebra/PiTensorProduct.lean index d4781066bd33e..532555aaea288 100644 --- a/Mathlib/LinearAlgebra/PiTensorProduct.lean +++ b/Mathlib/LinearAlgebra/PiTensorProduct.lean @@ -13,7 +13,7 @@ import Mathlib.Tactic.LibrarySearch # Tensor product of an indexed family of modules over commutative semirings We define the tensor product of an indexed family `s : ι → Type*` of modules over commutative -semirings. We denote this space by `⨂[R] i, s i` and define it as `FreeAddMonoid (R × ∀ i, s i)` +semirings. We denote this space by `⨂[R] i, s i` and define it as `FreeAddMonoid (R × Π i, s i)` quotiented by the appropriate equivalence relation. The treatment follows very closely that of the binary tensor product in `LinearAlgebra/TensorProduct.lean`. @@ -21,10 +21,10 @@ binary tensor product in `LinearAlgebra/TensorProduct.lean`. * `PiTensorProduct R s` with `R` a commutative semiring and `s : ι → Type*` is the tensor product of all the `s i`'s. This is denoted by `⨂[R] i, s i`. -* `tprod R f` with `f : ∀ i, s i` is the tensor product of the vectors `f i` over all `i : ι`. - This is bundled as a multilinear map from `∀ i, s i` to `⨂[R] i, s i`. +* `tprod R f` with `f : Π i, s i` is the tensor product of the vectors `f i` over all `i : ι`. + This is bundled as a multilinear map from `Π i, s i` to `⨂[R] i, s i`. * `liftAddHom` constructs an `AddMonoidHom` from `(⨂[R] i, s i)` to some space `F` from a - function `φ : (R × ∀ i, s i) → F` with the appropriate properties. + function `φ : (R × Π i, s i) → F` with the appropriate properties. * `lift φ` with `φ : MultilinearMap R s E` is the corresponding linear map `(⨂[R] i, s i) →ₗ[R] E`. This is bundled as a linear equivalence. * `PiTensorProduct.reindex e` re-indexes the components of `⨂[R] i : ι, M` along `e : ι ≃ ι₂`. @@ -38,8 +38,8 @@ binary tensor product in `LinearAlgebra/TensorProduct.lean`. ## Implementation notes -* We define it via `FreeAddMonoid (R × ∀ i, s i)` with the `R` representing a "hidden" tensor - factor, rather than `FreeAddMonoid (∀ i, s i)` to ensure that, if `ι` is an empty type, +* We define it via `FreeAddMonoid (R × Π i, s i)` with the `R` representing a "hidden" tensor + factor, rather than `FreeAddMonoid (Π i, s i)` to ensure that, if `ι` is an empty type, the space is isomorphic to the base ring `R`. * We have not restricted the index type `ι` to be a `Fintype`, as nothing we do here strictly requires it. However, problems may arise in the case where `ι` is infinite; use at your own @@ -86,17 +86,17 @@ namespace PiTensorProduct variable (R) (s) -/-- The relation on `FreeAddMonoid (R × ∀ i, s i)` that generates a congruence whose quotient is +/-- The relation on `FreeAddMonoid (R × Π i, s i)` that generates a congruence whose quotient is the tensor product. -/ -inductive Eqv : FreeAddMonoid (R × ∀ i, s i) → FreeAddMonoid (R × ∀ i, s i) → Prop - | of_zero : ∀ (r : R) (f : ∀ i, s i) (i : ι) (_ : f i = 0), Eqv (FreeAddMonoid.of (r, f)) 0 - | of_zero_scalar : ∀ f : ∀ i, s i, Eqv (FreeAddMonoid.of (0, f)) 0 - | of_add : ∀ (_ : DecidableEq ι) (r : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i), +inductive Eqv : FreeAddMonoid (R × Π i, s i) → FreeAddMonoid (R × Π i, s i) → Prop + | of_zero : ∀ (r : R) (f : Π i, s i) (i : ι) (_ : f i = 0), Eqv (FreeAddMonoid.of (r, f)) 0 + | of_zero_scalar : ∀ f : Π i, s i, Eqv (FreeAddMonoid.of (0, f)) 0 + | of_add : ∀ (_ : DecidableEq ι) (r : R) (f : Π i, s i) (i : ι) (m₁ m₂ : s i), Eqv (FreeAddMonoid.of (r, update f i m₁) + FreeAddMonoid.of (r, update f i m₂)) (FreeAddMonoid.of (r, update f i (m₁ + m₂))) - | of_add_scalar : ∀ (r r' : R) (f : ∀ i, s i), + | of_add_scalar : ∀ (r r' : R) (f : Π i, s i), Eqv (FreeAddMonoid.of (r, f) + FreeAddMonoid.of (r', f)) (FreeAddMonoid.of (r + r', f)) - | of_smul : ∀ (_ : DecidableEq ι) (r : R) (f : ∀ i, s i) (i : ι) (r' : R), + | of_smul : ∀ (_ : DecidableEq ι) (r : R) (f : Π i, s i) (i : ι) (r' : R), Eqv (FreeAddMonoid.of (r, update f i (r' • f i))) (FreeAddMonoid.of (r' * r, f)) | add_comm : ∀ x y, Eqv (x + y) (y + x) #align pi_tensor_product.eqv PiTensorProduct.Eqv @@ -134,40 +134,40 @@ instance : Inhabited (⨂[R] i, s i) := ⟨0⟩ variable (R) {s} -/-- `tprodCoeff R r f` with `r : R` and `f : ∀ i, s i` is the tensor product of the vectors `f i` +/-- `tprodCoeff R r f` with `r : R` and `f : Π i, s i` is the tensor product of the vectors `f i` over all `i : ι`, multiplied by the coefficient `r`. Note that this is meant as an auxiliary definition for this file alone, and that one should use `tprod` defined below for most purposes. -/ -def tprodCoeff (r : R) (f : ∀ i, s i) : ⨂[R] i, s i := +def tprodCoeff (r : R) (f : Π i, s i) : ⨂[R] i, s i := AddCon.mk' _ <| FreeAddMonoid.of (r, f) #align pi_tensor_product.tprod_coeff PiTensorProduct.tprodCoeff variable {R} -theorem zero_tprodCoeff (f : ∀ i, s i) : tprodCoeff R 0 f = 0 := +theorem zero_tprodCoeff (f : Π i, s i) : tprodCoeff R 0 f = 0 := Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero_scalar _ #align pi_tensor_product.zero_tprod_coeff PiTensorProduct.zero_tprodCoeff -theorem zero_tprodCoeff' (z : R) (f : ∀ i, s i) (i : ι) (hf : f i = 0) : tprodCoeff R z f = 0 := +theorem zero_tprodCoeff' (z : R) (f : Π i, s i) (i : ι) (hf : f i = 0) : tprodCoeff R z f = 0 := Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_zero _ _ i hf #align pi_tensor_product.zero_tprod_coeff' PiTensorProduct.zero_tprodCoeff' -theorem add_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i) : +theorem add_tprodCoeff [DecidableEq ι] (z : R) (f : Π i, s i) (i : ι) (m₁ m₂ : s i) : tprodCoeff R z (update f i m₁) + tprodCoeff R z (update f i m₂) = tprodCoeff R z (update f i (m₁ + m₂)) := Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add _ z f i m₁ m₂) #align pi_tensor_product.add_tprod_coeff PiTensorProduct.add_tprodCoeff -theorem add_tprodCoeff' (z₁ z₂ : R) (f : ∀ i, s i) : +theorem add_tprodCoeff' (z₁ z₂ : R) (f : Π i, s i) : tprodCoeff R z₁ f + tprodCoeff R z₂ f = tprodCoeff R (z₁ + z₂) f := Quotient.sound' <| AddConGen.Rel.of _ _ (Eqv.of_add_scalar z₁ z₂ f) #align pi_tensor_product.add_tprod_coeff' PiTensorProduct.add_tprodCoeff' -theorem smul_tprodCoeff_aux [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R) : +theorem smul_tprodCoeff_aux [DecidableEq ι] (z : R) (f : Π i, s i) (i : ι) (r : R) : tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r * z) f := Quotient.sound' <| AddConGen.Rel.of _ _ <| Eqv.of_smul _ _ _ _ _ #align pi_tensor_product.smul_tprod_coeff_aux PiTensorProduct.smul_tprodCoeff_aux -theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : R₁) [SMul R₁ R] +theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : Π i, s i) (i : ι) (r : R₁) [SMul R₁ R] [IsScalarTower R₁ R R] [SMul R₁ (s i)] [IsScalarTower R₁ R (s i)] : tprodCoeff R z (update f i (r • f i)) = tprodCoeff R (r • z) f := by have h₁ : r • z = r • (1 : R) * z := by rw [smul_mul_assoc, one_mul] @@ -177,14 +177,14 @@ theorem smul_tprodCoeff [DecidableEq ι] (z : R) (f : ∀ i, s i) (i : ι) (r : #align pi_tensor_product.smul_tprod_coeff PiTensorProduct.smul_tprodCoeff /-- Construct an `AddMonoidHom` from `(⨂[R] i, s i)` to some space `F` from a function -`φ : (R × ∀ i, s i) → F` with the appropriate properties. -/ -def liftAddHom (φ : (R × ∀ i, s i) → F) - (C0 : ∀ (r : R) (f : ∀ i, s i) (i : ι) (_ : f i = 0), φ (r, f) = 0) - (C0' : ∀ f : ∀ i, s i, φ (0, f) = 0) - (C_add : ∀ [DecidableEq ι] (r : R) (f : ∀ i, s i) (i : ι) (m₁ m₂ : s i), +`φ : (R × Π i, s i) → F` with the appropriate properties. -/ +def liftAddHom (φ : (R × Π i, s i) → F) + (C0 : ∀ (r : R) (f : Π i, s i) (i : ι) (_ : f i = 0), φ (r, f) = 0) + (C0' : ∀ f : Π i, s i, φ (0, f) = 0) + (C_add : ∀ [DecidableEq ι] (r : R) (f : Π i, s i) (i : ι) (m₁ m₂ : s i), φ (r, update f i m₁) + φ (r, update f i m₂) = φ (r, update f i (m₁ + m₂))) - (C_add_scalar : ∀ (r r' : R) (f : ∀ i, s i), φ (r, f) + φ (r', f) = φ (r + r', f)) - (C_smul : ∀ [DecidableEq ι] (r : R) (f : ∀ i, s i) (i : ι) (r' : R), + (C_add_scalar : ∀ (r r' : R) (f : Π i, s i), φ (r, f) + φ (r', f) = φ (r + r', f)) + (C_smul : ∀ [DecidableEq ι] (r : R) (f : Π i, s i) (i : ι) (r' : R), φ (r, update f i (r' • f i)) = φ (r' * r, f)) : (⨂[R] i, s i) →+ F := (addConGen (PiTensorProduct.Eqv R s)).lift (FreeAddMonoid.lift φ) <| @@ -206,7 +206,7 @@ def liftAddHom (φ : (R × ∀ i, s i) → F) @[elab_as_elim] protected theorem induction_on' {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i) - (C1 : ∀ {r : R} {f : ∀ i, s i}, C (tprodCoeff R r f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) : + (C1 : ∀ {r : R} {f : Π i, s i}, C (tprodCoeff R r f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) : C z := by have C0 : C 0 := by have h₁ := @C1 0 0 @@ -227,7 +227,7 @@ variable [Monoid R₂] [DistribMulAction R₂ R] [SMulCommClass R₂ R R] -- to find. instance hasSMul' : SMul R₁ (⨂[R] i, s i) := ⟨fun r ↦ - liftAddHom (fun f : R × ∀ i, s i ↦ tprodCoeff R (r • f.1) f.2) + liftAddHom (fun f : R × Π i, s i ↦ tprodCoeff R (r • f.1) f.2) (fun r' f i hf ↦ by simp_rw [zero_tprodCoeff' _ f i hf]) (fun f ↦ by simp [zero_tprodCoeff]) (fun r' f i m₁ m₂ ↦ by simp [add_tprodCoeff]) (fun r' r'' f ↦ by simp [add_tprodCoeff', mul_add]) fun z f i r' ↦ by @@ -237,7 +237,7 @@ instance hasSMul' : SMul R₁ (⨂[R] i, s i) := instance : SMul R (⨂[R] i, s i) := PiTensorProduct.hasSMul' -theorem smul_tprodCoeff' (r : R₁) (z : R) (f : ∀ i, s i) : +theorem smul_tprodCoeff' (r : R₁) (z : R) (f : Π i, s i) : r • tprodCoeff R z f = tprodCoeff R (r • z) f := rfl #align pi_tensor_product.smul_tprod_coeff' PiTensorProduct.smul_tprodCoeff' @@ -318,14 +318,14 @@ theorem tprod_eq_tprodCoeff_one : ⇑(tprod R : MultilinearMap R s (⨂[R] i, s i)) = tprodCoeff R 1 := rfl @[simp] -theorem tprodCoeff_eq_smul_tprod (z : R) (f : ∀ i, s i) : tprodCoeff R z f = z • tprod R f := by +theorem tprodCoeff_eq_smul_tprod (z : R) (f : Π i, s i) : tprodCoeff R z f = z • tprod R f := by have : z = z • (1 : R) := by simp only [mul_one, Algebra.id.smul_eq_mul] conv_lhs => rw [this] #align pi_tensor_product.tprod_coeff_eq_smul_tprod PiTensorProduct.tprodCoeff_eq_smul_tprod @[elab_as_elim] protected theorem induction_on {C : (⨂[R] i, s i) → Prop} (z : ⨂[R] i, s i) - (C1 : ∀ {r : R} {f : ∀ i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) : + (C1 : ∀ {r : R} {f : Π i, s i}, C (r • tprod R f)) (Cp : ∀ {x y}, C x → C y → C (x + y)) : C z := by simp_rw [← tprodCoeff_eq_smul_tprod] at C1 exact PiTensorProduct.induction_on' z @C1 @Cp @@ -355,7 +355,7 @@ variable {s} `MultilinearMap R s E` with the property that its composition with the canonical `MultilinearMap R s (⨂[R] i, s i)` is the given multilinear map. -/ def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E := - liftAddHom (fun p : R × ∀ i, s i ↦ p.1 • φ p.2) + liftAddHom (fun p : R × Π i, s i ↦ p.1 • φ p.2) (fun z f i hf ↦ by simp_rw [map_coord_zero φ i hf, smul_zero]) (fun f ↦ by simp_rw [zero_smul]) (fun z f i m₁ m₂ ↦ by simp_rw [← smul_add, φ.map_add]) @@ -363,7 +363,7 @@ def liftAux (φ : MultilinearMap R s E) : (⨂[R] i, s i) →+ E := fun z f i r ↦ by simp [φ.map_smul, smul_smul, mul_comm] #align pi_tensor_product.lift_aux PiTensorProduct.liftAux -theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ (tprod R f) = φ f := by +theorem liftAux_tprod (φ : MultilinearMap R s E) (f : Π i, s i) : liftAux φ (tprod R f) = φ f := by simp only [liftAux, liftAddHom, tprod_eq_tprodCoeff_one, tprodCoeff, AddCon.coe_mk'] -- The end of this proof was very different before leanprover/lean4#2644: -- rw [FreeAddMonoid.of, FreeAddMonoid.ofList, Equiv.refl_apply, AddCon.lift_coe] @@ -380,7 +380,7 @@ theorem liftAux_tprod (φ : MultilinearMap R s E) (f : ∀ i, s i) : liftAux φ #align pi_tensor_product.lift_aux_tprod PiTensorProduct.liftAux_tprod -theorem liftAux_tprodCoeff (φ : MultilinearMap R s E) (z : R) (f : ∀ i, s i) : +theorem liftAux_tprodCoeff (φ : MultilinearMap R s E) (z : R) (f : Π i, s i) : liftAux φ (tprodCoeff R z f) = z • φ f := rfl #align pi_tensor_product.lift_aux_tprod_coeff PiTensorProduct.liftAux_tprodCoeff @@ -416,7 +416,7 @@ def lift : MultilinearMap R s E ≃ₗ[R] (⨂[R] i, s i) →ₗ[R] E where variable {φ : MultilinearMap R s E} @[simp] -theorem lift.tprod (f : ∀ i, s i) : lift φ (tprod R f) = φ f := +theorem lift.tprod (f : Π i, s i) : lift φ (tprod R f) = φ f := liftAux_tprod φ f #align pi_tensor_product.lift.tprod PiTensorProduct.lift.tprod @@ -444,61 +444,55 @@ section variable (R M) -/-- Re-index the components of the tensor power by `e`. - -For simplicity, this is defined only for homogeneously- (rather than dependently-) typed components. --/ -def reindex (e : ι ≃ ι₂) : (⨂[R] _ : ι, M) ≃ₗ[R] ⨂[R] _ : ι₂, M := - LinearEquiv.ofLinear (lift (domDomCongr e.symm (tprod R : MultilinearMap R _ (⨂[R] _ : ι₂, M)))) - (lift (domDomCongr e (tprod R : MultilinearMap R _ (⨂[R] _ : ι, M)))) - (by - ext - simp only [LinearMap.comp_apply, LinearMap.id_apply, lift_tprod, - LinearMap.compMultilinearMap_apply, lift.tprod, domDomCongr_apply] - congr - ext - rw [e.apply_symm_apply]) - (by - ext - simp only [LinearMap.comp_apply, LinearMap.id_apply, lift_tprod, - LinearMap.compMultilinearMap_apply, lift.tprod, domDomCongr_apply] - congr - ext - rw [e.symm_apply_apply]) +variable (s) in +/-- Re-index the components of the tensor power by `e`.-/ +def reindex (e : ι ≃ ι₂) : (⨂[R] i : ι, s i) ≃ₗ[R] ⨂[R] i : ι₂, s (e.symm i) := + let f := domDomCongrLinearEquiv' R R s (⨂[R] (i : ι₂), s (e.symm i)) e + let g := domDomCongrLinearEquiv' R R s (⨂[R] (i : ι), s i) e + LinearEquiv.ofLinear (lift <| f.symm <| tprod R) (lift <| g <| tprod R) (by aesop) (by aesop) #align pi_tensor_product.reindex PiTensorProduct.reindex end @[simp] -theorem reindex_tprod (e : ι ≃ ι₂) (f : ∀ _, M) : - reindex R M e (tprod R f) = tprod R fun i ↦ f (e.symm i) := by +theorem reindex_tprod (e : ι ≃ ι₂) (f : Π i, s i) : + reindex R s e (tprod R f) = tprod R fun i ↦ f (e.symm i) := by dsimp [reindex] exact liftAux_tprod _ f #align pi_tensor_product.reindex_tprod PiTensorProduct.reindex_tprod @[simp] theorem reindex_comp_tprod (e : ι ≃ ι₂) : - (reindex R M e : (⨂[R] _ : ι, M) →ₗ[R] ⨂[R] _ : ι₂, M).compMultilinearMap (tprod R) = - (tprod R : MultilinearMap R (fun _ ↦ M) _).domDomCongr e.symm := + (reindex R s e).compMultilinearMap (tprod R) = + (domDomCongrLinearEquiv' R R s _ e).symm (tprod R) := MultilinearMap.ext <| reindex_tprod e #align pi_tensor_product.reindex_comp_tprod PiTensorProduct.reindex_comp_tprod -@[simp] -theorem lift_comp_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ : ι₂ ↦ M) E) : - lift φ ∘ₗ ↑(reindex R M e) = lift (φ.domDomCongr e.symm) := by - ext - simp +theorem lift_comp_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun i ↦ s (e.symm i)) E) : + lift φ ∘ₗ (reindex R s e) = lift ((domDomCongrLinearEquiv' R R s _ e).symm φ) := by + ext; simp [reindex] #align pi_tensor_product.lift_comp_reindex PiTensorProduct.lift_comp_reindex @[simp] -theorem lift_reindex (e : ι ≃ ι₂) (φ : MultilinearMap R (fun _ ↦ M) E) (x : ⨂[R] _, M) : - lift φ (reindex R M e x) = lift (φ.domDomCongr e.symm) x := +theorem lift_comp_reindex_symm (e : ι ≃ ι₂) (φ : MultilinearMap R s E) : + lift φ ∘ₗ (reindex R s e).symm = lift (domDomCongrLinearEquiv' R R s _ e φ) := by + ext; simp [reindex] + +theorem lift_reindex + (e : ι ≃ ι₂) (φ : MultilinearMap R (fun i ↦ s (e.symm i)) E) (x : ⨂[R] i, s i) : + lift φ (reindex R s e x) = lift ((domDomCongrLinearEquiv' R R s _ e).symm φ) x := LinearMap.congr_fun (lift_comp_reindex e φ) x #align pi_tensor_product.lift_reindex PiTensorProduct.lift_reindex +@[simp] +theorem lift_reindex_symm + (e : ι ≃ ι₂) (φ : MultilinearMap R s E) (x : ⨂[R] i, s (e.symm i)) : + lift φ (reindex R s e |>.symm x) = lift (domDomCongrLinearEquiv' R R s _ e φ) x := + LinearMap.congr_fun (lift_comp_reindex_symm e φ) x + @[simp] theorem reindex_trans (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) : - (reindex R M e).trans (reindex R M e') = reindex R M (e.trans e') := by + (reindex R s e).trans (reindex R _ e') = reindex R s (e.trans e') := by apply LinearEquiv.toLinearMap_injective ext f simp only [LinearEquiv.trans_apply, LinearEquiv.coe_coe, reindex_tprod, @@ -507,22 +501,30 @@ theorem reindex_trans (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) : congr #align pi_tensor_product.reindex_trans PiTensorProduct.reindex_trans -@[simp] -theorem reindex_reindex (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) (x : ⨂[R] _, M) : - reindex R M e' (reindex R M e x) = reindex R M (e.trans e') x := - LinearEquiv.congr_fun (reindex_trans e e' : _ = reindex R M (e.trans e')) x +theorem reindex_reindex (e : ι ≃ ι₂) (e' : ι₂ ≃ ι₃) (x : ⨂[R] i, s i) : + reindex R _ e' (reindex R s e x) = reindex R s (e.trans e') x := + LinearEquiv.congr_fun (reindex_trans e e' : _ = reindex R s (e.trans e')) x #align pi_tensor_product.reindex_reindex PiTensorProduct.reindex_reindex +/-- This lemma is impractical to state in the dependent case. -/ @[simp] -theorem reindex_symm (e : ι ≃ ι₂) : (reindex R M e).symm = reindex R M e.symm := rfl +theorem reindex_symm (e : ι ≃ ι₂) : + (reindex R (fun _ ↦ M) e).symm = reindex R (fun _ ↦ M) e.symm := by + ext x + simp only [reindex, domDomCongrLinearEquiv', LinearEquiv.coe_symm_mk, LinearEquiv.coe_mk, + LinearEquiv.ofLinear_symm_apply, Equiv.symm_symm_apply, LinearEquiv.ofLinear_apply, + Equiv.piCongrLeft'_symm] #align pi_tensor_product.reindex_symm PiTensorProduct.reindex_symm @[simp] -theorem reindex_refl : reindex R M (Equiv.refl ι) = LinearEquiv.refl R _ := by +theorem reindex_refl : reindex R s (Equiv.refl ι) = LinearEquiv.refl R _ := by apply LinearEquiv.toLinearMap_injective ext - rw [reindex_comp_tprod, LinearEquiv.refl_toLinearMap, Equiv.refl_symm] - rfl + simp only [Equiv.refl_symm, Equiv.refl_apply, reindex, domDomCongrLinearEquiv', + LinearEquiv.coe_symm_mk, LinearMap.compMultilinearMap_apply, LinearEquiv.coe_coe, + LinearEquiv.refl_toLinearMap, LinearMap.id_coe, id_eq] + erw [lift.tprod] + congr #align pi_tensor_product.reindex_refl PiTensorProduct.reindex_refl variable (ι) @@ -530,7 +532,7 @@ variable (ι) attribute [local simp] eq_iff_true_of_subsingleton in /-- The tensor product over an empty index type `ι` is isomorphic to the base ring. -/ @[simps symm_apply] -def isEmptyEquiv [IsEmpty ι] : (⨂[R] _ : ι, M) ≃ₗ[R] R where +def isEmptyEquiv [IsEmpty ι] : (⨂[R] i : ι, s i) ≃ₗ[R] R where toFun := lift (constOfIsEmpty R _ 1) invFun r := r • tprod R (@isEmptyElim _ _ _) left_inv x := by @@ -551,7 +553,8 @@ def isEmptyEquiv [IsEmpty ι] : (⨂[R] _ : ι, M) ≃ₗ[R] R where #align pi_tensor_product.is_empty_equiv PiTensorProduct.isEmptyEquiv @[simp] -theorem isEmptyEquiv_apply_tprod [IsEmpty ι] (f : ι → M) : isEmptyEquiv ι (tprod R f) = 1 := +theorem isEmptyEquiv_apply_tprod [IsEmpty ι] (f : (i : ι) → s i) : + isEmptyEquiv ι (tprod R f) = 1 := lift.tprod _ #align pi_tensor_product.is_empty_equiv_apply_tprod PiTensorProduct.isEmptyEquiv_apply_tprod diff --git a/Mathlib/LinearAlgebra/Prod.lean b/Mathlib/LinearAlgebra/Prod.lean index 5749201ff8828..755767fb22164 100644 --- a/Mathlib/LinearAlgebra/Prod.lean +++ b/Mathlib/LinearAlgebra/Prod.lean @@ -449,7 +449,7 @@ theorem range_coprod (f : M →ₗ[R] M₃) (g : M₂ →ₗ[R] M₃) : range (f Submodule.ext fun x => by simp [mem_sup] #align linear_map.range_coprod LinearMap.range_coprod -theorem isCompl_range_inl_inr : IsCompl (range $ inl R M M₂) (range $ inr R M M₂) := by +theorem isCompl_range_inl_inr : IsCompl (range <| inl R M M₂) (range <| inr R M M₂) := by constructor · rw [disjoint_def] rintro ⟨_, _⟩ ⟨x, hx⟩ ⟨y, hy⟩ @@ -462,11 +462,11 @@ theorem isCompl_range_inl_inr : IsCompl (range $ inl R M M₂) (range $ inr R M simp #align linear_map.is_compl_range_inl_inr LinearMap.isCompl_range_inl_inr -theorem sup_range_inl_inr : (range $ inl R M M₂) ⊔ (range $ inr R M M₂) = ⊤ := +theorem sup_range_inl_inr : (range <| inl R M M₂) ⊔ (range <| inr R M M₂) = ⊤ := IsCompl.sup_eq_top isCompl_range_inl_inr #align linear_map.sup_range_inl_inr LinearMap.sup_range_inl_inr -theorem disjoint_inl_inr : Disjoint (range $ inl R M M₂) (range $ inr R M M₂) := by +theorem disjoint_inl_inr : Disjoint (range <| inl R M M₂) (range <| inr R M M₂) := by simp (config := { contextual := true }) [disjoint_def, @eq_comm M 0, @eq_comm M₂ 0] #align linear_map.disjoint_inl_inr LinearMap.disjoint_inl_inr @@ -976,7 +976,7 @@ theorem tailing_le_tunnel (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : #align linear_map.tailing_le_tunnel LinearMap.tailing_le_tunnel theorem tailing_disjoint_tunnel_succ (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : - Disjoint (tailing f i n) (OrderDual.ofDual $ tunnel f i (n + 1)) := by + Disjoint (tailing f i n) (OrderDual.ofDual <| tunnel f i (n + 1)) := by rw [disjoint_iff] dsimp [tailing, tunnel, tunnel'] erw [Submodule.map_inf_eq_map_inf_comap, @@ -985,8 +985,8 @@ theorem tailing_disjoint_tunnel_succ (f : M × N →ₗ[R] M) (i : Injective f) #align linear_map.tailing_disjoint_tunnel_succ LinearMap.tailing_disjoint_tunnel_succ theorem tailing_sup_tunnel_succ_le_tunnel (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : - tailing f i n ⊔ (OrderDual.ofDual $ tunnel f i (n + 1)) ≤ - (OrderDual.ofDual $ tunnel f i n) := by + tailing f i n ⊔ (OrderDual.ofDual <| tunnel f i (n + 1)) ≤ + (OrderDual.ofDual <| tunnel f i n) := by dsimp [tailing, tunnel, tunnel', tunnelAux] erw [← Submodule.map_sup, sup_comm, Submodule.fst_sup_snd, Submodule.map_comp, Submodule.map_comp] apply Submodule.map_subtype_le @@ -1008,7 +1008,7 @@ theorem tailings_succ (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : #align linear_map.tailings_succ LinearMap.tailings_succ theorem tailings_disjoint_tunnel (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : - Disjoint (tailings f i n) (OrderDual.ofDual $ tunnel f i (n + 1)) := by + Disjoint (tailings f i n) (OrderDual.ofDual <| tunnel f i (n + 1)) := by induction' n with n ih · simp only [tailings_zero] apply tailing_disjoint_tunnel_succ diff --git a/Mathlib/LinearAlgebra/Projection.lean b/Mathlib/LinearAlgebra/Projection.lean index 33e8c0740e4c6..19def9b09d3d2 100644 --- a/Mathlib/LinearAlgebra/Projection.lean +++ b/Mathlib/LinearAlgebra/Projection.lean @@ -373,7 +373,7 @@ of `E` to `p` and fixes every element of `p`. The definition allow more generally any `FunLike` type and not just linear maps, so that it can be used for example with `ContinuousLinearMap` or `Matrix`. -/ -structure IsProj {F : Type*} [FunLike F M fun _ => M] (f : F) : Prop where +structure IsProj {F : Type*} [FunLike F M M] (f : F) : Prop where map_mem : ∀ x, f x ∈ m map_id : ∀ x ∈ m, f x = x #align linear_map.is_proj LinearMap.IsProj diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean index 309f280cad304..e560b9de524be 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean @@ -147,25 +147,25 @@ structure QuadraticForm (R : Type u) (M : Type v) [CommSemiring R] [AddCommMonoi namespace QuadraticForm -section FunLike +section DFunLike variable [CommSemiring R] [AddCommMonoid M] [Module R M] variable {Q Q' : QuadraticForm R M} -instance funLike : FunLike (QuadraticForm R M) M fun _ => R where +instance instFunLike : FunLike (QuadraticForm R M) M R where coe := toFun coe_injective' x y h := by cases x; cases y; congr -#align quadratic_form.fun_like QuadraticForm.funLike +#align quadratic_form.fun_like QuadraticForm.instFunLike /-- Helper instance for when there's too many metavariables to apply -`FunLike.hasCoeToFun` directly. -/ +`DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (QuadraticForm R M) fun _ => M → R := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ variable (Q) -/-- The `simp` normal form for a quadratic form is `FunLike.coe`, not `toFun`. -/ +/-- The `simp` normal form for a quadratic form is `DFunLike.coe`, not `toFun`. -/ @[simp] theorem toFun_eq_coe : Q.toFun = ⇑Q := rfl @@ -178,15 +178,15 @@ variable {Q} @[ext] theorem ext (H : ∀ x : M, Q x = Q' x) : Q = Q' := - FunLike.ext _ _ H + DFunLike.ext _ _ H #align quadratic_form.ext QuadraticForm.ext theorem congr_fun (h : Q = Q') (x : M) : Q x = Q' x := - FunLike.congr_fun h _ + DFunLike.congr_fun h _ #align quadratic_form.congr_fun QuadraticForm.congr_fun theorem ext_iff : Q = Q' ↔ ∀ x, Q x = Q' x := - FunLike.ext_iff + DFunLike.ext_iff #align quadratic_form.ext_iff QuadraticForm.ext_iff /-- Copy of a `QuadraticForm` with a new `toFun` equal to the old one. Useful to fix definitional @@ -203,10 +203,10 @@ theorem coe_copy (Q : QuadraticForm R M) (Q' : M → R) (h : Q' = ⇑Q) : ⇑(Q. #align quadratic_form.coe_copy QuadraticForm.coe_copy theorem copy_eq (Q : QuadraticForm R M) (Q' : M → R) (h : Q' = ⇑Q) : Q.copy Q' h = Q := - FunLike.ext' h + DFunLike.ext' h #align quadratic_form.copy_eq QuadraticForm.copy_eq -end FunLike +end DFunLike section CommSemiring @@ -241,7 +241,7 @@ theorem map_zero : Q 0 = 0 := by #align quadratic_form.map_zero QuadraticForm.map_zero instance zeroHomClass : ZeroHomClass (QuadraticForm R M) M R := - { QuadraticForm.funLike with map_zero := map_zero } + { QuadraticForm.instFunLike with map_zero := map_zero } #align quadratic_form.zero_hom_class QuadraticForm.zeroHomClass theorem map_smul_of_tower [CommSemiring S] [Algebra S R] [Module S M] [IsScalarTower S R M] (a : S) @@ -447,14 +447,14 @@ theorem add_apply (Q Q' : QuadraticForm R M) (x : M) : (Q + Q') x = Q x + Q' x : #align quadratic_form.add_apply QuadraticForm.add_apply instance : AddCommMonoid (QuadraticForm R M) := - FunLike.coe_injective.addCommMonoid _ coeFn_zero coeFn_add fun _ _ => coeFn_smul _ _ + DFunLike.coe_injective.addCommMonoid _ coeFn_zero coeFn_add fun _ _ => coeFn_smul _ _ /-- `@CoeFn (QuadraticForm R M)` as an `AddMonoidHom`. This API mirrors `AddMonoidHom.coeFn`. -/ @[simps apply] def coeFnAddMonoidHom : QuadraticForm R M →+ M → R where - toFun := FunLike.coe + toFun := DFunLike.coe map_zero' := coeFn_zero map_add' := coeFn_add #align quadratic_form.coe_fn_add_monoid_hom QuadraticForm.coeFnAddMonoidHom @@ -538,7 +538,7 @@ theorem sub_apply (Q Q' : QuadraticForm R M) (x : M) : (Q - Q') x = Q x - Q' x : #align quadratic_form.sub_apply QuadraticForm.sub_apply instance : AddCommGroup (QuadraticForm R M) := - FunLike.coe_injective.addCommGroup _ coeFn_zero coeFn_add coeFn_neg coeFn_sub + DFunLike.coe_injective.addCommGroup _ coeFn_zero coeFn_add coeFn_neg coeFn_sub (fun _ _ => coeFn_smul _ _) fun _ _ => coeFn_smul _ _ end RingOperators @@ -770,7 +770,7 @@ theorem polarBilin_toQuadraticForm : polarBilin (toQuadraticForm B) = B + flip' theorem _root_.QuadraticForm.polarBilin_injective (h : IsUnit (2 : R)) : Function.Injective (polarBilin : QuadraticForm R M → _) := fun Q₁ Q₂ h₁₂ => QuadraticForm.ext fun x => h.mul_left_cancel <| by - simpa using FunLike.congr_fun (congr_arg toQuadraticForm h₁₂) x + simpa using DFunLike.congr_fun (congr_arg toQuadraticForm h₁₂) x variable {N : Type v} variable [CommRing S] [Algebra S R] [Module S M] [IsScalarTower S R M] @@ -817,7 +817,7 @@ def associatedHom : QuadraticForm R M →ₗ[S] BilinForm R M := (⟨⅟2, Set.invOf_mem_center (Set.ofNat_mem_center _ _)⟩ : Submonoid.center R) • { toFun := polarBilin map_add' := fun _x _y => BilinForm.ext <| polar_add _ _ - map_smul' := fun _c _x => BilinForm.ext <| polar_smul _ _ } + map_smul' := fun _c _x => BilinForm.ext <| polar_smul _ _ } #align quadratic_form.associated_hom QuadraticForm.associatedHom variable (Q : QuadraticForm R M) diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Dual.lean b/Mathlib/LinearAlgebra/QuadraticForm/Dual.lean index b64bc00aa7e9a..e33fe22142f55 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Dual.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Dual.lean @@ -113,7 +113,7 @@ variable {R M N} @[simps!] def dualProdIsometry (f : M ≃ₗ[R] N) : (dualProd R M).IsometryEquiv (dualProd R N) where toLinearEquiv := f.dualMap.symm.prod f - map_app' x := FunLike.congr_arg x.fst <| f.symm_apply_apply _ + map_app' x := DFunLike.congr_arg x.fst <| f.symm_apply_apply _ #align quadratic_form.dual_prod_isometry QuadraticForm.dualProdIsometry /-- `QuadraticForm.dualProd` commutes (isometrically) with `QuadraticForm.prod`. -/ @@ -124,7 +124,7 @@ def dualProdProdIsometry : (dualProd R (M × N)).IsometryEquiv ((dualProd R M).p (Module.dualProdDualEquivDual R M N).symm.prod (LinearEquiv.refl R (M × N)) ≪≫ₗ LinearEquiv.prodProdProdComm R _ _ M N map_app' m := - (m.fst.map_add _ _).symm.trans <| FunLike.congr_arg m.fst <| Prod.ext (add_zero _) (zero_add _) + (m.fst.map_add _ _).symm.trans <| DFunLike.congr_arg m.fst <| Prod.ext (add_zero _) (zero_add _) #align quadratic_form.dual_prod_prod_isometry QuadraticForm.dualProdProdIsometry end Semiring @@ -135,7 +135,7 @@ variable [CommRing R] [AddCommGroup M] [Module R M] variable {R M} -/-- The isometry sending `(Q.prod $ -Q)` to `(QuadraticForm.dualProd R M)`. +/-- The isometry sending `(Q.prod <| -Q)` to `(QuadraticForm.dualProd R M)`. This is `σ` from Proposition 4.8, page 84 of [*Hermitian K-Theory and Geometric Applications*][hyman1973]; though we swap the order of the pairs. diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Isometry.lean b/Mathlib/LinearAlgebra/QuadraticForm/Isometry.lean index ceda437bb1dde..50448c4b7eab8 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Isometry.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Isometry.lean @@ -42,17 +42,17 @@ variable {Q₃ : QuadraticForm R M₃} {Q₄ : QuadraticForm R M₄} instance instLinearMapClass : LinearMapClass (Q₁ →qᵢ Q₂) R M₁ M₂ where coe f := f.toLinearMap - coe_injective' f g h := by cases f; cases g; congr; exact FunLike.coe_injective h + coe_injective' f g h := by cases f; cases g; congr; exact DFunLike.coe_injective h map_add f := f.toLinearMap.map_add map_smulₛₗ f := f.toLinearMap.map_smul theorem toLinearMap_injective : Function.Injective (Isometry.toLinearMap : (Q₁ →qᵢ Q₂) → M₁ →ₗ[R] M₂) := fun _f _g h => - FunLike.coe_injective (congr_arg FunLike.coe h : _) + DFunLike.coe_injective (congr_arg DFunLike.coe h : _) @[ext] theorem ext ⦃f g : Q₁ →qᵢ Q₂⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h /-- See Note [custom simps projection]. -/ protected def Simps.apply (f : Q₁ →qᵢ Q₂) : M₁ → M₂ := f diff --git a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean index a82a1a4c39d7e..2b223d898d4cd 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.LinearAlgebra.QuadraticForm.IsometryEquiv -import Mathlib.Algebra.Category.AlgebraCat.Basic +import Mathlib.Algebra.Category.ModuleCat.Basic /-! # The category of quadratic modules @@ -80,7 +80,7 @@ instance concreteCategory : ConcreteCategory.{v} (QuadraticModuleCat.{v} R) wher { obj := fun M => M map := @fun M N f => f.toIsometry } forget_faithful := - { map_injective := @fun M N => FunLike.coe_injective.comp <| Hom.toIsometry_injective _ _ } + { map_injective := @fun M N => DFunLike.coe_injective.comp <| Hom.toIsometry_injective _ _ } instance hasForgetToModule : HasForget₂ (QuadraticModuleCat R) (ModuleCat R) where forget₂ := @@ -107,8 +107,8 @@ variable {Q₁ : QuadraticForm R X} {Q₂ : QuadraticForm R Y} {Q₃ : Quadratic def ofIso (e : Q₁.IsometryEquiv Q₂) : QuadraticModuleCat.of Q₁ ≅ QuadraticModuleCat.of Q₂ where hom := ⟨e.toIsometry⟩ inv := ⟨e.symm.toIsometry⟩ - hom_inv_id := Hom.ext _ _ <| FunLike.ext _ _ e.left_inv - inv_hom_id := Hom.ext _ _ <| FunLike.ext _ _ e.right_inv + hom_inv_id := Hom.ext _ _ <| DFunLike.ext _ _ e.left_inv + inv_hom_id := Hom.ext _ _ <| DFunLike.ext _ _ e.right_inv @[simp] theorem ofIso_refl : ofIso (IsometryEquiv.refl Q₁) = .refl _ := rfl diff --git a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat/Monoidal.lean b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat/Monoidal.lean index a064029c7d484..64362a66e5e54 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat/Monoidal.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat/Monoidal.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.CategoryTheory.Monoidal.Braided import Mathlib.CategoryTheory.Monoidal.Transport import Mathlib.Algebra.Category.ModuleCat.Monoidal.Basic import Mathlib.LinearAlgebra.QuadraticForm.QuadraticModuleCat diff --git a/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct/Isometries.lean b/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct/Isometries.lean index 5fdc6d254064e..ad6c8f9c55282 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct/Isometries.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct/Isometries.lean @@ -51,7 +51,7 @@ theorem tmul_tensorMap_apply {Q₃ : QuadraticForm R M₃} {Q₄ : QuadraticForm R M₄} (f : Q₁ →qᵢ Q₂) (g : Q₃ →qᵢ Q₄) (x : M₁ ⊗[R] M₃) : Q₂.tmul Q₄ (TensorProduct.map f.toLinearMap g.toLinearMap x) = Q₁.tmul Q₃ x := - FunLike.congr_fun (tmul_comp_tensorMap f g) x + DFunLike.congr_fun (tmul_comp_tensorMap f g) x namespace Isometry @@ -89,7 +89,7 @@ theorem tmul_comp_tensorComm (Q₁ : QuadraticForm R M₁) (Q₂ : QuadraticForm theorem tmul_tensorComm_apply (Q₁ : QuadraticForm R M₁) (Q₂ : QuadraticForm R M₂) (x : M₁ ⊗[R] M₂) : Q₂.tmul Q₁ (TensorProduct.comm R M₁ M₂ x) = Q₁.tmul Q₂ x := - FunLike.congr_fun (tmul_comp_tensorComm Q₁ Q₂) x + DFunLike.congr_fun (tmul_comp_tensorComm Q₁ Q₂) x /-- `TensorProduct.comm` preserves tensor products of quadratic forms. -/ @[simps toLinearEquiv] @@ -127,7 +127,7 @@ theorem tmul_tensorAssoc_apply (Q₁ : QuadraticForm R M₁) (Q₂ : QuadraticForm R M₂) (Q₃ : QuadraticForm R M₃) (x : (M₁ ⊗[R] M₂) ⊗[R] M₃): Q₁.tmul (Q₂.tmul Q₃) (TensorProduct.assoc R M₁ M₂ M₃ x) = (Q₁.tmul Q₂).tmul Q₃ x := - FunLike.congr_fun (tmul_comp_tensorAssoc Q₁ Q₂ Q₃) x + DFunLike.congr_fun (tmul_comp_tensorAssoc Q₁ Q₂ Q₃) x /-- `TensorProduct.assoc` preserves tensor products of quadratic forms. -/ @[simps toLinearEquiv] @@ -165,7 +165,7 @@ theorem comp_tensorRId_eq (Q₁ : QuadraticForm R M₁) : theorem tmul_tensorRId_apply (Q₁ : QuadraticForm R M₁) (x : M₁ ⊗[R] R) : Q₁ (TensorProduct.rid R M₁ x) = Q₁.tmul (sq (R := R)) x := - FunLike.congr_fun (comp_tensorRId_eq Q₁) x + DFunLike.congr_fun (comp_tensorRId_eq Q₁) x /-- `TensorProduct.rid` preserves tensor products of quadratic forms. -/ @[simps toLinearEquiv] @@ -199,7 +199,7 @@ theorem comp_tensorLId_eq (Q₂ : QuadraticForm R M₂) : theorem tmul_tensorLId_apply (Q₂ : QuadraticForm R M₂) (x : R ⊗[R] M₂) : Q₂ (TensorProduct.lid R M₂ x) = (sq (R := R)).tmul Q₂ x := - FunLike.congr_fun (comp_tensorLId_eq Q₂) x + DFunLike.congr_fun (comp_tensorLId_eq Q₂) x /-- `TensorProduct.lid` preserves tensor products of quadratic forms. -/ @[simps toLinearEquiv] diff --git a/Mathlib/LinearAlgebra/Ray.lean b/Mathlib/LinearAlgebra/Ray.lean index 9b2fff056906a..e8017fd3a89bc 100644 --- a/Mathlib/LinearAlgebra/Ray.lean +++ b/Mathlib/LinearAlgebra/Ray.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Joseph Myers. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Myers -/ +import Mathlib.Algebra.Order.Module.Algebra import Mathlib.GroupTheory.Subgroup.Actions import Mathlib.LinearAlgebra.LinearIndependent @@ -114,47 +115,50 @@ theorem trans (hxy : SameRay R x y) (hyz : SameRay R y z) (hy : y = 0 → x = 0 rw [mul_smul, mul_smul, h₁, ← h₂, smul_comm] #align same_ray.trans SameRay.trans +variable {S : Type*} [OrderedCommSemiring S] [Algebra S R] [Module S M] [SMulPosMono S R] + [IsScalarTower S R M] {a : S} + /-- A vector is in the same ray as a nonnegative multiple of itself. -/ -theorem sameRay_nonneg_smul_right (v : M) {r : R} (h : 0 ≤ r) : SameRay R v (r • v) := - Or.inr <| - h.eq_or_lt.imp (fun (h : 0 = r) => h ▸ zero_smul R v) fun h => - ⟨r, 1, h, by - nontriviality R - exact zero_lt_one, (one_smul _ _).symm⟩ +lemma sameRay_nonneg_smul_right (v : M) (h : 0 ≤ a) : SameRay R v (a • v) := by + obtain h | h := (algebraMap_nonneg R h).eq_or_gt + · rw [← algebraMap_smul R a v, h, zero_smul] + exact zero_right _ + · refine Or.inr $ Or.inr ⟨algebraMap S R a, 1, h, by nontriviality R; exact zero_lt_one, ?_⟩ + rw [algebraMap_smul, one_smul] #align same_ray_nonneg_smul_right SameRay.sameRay_nonneg_smul_right -/-- A vector is in the same ray as a positive multiple of itself. -/ -theorem sameRay_pos_smul_right (v : M) {r : R} (h : 0 < r) : SameRay R v (r • v) := - sameRay_nonneg_smul_right v h.le -#align same_ray_pos_smul_right SameRay.sameRay_pos_smul_right - -/-- A vector is in the same ray as a nonnegative multiple of one it is in the same ray as. -/ -theorem nonneg_smul_right {r : R} (h : SameRay R x y) (hr : 0 ≤ r) : SameRay R x (r • y) := - h.trans (sameRay_nonneg_smul_right y hr) fun hy => Or.inr <| by rw [hy, smul_zero] -#align same_ray.nonneg_smul_right SameRay.nonneg_smul_right - -/-- A vector is in the same ray as a positive multiple of one it is in the same ray as. -/ -theorem pos_smul_right {r : R} (h : SameRay R x y) (hr : 0 < r) : SameRay R x (r • y) := - h.nonneg_smul_right hr.le -#align same_ray.pos_smul_right SameRay.pos_smul_right - /-- A nonnegative multiple of a vector is in the same ray as that vector. -/ -theorem sameRay_nonneg_smul_left (v : M) {r : R} (h : 0 ≤ r) : SameRay R (r • v) v := - (sameRay_nonneg_smul_right v h).symm +lemma sameRay_nonneg_smul_left (v : M) (ha : 0 ≤ a) : SameRay R (a • v) v := + (sameRay_nonneg_smul_right v ha).symm #align same_ray_nonneg_smul_left SameRay.sameRay_nonneg_smul_left +/-- A vector is in the same ray as a positive multiple of itself. -/ +lemma sameRay_pos_smul_right (v : M) (ha : 0 < a) : SameRay R v (a • v) := + sameRay_nonneg_smul_right v ha.le +#align same_ray_pos_smul_right SameRay.sameRay_pos_smul_right + /-- A positive multiple of a vector is in the same ray as that vector. -/ -theorem sameRay_pos_smul_left (v : M) {r : R} (h : 0 < r) : SameRay R (r • v) v := - sameRay_nonneg_smul_left v h.le +lemma sameRay_pos_smul_left (v : M) (ha : 0 < a) : SameRay R (a • v) v := + sameRay_nonneg_smul_left v ha.le #align same_ray_pos_smul_left SameRay.sameRay_pos_smul_left +/-- A vector is in the same ray as a nonnegative multiple of one it is in the same ray as. -/ +lemma nonneg_smul_right (h : SameRay R x y) (ha : 0 ≤ a) : SameRay R x (a • y) := + h.trans (sameRay_nonneg_smul_right y ha) fun hy => Or.inr <| by rw [hy, smul_zero] +#align same_ray.nonneg_smul_right SameRay.nonneg_smul_right + /-- A nonnegative multiple of a vector is in the same ray as one it is in the same ray as. -/ -theorem nonneg_smul_left {r : R} (h : SameRay R x y) (hr : 0 ≤ r) : SameRay R (r • x) y := - (h.symm.nonneg_smul_right hr).symm +lemma nonneg_smul_left (h : SameRay R x y) (ha : 0 ≤ a) : SameRay R (a • x) y := + (h.symm.nonneg_smul_right ha).symm #align same_ray.nonneg_smul_left SameRay.nonneg_smul_left +/-- A vector is in the same ray as a positive multiple of one it is in the same ray as. -/ +theorem pos_smul_right (h : SameRay R x y) (ha : 0 < a) : SameRay R x (a • y) := + h.nonneg_smul_right ha.le +#align same_ray.pos_smul_right SameRay.pos_smul_right + /-- A positive multiple of a vector is in the same ray as one it is in the same ray as. -/ -theorem pos_smul_left {r : R} (h : SameRay R x y) (hr : 0 < r) : SameRay R (r • x) y := +theorem pos_smul_left (h : SameRay R x y) (hr : 0 < a) : SameRay R (a • x) y := h.nonneg_smul_left hr.le #align same_ray.pos_smul_left SameRay.pos_smul_left diff --git a/Mathlib/LinearAlgebra/SesquilinearForm.lean b/Mathlib/LinearAlgebra/SesquilinearForm.lean index 3e74b461f877e..79ab35b2c51a9 100644 --- a/Mathlib/LinearAlgebra/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/SesquilinearForm.lean @@ -4,20 +4,19 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andreas Swerdlow -/ import Mathlib.Algebra.Module.LinearMap -import Mathlib.LinearAlgebra.Basis.Bilinear import Mathlib.LinearAlgebra.BilinearMap import Mathlib.Algebra.EuclideanDomain.Instances -import Mathlib.Algebra.GroupWithZero.NonZeroDivisors +import Mathlib.LinearAlgebra.Basis #align_import linear_algebra.sesquilinear_form from "leanprover-community/mathlib"@"87c54600fe3cdc7d32ff5b50873ac724d86aef8d" /-! -# Sesquilinear form +# Sesquilinear maps -This files provides properties about sesquilinear forms. The maps considered are of the form -`M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R`, where `I₁ : R₁ →+* R` and `I₂ : R₂ →+* R` are ring homomorphisms and -`M₁` is a module over `R₁` and `M₂` is a module over `R₂`. -Sesquilinear forms are the special case that `M₁ = M₂`, `R₁ = R₂ = R`, and `I₁ = RingHom.id R`. +This files provides properties about sesquilinear maps and forms. The maps considered are of the +form `M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M`, where `I₁ : R₁ →+* R` and `I₂ : R₂ →+* R` are ring homomorphisms and +`M₁` is a module over `R₁`, `M₂` is a module over `R₂` and `M` is a module over `R`. +Sesquilinear forms are the special case that `M₁ = M₂`, `M = R₁ = R₂ = R`, and `I₁ = RingHom.id R`. Taking additionally `I₂ = RingHom.id R`, then one obtains bilinear forms. These forms are a special case of the bilinear maps defined in `BilinearMap.lean` and all basic @@ -25,7 +24,7 @@ lemmas about construction and elementary calculations are found there. ## Main declarations -* `IsOrtho`: states that two vectors are orthogonal with respect to a sesquilinear form +* `IsOrtho`: states that two vectors are orthogonal with respect to a sesquilinear map * `IsSymm`, `IsAlt`: states that a sesquilinear form is symmetric and alternating, respectively * `orthogonalBilin`: provides the orthogonal complement with respect to sesquilinear form @@ -35,13 +34,13 @@ lemmas about construction and elementary calculations are found there. ## Tags -Sesquilinear form, +Sesquilinear form, Sesquilinear map, -/ open BigOperators -variable {R R₁ R₂ R₃ M M₁ M₂ Mₗ₁ Mₗ₁' Mₗ₂ Mₗ₂' K K₁ K₂ V V₁ V₂ n : Type*} +variable {R R₁ R₂ R₃ M M₁ M₂ M₃ Mₗ₁ Mₗ₁' Mₗ₂ Mₗ₂' K K₁ K₂ V V₁ V₂ n : Type*} namespace LinearMap @@ -52,45 +51,46 @@ section CommRing -- the `ₗ` subscript variables are for special cases about linear (as opposed to semilinear) maps variable [CommSemiring R] [CommSemiring R₁] [AddCommMonoid M₁] [Module R₁ M₁] [CommSemiring R₂] - [AddCommMonoid M₂] [Module R₂ M₂] {I₁ : R₁ →+* R} {I₂ : R₂ →+* R} {I₁' : R₁ →+* R} + [AddCommMonoid M₂] [Module R₂ M₂] [AddCommMonoid M] [Module R M] + {I₁ : R₁ →+* R} {I₂ : R₂ →+* R} {I₁' : R₁ →+* R} -/-- The proposition that two elements of a sesquilinear form space are orthogonal -/ -def IsOrtho (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R) (x : M₁) (y : M₂) : Prop := +/-- The proposition that two elements of a sesquilinear map space are orthogonal -/ +def IsOrtho (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M) (x : M₁) (y : M₂) : Prop := B x y = 0 #align linear_map.is_ortho LinearMap.IsOrtho -theorem isOrtho_def {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} {x y} : B.IsOrtho x y ↔ B x y = 0 := +theorem isOrtho_def {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} {x y} : B.IsOrtho x y ↔ B x y = 0 := Iff.rfl #align linear_map.is_ortho_def LinearMap.isOrtho_def -theorem isOrtho_zero_left (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R) (x) : IsOrtho B (0 : M₁) x := by +theorem isOrtho_zero_left (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M) (x) : IsOrtho B (0 : M₁) x := by dsimp only [IsOrtho] rw [map_zero B, zero_apply] #align linear_map.is_ortho_zero_left LinearMap.isOrtho_zero_left -theorem isOrtho_zero_right (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R) (x) : IsOrtho B x (0 : M₂) := +theorem isOrtho_zero_right (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M) (x) : IsOrtho B x (0 : M₂) := map_zero (B x) #align linear_map.is_ortho_zero_right LinearMap.isOrtho_zero_right -theorem isOrtho_flip {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] R} {x y} : B.IsOrtho x y ↔ B.flip.IsOrtho y x := by +theorem isOrtho_flip {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] M} {x y} : B.IsOrtho x y ↔ B.flip.IsOrtho y x := by simp_rw [isOrtho_def, flip_apply] #align linear_map.is_ortho_flip LinearMap.isOrtho_flip -/-- A set of vectors `v` is orthogonal with respect to some bilinear form `B` if and only +/-- A set of vectors `v` is orthogonal with respect to some bilinear map `B` if and only if for all `i ≠ j`, `B (v i) (v j) = 0`. For orthogonality between two elements, use `BilinForm.isOrtho` -/ -def IsOrthoᵢ (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] R) (v : n → M₁) : Prop := +def IsOrthoᵢ (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] M) (v : n → M₁) : Prop := Pairwise (B.IsOrtho on v) set_option linter.uppercaseLean3 false in #align linear_map.is_Ortho LinearMap.IsOrthoᵢ -theorem isOrthoᵢ_def {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] R} {v : n → M₁} : +theorem isOrthoᵢ_def {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] M} {v : n → M₁} : B.IsOrthoᵢ v ↔ ∀ i j : n, i ≠ j → B (v i) (v j) = 0 := Iff.rfl set_option linter.uppercaseLean3 false in #align linear_map.is_Ortho_def LinearMap.isOrthoᵢ_def -theorem isOrthoᵢ_flip (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] R) {v : n → M₁} : +theorem isOrthoᵢ_flip (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] M) {v : n → M₁} : B.IsOrthoᵢ v ↔ B.flip.IsOrthoᵢ v := by simp_rw [isOrthoᵢ_def] constructor <;> intro h i j hij @@ -105,11 +105,12 @@ end CommRing section Field -variable [Field K] [Field K₁] [AddCommGroup V₁] [Module K₁ V₁] [Field K₂] [AddCommGroup V₂] - [Module K₂ V₂] {I₁ : K₁ →+* K} {I₂ : K₂ →+* K} {I₁' : K₁ →+* K} {J₁ : K →+* K} {J₂ : K →+* K} +variable [Field K] [AddCommGroup V] [Module K V] [Field K₁] [AddCommGroup V₁] [Module K₁ V₁] + [Field K₂] [AddCommGroup V₂] [Module K₂ V₂] + {I₁ : K₁ →+* K} {I₂ : K₂ →+* K} {I₁' : K₁ →+* K} {J₁ : K →+* K} {J₂ : K →+* K} -- todo: this also holds for [CommRing R] [IsDomain R] when J₁ is invertible -theorem ortho_smul_left {B : V₁ →ₛₗ[I₁] V₂ →ₛₗ[I₂] K} {x y} {a : K₁} (ha : a ≠ 0) : +theorem ortho_smul_left {B : V₁ →ₛₗ[I₁] V₂ →ₛₗ[I₂] V} {x y} {a : K₁} (ha : a ≠ 0) : IsOrtho B x y ↔ IsOrtho B (a • x) y := by dsimp only [IsOrtho] constructor <;> intro H @@ -122,7 +123,7 @@ theorem ortho_smul_left {B : V₁ →ₛₗ[I₁] V₂ →ₛₗ[I₂] K} {x y} #align linear_map.ortho_smul_left LinearMap.ortho_smul_left -- todo: this also holds for [CommRing R] [IsDomain R] when J₂ is invertible -theorem ortho_smul_right {B : V₁ →ₛₗ[I₁] V₂ →ₛₗ[I₂] K} {x y} {a : K₂} {ha : a ≠ 0} : +theorem ortho_smul_right {B : V₁ →ₛₗ[I₁] V₂ →ₛₗ[I₂] V} {x y} {a : K₂} {ha : a ≠ 0} : IsOrtho B x y ↔ IsOrtho B x (a • y) := by dsimp only [IsOrtho] constructor <;> intro H @@ -135,36 +136,36 @@ theorem ortho_smul_right {B : V₁ →ₛₗ[I₁] V₂ →ₛₗ[I₂] K} {x y} · exact H #align linear_map.ortho_smul_right LinearMap.ortho_smul_right -/-- A set of orthogonal vectors `v` with respect to some sesquilinear form `B` is linearly +/-- A set of orthogonal vectors `v` with respect to some sesquilinear map `B` is linearly independent if for all `i`, `B (v i) (v i) ≠ 0`. -/ -theorem linearIndependent_of_isOrthoᵢ {B : V₁ →ₛₗ[I₁] V₁ →ₛₗ[I₁'] K} {v : n → V₁} +theorem linearIndependent_of_isOrthoᵢ {B : V₁ →ₛₗ[I₁] V₁ →ₛₗ[I₁'] V} {v : n → V₁} (hv₁ : B.IsOrthoᵢ v) (hv₂ : ∀ i, ¬B.IsOrtho (v i) (v i)) : LinearIndependent K₁ v := by classical rw [linearIndependent_iff'] intro s w hs i hi have : B (s.sum fun i : n ↦ w i • v i) (v i) = 0 := by rw [hs, map_zero, zero_apply] - have hsum : (s.sum fun j : n ↦ I₁ (w j) * B (v j) (v i)) = I₁ (w i) * B (v i) (v i) := by + have hsum : (s.sum fun j : n ↦ I₁ (w j) • B (v j) (v i)) = I₁ (w i) • B (v i) (v i) := by apply Finset.sum_eq_single_of_mem i hi intro j _hj hij - rw [isOrthoᵢ_def.1 hv₁ _ _ hij, mul_zero] - simp_rw [B.map_sum₂, map_smulₛₗ₂, smul_eq_mul, hsum] at this + rw [isOrthoᵢ_def.1 hv₁ _ _ hij, smul_zero] + simp_rw [B.map_sum₂, map_smulₛₗ₂, hsum] at this apply (map_eq_zero I₁).mp - exact eq_zero_of_ne_zero_of_mul_right_eq_zero (hv₂ i) this + exact (smul_eq_zero.mp this).elim _root_.id (hv₂ i · |>.elim) set_option linter.uppercaseLean3 false in #align linear_map.linear_independent_of_is_Ortho LinearMap.linearIndependent_of_isOrthoᵢ end Field -/-! ### Reflexive bilinear forms -/ +/-! ### Reflexive bilinear maps -/ section Reflexive -variable [CommSemiring R] [CommSemiring R₁] [AddCommMonoid M₁] [Module R₁ M₁] {I₁ : R₁ →+* R} - {I₂ : R₁ →+* R} {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] R} +variable [CommSemiring R] [AddCommMonoid M] [Module R M] [CommSemiring R₁] [AddCommMonoid M₁] + [Module R₁ M₁] {I₁ : R₁ →+* R} {I₂ : R₁ →+* R} {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] M} -/-- The proposition that a sesquilinear form is reflexive -/ -def IsRefl (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] R) : Prop := +/-- The proposition that a sesquilinear map is reflexive -/ +def IsRefl (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] M) : Prop := ∀ x y, B x y = 0 → B y x = 0 #align linear_map.is_refl LinearMap.IsRefl @@ -251,16 +252,16 @@ theorem isSymm_iff_eq_flip {B : M →ₗ[R] M →ₗ[R] R} : B.IsSymm ↔ B = B. end Symmetric -/-! ### Alternating bilinear forms -/ +/-! ### Alternating bilinear maps -/ section Alternating -variable [CommRing R] [CommSemiring R₁] [AddCommMonoid M₁] [Module R₁ M₁] {I₁ : R₁ →+* R} - {I₂ : R₁ →+* R} {I : R₁ →+* R} {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] R} +variable [CommRing R] [AddCommGroup M] [Module R M] [CommSemiring R₁] [AddCommMonoid M₁] + [Module R₁ M₁] {I₁ : R₁ →+* R} {I₂ : R₁ →+* R} {I : R₁ →+* R} {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] M} -/-- The proposition that a sesquilinear form is alternating -/ -def IsAlt (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] R) : Prop := +/-- The proposition that a sesquilinear map is alternating -/ +def IsAlt (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] M) : Prop := ∀ x, B x x = 0 #align linear_map.is_alt LinearMap.IsAlt @@ -311,17 +312,17 @@ namespace Submodule /-! ### The orthogonal complement -/ -variable [CommRing R] [CommRing R₁] [AddCommGroup M₁] [Module R₁ M₁] {I₁ : R₁ →+* R} {I₂ : R₁ →+* R} - {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] R} +variable [CommRing R] [CommRing R₁] [AddCommGroup M₁] [Module R₁ M₁] [AddCommGroup M] [Module R M] + {I₁ : R₁ →+* R} {I₂ : R₁ →+* R} {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] M} -/-- The orthogonal complement of a submodule `N` with respect to some bilinear form is the set of +/-- The orthogonal complement of a submodule `N` with respect to some bilinear map is the set of elements `x` which are orthogonal to all elements of `N`; i.e., for all `y` in `N`, `B x y = 0`. -Note that for general (neither symmetric nor antisymmetric) bilinear forms this definition has a +Note that for general (neither symmetric nor antisymmetric) bilinear maps this definition has a chirality; in addition to this "left" orthogonal complement one could define a "right" orthogonal complement for which, for all `y` in `N`, `B y x = 0`. This variant definition is not currently provided in mathlib. -/ -def orthogonalBilin (N : Submodule R₁ M₁) (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] R) : Submodule R₁ M₁ +def orthogonalBilin (N : Submodule R₁ M₁) (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₂] M) : Submodule R₁ M₁ where carrier := { m | ∀ n ∈ N, B.IsOrtho n m } zero_mem' x _ := B.isOrtho_zero_right x @@ -354,10 +355,10 @@ namespace LinearMap section Orthogonal variable [Field K] [AddCommGroup V] [Module K V] [Field K₁] [AddCommGroup V₁] [Module K₁ V₁] - {J : K →+* K} {J₁ : K₁ →+* K} {J₁' : K₁ →+* K} + [AddCommGroup V₂] [Module K V₂] {J : K →+* K} {J₁ : K₁ →+* K} {J₁' : K₁ →+* K} -- ↓ This lemma only applies in fields as we require `a * b = 0 → a = 0 ∨ b = 0` -theorem span_singleton_inf_orthogonal_eq_bot (B : V₁ →ₛₗ[J₁] V₁ →ₛₗ[J₁'] K) (x : V₁) +theorem span_singleton_inf_orthogonal_eq_bot (B : V₁ →ₛₗ[J₁] V₁ →ₛₗ[J₁'] V₂) (x : V₁) (hx : ¬B.IsOrtho x x) : (K₁ ∙ x) ⊓ Submodule.orthogonalBilin (K₁ ∙ x) B = ⊥ := by rw [← Finset.coe_singleton] refine' eq_bot_iff.2 fun y h ↦ _ @@ -366,14 +367,14 @@ theorem span_singleton_inf_orthogonal_eq_bot (B : V₁ →ₛₗ[J₁] V₁ → rw [Finset.sum_singleton] at h ⊢ suffices hμzero : μ x = 0 · rw [hμzero, zero_smul, Submodule.mem_bot] - rw [isOrtho_def, map_smulₛₗ, smul_eq_mul] at h - exact Or.elim (zero_eq_mul.mp h.symm) + rw [isOrtho_def, map_smulₛₗ] at h + exact Or.elim (smul_eq_zero.mp h) (fun y ↦ by simpa using y) - (fun hfalse ↦ False.elim $ hx hfalse) + (fun hfalse ↦ False.elim <| hx hfalse) #align linear_map.span_singleton_inf_orthogonal_eq_bot LinearMap.span_singleton_inf_orthogonal_eq_bot -- ↓ This lemma only applies in fields since we use the `mul_eq_zero` -theorem orthogonal_span_singleton_eq_to_lin_ker {B : V →ₗ[K] V →ₛₗ[J] K} (x : V) : +theorem orthogonal_span_singleton_eq_to_lin_ker {B : V →ₗ[K] V →ₛₗ[J] V₂} (x : V) : Submodule.orthogonalBilin (K ∙ x) B = LinearMap.ker (B x) := by ext y simp_rw [Submodule.mem_orthogonalBilin_iff, LinearMap.mem_ker, Submodule.mem_span_singleton] @@ -386,7 +387,7 @@ theorem orthogonal_span_singleton_eq_to_lin_ker {B : V →ₗ[K] V →ₛₗ[J] -- todo: Generalize this to sesquilinear maps theorem span_singleton_sup_orthogonal_eq_top {B : V →ₗ[K] V →ₗ[K] K} {x : V} (hx : ¬B.IsOrtho x x) : - (K ∙ x) ⊔ @Submodule.orthogonalBilin _ _ _ _ _ _ (_) _ _ (K ∙ x) B = ⊤ := by + (K ∙ x) ⊔ Submodule.orthogonalBilin (N := K ∙ x) (B := B) = ⊤ := by rw [orthogonal_span_singleton_eq_to_lin_ker] exact (B x).span_singleton_sup_ker_eq_top hx #align linear_map.span_singleton_sup_orthogonal_eq_top LinearMap.span_singleton_sup_orthogonal_eq_top @@ -395,7 +396,7 @@ theorem span_singleton_sup_orthogonal_eq_top {B : V →ₗ[K] V →ₗ[K] K} {x /-- Given a bilinear form `B` and some `x` such that `B x x ≠ 0`, the span of the singleton of `x` is complement to its orthogonal complement. -/ theorem isCompl_span_singleton_orthogonal {B : V →ₗ[K] V →ₗ[K] K} {x : V} (hx : ¬B.IsOrtho x x) : - IsCompl (K ∙ x) (@Submodule.orthogonalBilin _ _ _ _ _ _ (_) _ _ (K ∙ x) B) := + IsCompl (K ∙ x) (Submodule.orthogonalBilin (N := K ∙ x) (B := B)) := { disjoint := disjoint_iff.2 <| span_singleton_inf_orthogonal_eq_bot B x hx codisjoint := codisjoint_iff.2 <| span_singleton_sup_orthogonal_eq_top hx } #align linear_map.is_compl_span_singleton_orthogonal LinearMap.isCompl_span_singleton_orthogonal @@ -417,15 +418,17 @@ variable [AddCommMonoid M₁] [Module R M₁] variable [AddCommMonoid M₂] [Module R M₂] +variable [AddCommMonoid M₃] [Module R M₃] + variable {I : R →+* R} -variable {B F : M →ₗ[R] M →ₛₗ[I] R} {B' : M₁ →ₗ[R] M₁ →ₛₗ[I] R} {B'' : M₂ →ₗ[R] M₂ →ₛₗ[I] R} +variable {B F : M →ₗ[R] M →ₛₗ[I] M₃} {B' : M₁ →ₗ[R] M₁ →ₛₗ[I] M₃} {B'' : M₂ →ₗ[R] M₂ →ₛₗ[I] M₃} variable {f f' : M →ₗ[R] M₁} {g g' : M₁ →ₗ[R] M} variable (B B' f g) -/-- Given a pair of modules equipped with bilinear forms, this is the condition for a pair of +/-- Given a pair of modules equipped with bilinear maps, this is the condition for a pair of maps between them to be mutually adjoint. -/ def IsAdjointPair := ∀ x y, B' (f x) y = B x (g y) @@ -473,7 +476,9 @@ variable [AddCommGroup M] [Module R M] variable [AddCommGroup M₁] [Module R M₁] -variable {B F : M →ₗ[R] M →ₗ[R] R} {B' : M₁ →ₗ[R] M₁ →ₗ[R] R} +variable [AddCommGroup M₂] [Module R M₂] + +variable {B F : M →ₗ[R] M →ₗ[R] M₂} {B' : M₁ →ₗ[R] M₁ →ₗ[R] M₂} variable {f f' : M →ₗ[R] M₁} {g g' : M₁ →ₗ[R] M} @@ -502,19 +507,21 @@ variable [CommSemiring R] variable [AddCommMonoid M] [Module R M] +variable [AddCommMonoid M₁] [Module R M₁] + variable {I : R →+* R} -variable (B F : M →ₗ[R] M →ₛₗ[I] R) +variable (B F : M →ₗ[R] M →ₛₗ[I] M₁) -/-- The condition for an endomorphism to be "self-adjoint" with respect to a pair of bilinear forms -on the underlying module. In the case that these two forms are identical, this is the usual concept -of self adjointness. In the case that one of the forms is the negation of the other, this is the +/-- The condition for an endomorphism to be "self-adjoint" with respect to a pair of bilinear maps +on the underlying module. In the case that these two maps are identical, this is the usual concept +of self adjointness. In the case that one of the maps is the negation of the other, this is the usual concept of skew adjointness. -/ def IsPairSelfAdjoint (f : Module.End R M) := IsAdjointPair B F f f #align linear_map.is_pair_self_adjoint LinearMap.IsPairSelfAdjoint -/-- An endomorphism of a module is self-adjoint with respect to a bilinear form if it serves as an +/-- An endomorphism of a module is self-adjoint with respect to a bilinear map if it serves as an adjoint for itself. -/ protected def IsSelfAdjoint (f : Module.End R M) := IsAdjointPair B B f f @@ -526,9 +533,9 @@ section AddCommGroup variable [CommRing R] -variable [AddCommGroup M] [Module R M] +variable [AddCommGroup M] [Module R M] [AddCommGroup M₁] [Module R M₁] -variable [AddCommGroup M₁] [Module R M₁] (B F : M →ₗ[R] M →ₗ[R] R) +variable [AddCommGroup M₂] [Module R M₂] (B F : M →ₗ[R] M →ₗ[R] M₂) /-- The set of pair-self-adjoint endomorphisms are a submodule of the type of all endomorphisms. -/ def isPairSelfAdjointSubmodule : Submodule R (Module.End R M) where @@ -538,19 +545,19 @@ def isPairSelfAdjointSubmodule : Submodule R (Module.End R M) where smul_mem' c _ h := h.smul c #align linear_map.is_pair_self_adjoint_submodule LinearMap.isPairSelfAdjointSubmodule -/-- An endomorphism of a module is skew-adjoint with respect to a bilinear form if its negation +/-- An endomorphism of a module is skew-adjoint with respect to a bilinear map if its negation serves as an adjoint. -/ def IsSkewAdjoint (f : Module.End R M) := IsAdjointPair B B f (-f) #align linear_map.is_skew_adjoint LinearMap.IsSkewAdjoint -/-- The set of self-adjoint endomorphisms of a module with bilinear form is a submodule. (In fact +/-- The set of self-adjoint endomorphisms of a module with bilinear map is a submodule. (In fact it is a Jordan subalgebra.) -/ def selfAdjointSubmodule := isPairSelfAdjointSubmodule B B #align linear_map.self_adjoint_submodule LinearMap.selfAdjointSubmodule -/-- The set of skew-adjoint endomorphisms of a module with bilinear form is a submodule. (In fact +/-- The set of skew-adjoint endomorphisms of a module with bilinear map is a submodule. (In fact it is a Lie subalgebra.) -/ def skewAdjointSubmodule := isPairSelfAdjointSubmodule (-B) B @@ -605,47 +612,49 @@ end AddCommGroup end SelfadjointPair -/-! ### Nondegenerate bilinear forms -/ +/-! ### Nondegenerate bilinear maps -/ section Nondegenerate section CommSemiring -variable [CommSemiring R] [CommSemiring R₁] [AddCommMonoid M₁] [Module R₁ M₁] [CommSemiring R₂] - [AddCommMonoid M₂] [Module R₂ M₂] {I₁ : R₁ →+* R} {I₂ : R₂ →+* R} {I₁' : R₁ →+* R} +variable [CommSemiring R] [AddCommMonoid M] [Module R M] [CommSemiring R₁] [AddCommMonoid M₁] + [Module R₁ M₁] [CommSemiring R₂] [AddCommMonoid M₂] [Module R₂ M₂] + {I₁ : R₁ →+* R} {I₂ : R₂ →+* R} {I₁' : R₁ →+* R} -/-- A bilinear form is called left-separating if +/-- A bilinear map is called left-separating if the only element that is left-orthogonal to every other element is `0`; i.e., for every nonzero `x` in `M₁`, there exists `y` in `M₂` with `B x y ≠ 0`.-/ -def SeparatingLeft (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R) : Prop := +def SeparatingLeft (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M) : Prop := ∀ x : M₁, (∀ y : M₂, B x y = 0) → x = 0 #align linear_map.separating_left LinearMap.SeparatingLeft variable (M₁ M₂ I₁ I₂) /-- In a non-trivial module, zero is not non-degenerate. -/ -theorem not_separatingLeft_zero [Nontrivial M₁] : ¬(0 : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R).SeparatingLeft := +theorem not_separatingLeft_zero [Nontrivial M₁] : ¬(0 : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M).SeparatingLeft := let ⟨m, hm⟩ := exists_ne (0 : M₁) fun h ↦ hm (h m fun _n ↦ rfl) #align linear_map.not_separating_left_zero LinearMap.not_separatingLeft_zero variable {M₁ M₂ I₁ I₂} -theorem SeparatingLeft.ne_zero [Nontrivial M₁] {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} +theorem SeparatingLeft.ne_zero [Nontrivial M₁] {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} (h : B.SeparatingLeft) : B ≠ 0 := fun h0 ↦ not_separatingLeft_zero M₁ M₂ I₁ I₂ <| h0 ▸ h #align linear_map.separating_left.ne_zero LinearMap.SeparatingLeft.ne_zero section Linear variable [AddCommMonoid Mₗ₁] [AddCommMonoid Mₗ₂] [AddCommMonoid Mₗ₁'] [AddCommMonoid Mₗ₂'] + [AddCommMonoid M] -variable [Module R Mₗ₁] [Module R Mₗ₂] [Module R Mₗ₁'] [Module R Mₗ₂'] +variable [Module R Mₗ₁] [Module R Mₗ₂] [Module R Mₗ₁'] [Module R Mₗ₂'] [Module R M] -variable {B : Mₗ₁ →ₗ[R] Mₗ₂ →ₗ[R] R} (e₁ : Mₗ₁ ≃ₗ[R] Mₗ₁') (e₂ : Mₗ₂ ≃ₗ[R] Mₗ₂') +variable {B : Mₗ₁ →ₗ[R] Mₗ₂ →ₗ[R] M} (e₁ : Mₗ₁ ≃ₗ[R] Mₗ₁') (e₂ : Mₗ₂ ≃ₗ[R] Mₗ₂') theorem SeparatingLeft.congr (h : B.SeparatingLeft) : - (e₁.arrowCongr (e₂.arrowCongr (LinearEquiv.refl R R)) B).SeparatingLeft := by + (e₁.arrowCongr (e₂.arrowCongr (LinearEquiv.refl R M)) B).SeparatingLeft := by intro x hx rw [← e₁.symm.map_eq_zero_iff] refine' h (e₁.symm x) fun y ↦ _ @@ -657,7 +666,7 @@ theorem SeparatingLeft.congr (h : B.SeparatingLeft) : @[simp] theorem separatingLeft_congr_iff : - (e₁.arrowCongr (e₂.arrowCongr (LinearEquiv.refl R R)) B).SeparatingLeft ↔ B.SeparatingLeft := + (e₁.arrowCongr (e₂.arrowCongr (LinearEquiv.refl R M)) B).SeparatingLeft ↔ B.SeparatingLeft := ⟨fun h ↦ by convert h.congr e₁.symm e₂.symm ext x y @@ -667,35 +676,35 @@ theorem separatingLeft_congr_iff : end Linear -/-- A bilinear form is called right-separating if +/-- A bilinear map is called right-separating if the only element that is right-orthogonal to every other element is `0`; i.e., for every nonzero `y` in `M₂`, there exists `x` in `M₁` with `B x y ≠ 0`.-/ -def SeparatingRight (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R) : Prop := +def SeparatingRight (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M) : Prop := ∀ y : M₂, (∀ x : M₁, B x y = 0) → y = 0 #align linear_map.separating_right LinearMap.SeparatingRight -/-- A bilinear form is called non-degenerate if it is left-separating and right-separating. -/ -def Nondegenerate (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R) : Prop := +/-- A bilinear map is called non-degenerate if it is left-separating and right-separating. -/ +def Nondegenerate (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M) : Prop := SeparatingLeft B ∧ SeparatingRight B #align linear_map.nondegenerate LinearMap.Nondegenerate @[simp] -theorem flip_separatingRight {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} : +theorem flip_separatingRight {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} : B.flip.SeparatingRight ↔ B.SeparatingLeft := ⟨fun hB x hy ↦ hB x hy, fun hB x hy ↦ hB x hy⟩ #align linear_map.flip_separating_right LinearMap.flip_separatingRight @[simp] -theorem flip_separatingLeft {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} : +theorem flip_separatingLeft {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} : B.flip.SeparatingLeft ↔ SeparatingRight B := by rw [← flip_separatingRight, flip_flip] #align linear_map.flip_separating_left LinearMap.flip_separatingLeft @[simp] -theorem flip_nondegenerate {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} : B.flip.Nondegenerate ↔ B.Nondegenerate := +theorem flip_nondegenerate {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} : B.flip.Nondegenerate ↔ B.Nondegenerate := Iff.trans and_comm (and_congr flip_separatingRight flip_separatingLeft) #align linear_map.flip_nondegenerate LinearMap.flip_nondegenerate -theorem separatingLeft_iff_linear_nontrivial {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} : +theorem separatingLeft_iff_linear_nontrivial {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} : B.SeparatingLeft ↔ ∀ x : M₁, B x = 0 → x = 0 := by constructor <;> intro h x hB · simpa only [hB, zero_apply, eq_self_iff_true, forall_const] using h x @@ -706,19 +715,19 @@ theorem separatingLeft_iff_linear_nontrivial {B : M₁ →ₛₗ[I₁] M₂ → exact h x h' #align linear_map.separating_left_iff_linear_nontrivial LinearMap.separatingLeft_iff_linear_nontrivial -theorem separatingRight_iff_linear_flip_nontrivial {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} : +theorem separatingRight_iff_linear_flip_nontrivial {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} : B.SeparatingRight ↔ ∀ y : M₂, B.flip y = 0 → y = 0 := by rw [← flip_separatingLeft, separatingLeft_iff_linear_nontrivial] #align linear_map.separating_right_iff_linear_flip_nontrivial LinearMap.separatingRight_iff_linear_flip_nontrivial -/-- A bilinear form is left-separating if and only if it has a trivial kernel. -/ -theorem separatingLeft_iff_ker_eq_bot {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} : +/-- A bilinear map is left-separating if and only if it has a trivial kernel. -/ +theorem separatingLeft_iff_ker_eq_bot {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} : B.SeparatingLeft ↔ LinearMap.ker B = ⊥ := Iff.trans separatingLeft_iff_linear_nontrivial LinearMap.ker_eq_bot'.symm #align linear_map.separating_left_iff_ker_eq_bot LinearMap.separatingLeft_iff_ker_eq_bot -/-- A bilinear form is right-separating if and only if its flip has a trivial kernel. -/ -theorem separatingRight_iff_flip_ker_eq_bot {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] R} : +/-- A bilinear map is right-separating if and only if its flip has a trivial kernel. -/ +theorem separatingRight_iff_flip_ker_eq_bot {B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M} : B.SeparatingRight ↔ LinearMap.ker B.flip = ⊥ := by rw [← flip_separatingLeft, separatingLeft_iff_ker_eq_bot] #align linear_map.separating_right_iff_flip_ker_eq_bot LinearMap.separatingRight_iff_flip_ker_eq_bot @@ -727,26 +736,26 @@ end CommSemiring section CommRing -variable [CommRing R] [AddCommGroup M] [Module R M] {I I' : R →+* R} +variable [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup M₁] [Module R M₁] {I I' : R →+* R} -theorem IsRefl.nondegenerate_of_separatingLeft {B : M →ₗ[R] M →ₗ[R] R} (hB : B.IsRefl) +theorem IsRefl.nondegenerate_of_separatingLeft {B : M →ₗ[R] M →ₗ[R] M₁} (hB : B.IsRefl) (hB' : B.SeparatingLeft) : B.Nondegenerate := by refine' ⟨hB', _⟩ rw [separatingRight_iff_flip_ker_eq_bot, hB.ker_eq_bot_iff_ker_flip_eq_bot.mp] rwa [← separatingLeft_iff_ker_eq_bot] #align linear_map.is_refl.nondegenerate_of_separating_left LinearMap.IsRefl.nondegenerate_of_separatingLeft -theorem IsRefl.nondegenerate_of_separatingRight {B : M →ₗ[R] M →ₗ[R] R} (hB : B.IsRefl) +theorem IsRefl.nondegenerate_of_separatingRight {B : M →ₗ[R] M →ₗ[R] M₁} (hB : B.IsRefl) (hB' : B.SeparatingRight) : B.Nondegenerate := by refine' ⟨_, hB'⟩ rw [separatingLeft_iff_ker_eq_bot, hB.ker_eq_bot_iff_ker_flip_eq_bot.mpr] rwa [← separatingRight_iff_flip_ker_eq_bot] #align linear_map.is_refl.nondegenerate_of_separating_right LinearMap.IsRefl.nondegenerate_of_separatingRight -/-- The restriction of a reflexive bilinear form `B` onto a submodule `W` is +/-- The restriction of a reflexive bilinear map `B` onto a submodule `W` is nondegenerate if `W` has trivial intersection with its orthogonal complement, that is `Disjoint W (W.orthogonalBilin B)`. -/ -theorem nondegenerateRestrictOfDisjointOrthogonal {B : M →ₗ[R] M →ₗ[R] R} (hB : B.IsRefl) +theorem nondegenerateRestrictOfDisjointOrthogonal {B : M →ₗ[R] M →ₗ[R] M₁} (hB : B.IsRefl) {W : Submodule R M} (hW : Disjoint W (W.orthogonalBilin B)) : (B.domRestrict₁₂ W W).Nondegenerate := by refine' (hB.domRestrict W).nondegenerate_of_separatingLeft _ @@ -759,10 +768,10 @@ theorem nondegenerateRestrictOfDisjointOrthogonal {B : M →ₗ[R] M →ₗ[R] R exact b₁ #align linear_map.nondegenerate_restrict_of_disjoint_orthogonal LinearMap.nondegenerateRestrictOfDisjointOrthogonal -/-- An orthogonal basis with respect to a left-separating bilinear form has no self-orthogonal +/-- An orthogonal basis with respect to a left-separating bilinear map has no self-orthogonal elements. -/ theorem IsOrthoᵢ.not_isOrtho_basis_self_of_separatingLeft [Nontrivial R] - {B : M →ₛₗ[I] M →ₛₗ[I'] R} {v : Basis n R M} (h : B.IsOrthoᵢ v) (hB : B.SeparatingLeft) + {B : M →ₛₗ[I] M →ₛₗ[I'] M₁} {v : Basis n R M} (h : B.IsOrthoᵢ v) (hB : B.SeparatingLeft) (i : n) : ¬B.IsOrtho (v i) (v i) := by intro ho refine' v.ne_zero i (hB (v i) fun m ↦ _) @@ -772,17 +781,17 @@ theorem IsOrthoᵢ.not_isOrtho_basis_self_of_separatingLeft [Nontrivial R] rintro j - rw [map_smulₛₗ] suffices : B (v i) (v j) = 0 - · rw [this, smul_eq_mul, mul_zero] + · rw [this, smul_zero] obtain rfl | hij := eq_or_ne i j · exact ho · exact h hij set_option linter.uppercaseLean3 false in #align linear_map.is_Ortho.not_is_ortho_basis_self_of_separating_left LinearMap.IsOrthoᵢ.not_isOrtho_basis_self_of_separatingLeft -/-- An orthogonal basis with respect to a right-separating bilinear form has no self-orthogonal +/-- An orthogonal basis with respect to a right-separating bilinear map has no self-orthogonal elements. -/ theorem IsOrthoᵢ.not_isOrtho_basis_self_of_separatingRight [Nontrivial R] - {B : M →ₛₗ[I] M →ₛₗ[I'] R} {v : Basis n R M} (h : B.IsOrthoᵢ v) (hB : B.SeparatingRight) + {B : M →ₛₗ[I] M →ₛₗ[I'] M₁} {v : Basis n R M} (h : B.IsOrthoᵢ v) (hB : B.SeparatingRight) (i : n) : ¬B.IsOrtho (v i) (v i) := by rw [isOrthoᵢ_flip] at h rw [isOrtho_flip] @@ -790,33 +799,33 @@ theorem IsOrthoᵢ.not_isOrtho_basis_self_of_separatingRight [Nontrivial R] set_option linter.uppercaseLean3 false in #align linear_map.is_Ortho.not_is_ortho_basis_self_of_separating_right LinearMap.IsOrthoᵢ.not_isOrtho_basis_self_of_separatingRight -/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is left-separating -if the basis has no elements which are self-orthogonal. -/ -theorem IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self [NoZeroDivisors R] {B : M →ₗ[R] M →ₗ[R] R} - (v : Basis n R M) (hO : B.IsOrthoᵢ v) (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingLeft := by +/-- Given an orthogonal basis with respect to a bilinear map, the bilinear map is left-separating if +the basis has no elements which are self-orthogonal. -/ +theorem IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self [NoZeroSMulDivisors R M₁] + {B : M →ₗ[R] M →ₗ[R] M₁} (v : Basis n R M) (hO : B.IsOrthoᵢ v) + (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingLeft := by intro m hB obtain ⟨vi, rfl⟩ := v.repr.symm.surjective m rw [LinearEquiv.map_eq_zero_iff] ext i rw [Finsupp.zero_apply] specialize hB (v i) - simp_rw [Basis.repr_symm_apply, Finsupp.total_apply, Finsupp.sum, map_sum₂, map_smulₛₗ₂, - smul_eq_mul] at hB + simp_rw [Basis.repr_symm_apply, Finsupp.total_apply, Finsupp.sum, map_sum₂, map_smulₛₗ₂] at hB rw [Finset.sum_eq_single i] at hB - · exact eq_zero_of_ne_zero_of_mul_right_eq_zero (h i) hB + · exact (smul_eq_zero.mp hB).elim _root_.id (h i).elim · intro j _hj hij replace hij : B (v j) (v i) = 0 := hO hij - rw [hij, RingHom.id_apply, mul_zero] + rw [hij, RingHom.id_apply, smul_zero] · intro hi replace hi : vi i = 0 := Finsupp.not_mem_support_iff.mp hi - rw [hi, RingHom.id_apply, zero_mul] + rw [hi, RingHom.id_apply, zero_smul] set_option linter.uppercaseLean3 false in #align linear_map.is_Ortho.separating_left_of_not_is_ortho_basis_self LinearMap.IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self -/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is right-separating +/-- Given an orthogonal basis with respect to a bilinear map, the bilinear map is right-separating if the basis has no elements which are self-orthogonal. -/ -theorem IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self [NoZeroDivisors R] - {B : M →ₗ[R] M →ₗ[R] R} (v : Basis n R M) (hO : B.IsOrthoᵢ v) +theorem IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self [NoZeroSMulDivisors R M₁] + {B : M →ₗ[R] M →ₗ[R] M₁} (v : Basis n R M) (hO : B.IsOrthoᵢ v) (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingRight := by rw [isOrthoᵢ_flip] at hO rw [← flip_separatingLeft] @@ -826,10 +835,11 @@ theorem IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self [NoZeroDivisors R] set_option linter.uppercaseLean3 false in #align linear_map.is_Ortho.separating_right_iff_not_is_ortho_basis_self LinearMap.IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self -/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is nondegenerate +/-- Given an orthogonal basis with respect to a bilinear map, the bilinear map is nondegenerate if the basis has no elements which are self-orthogonal. -/ -theorem IsOrthoᵢ.nondegenerate_of_not_isOrtho_basis_self [NoZeroDivisors R] {B : M →ₗ[R] M →ₗ[R] R} - (v : Basis n R M) (hO : B.IsOrthoᵢ v) (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.Nondegenerate := +theorem IsOrthoᵢ.nondegenerate_of_not_isOrtho_basis_self [NoZeroSMulDivisors R M₁] + {B : M →ₗ[R] M →ₗ[R] M₁} (v : Basis n R M) (hO : B.IsOrthoᵢ v) + (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.Nondegenerate := ⟨IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self v hO h, IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self v hO h⟩ set_option linter.uppercaseLean3 false in diff --git a/Mathlib/LinearAlgebra/Span.lean b/Mathlib/LinearAlgebra/Span.lean index 785b5937e9726..c55a299a76b29 100644 --- a/Mathlib/LinearAlgebra/Span.lean +++ b/Mathlib/LinearAlgebra/Span.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Frédéric Dupuis, Heather Macbeth -/ +import Mathlib.Algebra.Module.Submodule.RestrictScalars import Mathlib.LinearAlgebra.Basic import Mathlib.Order.CompactlyGenerated import Mathlib.Order.OmegaCompletePartialOrder @@ -180,6 +181,39 @@ theorem span_induction' {p : ∀ x, x ∈ span R s → Prop} fun r x hx => Exists.elim hx fun hx' hx => ⟨smul_mem _ _ hx', H2 r _ _ hx⟩ #align submodule.span_induction' Submodule.span_induction' +open AddSubmonoid in +theorem span_eq_closure {s : Set M} : (span R s).toAddSubmonoid = closure (@univ R • s) := by + refine le_antisymm + (fun x hx ↦ span_induction hx (fun x hx ↦ subset_closure ⟨1, trivial, x, hx, one_smul R x⟩) + (zero_mem _) (fun _ _ ↦ add_mem) fun r m hm ↦ closure_induction hm ?_ ?_ fun _ _ h h' ↦ ?_) + (closure_le.2 ?_) + · rintro _ ⟨r, -, m, hm, rfl⟩; exact smul_mem _ _ (subset_span hm) + · rintro _ ⟨r', -, m, hm, rfl⟩; exact subset_closure ⟨r * r', trivial, m, hm, mul_smul r r' m⟩ + · rw [smul_zero]; apply zero_mem + · rw [smul_add]; exact add_mem h h' + +/-- A variant of `span_induction` that combines `∀ x ∈ s, p x` and `∀ r x, p x → p (r • x)` +into a single condition `∀ r, ∀ x ∈ s, p (r • x)`, which can be easier to verify. -/ +@[elab_as_elim] +theorem closure_induction {p : M → Prop} (h : x ∈ span R s) (H0 : p 0) + (H1 : ∀ x y, p x → p y → p (x + y)) (H2 : ∀ r : R, ∀ x ∈ s, p (r • x)) : p x := by + rw [← mem_toAddSubmonoid, span_eq_closure] at h + refine AddSubmonoid.closure_induction h ?_ H0 H1 + rintro _ ⟨r, -, m, hm, rfl⟩ + exact H2 r m hm + +/-- A dependent version of `Submodule.closure_induction`. -/ +theorem closure_induction' {p : ∀ x, x ∈ span R s → Prop} + (H0 : p 0 (Submodule.zero_mem _)) + (H1 : ∀ x hx y hy, p x hx → p y hy → p (x + y) (Submodule.add_mem _ ‹_› ‹_›)) + (H2 : ∀ (r x) (h : x ∈ s), p (r • x) (Submodule.smul_mem _ _ <| subset_span h)) {x} + (hx : x ∈ span R s) : p x hx := by + refine Exists.elim ?_ fun (hx : x ∈ span R s) (hc : p x hx) ↦ hc + refine closure_induction hx ⟨zero_mem _, H0⟩ + (fun x y hx hy ↦ Exists.elim hx fun hx' hx ↦ + Exists.elim hy fun hy' hy ↦ ⟨add_mem hx' hy', H1 _ _ _ _ hx hy⟩) + fun r x hx ↦ ⟨smul_mem _ _ (subset_span hx), H2 r x hx⟩ + @[simp] theorem span_span_coe_preimage : span R (((↑) : span R s → M) ⁻¹' s) = ⊤ := eq_top_iff.2 fun x ↦ Subtype.recOn x fun x hx _ ↦ by @@ -880,8 +914,8 @@ section DivisionRing variable [DivisionRing K] [AddCommGroup V] [Module K V] -/-- There is no vector subspace between `p` and `(K ∙ x) ⊔ p`, `Wcovby` version. -/ -theorem wcovby_span_singleton_sup (x : V) (p : Submodule K V) : Wcovby p ((K ∙ x) ⊔ p) := by +/-- There is no vector subspace between `p` and `(K ∙ x) ⊔ p`, `WCovBy` version. -/ +theorem wcovBy_span_singleton_sup (x : V) (p : Submodule K V) : WCovBy p ((K ∙ x) ⊔ p) := by refine ⟨le_sup_right, fun q hpq hqp ↦ hqp.not_le ?_⟩ rcases SetLike.exists_of_lt hpq with ⟨y, hyq, hyp⟩ obtain ⟨c, z, hz, rfl⟩ : ∃ c : K, ∃ z ∈ p, c • x + z = y := by @@ -892,9 +926,9 @@ theorem wcovby_span_singleton_sup (x : V) (p : Submodule K V) : Wcovby p ((K ∙ · rwa [q.add_mem_iff_left (hpq.le hz), q.smul_mem_iff hc] at hyq simp [hpq.le, this] -/-- There is no vector subspace between `p` and `(K ∙ x) ⊔ p`, `Covby` version. -/ -theorem covby_span_singleton_sup {x : V} {p : Submodule K V} (h : x ∉ p) : Covby p ((K ∙ x) ⊔ p) := - ⟨by simpa, (wcovby_span_singleton_sup _ _).2⟩ +/-- There is no vector subspace between `p` and `(K ∙ x) ⊔ p`, `CovBy` version. -/ +theorem covBy_span_singleton_sup {x : V} {p : Submodule K V} (h : x ∉ p) : CovBy p ((K ∙ x) ⊔ p) := + ⟨by simpa, (wcovBy_span_singleton_sup _ _).2⟩ end DivisionRing @@ -998,7 +1032,7 @@ theorem eqOn_span {s : Set M} {f g : F} (H : Set.EqOn f g s) ⦃x⦄ (h : x ∈ /-- If `s` generates the whole module and linear maps `f`, `g` are equal on `s`, then they are equal. -/ theorem ext_on {s : Set M} {f g : F} (hv : span R s = ⊤) (h : Set.EqOn f g s) : f = g := - FunLike.ext _ _ fun _ => eqOn_span h (eq_top_iff'.1 hv _) + DFunLike.ext _ _ fun _ => eqOn_span h (eq_top_iff'.1 hv _) #align linear_map.ext_on LinearMap.ext_on /-- If the range of `v : ι → M` generates the whole module and linear maps `f`, `g` are equal at @@ -1051,7 +1085,7 @@ def toSpanNonzeroSingleton : R ≃ₗ[R] R ∙ x := LinearEquiv.trans (LinearEquiv.ofInjective (LinearMap.toSpanSingleton R M x) (ker_eq_bot.1 <| ker_toSpanSingleton R M h)) - (LinearEquiv.ofEq (range $ toSpanSingleton R M x) (R ∙ x) (span_singleton_eq_range R M x).symm) + (LinearEquiv.ofEq (range <| toSpanSingleton R M x) (R ∙ x) (span_singleton_eq_range R M x).symm) #align linear_equiv.to_span_nonzero_singleton LinearEquiv.toSpanNonzeroSingleton theorem toSpanNonzeroSingleton_one : diff --git a/Mathlib/LinearAlgebra/StdBasis.lean b/Mathlib/LinearAlgebra/StdBasis.lean index 23df7cef52a10..e98a3c572ef60 100644 --- a/Mathlib/LinearAlgebra/StdBasis.lean +++ b/Mathlib/LinearAlgebra/StdBasis.lean @@ -271,7 +271,7 @@ section variable (R η) /-- The basis on `η → R` where the `i`th basis vector is `Function.update 0 i 1`. -/ -noncomputable def basisFun : Basis η R (∀ _ : η, R) := +noncomputable def basisFun : Basis η R (η → R) := Basis.ofEquivFun (LinearEquiv.refl _ _) #align pi.basis_fun Pi.basisFun diff --git a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean index 7cb1fcbf8a33e..21ea4f375cf15 100644 --- a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean +++ b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean @@ -120,7 +120,7 @@ theorem ofDirectSum_toDirectSum (x : TensorAlgebra R M) : @[simp, nolint simpNF] -- see std4#365 for the simpNF issue theorem mk_reindex_cast {n m : ℕ} (h : n = m) (x : (⨂[R]^n) M) : GradedMonoid.mk (A := fun i => (⨂[R]^i) M) m - (PiTensorProduct.reindex R M (Equiv.cast <| congr_arg Fin h) x) = + (PiTensorProduct.reindex R (fun _ ↦ M) (Equiv.cast <| congr_arg Fin h) x) = GradedMonoid.mk n x := Eq.symm (PiTensorProduct.gradedMonoid_eq_of_reindex_cast h rfl) #align tensor_algebra.mk_reindex_cast TensorAlgebra.mk_reindex_cast @@ -128,7 +128,7 @@ theorem mk_reindex_cast {n m : ℕ} (h : n = m) (x : (⨂[R]^n) M) : @[simp] theorem mk_reindex_fin_cast {n m : ℕ} (h : n = m) (x : (⨂[R]^n) M) : GradedMonoid.mk (A := fun i => (⨂[R]^i) M) m - (PiTensorProduct.reindex R M (Fin.castIso h).toEquiv x) = GradedMonoid.mk n x := by + (PiTensorProduct.reindex R (fun _ ↦ M) (Fin.castIso h).toEquiv x) = GradedMonoid.mk n x := by rw [Fin.castIso_to_equiv, mk_reindex_cast h] #align tensor_algebra.mk_reindex_fin_cast TensorAlgebra.mk_reindex_fin_cast diff --git a/Mathlib/LinearAlgebra/TensorPower.lean b/Mathlib/LinearAlgebra/TensorPower.lean index b742de299280f..a40c46ac1f585 100644 --- a/Mathlib/LinearAlgebra/TensorPower.lean +++ b/Mathlib/LinearAlgebra/TensorPower.lean @@ -52,8 +52,8 @@ are equal after a canonical reindexing. -/ @[ext] theorem gradedMonoid_eq_of_reindex_cast {ιι : Type*} {ι : ιι → Type*} : ∀ {a b : GradedMonoid fun ii => ⨂[R] _ : ι ii, M} (h : a.fst = b.fst), - reindex R M (Equiv.cast <| congr_arg ι h) a.snd = b.snd → a = b - | ⟨ai, a⟩, ⟨bi, b⟩ => fun (hi : ai = bi) (h : reindex R M _ a = b) => by + reindex R (fun _ ↦ M) (Equiv.cast <| congr_arg ι h) a.snd = b.snd → a = b + | ⟨ai, a⟩, ⟨bi, b⟩ => fun (hi : ai = bi) (h : reindex R (fun _ ↦ M) _ a = b) => by subst hi simp_all #align pi_tensor_product.graded_monoid_eq_of_reindex_cast PiTensorProduct.gradedMonoid_eq_of_reindex_cast @@ -78,7 +78,7 @@ theorem gOne_def : ₜ1 = tprod R (@Fin.elim0' M) := /-- A variant of `PiTensorProduct.tmulEquiv` with the result indexed by `Fin (n + m)`. -/ def mulEquiv {n m : ℕ} : (⨂[R]^n) M ⊗[R] (⨂[R]^m) M ≃ₗ[R] (⨂[R]^(n + m)) M := - (tmulEquiv R M).trans (reindex R M finSumFinEquiv) + (tmulEquiv R M).trans (reindex R (fun _ ↦ M) finSumFinEquiv) #align tensor_power.mul_equiv TensorPower.mulEquiv /-- As a graded monoid, `⨂[R]^i M` has a `(*) : ⨂[R]^i M → ⨂[R]^j M → ⨂[R]^(i + j) M`. -/ @@ -104,7 +104,7 @@ variable (R M) /-- Cast between "equal" tensor powers. -/ def cast {i j} (h : i = j) : (⨂[R]^i) M ≃ₗ[R] (⨂[R]^j) M := - reindex R M (Fin.castIso h).toEquiv + reindex R (fun _ ↦ M) (Fin.castIso h).toEquiv #align tensor_power.cast TensorPower.cast theorem cast_tprod {i j} (h : i = j) (a : Fin i → M) : @@ -114,7 +114,8 @@ theorem cast_tprod {i j} (h : i = j) (a : Fin i → M) : @[simp] theorem cast_refl {i} (h : i = i) : cast R M h = LinearEquiv.refl _ _ := - ((congr_arg fun f => reindex R M (RelIso.toEquiv f)) <| Fin.castIso_refl h).trans reindex_refl + ((congr_arg fun f => reindex R (fun _ ↦ M) (RelIso.toEquiv f)) <| Fin.castIso_refl h).trans + reindex_refl #align tensor_power.cast_refl TensorPower.cast_refl @[simp] diff --git a/Mathlib/LinearAlgebra/TensorProduct.lean b/Mathlib/LinearAlgebra/TensorProduct.lean index e0c263c692f81..9a2209225680d 100644 --- a/Mathlib/LinearAlgebra/TensorProduct.lean +++ b/Mathlib/LinearAlgebra/TensorProduct.lean @@ -805,7 +805,7 @@ lemma map_comp_comm_eq (f : M →ₗ[R] P) (g : N →ₗ[R] Q) : lemma map_comm (f : M →ₗ[R] P) (g : N →ₗ[R] Q) (x : N ⊗[R] M): map f g (TensorProduct.comm R N M x) = TensorProduct.comm R Q P (map g f x) := - FunLike.congr_fun (map_comp_comm_eq _ _) _ + DFunLike.congr_fun (map_comp_comm_eq _ _) _ /-- Given linear maps `f : M → Q`, `g : N → S`, and `h : P → T`, if we identify `(M ⊗ N) ⊗ P` with `M ⊗ (N ⊗ P)` and `(Q ⊗ S) ⊗ T` with `Q ⊗ (S ⊗ T)`, then this lemma states that @@ -818,7 +818,7 @@ lemma map_map_comp_assoc_eq (f : M →ₗ[R] Q) (g : N →ₗ[R] S) (h : P → lemma map_map_assoc (f : M →ₗ[R] Q) (g : N →ₗ[R] S) (h : P →ₗ[R] T) (x : (M ⊗[R] N) ⊗[R] P) : map f (map g h) (TensorProduct.assoc R M N P x) = TensorProduct.assoc R Q S T (map (map f g) h x) := - FunLike.congr_fun (map_map_comp_assoc_eq _ _ _) _ + DFunLike.congr_fun (map_map_comp_assoc_eq _ _ _) _ /-- Given linear maps `f : M → Q`, `g : N → S`, and `h : P → T`, if we identify `M ⊗ (N ⊗ P)` with `(M ⊗ N) ⊗ P` and `Q ⊗ (S ⊗ T)` with `(Q ⊗ S) ⊗ T`, then this lemma states that @@ -831,7 +831,7 @@ lemma map_map_comp_assoc_symm_eq (f : M →ₗ[R] Q) (g : N →ₗ[R] S) (h : P lemma map_map_assoc_symm (f : M →ₗ[R] Q) (g : N →ₗ[R] S) (h : P →ₗ[R] T) (x : M ⊗[R] (N ⊗[R] P)) : map (map f g) h ((TensorProduct.assoc R M N P).symm x) = (TensorProduct.assoc R Q S T).symm (map f (map g h) x) := - FunLike.congr_fun (map_map_comp_assoc_symm_eq _ _ _) _ + DFunLike.congr_fun (map_map_comp_assoc_symm_eq _ _ _) _ theorem map_range_eq_span_tmul (f : M →ₗ[R] P) (g : N →ₗ[R] Q) : range (map f g) = Submodule.span R { t | ∃ m n, f m ⊗ₜ g n = t } := by diff --git a/Mathlib/LinearAlgebra/TensorProduct/Graded/External.lean b/Mathlib/LinearAlgebra/TensorProduct/Graded/External.lean index 0d2eefaed5243..274d941c7ac1a 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Graded/External.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Graded/External.lean @@ -128,7 +128,7 @@ theorem gradedComm_tmul_of_zero (a : ⨁ i, 𝒜 i) (b : ℬ 0) : (gradedComm R 𝒜 ℬ).toLinearMap ∘ₗ (TensorProduct.mk R (⨁ i, 𝒜 i) (⨁ i, ℬ i)).flip (lof R _ ℬ 0 b) = TensorProduct.mk R _ _ (lof R _ ℬ 0 b) from - FunLike.congr_fun this a + DFunLike.congr_fun this a ext i a dsimp rw [gradedComm_of_tmul_of, zero_mul, uzpow_zero, one_smul] @@ -138,7 +138,7 @@ theorem gradedComm_of_zero_tmul (a : 𝒜 0) (b : ⨁ i, ℬ i) : suffices (gradedComm R 𝒜 ℬ).toLinearMap ∘ₗ (TensorProduct.mk R (⨁ i, 𝒜 i) (⨁ i, ℬ i)) (lof R _ 𝒜 0 a) = (TensorProduct.mk R _ _).flip (lof R _ 𝒜 0 a) from - FunLike.congr_fun this b + DFunLike.congr_fun this b ext i b dsimp rw [gradedComm_of_tmul_of, mul_zero, uzpow_zero, one_smul] @@ -198,7 +198,7 @@ variable {R} theorem algebraMap_gradedMul (r : R) (x : (⨁ i, 𝒜 i) ⊗[R] (⨁ i, ℬ i)) : gradedMul R 𝒜 ℬ (algebraMap R _ r ⊗ₜ 1) x = r • x := by suffices gradedMul R 𝒜 ℬ (algebraMap R _ r ⊗ₜ 1) = DistribMulAction.toLinearMap R _ r by - exact FunLike.congr_fun this x + exact DFunLike.congr_fun this x ext ia a ib b dsimp erw [tmul_of_gradedMul_of_tmul] @@ -212,7 +212,7 @@ theorem one_gradedMul (x : (⨁ i, 𝒜 i) ⊗[R] (⨁ i, ℬ i)) : theorem gradedMul_algebraMap (x : (⨁ i, 𝒜 i) ⊗[R] (⨁ i, ℬ i)) (r : R) : gradedMul R 𝒜 ℬ x (algebraMap R _ r ⊗ₜ 1) = r • x := by suffices (gradedMul R 𝒜 ℬ).flip (algebraMap R _ r ⊗ₜ 1) = DistribMulAction.toLinearMap R _ r by - exact FunLike.congr_fun this x + exact DFunLike.congr_fun this x ext dsimp erw [tmul_of_gradedMul_of_tmul] @@ -230,7 +230,7 @@ theorem gradedMul_assoc (x y z : DirectSum _ 𝒜 ⊗[R] DirectSum _ ℬ) : -- restate as an equality of morphisms so that we can use `ext` suffices LinearMap.llcomp R _ _ _ mA ∘ₗ mA = (LinearMap.llcomp R _ _ _ LinearMap.lflip <| LinearMap.llcomp R _ _ _ mA.flip ∘ₗ mA).flip by - exact FunLike.congr_fun (FunLike.congr_fun (FunLike.congr_fun this x) y) z + exact DFunLike.congr_fun (DFunLike.congr_fun (DFunLike.congr_fun this x) y) z ext ixa xa ixb xb iya ya iyb yb iza za izb zb dsimp simp_rw [tmul_of_gradedMul_of_tmul, Units.smul_def, zsmul_eq_smul_cast R, diff --git a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean index 8988e8863e9f3..6fa54b55e35c3 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean @@ -5,6 +5,7 @@ Authors: Eric Wieser -/ import Mathlib.LinearAlgebra.TensorProduct.Graded.External import Mathlib.RingTheory.GradedAlgebra.Basic +import Mathlib.GroupTheory.GroupAction.Ring /-! # Graded tensor products over graded algebras diff --git a/Mathlib/Logic/Basic.lean b/Mathlib/Logic/Basic.lean index 7636444aa89e1..4b35de4a91df6 100644 --- a/Mathlib/Logic/Basic.lean +++ b/Mathlib/Logic/Basic.lean @@ -6,7 +6,6 @@ Authors: Jeremy Avigad, Leonardo de Moura import Mathlib.Init.Logic import Mathlib.Init.Function import Mathlib.Init.Algebra.Classes -import Mathlib.Tactic.Basic import Std.Util.LibraryNote import Std.Tactic.Lint.Basic @@ -527,23 +526,17 @@ theorem ball_mem_comm {α β} [Membership α β] {s : β} {p : α → α → Pro ball_cond_comm #align ball_mem_comm ball_mem_comm -theorem ne_of_apply_ne {α β : Sort*} (f : α → β) {x y : α} (h : f x ≠ f y) : x ≠ y := - fun w : x = y ↦ h (congr_arg f w) #align ne_of_apply_ne ne_of_apply_ne theorem eq_equivalence : Equivalence (@Eq α) := ⟨Eq.refl, @Eq.symm _, @Eq.trans _⟩ #align eq_equivalence eq_equivalence -@[simp] theorem eq_mp_eq_cast (h : α = β) : Eq.mp h = cast h := rfl -#align eq_mp_eq_cast eq_mp_eq_cast +-- These were migrated to Std but the `@[simp]` attributes were (mysteriously?) removed. +attribute [simp] eq_mp_eq_cast eq_mpr_eq_cast -@[simp] theorem eq_mpr_eq_cast (h : α = β) : Eq.mpr h = cast h.symm := rfl +#align eq_mp_eq_cast eq_mp_eq_cast #align eq_mpr_eq_cast eq_mpr_eq_cast - -@[simp] theorem cast_cast : ∀ (ha : α = β) (hb : β = γ) (a : α), - cast hb (cast ha a) = cast (ha.trans hb) a - | rfl, rfl, _ => rfl #align cast_cast cast_cast -- @[simp] -- FIXME simp ignores proof rewrites @@ -569,12 +562,7 @@ theorem congr_fun_congr_arg (f : α → β → γ) {a a' : α} (p : a = a') (b : congr_fun (congr_arg f p) b = congr_arg (fun a ↦ f a b) p := rfl #align congr_fun_congr_arg congr_fun_congr_arg -theorem heq_of_cast_eq : ∀ (e : α = β) (_ : cast e a = a'), HEq a a' - | rfl, h => Eq.recOn h (HEq.refl _) #align heq_of_cast_eq heq_of_cast_eq - -theorem cast_eq_iff_heq : cast e a = a' ↔ HEq a a' := - ⟨heq_of_cast_eq _, fun h ↦ by cases h; rfl⟩ #align cast_eq_iff_heq cast_eq_iff_heq theorem Eq.rec_eq_cast {α : Sort _} {P : α → Sort _} {x y : α} (h : x = y) (z : P x) : @@ -598,36 +586,16 @@ theorem heq_rec_iff_heq {C : α → Sort*} {x : β} {y : C a} {e : a = b} : HEq x (e ▸ y) ↔ HEq x y := by subst e; rfl #align heq_rec_iff_heq heq_rec_iff_heq -protected theorem Eq.congr (h₁ : x₁ = y₁) (h₂ : x₂ = y₂) : x₁ = x₂ ↔ y₁ = y₂ := by - subst h₁; subst h₂; rfl #align eq.congr Eq.congr - -theorem Eq.congr_left {x y z : α} (h : x = y) : x = z ↔ y = z := by rw [h] #align eq.congr_left Eq.congr_left - -theorem Eq.congr_right {x y z : α} (h : x = y) : z = x ↔ z = y := by rw [h] #align eq.congr_right Eq.congr_right - -alias congr_arg₂ := congrArg₂ #align congr_arg2 congr_arg₂ variable {β : α → Sort*} {γ : ∀ a, β a → Sort*} {δ : ∀ a b, γ a b → Sort*} -theorem congr_fun₂ {f g : ∀ a b, γ a b} (h : f = g) (a : α) (b : β a) : f a b = g a b := - congr_fun (congr_fun h _) _ #align congr_fun₂ congr_fun₂ - -theorem congr_fun₃ {f g : ∀ a b c, δ a b c} (h : f = g) (a : α) (b : β a) (c : γ a b) : - f a b c = g a b c := - congr_fun₂ (congr_fun h _) _ _ #align congr_fun₃ congr_fun₃ - -theorem funext₂ {f g : ∀ a b, γ a b} (h : ∀ a b, f a b = g a b) : f = g := - funext fun _ ↦ funext <| h _ #align funext₂ funext₂ - -theorem funext₃ {f g : ∀ a b c, δ a b c} (h : ∀ a b c, f a b c = g a b c) : f = g := - funext fun _ ↦ funext₂ <| h _ #align funext₃ funext₃ end Equality diff --git a/Mathlib/Logic/Denumerable.lean b/Mathlib/Logic/Denumerable.lean index c28dd184e9cd1..8a334841bbafc 100644 --- a/Mathlib/Logic/Denumerable.lean +++ b/Mathlib/Logic/Denumerable.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Fintype.Lattice +import Mathlib.Data.Fintype.Card import Mathlib.Data.List.MinMax import Mathlib.Data.Nat.Order.Lemmas import Mathlib.Logic.Encodable.Basic diff --git a/Mathlib/Logic/Embedding/Basic.lean b/Mathlib/Logic/Embedding/Basic.lean index 317095471c93f..ad6dce0c7a0f5 100644 --- a/Mathlib/Logic/Embedding/Basic.lean +++ b/Mathlib/Logic/Embedding/Basic.lean @@ -42,6 +42,11 @@ initialize_simps_projections Embedding (toFun → apply) -- porting note: this needs `tactic.lift`. --instance {α β : Sort*} : CanLift (α → β) (α ↪ β) coeFn Injective where prf f hf := ⟨⟨f, hf⟩, rfl⟩ +theorem exists_surjective_iff : + (∃ f : α → β, Surjective f) ↔ Nonempty (α → β) ∧ Nonempty (β ↪ α) := + ⟨fun ⟨f, h⟩ ↦ ⟨⟨f⟩, ⟨⟨_, injective_surjInv h⟩⟩⟩, fun ⟨h, ⟨e⟩⟩ ↦ (nonempty_fun.mp h).elim + (fun _ ↦ ⟨isEmptyElim, (isEmptyElim <| e ·)⟩) fun _ ↦ ⟨_, invFun_surjective e.inj'⟩⟩ + end Function section Equiv @@ -74,6 +79,9 @@ theorem Equiv.toEmbedding_apply (a : α) : f.toEmbedding a = f a := rfl #align equiv.to_embedding_apply Equiv.toEmbedding_apply +theorem Equiv.toEmbedding_injective : Function.Injective (Equiv.toEmbedding : (α ≃ β) → (α ↪ β)) := + fun _ _ h ↦ by rwa [DFunLike.ext'_iff] at h ⊢ + instance Equiv.coeEmbedding : Coe (α ≃ β) (α ↪ β) := ⟨Equiv.toEmbedding⟩ #align equiv.coe_embedding Equiv.coeEmbedding @@ -93,17 +101,17 @@ namespace Function namespace Embedding theorem coe_injective {α β} : @Injective (α ↪ β) (α → β) (λ f => ↑f) := - FunLike.coe_injective + DFunLike.coe_injective #align function.embedding.coe_injective Function.Embedding.coe_injective @[ext] theorem ext {α β} {f g : Embedding α β} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align function.embedding.ext Function.Embedding.ext --- port note : in Lean 3 `FunLike.ext_iff.symm` works +-- port note : in Lean 3 `DFunLike.ext_iff.symm` works theorem ext_iff {α β} {f g : Embedding α β} : (∀ x, f x = g x) ↔ f = g := - Iff.symm (FunLike.ext_iff) + Iff.symm (DFunLike.ext_iff) #align function.embedding.ext_iff Function.Embedding.ext_iff @[simp] diff --git a/Mathlib/Logic/Equiv/Array.lean b/Mathlib/Logic/Equiv/Array.lean index 35ecc8272bc81..6be3c42d10893 100644 --- a/Mathlib/Logic/Equiv/Array.lean +++ b/Mathlib/Logic/Equiv/Array.lean @@ -5,7 +5,6 @@ Authors: Mario Carneiro -/ import Mathlib.Data.Vector.Basic import Mathlib.Logic.Equiv.List -import Mathlib.Control.Traversable.Equiv #align_import logic.equiv.array from "leanprover-community/mathlib"@"1126441d6bccf98c81214a0780c73d499f6721fe" diff --git a/Mathlib/Logic/Equiv/Basic.lean b/Mathlib/Logic/Equiv/Basic.lean index 6309c117651f0..bbc0360364928 100644 --- a/Mathlib/Logic/Equiv/Basic.lean +++ b/Mathlib/Logic/Equiv/Basic.lean @@ -1476,27 +1476,6 @@ theorem subtypeEquivCodomain_symm_apply_ne end subtypeEquivCodomain -/-- If `f` is a bijective function, then its domain is equivalent to its codomain. -/ -@[simps apply] -noncomputable def ofBijective (f : α → β) (hf : Bijective f) : α ≃ β where - toFun := f - invFun := Function.surjInv hf.surjective - left_inv := Function.leftInverse_surjInv hf - right_inv := Function.rightInverse_surjInv _ -#align equiv.of_bijective Equiv.ofBijective -#align equiv.of_bijective_apply Equiv.ofBijective_apply - -theorem ofBijective_apply_symm_apply (f : α → β) (hf : Bijective f) (x : β) : - f ((ofBijective f hf).symm x) = x := - (ofBijective f hf).apply_symm_apply x -#align equiv.of_bijective_apply_symm_apply Equiv.ofBijective_apply_symm_apply - -@[simp] -theorem ofBijective_symm_apply_apply (f : α → β) (hf : Bijective f) (x : α) : - (ofBijective f hf).symm (f x) = x := - (ofBijective f hf).symm_apply_apply x -#align equiv.of_bijective_symm_apply_apply Equiv.ofBijective_symm_apply_apply - instance : CanLift (α → β) (α ≃ β) (↑) Bijective where prf f hf := ⟨ofBijective f hf, rfl⟩ section @@ -1679,7 +1658,7 @@ theorem swap_eq_update (i j : α) : (Equiv.swap i j : α → α) = update (updat theorem comp_swap_eq_update (i j : α) (f : α → β) : f ∘ Equiv.swap i j = update (update f j (f i)) i (f j) := by - rw [swap_eq_update, comp_update, comp_update, comp.right_id] + rw [swap_eq_update, comp_update, comp_update, comp_id] #align equiv.comp_swap_eq_update Equiv.comp_swap_eq_update @[simp] @@ -1740,7 +1719,7 @@ theorem sumCongr_swap_refl {α β : Sort _} [DecidableEq α] [DecidableEq β] (i Equiv.Perm.sumCongr (Equiv.swap i j) (Equiv.refl β) = Equiv.swap (Sum.inl i) (Sum.inl j) := by ext x cases x - · simp only [Equiv.sumCongr_apply, Sum.map, coe_refl, comp.right_id, Sum.elim_inl, comp_apply, + · simp only [Equiv.sumCongr_apply, Sum.map, coe_refl, comp_id, Sum.elim_inl, comp_apply, swap_apply_def, Sum.inl.injEq] split_ifs <;> rfl · simp [Sum.map, swap_apply_of_ne_of_ne] @@ -1753,7 +1732,7 @@ theorem sumCongr_refl_swap {α β : Sort _} [DecidableEq α] [DecidableEq β] (i cases x · simp [Sum.map, swap_apply_of_ne_of_ne] - · simp only [Equiv.sumCongr_apply, Sum.map, coe_refl, comp.right_id, Sum.elim_inr, comp_apply, + · simp only [Equiv.sumCongr_apply, Sum.map, coe_refl, comp_id, Sum.elim_inr, comp_apply, swap_apply_def, Sum.inr.injEq] split_ifs <;> rfl #align equiv.perm.sum_congr_refl_swap Equiv.Perm.sumCongr_refl_swap @@ -1837,6 +1816,11 @@ LHS would have type `P a` while the RHS would have type `P (e.symm (e a))`. For we have to explicitly substitute along `e.symm (e a) = a` in the statement of this lemma. -/ add_decl_doc Equiv.piCongrLeft'_symm_apply +/-- This lemma is impractical to state in the dependent case. -/ +@[simp] +theorem piCongrLeft'_symm (P : Sort*) (e : α ≃ β) : + (piCongrLeft' (fun _ => P) e).symm = piCongrLeft' _ e.symm := by ext; simp [piCongrLeft'] + /-- Note: the "obvious" statement `(piCongrLeft' P e).symm g a = g (e a)` doesn't typecheck: the LHS would have type `P a` while the RHS would have type `P (e.symm (e a))`. This lemma is a way around it in the case where `a` is of the form `e.symm b`, so we can use `g b` instead of diff --git a/Mathlib/Logic/Equiv/Defs.lean b/Mathlib/Logic/Equiv/Defs.lean index 3963650a42f8f..3ab7468d01076 100644 --- a/Mathlib/Logic/Equiv/Defs.lean +++ b/Mathlib/Logic/Equiv/Defs.lean @@ -3,6 +3,7 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Mario Carneiro -/ +import Std.Tactic.CoeExt import Mathlib.Data.FunLike.Equiv import Mathlib.Data.Quot import Mathlib.Init.Data.Bool.Lemmas @@ -103,8 +104,8 @@ instance : EquivLike (α ≃ β) α β where /-- Helper instance when inference gets stuck on following the normal chain `EquivLike → EmbeddingLike → FunLike → CoeFun`. -/ -instance : FunLike (α ≃ β) α (fun _ => β) := - EmbeddingLike.toFunLike +instance : FunLike (α ≃ β) α β := + EmbeddingLike.toDFunLike @[simp, norm_cast] lemma _root_.EquivLike.coe_coe {F} [EquivLike F α β] (e : F) : @@ -116,25 +117,25 @@ lemma _root_.EquivLike.coe_coe {F} [EquivLike F α β] (e : F) : /-- The map `(r ≃ s) → (r → s)` is injective. -/ theorem coe_fn_injective : @Function.Injective (α ≃ β) (α → β) (fun e => e) := - FunLike.coe_injective' + DFunLike.coe_injective' #align equiv.coe_fn_injective Equiv.coe_fn_injective protected theorem coe_inj {e₁ e₂ : α ≃ β} : (e₁ : α → β) = e₂ ↔ e₁ = e₂ := - @FunLike.coe_fn_eq _ _ _ _ e₁ e₂ + @DFunLike.coe_fn_eq _ _ _ _ e₁ e₂ #align equiv.coe_inj Equiv.coe_inj -@[ext] theorem ext {f g : Equiv α β} (H : ∀ x, f x = g x) : f = g := FunLike.ext f g H +@[ext] theorem ext {f g : Equiv α β} (H : ∀ x, f x = g x) : f = g := DFunLike.ext f g H #align equiv.ext Equiv.ext protected theorem congr_arg {f : Equiv α β} {x x' : α} : x = x' → f x = f x' := - FunLike.congr_arg f + DFunLike.congr_arg f #align equiv.congr_arg Equiv.congr_arg protected theorem congr_fun {f g : Equiv α β} (h : f = g) (x : α) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align equiv.congr_fun Equiv.congr_fun -theorem ext_iff {f g : Equiv α β} : f = g ↔ ∀ x, f x = g x := FunLike.ext_iff +theorem ext_iff {f g : Equiv α β} : f = g ↔ ∀ x, f x = g x := DFunLike.ext_iff #align equiv.ext_iff Equiv.ext_iff @[ext] theorem Perm.ext {σ τ : Equiv.Perm α} (H : ∀ x, σ x = τ x) : σ = τ := Equiv.ext H @@ -186,7 +187,7 @@ instance : Trans Equiv Equiv Equiv where trans := Equiv.trans -- porting note: this is not a syntactic tautology any more because --- the coercion from `e` to a function is now `FunLike.coe` not `e.toFun` +-- the coercion from `e` to a function is now `DFunLike.coe` not `e.toFun` @[simp, mfld_simps] theorem toFun_as_coe (e : α ≃ β) : e.toFun = e := rfl #align equiv.to_fun_as_coe Equiv.toFun_as_coe @@ -918,6 +919,27 @@ protected theorem exists_congr_left {α β} (f : α ≃ β) {p : α → Prop} : ⟨fun ⟨a, h⟩ => ⟨f a, by simpa using h⟩, fun ⟨b, h⟩ => ⟨_, h⟩⟩ #align equiv.exists_congr_left Equiv.exists_congr_left +/-- If `f` is a bijective function, then its domain is equivalent to its codomain. -/ +@[simps apply] +noncomputable def ofBijective (f : α → β) (hf : Bijective f) : α ≃ β where + toFun := f + invFun := surjInv hf.surjective + left_inv := leftInverse_surjInv hf + right_inv := rightInverse_surjInv _ +#align equiv.of_bijective Equiv.ofBijective +#align equiv.of_bijective_apply Equiv.ofBijective_apply + +lemma ofBijective_apply_symm_apply (f : α → β) (hf : Bijective f) (x : β) : + f ((ofBijective f hf).symm x) = x := + (ofBijective f hf).apply_symm_apply x +#align equiv.of_bijective_apply_symm_apply Equiv.ofBijective_apply_symm_apply + +@[simp] +lemma ofBijective_symm_apply_apply (f : α → β) (hf : Bijective f) (x : α) : + (ofBijective f hf).symm (f x) = x := + (ofBijective f hf).symm_apply_apply x +#align equiv.of_bijective_symm_apply_apply Equiv.ofBijective_symm_apply_apply + end Equiv namespace Quot diff --git a/Mathlib/Logic/Equiv/Nat.lean b/Mathlib/Logic/Equiv/Nat.lean index ec7051e529482..c938dd079da83 100644 --- a/Mathlib/Logic/Equiv/Nat.lean +++ b/Mathlib/Logic/Equiv/Nat.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ +import Mathlib.Data.Nat.Bits import Mathlib.Data.Nat.Pairing #align_import logic.equiv.nat from "leanprover-community/mathlib"@"207cfac9fcd06138865b5d04f7091e46d9320432" diff --git a/Mathlib/Logic/Equiv/PartialEquiv.lean b/Mathlib/Logic/Equiv/PartialEquiv.lean index c3a0d71e6b55d..56c00ea866b56 100644 --- a/Mathlib/Logic/Equiv/PartialEquiv.lean +++ b/Mathlib/Logic/Equiv/PartialEquiv.lean @@ -788,39 +788,6 @@ theorem mem_symm_trans_source {e' : PartialEquiv α γ} {x : α} (he : x ∈ e.s ⟨e.mapsTo he, by rwa [mem_preimage, PartialEquiv.symm_symm, e.left_inv he]⟩ #align local_equiv.mem_symm_trans_source PartialEquiv.mem_symm_trans_source -/-- Postcompose a partial equivalence with an equivalence. -We modify the source and target to have better definitional behavior. -/ -@[simps!] -def transEquiv (e' : β ≃ γ) : PartialEquiv α γ := - (e.trans e'.toPartialEquiv).copy _ rfl _ rfl e.source (inter_univ _) (e'.symm ⁻¹' e.target) - (univ_inter _) -#align local_equiv.trans_equiv PartialEquiv.transEquiv -#align local_equiv.trans_equiv_source PartialEquiv.transEquiv_source -#align local_equiv.trans_equiv_apply PartialEquiv.transEquiv_apply -#align local_equiv.trans_equiv_target PartialEquiv.transEquiv_target -#align local_equiv.trans_equiv_symm_apply PartialEquiv.transEquiv_symm_apply - -theorem transEquiv_eq_trans (e' : β ≃ γ) : e.transEquiv e' = e.trans e'.toPartialEquiv := - copy_eq .. -#align local_equiv.trans_equiv_eq_trans PartialEquiv.transEquiv_eq_trans - -/-- Precompose a partial equivalence with an equivalence. -We modify the source and target to have better definitional behavior. -/ -@[simps!] -def _root_.Equiv.transPartialEquiv (e : α ≃ β) : PartialEquiv α γ := - (e.toPartialEquiv.trans e').copy _ rfl _ rfl (e ⁻¹' e'.source) (univ_inter _) e'.target - (inter_univ _) -#align equiv.trans_local_equiv Equiv.transPartialEquiv -#align equiv.trans_local_equiv_target Equiv.transPartialEquiv_target -#align equiv.trans_local_equiv_apply Equiv.transPartialEquiv_apply -#align equiv.trans_local_equiv_source Equiv.transPartialEquiv_source -#align equiv.trans_local_equiv_symm_apply Equiv.transPartialEquiv_symm_apply - -theorem _root_.Equiv.transPartialEquiv_eq_trans (e : α ≃ β) : - e.transPartialEquiv e' = e.toPartialEquiv.trans e' := - copy_eq .. -#align equiv.trans_local_equiv_eq_trans Equiv.transPartialEquiv_eq_trans - /-- `EqOnSource e e'` means that `e` and `e'` have the same source, and coincide there. Then `e` and `e'` should really be considered the same partial equiv. -/ def EqOnSource (e e' : PartialEquiv α β) : Prop := @@ -907,7 +874,7 @@ theorem self_trans_symm : e.trans e.symm ≈ ofSet e.source := by /-- Composition of the inverse of a partial equivalence and this partial equivalence is equivalent to the restriction of the identity to the target. -/ -theorem symm_trans_self : e.symm.trans e ≈ PartialEquiv.ofSet e.target := +theorem symm_trans_self : e.symm.trans e ≈ ofSet e.target := self_trans_symm e.symm #align local_equiv.symm_trans_self PartialEquiv.symm_trans_self @@ -1141,4 +1108,62 @@ theorem trans_toPartialEquiv : (by simp [PartialEquiv.trans_source, Equiv.toPartialEquiv]) #align equiv.trans_to_local_equiv Equiv.trans_toPartialEquiv +/-- Precompose a partial equivalence with an equivalence. +We modify the source and target to have better definitional behavior. -/ +@[simps!] +def transPartialEquiv (e : α ≃ β) (f' : PartialEquiv β γ) : PartialEquiv α γ := + (e.toPartialEquiv.trans f').copy _ rfl _ rfl (e ⁻¹' f'.source) (univ_inter _) f'.target + (inter_univ _) +#align equiv.trans_local_equiv Equiv.transPartialEquiv +#align equiv.trans_local_equiv_target Equiv.transPartialEquiv_target +#align equiv.trans_local_equiv_apply Equiv.transPartialEquiv_apply +#align equiv.trans_local_equiv_source Equiv.transPartialEquiv_source +#align equiv.trans_local_equiv_symm_apply Equiv.transPartialEquiv_symm_apply + +theorem transPartialEquiv_eq_trans (e : α ≃ β) (f' : PartialEquiv β γ) : + e.transPartialEquiv f' = e.toPartialEquiv.trans f' := + PartialEquiv.copy_eq .. +#align equiv.trans_local_equiv_eq_trans Equiv.transPartialEquiv_eq_trans + +@[simp, mfld_simps] +theorem transPartialEquiv_trans (e : α ≃ β) (f' : PartialEquiv β γ) (f'' : PartialEquiv γ δ) : + (e.transPartialEquiv f').trans f'' = e.transPartialEquiv (f'.trans f'') := by + simp only [transPartialEquiv_eq_trans, PartialEquiv.trans_assoc] + +@[simp, mfld_simps] +theorem trans_transPartialEquiv (e : α ≃ β) (e' : β ≃ γ) (f'' : PartialEquiv γ δ) : + (e.trans e').transPartialEquiv f'' = e.transPartialEquiv (e'.transPartialEquiv f'') := by + simp only [transPartialEquiv_eq_trans, PartialEquiv.trans_assoc, trans_toPartialEquiv] + end Equiv + +namespace PartialEquiv + +/-- Postcompose a partial equivalence with an equivalence. +We modify the source and target to have better definitional behavior. -/ +@[simps!] +def transEquiv (e : PartialEquiv α β) (f' : β ≃ γ) : PartialEquiv α γ := + (e.trans f'.toPartialEquiv).copy _ rfl _ rfl e.source (inter_univ _) (f'.symm ⁻¹' e.target) + (univ_inter _) +#align local_equiv.trans_equiv PartialEquiv.transEquiv +#align local_equiv.trans_equiv_source PartialEquiv.transEquiv_source +#align local_equiv.trans_equiv_apply PartialEquiv.transEquiv_apply +#align local_equiv.trans_equiv_target PartialEquiv.transEquiv_target +#align local_equiv.trans_equiv_symm_apply PartialEquiv.transEquiv_symm_apply + +theorem transEquiv_eq_trans (e : PartialEquiv α β) (e' : β ≃ γ) : + e.transEquiv e' = e.trans e'.toPartialEquiv := + copy_eq .. +#align local_equiv.trans_equiv_eq_trans PartialEquiv.transEquiv_eq_trans + +@[simp, mfld_simps] +theorem transEquiv_transEquiv (e : PartialEquiv α β) (f' : β ≃ γ) (f'' : γ ≃ δ) : + (e.transEquiv f').transEquiv f'' = e.transEquiv (f'.trans f'') := by + simp only [transEquiv_eq_trans, trans_assoc, Equiv.trans_toPartialEquiv] + +@[simp, mfld_simps] +theorem trans_transEquiv (e : PartialEquiv α β) (e' : PartialEquiv β γ) (f'' : γ ≃ δ) : + (e.trans e').transEquiv f'' = e.trans (e'.transEquiv f'') := by + simp only [transEquiv_eq_trans, trans_assoc, Equiv.trans_toPartialEquiv] + +end PartialEquiv diff --git a/Mathlib/Logic/Equiv/Set.lean b/Mathlib/Logic/Equiv/Set.lean index d5330650f44e2..82cb9a73b3420 100644 --- a/Mathlib/Logic/Equiv/Set.lean +++ b/Mathlib/Logic/Equiv/Set.lean @@ -62,18 +62,22 @@ theorem _root_.Set.preimage_equiv_eq_image_symm {α β} (S : Set α) (f : β ≃ -- Porting note: increased priority so this fires before `image_subset_iff` @[simp high] -protected theorem subset_image {α β} (e : α ≃ β) (s : Set α) (t : Set β) : +protected theorem symm_image_subset {α β} (e : α ≃ β) (s : Set α) (t : Set β) : e.symm '' t ⊆ s ↔ t ⊆ e '' s := by rw [image_subset_iff, e.image_eq_preimage] -#align equiv.subset_image Equiv.subset_image +#align equiv.subset_image Equiv.symm_image_subset + +@[deprecated] alias subset_image := Equiv.symm_image_subset -- deprecated since 2024-01-19 -- Porting note: increased priority so this fires before `image_subset_iff` @[simp high] -protected theorem subset_image' {α β} (e : α ≃ β) (s : Set α) (t : Set β) : +protected theorem subset_symm_image {α β} (e : α ≃ β) (s : Set α) (t : Set β) : s ⊆ e.symm '' t ↔ e '' s ⊆ t := calc - s ⊆ e.symm '' t ↔ e.symm.symm '' s ⊆ t := by rw [e.symm.subset_image] + s ⊆ e.symm '' t ↔ e.symm.symm '' s ⊆ t := by rw [e.symm.symm_image_subset] _ ↔ e '' s ⊆ t := by rw [e.symm_symm] -#align equiv.subset_image' Equiv.subset_image' +#align equiv.subset_image' Equiv.subset_symm_image + +@[deprecated] alias subset_image' := Equiv.subset_symm_image -- deprecated since 2024-01-19 @[simp] theorem symm_image_image {α β} (e : α ≃ β) (s : Set α) : e.symm '' (e '' s) = s := diff --git a/Mathlib/Logic/Function/Basic.lean b/Mathlib/Logic/Function/Basic.lean index 80056acaad0f0..8387a384f58c3 100644 --- a/Mathlib/Logic/Function/Basic.lean +++ b/Mathlib/Logic/Function/Basic.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Logic.Nonempty import Mathlib.Init.Set +import Mathlib.Logic.Basic #align_import logic.function.basic from "leanprover-community/mathlib"@"29cb56a7b35f72758b05a30490e1f10bd62c35c1" @@ -37,16 +38,6 @@ theorem const_def {y : β} : (fun _ : α ↦ y) = const α y := rfl #align function.const_def Function.const_def -@[simp] -theorem const_comp {f : α → β} {c : γ} : const β c ∘ f = const α c := - rfl -#align function.const_comp Function.const_comp - -@[simp] -theorem comp_const {f : β → γ} {b : β} : f ∘ const α b = const α (f b) := - rfl -#align function.comp_const Function.comp_const - theorem const_injective [Nonempty α] : Injective (const α : β → α → β) := fun y₁ y₂ h ↦ let ⟨x⟩ := ‹Nonempty α› congr_fun h x @@ -162,14 +153,13 @@ lemma Injective.dite (p : α → Prop) [DecidablePred p] {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β} (hf : Injective f) (hf' : Injective f') (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) : - Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) := -by intros x₁ x₂ h - dsimp only at h - by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂ - · rw [dif_pos h₁, dif_pos h₂] at h; injection (hf h) - · rw [dif_pos h₁, dif_neg h₂] at h; exact (im_disj h).elim - · rw [dif_neg h₁, dif_pos h₂] at h; exact (im_disj h.symm).elim - · rw [dif_neg h₁, dif_neg h₂] at h; injection (hf' h) + Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) := fun x₁ x₂ h => by + dsimp only at h + by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂ + · rw [dif_pos h₁, dif_pos h₂] at h; injection (hf h) + · rw [dif_pos h₁, dif_neg h₂] at h; exact (im_disj h).elim + · rw [dif_neg h₁, dif_pos h₂] at h; exact (im_disj h.symm).elim + · rw [dif_neg h₁, dif_neg h₂] at h; injection (hf' h) #align function.injective.dite Function.Injective.dite theorem Surjective.of_comp {g : γ → α} (S : Surjective (f ∘ g)) : Surjective f := fun y ↦ @@ -209,12 +199,12 @@ protected theorem Surjective.forall (hf : Surjective f) {p : β → Prop} : protected theorem Surjective.forall₂ (hf : Surjective f) {p : β → β → Prop} : (∀ y₁ y₂, p y₁ y₂) ↔ ∀ x₁ x₂, p (f x₁) (f x₂) := - hf.forall.trans $ forall_congr' fun _ ↦ hf.forall + hf.forall.trans <| forall_congr' fun _ ↦ hf.forall #align function.surjective.forall₂ Function.Surjective.forall₂ protected theorem Surjective.forall₃ (hf : Surjective f) {p : β → β → β → Prop} : (∀ y₁ y₂ y₃, p y₁ y₂ y₃) ↔ ∀ x₁ x₂ x₃, p (f x₁) (f x₂) (f x₃) := - hf.forall.trans $ forall_congr' fun _ ↦ hf.forall₂ + hf.forall.trans <| forall_congr' fun _ ↦ hf.forall₂ #align function.surjective.forall₃ Function.Surjective.forall₃ protected theorem Surjective.exists (hf : Surjective f) {p : β → Prop} : @@ -400,8 +390,8 @@ theorem RightInverse.leftInverse_of_injective {f : α → β} {g : β → α} : theorem LeftInverse.eq_rightInverse {f : α → β} {g₁ g₂ : β → α} (h₁ : LeftInverse g₁ f) (h₂ : RightInverse g₂ f) : g₁ = g₂ := calc - g₁ = g₁ ∘ f ∘ g₂ := by rw [h₂.comp_eq_id, comp.right_id] - _ = g₂ := by rw [← comp.assoc, h₁.comp_eq_id, comp.left_id] + g₁ = g₁ ∘ f ∘ g₂ := by rw [h₂.comp_eq_id, comp_id] + _ = g₂ := by rw [← comp.assoc, h₁.comp_eq_id, id_comp] #align function.left_inverse.eq_right_inverse Function.LeftInverse.eq_rightInverse attribute [local instance] Classical.propDecidable @@ -802,7 +792,7 @@ theorem Injective.surjective_comp_right [Nonempty γ] (hf : Injective f) : theorem Bijective.comp_right (hf : Bijective f) : Bijective fun g : β → γ ↦ g ∘ f := ⟨hf.surjective.injective_comp_right, fun g ↦ ⟨g ∘ surjInv hf.surjective, - by simp only [comp.assoc g _ f, (leftInverse_surjInv hf).comp_eq_id, comp.right_id]⟩⟩ + by simp only [comp.assoc g _ f, (leftInverse_surjInv hf).comp_eq_id, comp_id]⟩⟩ #align function.bijective.comp_right Function.Bijective.comp_right end Extend diff --git a/Mathlib/Logic/Function/Conjugate.lean b/Mathlib/Logic/Function/Conjugate.lean index 1635771c55849..d7f6e31f0fe43 100644 --- a/Mathlib/Logic/Function/Conjugate.lean +++ b/Mathlib/Logic/Function/Conjugate.lean @@ -36,37 +36,67 @@ namespace Semiconj variable {f fab : α → β} {fbc : β → γ} {ga ga' : α → α} {gb gb' : β → β} {gc gc' : γ → γ} -protected theorem comp_eq (h : Semiconj f ga gb) : f ∘ ga = gb ∘ f := - funext h +/-- Definition of `Function.Semiconj` in terms of functional equality. -/ +lemma _root_.Function.semiconj_iff_comp_eq : Semiconj f ga gb ↔ f ∘ ga = gb ∘ f := funext_iff.symm + +protected alias ⟨comp_eq, _⟩ := semiconj_iff_comp_eq #align function.semiconj.comp_eq Function.Semiconj.comp_eq protected theorem eq (h : Semiconj f ga gb) (x : α) : f (ga x) = gb (f x) := h x #align function.semiconj.eq Function.Semiconj.eq +/-- If `f` semiconjugates `ga` to `gb` and `ga'` to `gb'`, +then it semiconjugates `ga ∘ ga'` to `gb ∘ gb'`. -/ theorem comp_right (h : Semiconj f ga gb) (h' : Semiconj f ga' gb') : - Semiconj f (ga ∘ ga') (gb ∘ gb') := - fun x ↦ by simp only [comp_apply, h.eq, h'.eq] + Semiconj f (ga ∘ ga') (gb ∘ gb') := fun x ↦ by + simp only [comp_apply, h.eq, h'.eq] #align function.semiconj.comp_right Function.Semiconj.comp_right -theorem comp_left (hab : Semiconj fab ga gb) (hbc : Semiconj fbc gb gc) : +/-- If `fab : α → β` semiconjugates `ga` to `gb` and `fbc : β → γ` semiconjugates `gb` to `gc`, +then `fbc ∘ fab` semiconjugates `ga` to `gc`. + +See also `Function.Semiconj.comp_left` for a version with reversed arguments. -/ +protected theorem trans (hab : Semiconj fab ga gb) (hbc : Semiconj fbc gb gc) : + Semiconj (fbc ∘ fab) ga gc := fun x ↦ by + simp only [comp_apply, hab.eq, hbc.eq] +#align function.semiconj.comp_left Function.Semiconj.trans + +/-- If `fbc : β → γ` semiconjugates `gb` to `gc` and `fab : α → β` semiconjugates `ga` to `gb`, +then `fbc ∘ fab` semiconjugates `ga` to `gc`. + +See also `Function.Semiconj.trans` for a version with reversed arguments. + +**Backward compatibility note:** before 2024/01/13, +this lemma used to have the same order of arguments that `Function.Semiconj.trans` has now. -/ +theorem comp_left (hbc : Semiconj fbc gb gc) (hab : Semiconj fab ga gb) : Semiconj (fbc ∘ fab) ga gc := - fun x ↦ by simp only [comp_apply, hab.eq, hbc.eq] -#align function.semiconj.comp_left Function.Semiconj.comp_left + hab.trans hbc -theorem id_right : Semiconj f id id := - fun _ ↦ rfl +/-- Any function semiconjugates the identity function to the identity function. -/ +theorem id_right : Semiconj f id id := fun _ ↦ rfl #align function.semiconj.id_right Function.Semiconj.id_right -theorem id_left : Semiconj id ga ga := - fun _ ↦ rfl +/-- The identity function semiconjugates any function to itself. -/ +theorem id_left : Semiconj id ga ga := fun _ ↦ rfl #align function.semiconj.id_left Function.Semiconj.id_left +/-- If `f : α → β` semiconjugates `ga : α → α` to `gb : β → β`, +`ga'` is a right inverse of `ga`, and `gb'` is a left inverse of `gb`, +then `f` semiconjugates `ga'` to `gb'` as well. -/ theorem inverses_right (h : Semiconj f ga gb) (ha : RightInverse ga' ga) (hb : LeftInverse gb' gb) : - Semiconj f ga' gb' := - fun x ↦ by rw [← hb (f (ga' x)), ← h.eq, ha x] + Semiconj f ga' gb' := fun x ↦ by + rw [← hb (f (ga' x)), ← h.eq, ha x] #align function.semiconj.inverses_right Function.Semiconj.inverses_right +/-- If `f` semiconjugates `ga` to `gb` and `f'` is both a left and a right inverse of `f`, +then `f'` semiconjugates `gb` to `ga`. -/ +lemma inverse_left {f' : β → α} (h : Semiconj f ga gb) + (hf₁ : LeftInverse f' f) (hf₂ : RightInverse f' f) : Semiconj f' gb ga := fun x ↦ by + rw [← hf₁.injective.eq_iff, h, hf₂, hf₂] + +/-- If `f : α → β` semiconjugates `ga : α → α` to `gb : β → β`, +then `Option.map f` semiconjugates `Option.map ga` to `Option.map gb`. -/ theorem option_map {f : α → β} {ga : α → α} {gb : β → β} (h : Semiconj f ga gb) : Semiconj (Option.map f) (Option.map ga) (Option.map gb) | none => rfl @@ -100,33 +130,35 @@ definitionally equal but have different dot-notation lemmas. -/ theorem semiconj (h : Commute f g) : Semiconj f g g := h @[refl] -theorem refl (f : α → α) : Commute f f := - fun _ ↦ Eq.refl _ +theorem refl (f : α → α) : Commute f f := fun _ ↦ Eq.refl _ #align function.commute.refl Function.Commute.refl @[symm] -theorem symm (h : Commute f g) : Commute g f := - fun x ↦ (h x).symm +theorem symm (h : Commute f g) : Commute g f := fun x ↦ (h x).symm #align function.commute.symm Function.Commute.symm +/-- If `f` commutes with `g` and `g'`, then it commutes with `g ∘ g'`. -/ theorem comp_right (h : Commute f g) (h' : Commute f g') : Commute f (g ∘ g') := Semiconj.comp_right h h' #align function.commute.comp_right Function.Commute.comp_right -theorem comp_left (h : Commute f g) (h' : Commute f' g) : Commute (f ∘ f') g := - (h.symm.comp_right h'.symm).symm +/-- If `f` and `f'` commute with `g`, then `f ∘ f'` commutes with `g` as well. -/ +nonrec theorem comp_left (h : Commute f g) (h' : Commute f' g) : Commute (f ∘ f') g := + h.comp_left h' #align function.commute.comp_left Function.Commute.comp_left -theorem id_right : Commute f id := - Semiconj.id_right +/-- Any self-map commutes with the identity map. -/ +theorem id_right : Commute f id := Semiconj.id_right #align function.commute.id_right Function.Commute.id_right +/-- The identity map commutes with any self-map. -/ theorem id_left : Commute id f := Semiconj.id_left #align function.commute.id_left Function.Commute.id_left -theorem option_map {f g : α → α} : Commute f g → Commute (Option.map f) (Option.map g) := - Semiconj.option_map +/-- If `f` commutes with `g`, then `Option.map f` commutes with `Option.map g`. -/ +nonrec theorem option_map {f g : α → α} (h : Commute f g) : Commute (Option.map f) (Option.map g) := + h.option_map #align function.commute.option_map Function.Commute.option_map end Commute diff --git a/Mathlib/Logic/Function/Iterate.lean b/Mathlib/Logic/Function/Iterate.lean index 09f3b151eb3e6..1c60f5679c9f1 100644 --- a/Mathlib/Logic/Function/Iterate.lean +++ b/Mathlib/Logic/Function/Iterate.lean @@ -69,7 +69,7 @@ theorem iterate_succ_apply (n : ℕ) (x : α) : f^[n.succ] x = f^[n] (f x) := @[simp] theorem iterate_id (n : ℕ) : (id : α → α)^[n] = id := - Nat.recOn n rfl fun n ihn ↦ by rw [iterate_succ, ihn, comp.left_id] + Nat.recOn n rfl fun n ihn ↦ by rw [iterate_succ, ihn, id_comp] #align function.iterate_id Function.iterate_id theorem iterate_add (m : ℕ) : ∀ n : ℕ, f^[m + n] = f^[m] ∘ f^[n] @@ -125,7 +125,7 @@ theorem iterate_left {g : ℕ → α → α} (H : ∀ n, Semiconj f (g n) (g <| exact id_left | succ n ihn => rw [Nat.succ_eq_add_one, Nat.add_right_comm, Nat.add_assoc] - exact (H k).comp_left (ihn (k + 1)) + exact (H k).trans (ihn (k + 1)) #align function.semiconj.iterate_left Function.Semiconj.iterate_left end Semiconj diff --git a/Mathlib/Logic/IsEmpty.lean b/Mathlib/Logic/IsEmpty.lean index 6f12933a53994..9b10e299d2ccd 100644 --- a/Mathlib/Logic/IsEmpty.lean +++ b/Mathlib/Logic/IsEmpty.lean @@ -153,6 +153,14 @@ theorem isEmpty_pi {π : α → Sort*} : IsEmpty (∀ a, π a) ↔ ∃ a, IsEmpt simp only [← not_nonempty_iff, Classical.nonempty_pi, not_forall] #align is_empty_pi isEmpty_pi +@[simp] +theorem isEmpty_fun : IsEmpty (α → β) ↔ Nonempty α ∧ IsEmpty β := by + rw [isEmpty_pi, ← exists_true_iff_nonempty, ← exists_and_right, true_and] + +@[simp] +theorem nonempty_fun : Nonempty (α → β) ↔ IsEmpty α ∨ Nonempty β := + not_iff_not.mp <| by rw [not_or, not_nonempty_iff, not_nonempty_iff, isEmpty_fun, not_isEmpty_iff] + @[simp] theorem isEmpty_sigma {α} {E : α → Type*} : IsEmpty (Sigma E) ↔ ∀ a, IsEmpty (E a) := by simp only [← not_nonempty_iff, nonempty_sigma, not_exists] diff --git a/Mathlib/Logic/Nonempty.lean b/Mathlib/Logic/Nonempty.lean index 2775263e88129..f25c74f095e65 100644 --- a/Mathlib/Logic/Nonempty.lean +++ b/Mathlib/Logic/Nonempty.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Init.ZeroOne -import Mathlib.Logic.Basic +import Mathlib.Init.Function #align_import logic.nonempty from "leanprover-community/mathlib"@"d2d8742b0c21426362a9dacebc6005db895ca963" @@ -25,10 +25,10 @@ set_option autoImplicit true variable {γ : α → Type*} -instance (priority := 20) Zero.nonempty [Zero α] : Nonempty α := +instance (priority := 20) Zero.instNonempty [Zero α] : Nonempty α := ⟨0⟩ -instance (priority := 20) One.nonempty [One α] : Nonempty α := +instance (priority := 20) One.instNonempty [One α] : Nonempty α := ⟨1⟩ theorem exists_true_iff_nonempty {α : Sort*} : (∃ _ : α, True) ↔ Nonempty α := @@ -155,15 +155,15 @@ theorem Nonempty.elim_to_inhabited {α : Sort*} [h : Nonempty α] {p : Prop} (f h.elim <| f ∘ Inhabited.mk #align nonempty.elim_to_inhabited Nonempty.elim_to_inhabited -protected instance Prod.Nonempty {α β} [h : Nonempty α] [h2 : Nonempty β] : Nonempty (α × β) := +protected instance Prod.instNonempty {α β} [h : Nonempty α] [h2 : Nonempty β] : Nonempty (α × β) := h.elim fun g ↦ h2.elim fun g2 ↦ ⟨⟨g, g2⟩⟩ -protected instance Pi.Nonempty {ι : Sort*} {α : ι → Sort*} [∀ i, Nonempty (α i)] : +protected instance Pi.instNonempty {ι : Sort*} {α : ι → Sort*} [∀ i, Nonempty (α i)] : Nonempty (∀ i, α i) := ⟨fun _ ↦ Classical.arbitrary _⟩ theorem Classical.nonempty_pi {ι} {α : ι → Sort*} : Nonempty (∀ i, α i) ↔ ∀ i, Nonempty (α i) := - ⟨fun ⟨f⟩ a ↦ ⟨f a⟩, @Pi.Nonempty _ _⟩ + ⟨fun ⟨f⟩ a ↦ ⟨f a⟩, @Pi.instNonempty _ _⟩ #align classical.nonempty_pi Classical.nonempty_pi theorem subsingleton_of_not_nonempty {α : Sort*} (h : ¬Nonempty α) : Subsingleton α := diff --git a/Mathlib/Logic/Nontrivial/Defs.lean b/Mathlib/Logic/Nontrivial/Defs.lean index f9cebabe09c90..589a0519b12b4 100644 --- a/Mathlib/Logic/Nontrivial/Defs.lean +++ b/Mathlib/Logic/Nontrivial/Defs.lean @@ -3,7 +3,9 @@ Copyright (c) 2020 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 Mathlib.Init.Logic import Mathlib.Init.Function +import Mathlib.Tactic.TypeStar #align_import logic.nontrivial from "leanprover-community/mathlib"@"48fb5b5280e7c81672afc9524185ae994553ebf4" diff --git a/Mathlib/Logic/Pairwise.lean b/Mathlib/Logic/Pairwise.lean index 930ee764dd484..65666e0d74508 100644 --- a/Mathlib/Logic/Pairwise.lean +++ b/Mathlib/Logic/Pairwise.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Logic.Function.Basic -import Mathlib.Logic.Relation import Mathlib.Init.Set import Mathlib.Tactic.Common diff --git a/Mathlib/Logic/Relator.lean b/Mathlib/Logic/Relator.lean index 1bb3e1be03234..c18faf8840c0c 100644 --- a/Mathlib/Logic/Relator.lean +++ b/Mathlib/Logic/Relator.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ -import Mathlib.Logic.Basic +import Mathlib.Init.Function #align_import logic.relator from "leanprover-community/mathlib"@"c4658a649d216f57e99621708b09dcb3dcccbd23" @@ -135,7 +135,7 @@ lemma rel_iff : ((·↔·) ⇒ (·↔·) ⇒ (·↔·)) (·↔·) (·↔·) := #align relator.rel_iff Relator.rel_iff lemma rel_eq {r : α → β → Prop} (hr : BiUnique r) : (r ⇒ r ⇒ (·↔·)) (·=·) (·=·) := - fun _ _ h₁ _ _ h₂ => ⟨fun h => hr.right h₁ $ h.symm ▸ h₂, fun h => hr.left h₁ $ h.symm ▸ h₂⟩ + fun _ _ h₁ _ _ h₂ => ⟨fun h => hr.right h₁ <| h.symm ▸ h₂, fun h => hr.left h₁ <| h.symm ▸ h₂⟩ #align relator.rel_eq Relator.rel_eq open Function diff --git a/Mathlib/Mathport/Notation.lean b/Mathlib/Mathport/Notation.lean index 86f6e6b78a12e..16c9d3af4baed 100644 --- a/Mathlib/Mathport/Notation.lean +++ b/Mathlib/Mathport/Notation.lean @@ -4,11 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kyle Miller -/ import Mathlib.Lean.Elab.Term -import Mathlib.Lean.Expr import Mathlib.Lean.PrettyPrinter.Delaborator import Mathlib.Tactic.ScopedNS import Mathlib.Util.Syntax -import Std.Data.Option.Basic +import Std.Linter.UnreachableTactic +import Std.Util.ExtendedBinder /-! # The notation3 macro, simulating Lean 3's notation. diff --git a/Mathlib/Mathport/Rename.lean b/Mathlib/Mathport/Rename.lean index c87acc945db71..e81f9af349f6c 100644 --- a/Mathlib/Mathport/Rename.lean +++ b/Mathlib/Mathport/Rename.lean @@ -3,7 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Daniel Selsam -/ -import Lean +import Lean.Elab.Command +import Lean.Linter.Util set_option autoImplicit true @@ -187,7 +188,7 @@ syntax (name := noalign) "#noalign " ident : command @[command_elab noalign] def elabNoAlign : CommandElab | `(#noalign $id3:ident) => do withRef id3 <| ensureUnused id3.getId - liftCoreM $ addNameAlignment id3.getId .anonymous + liftCoreM <| addNameAlignment id3.getId .anonymous | _ => throwUnsupportedSyntax /-- Show information about the alignment status of a lean 3 definition. -/ diff --git a/Mathlib/Mathport/Syntax.lean b/Mathlib/Mathport/Syntax.lean index 84b71343007e6..79eaaf1b29b5e 100644 --- a/Mathlib/Mathport/Syntax.lean +++ b/Mathlib/Mathport/Syntax.lean @@ -61,6 +61,7 @@ import Mathlib.Tactic.Measurability import Mathlib.Tactic.MkIffOfInductiveProp import Mathlib.Tactic.ModCases import Mathlib.Tactic.Monotonicity +import Mathlib.Tactic.NoncommRing import Mathlib.Tactic.Nontriviality import Mathlib.Tactic.NormNum import Mathlib.Tactic.NthRewrite @@ -210,8 +211,6 @@ syntax termList := " [" term,* "]" /- E -/ syntax (name := applyNormed) "apply_normed " term : tactic -/- E -/ syntax (name := noncommRing) "noncomm_ring" : tactic - /- B -/ syntax (name := acMono) "ac_mono" ("*" <|> ("^" num))? (config)? ((" : " term) <|> (" := " term))? : tactic diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean index 450fd905a4a82..718a20d11c086 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean @@ -1963,7 +1963,7 @@ def finiteSpanningSetsInIooRat (μ : Measure ℝ) [IsLocallyFiniteMeasure μ] : finite n := measure_Ioo_lt_top spanning := iUnion_eq_univ_iff.2 fun x => - ⟨⌊|x|⌋₊, neg_lt.1 ((neg_le_abs_self x).trans_lt (Nat.lt_floor_add_one _)), + ⟨⌊|x|⌋₊, neg_lt.1 ((neg_le_abs x).trans_lt (Nat.lt_floor_add_one _)), (le_abs_self x).trans_lt (Nat.lt_floor_add_one _)⟩ #align real.finite_spanning_sets_in_Ioo_rat Real.finiteSpanningSetsInIooRat diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/ContinuousLinearMap.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/ContinuousLinearMap.lean index e0ceaa1193e7a..f43be918fcc4c 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/ContinuousLinearMap.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/ContinuousLinearMap.lean @@ -3,8 +3,9 @@ Copyright (c) 2020 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot -/ -import Mathlib.Analysis.NormedSpace.FiniteDimension import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic +import Mathlib.Analysis.NormedSpace.OperatorNorm +import Mathlib.Topology.Algebra.Module.FiniteDimension #align_import measure_theory.constructions.borel_space.continuous_linear_map from "leanprover-community/mathlib"@"bf6a01357ff5684b1ebcd0f1a13be314fc82c0bf" diff --git a/Mathlib/MeasureTheory/Constructions/Cylinders.lean b/Mathlib/MeasureTheory/Constructions/Cylinders.lean index 861593ce0149f..263adb164347f 100644 --- a/Mathlib/MeasureTheory/Constructions/Cylinders.lean +++ b/Mathlib/MeasureTheory/Constructions/Cylinders.lean @@ -3,7 +3,10 @@ Copyright (c) 2023 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne, Peter Pfaffelhuber -/ -import Mathlib.MeasureTheory.Constructions.Pi +import Mathlib.MeasureTheory.PiSystem +import Mathlib.Order.OmegaCompletePartialOrder +import Mathlib.Topology.Constructions +import Mathlib.MeasureTheory.MeasurableSpace.Basic /-! # π-systems of cylinders and square cylinders diff --git a/Mathlib/MeasureTheory/Constructions/Prod/Basic.lean b/Mathlib/MeasureTheory/Constructions/Prod/Basic.lean index decdc84c54ed3..906b6d3e57202 100644 --- a/Mathlib/MeasureTheory/Constructions/Prod/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/Prod/Basic.lean @@ -233,6 +233,44 @@ theorem MeasurableEmbedding.prod_mk {α β γ δ : Type*} {mα : MeasurableSpace exact MeasurableSet.iUnion hg #align measurable_embedding.prod_mk MeasurableEmbedding.prod_mk +lemma MeasurableEmbedding.prod_mk_left {β γ : Type*} [MeasurableSingletonClass α] + {mβ : MeasurableSpace β} {mγ : MeasurableSpace γ} + (x : α) {f : γ → β} (hf : MeasurableEmbedding f) : + MeasurableEmbedding (fun y ↦ (x, f y)) where + injective := by + intro y y' + simp only [Prod.mk.injEq, true_and] + exact fun h ↦ hf.injective h + measurable := Measurable.prod_mk measurable_const hf.measurable + measurableSet_image' := by + intro s hs + convert (MeasurableSet.singleton x).prod (hf.measurableSet_image.mpr hs) + ext x + simp + +lemma measurableEmbedding_prod_mk_left [MeasurableSingletonClass α] (x : α) : + MeasurableEmbedding (Prod.mk x : β → α × β) := + MeasurableEmbedding.prod_mk_left x MeasurableEmbedding.id + +lemma MeasurableEmbedding.prod_mk_right {β γ : Type*} [MeasurableSingletonClass α] + {mβ : MeasurableSpace β} {mγ : MeasurableSpace γ} + {f : γ → β} (hf : MeasurableEmbedding f) (x : α) : + MeasurableEmbedding (fun y ↦ (f y, x)) where + injective := by + intro y y' + simp only [Prod.mk.injEq, and_true] + exact fun h ↦ hf.injective h + measurable := Measurable.prod_mk hf.measurable measurable_const + measurableSet_image' := by + intro s hs + convert (hf.measurableSet_image.mpr hs).prod (MeasurableSet.singleton x) + ext x + simp + +lemma measurableEmbedding_prod_mk_right [MeasurableSingletonClass α] (x : α) : + MeasurableEmbedding (fun y ↦ (y, x) : β → β × α) := + MeasurableEmbedding.prod_mk_right MeasurableEmbedding.id x + /-- The Lebesgue integral is measurable. This shows that the integrand of (the right-hand-side of) Tonelli's theorem is measurable. -/ theorem Measurable.lintegral_prod_right' [SFinite ν] : diff --git a/Mathlib/MeasureTheory/Constructions/Projective.lean b/Mathlib/MeasureTheory/Constructions/Projective.lean index 74f1c69477b4a..9ee5f1faacb68 100644 --- a/Mathlib/MeasureTheory/Constructions/Projective.lean +++ b/Mathlib/MeasureTheory/Constructions/Projective.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne, Peter Pfaffelhuber -/ import Mathlib.MeasureTheory.Constructions.Cylinders +import Mathlib.MeasureTheory.Measure.Typeclasses /-! # Projective measure families and projective limits diff --git a/Mathlib/MeasureTheory/Covering/Besicovitch.lean b/Mathlib/MeasureTheory/Covering/Besicovitch.lean index 76fe1079012fa..c6c051cbb8c89 100644 --- a/Mathlib/MeasureTheory/Covering/Besicovitch.lean +++ b/Mathlib/MeasureTheory/Covering/Besicovitch.lean @@ -9,6 +9,7 @@ import Mathlib.MeasureTheory.Integral.Lebesgue import Mathlib.MeasureTheory.Measure.Regular import Mathlib.SetTheory.Ordinal.Arithmetic import Mathlib.Topology.MetricSpace.Basic +import Mathlib.Data.Set.Pairwise.Lattice #align_import measure_theory.covering.besicovitch from "leanprover-community/mathlib"@"5f6e827d81dfbeb6151d7016586ceeb0099b9655" @@ -250,7 +251,7 @@ noncomputable def index : Ordinal.{u} → β -- return an index `b` for which the center `c b` is not in `Z`, and the radius is at -- least `R / τ`, if such an index exists (and garbage otherwise). Classical.epsilon fun b : β => p.c b ∉ Z ∧ R ≤ p.τ * p.r b - termination_by index i => i + termination_by i => i decreasing_by exact j.2 #align besicovitch.tau_package.index Besicovitch.TauPackage.index @@ -280,7 +281,7 @@ noncomputable def color : Ordinal.{u} → ℕ (_ : (closedBall (p.c (p.index j)) (p.r (p.index j)) ∩ closedBall (p.c (p.index i)) (p.r (p.index i))).Nonempty), {color j} sInf (univ \ A) - termination_by color i => i + termination_by i => i decreasing_by exact j.2 #align besicovitch.tau_package.color Besicovitch.TauPackage.color @@ -328,12 +329,11 @@ theorem mem_iUnionUpTo_lastStep (x : β) : p.c x ∈ p.iUnionUpTo p.lastStep := have B : p.τ⁻¹ * p.R p.lastStep < p.R p.lastStep := by conv_rhs => rw [← one_mul (p.R p.lastStep)] exact mul_lt_mul (inv_lt_one p.one_lt_tau) le_rfl Rpos zero_le_one - obtain ⟨y, hy1, hy2⟩ : - ∃ y : β, p.c y ∉ p.iUnionUpTo p.lastStep ∧ p.τ⁻¹ * p.R p.lastStep < p.r y := by + obtain ⟨y, hy1, hy2⟩ : ∃ y, p.c y ∉ p.iUnionUpTo p.lastStep ∧ p.τ⁻¹ * p.R p.lastStep < p.r y := by have := exists_lt_of_lt_csSup ?_ B · simpa only [exists_prop, mem_range, exists_exists_and_eq_and, Subtype.exists, Subtype.coe_mk] - rw [← image_univ, nonempty_image_iff] + rw [← image_univ, image_nonempty] exact ⟨⟨_, h⟩, mem_univ _⟩ rcases A y with (Hy | Hy) · exact hy1 Hy @@ -548,10 +548,8 @@ there are no satellite configurations with `N+1` points. theorem exist_finset_disjoint_balls_large_measure (μ : Measure α) [IsFiniteMeasure μ] {N : ℕ} {τ : ℝ} (hτ : 1 < τ) (hN : IsEmpty (SatelliteConfig α N τ)) (s : Set α) (r : α → ℝ) (rpos : ∀ x ∈ s, 0 < r x) (rle : ∀ x ∈ s, r x ≤ 1) : - ∃ t : Finset α, - ↑t ⊆ s ∧ - μ (s \ ⋃ x ∈ t, closedBall x (r x)) ≤ N / (N + 1) * μ s ∧ - (t : Set α).PairwiseDisjoint fun x => closedBall x (r x) := by + ∃ t : Finset α, ↑t ⊆ s ∧ μ (s \ ⋃ x ∈ t, closedBall x (r x)) ≤ N / (N + 1) * μ s ∧ + (t : Set α).PairwiseDisjoint fun x => closedBall x (r x) := by -- exclude the trivial case where `μ s = 0`. rcases le_or_lt (μ s) 0 with (hμs | hμs) · have : μ s = 0 := le_bot_iff.1 hμs @@ -688,12 +686,9 @@ For a version giving the conclusion in a nicer form, see `exists_disjoint_closed theorem exists_disjoint_closedBall_covering_ae_of_finiteMeasure_aux (μ : Measure α) [IsFiniteMeasure μ] (f : α → Set ℝ) (s : Set α) (hf : ∀ x ∈ s, ∀ δ > 0, (f x ∩ Ioo 0 δ).Nonempty) : - ∃ t : Set (α × ℝ), - t.Countable ∧ - (∀ p : α × ℝ, p ∈ t → p.1 ∈ s) ∧ - (∀ p : α × ℝ, p ∈ t → p.2 ∈ f p.1) ∧ - μ (s \ ⋃ (p : α × ℝ) (_ : p ∈ t), closedBall p.1 p.2) = 0 ∧ - t.PairwiseDisjoint fun p => closedBall p.1 p.2 := by + ∃ t : Set (α × ℝ), t.Countable ∧ (∀ p ∈ t, p.1 ∈ s) ∧ (∀ p ∈ t, p.2 ∈ f p.1) ∧ + μ (s \ ⋃ (p : α × ℝ) (_ : p ∈ t), closedBall p.1 p.2) = 0 ∧ + t.PairwiseDisjoint fun p => closedBall p.1 p.2 := by rcases HasBesicovitchCovering.no_satelliteConfig (α := α) with ⟨N, τ, hτ, hN⟩ /- Introduce a property `P` on finsets saying that we have a nice disjoint covering of a subset of `s` by admissible balls. -/ @@ -832,10 +827,9 @@ For a version giving the conclusion in a nicer form, see `exists_disjoint_closed -/ theorem exists_disjoint_closedBall_covering_ae_aux (μ : Measure α) [SigmaFinite μ] (f : α → Set ℝ) (s : Set α) (hf : ∀ x ∈ s, ∀ δ > 0, (f x ∩ Ioo 0 δ).Nonempty) : - ∃ t : Set (α × ℝ), t.Countable ∧ (∀ p : α × ℝ, p ∈ t → p.1 ∈ s) ∧ - (∀ p : α × ℝ, p ∈ t → p.2 ∈ f p.1) ∧ - μ (s \ ⋃ (p : α × ℝ) (_ : p ∈ t), closedBall p.1 p.2) = 0 ∧ - t.PairwiseDisjoint fun p => closedBall p.1 p.2 := by + ∃ t : Set (α × ℝ), t.Countable ∧ (∀ p ∈ t, p.1 ∈ s) ∧ (∀ p ∈ t, p.2 ∈ f p.1) ∧ + μ (s \ ⋃ (p : α × ℝ) (_ : p ∈ t), closedBall p.1 p.2) = 0 ∧ + t.PairwiseDisjoint fun p => closedBall p.1 p.2 := by /- This is deduced from the finite measure case, by using a finite measure with respect to which the initial sigma-finite measure is absolutely continuous. -/ rcases exists_absolutelyContinuous_isFiniteMeasure μ with ⟨ν, hν, hμν⟩ @@ -859,57 +853,19 @@ theorem exists_disjoint_closedBall_covering_ae (μ : Measure α) [SigmaFinite μ (∀ x ∈ t, r x ∈ f x ∩ Ioo 0 (R x)) ∧ μ (s \ ⋃ x ∈ t, closedBall x (r x)) = 0 ∧ t.PairwiseDisjoint fun x => closedBall x (r x) := by let g x := f x ∩ Ioo 0 (R x) - have hg : ∀ x ∈ s, ∀ δ > 0, (g x ∩ Ioo 0 δ).Nonempty := by - intro x hx δ δpos + have hg : ∀ x ∈ s, ∀ δ > 0, (g x ∩ Ioo 0 δ).Nonempty := fun x hx δ δpos ↦ by rcases hf x hx (min δ (R x)) (lt_min δpos (hR x hx)) with ⟨r, hr⟩ - exact - ⟨r, - ⟨⟨hr.1, hr.2.1, hr.2.2.trans_le (min_le_right _ _)⟩, - ⟨hr.2.1, hr.2.2.trans_le (min_le_left _ _)⟩⟩⟩ + exact ⟨r, ⟨⟨hr.1, hr.2.1, hr.2.2.trans_le (min_le_right _ _)⟩, + ⟨hr.2.1, hr.2.2.trans_le (min_le_left _ _)⟩⟩⟩ rcases exists_disjoint_closedBall_covering_ae_aux μ g s hg with ⟨v, v_count, vs, vg, μv, v_disj⟩ - let t := Prod.fst '' v - have : ∀ x ∈ t, ∃ r : ℝ, (x, r) ∈ v := by - intro x hx - rcases (mem_image _ _ _).1 hx with ⟨⟨p, q⟩, hp, rfl⟩ - exact ⟨q, hp⟩ - choose! r hr using this - have im_t : (fun x => (x, r x)) '' t = v := by - have I : ∀ p : α × ℝ, p ∈ v → 0 ≤ p.2 := fun p hp => (vg p hp).2.1.le - apply Subset.antisymm - · simp only [image_subset_iff] - rintro ⟨x, p⟩ hxp - simp only [mem_preimage] - exact hr _ (mem_image_of_mem _ hxp) - · rintro ⟨x, p⟩ hxp - have hxrx : (x, r x) ∈ v := hr _ (mem_image_of_mem _ hxp) - have : p = r x := by - by_contra h - have A : (x, p) ≠ (x, r x) := by - simpa only [true_and_iff, Prod.mk.inj_iff, eq_self_iff_true, Ne.def] using h - have H := v_disj hxp hxrx A - contrapose H - rw [not_disjoint_iff_nonempty_inter] - refine' ⟨x, by simp (config := { proj := false }) [I _ hxp, I _ hxrx]⟩ - rw [this] - apply mem_image_of_mem - exact mem_image_of_mem _ hxp - refine' ⟨t, r, v_count.image _, _, _, _, _⟩ - · intro x hx - rcases (mem_image _ _ _).1 hx with ⟨⟨p, q⟩, hp, rfl⟩ - exact vs _ hp - · intro x hx - rcases (mem_image _ _ _).1 hx with ⟨⟨p, q⟩, _, rfl⟩ - exact vg _ (hr _ hx) - · have : - ⋃ (x : α) (_ : x ∈ t), closedBall x (r x) = - ⋃ (p : α × ℝ) (_ : p ∈ (fun x => (x, r x)) '' t), closedBall p.1 p.2 := - by conv_rhs => rw [biUnion_image] - rw [this, im_t] - exact μv - · have A : InjOn (fun x : α => (x, r x)) t := by - simp (config := { contextual := true }) only [InjOn, Prod.mk.inj_iff, imp_true_iff, - eq_self_iff_true] - rwa [← im_t, A.pairwiseDisjoint_image] at v_disj + obtain ⟨r, t, rfl⟩ : ∃ (r : α → ℝ) (t : Set α), v = graphOn r t := by + have I : ∀ p ∈ v, 0 ≤ p.2 := fun p hp => (vg p hp).2.1.le + rw [exists_eq_graphOn] + refine fun x hx y hy heq ↦ v_disj.eq hx hy <| not_disjoint_iff.2 ⟨x.1, ?_⟩ + simp [*] + have hinj : InjOn (fun x ↦ (x, r x)) t := LeftInvOn.injOn (f₁' := Prod.fst) fun _ _ ↦ rfl + simp only [graphOn, ball_image_iff, biUnion_image, hinj.pairwiseDisjoint_image] at * + exact ⟨t, r, countable_of_injective_of_countable_image hinj v_count, vs, vg, μv, v_disj⟩ #align besicovitch.exists_disjoint_closed_ball_covering_ae Besicovitch.exists_disjoint_closedBall_covering_ae /-- In a space with the Besicovitch property, any set `s` can be covered with balls whose measures @@ -1085,22 +1041,14 @@ theorem exists_closedBall_covering_tsum_measure_le (μ : Measure α) [SigmaFinit /-! ### Consequences on differentiation of measures -/ - /-- In a space with the Besicovitch covering property, the set of closed balls with positive radius forms a Vitali family. This is essentially a restatement of the measurable Besicovitch theorem. -/ protected def vitaliFamily (μ : Measure α) [SigmaFinite μ] : VitaliFamily μ where setsAt x := (fun r : ℝ => closedBall x r) '' Ioi (0 : ℝ) - MeasurableSet' := by - intro x y hy - obtain ⟨r, _, rfl⟩ : ∃ r : ℝ, 0 < r ∧ closedBall x r = y := by - simpa only [mem_image, mem_Ioi] using hy - exact isClosed_ball.measurableSet - nonempty_interior := by - intro x y hy - obtain ⟨r, rpos, rfl⟩ : ∃ r : ℝ, 0 < r ∧ closedBall x r = y := by - simpa only [mem_image, mem_Ioi] using hy - simp only [Nonempty.mono ball_subset_interior_closedBall, rpos, nonempty_ball] - Nontrivial x ε εpos := ⟨closedBall x ε, mem_image_of_mem _ εpos, Subset.refl _⟩ + measurableSet _ := ball_image_iff.2 fun _ _ ↦ isClosed_ball.measurableSet + nonempty_interior _ := ball_image_iff.2 fun r rpos ↦ + (nonempty_ball.2 rpos).mono ball_subset_interior_closedBall + nontrivial x ε εpos := ⟨closedBall x ε, mem_image_of_mem _ εpos, Subset.rfl⟩ covering := by intro s f fsubset ffine let g : α → Set ℝ := fun x => {r | 0 < r ∧ closedBall x r ∈ f x} diff --git a/Mathlib/MeasureTheory/Covering/Differentiation.lean b/Mathlib/MeasureTheory/Covering/Differentiation.lean index 392596f7e5807..febdb75256aea 100644 --- a/Mathlib/MeasureTheory/Covering/Differentiation.lean +++ b/Mathlib/MeasureTheory/Covering/Differentiation.lean @@ -136,7 +136,7 @@ theorem measure_le_of_frequently_le [SecondCountableTopology α] [BorelSpace α] apply v.fineSubfamilyOn_of_frequently f s fun x hx => ?_ have := (hs x hx).and_eventually - ((v.eventually_filterAt_mem_sets x).and + ((v.eventually_filterAt_mem_setsAt x).and (v.eventually_filterAt_subset_of_nhds (U_open.mem_nhds (sU hx)))) apply Frequently.mono this rintro a ⟨ρa, _, aU⟩ diff --git a/Mathlib/MeasureTheory/Covering/Vitali.lean b/Mathlib/MeasureTheory/Covering/Vitali.lean index 34bafa877746a..2f95826bbc724 100644 --- a/Mathlib/MeasureTheory/Covering/Vitali.lean +++ b/Mathlib/MeasureTheory/Covering/Vitali.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic import Mathlib.MeasureTheory.Covering.VitaliFamily +import Mathlib.Data.Set.Pairwise.Lattice #align_import measure_theory.covering.vitali from "leanprover-community/mathlib"@"bf6a01357ff5684b1ebcd0f1a13be314fc82c0bf" @@ -116,7 +117,7 @@ theorem exists_disjoint_subfamily_covering_enlargment (B : ι → Set α) (t : S rw [div_lt_iff (zero_lt_one.trans hτ)] conv_lhs => rw [← mul_one m] exact (mul_lt_mul_left mpos).2 hτ - rcases exists_lt_of_lt_csSup (nonempty_image_iff.2 Anonempty) I with ⟨x, xA, hx⟩ + rcases exists_lt_of_lt_csSup (Anonempty.image _) I with ⟨x, xA, hx⟩ rcases (mem_image _ _ _).1 xA with ⟨a', ha', rfl⟩ exact ⟨a', ha', hx.le⟩ clear hat hu a_disj a @@ -291,7 +292,7 @@ theorem exists_disjoint_covering_ae [MetricSpace α] [MeasurableSpace α] [Opens exact lt_irrefl _ (R0pos.trans_le (le_of_eq R0_def)) obtain ⟨a, hav, R0a⟩ : ∃ a ∈ v, R0 / 2 < r a := by obtain ⟨r', r'mem, hr'⟩ : ∃ r' ∈ r '' v, R0 / 2 < r' := - exists_lt_of_lt_csSup (nonempty_image_iff.2 vnonempty) (half_lt_self R0pos) + exists_lt_of_lt_csSup (vnonempty.image _) (half_lt_self R0pos) rcases (mem_image _ _ _).1 r'mem with ⟨a, hav, rfl⟩ exact ⟨a, hav, hr'⟩ refine' ⟨8 * R0, _, _⟩ @@ -404,9 +405,9 @@ protected def vitaliFamily [MetricSpace α] [MeasurableSpace α] [OpensMeasurabl VitaliFamily μ where setsAt x := { a | IsClosed a ∧ (interior a).Nonempty ∧ ∃ r, a ⊆ closedBall x r ∧ μ (closedBall x (3 * r)) ≤ C * μ a } - MeasurableSet' x a ha := ha.1.measurableSet + measurableSet x a ha := ha.1.measurableSet nonempty_interior x a ha := ha.2.1 - Nontrivial x ε εpos := by + nontrivial x ε εpos := by obtain ⟨r, μr, rpos, rε⟩ : ∃ r, μ (closedBall x (3 * r)) ≤ C * μ (closedBall x r) ∧ r ∈ Ioc (0 : ℝ) ε := ((h x).and_eventually (Ioc_mem_nhdsWithin_Ioi ⟨le_rfl, εpos⟩)).exists diff --git a/Mathlib/MeasureTheory/Covering/VitaliFamily.lean b/Mathlib/MeasureTheory/Covering/VitaliFamily.lean index c8bde019a7485..d46b159878b12 100644 --- a/Mathlib/MeasureTheory/Covering/VitaliFamily.lean +++ b/Mathlib/MeasureTheory/Covering/VitaliFamily.lean @@ -66,15 +66,22 @@ differentiations of measure that apply in both contexts. -/ -- @[nolint has_nonempty_instance] -- Porting note: This linter does not exist yet. structure VitaliFamily {m : MeasurableSpace α} (μ : Measure α) where - setsAt : ∀ _ : α, Set (Set α) - MeasurableSet' : ∀ x : α, ∀ a : Set α, a ∈ setsAt x → MeasurableSet a - nonempty_interior : ∀ x : α, ∀ y : Set α, y ∈ setsAt x → (interior y).Nonempty - Nontrivial : ∀ (x : α), ∀ ε > (0 : ℝ), ∃ y ∈ setsAt x, y ⊆ closedBall x ε - covering : ∀ (s : Set α) (f : ∀ _ : α, Set (Set α)), + /-- Sets of the family "centered" at a given point. -/ + setsAt : α → Set (Set α) + /-- All sets of the family are measurable. -/ + measurableSet : ∀ x : α, ∀ s ∈ setsAt x, MeasurableSet s + /-- All sets of the family have nonempty interior. -/ + nonempty_interior : ∀ x : α, ∀ s ∈ setsAt x, (interior s).Nonempty + /-- For any closed ball around `x`, there exists a set of the family contained in this ball. -/ + nontrivial : ∀ (x : α), ∀ ε > (0 : ℝ), ∃ s ∈ setsAt x, s ⊆ closedBall x ε + /-- Consider a (possibly non-measurable) set `s`, + and for any `x` in `s` a subfamily `f x` of `setsAt x` + containing sets of arbitrarily small diameter. + Then one can extract a disjoint subfamily covering almost all `s`. -/ + covering : ∀ (s : Set α) (f : α → Set (Set α)), (∀ x ∈ s, f x ⊆ setsAt x) → (∀ x ∈ s, ∀ ε > (0 : ℝ), ∃ a ∈ f x, a ⊆ closedBall x ε) → - ∃ t : Set (α × Set α), - (∀ p : α × Set α, p ∈ t → p.1 ∈ s) ∧ (t.PairwiseDisjoint fun p => p.2) ∧ - (∀ p : α × Set α, p ∈ t → p.2 ∈ f p.1) ∧ μ (s \ ⋃ (p : α × Set α) (_ : p ∈ t), p.2) = 0 + ∃ t : Set (α × Set α), (∀ p ∈ t, p.1 ∈ s) ∧ (t.PairwiseDisjoint fun p ↦ p.2) ∧ + (∀ p ∈ t, p.2 ∈ f p.1) ∧ μ (s \ ⋃ p ∈ t, p.2) = 0 #align vitali_family VitaliFamily namespace VitaliFamily @@ -84,13 +91,10 @@ variable {m0 : MeasurableSpace α} {μ : Measure α} /-- A Vitali family for a measure `μ` is also a Vitali family for any measure absolutely continuous with respect to `μ`. -/ def mono (v : VitaliFamily μ) (ν : Measure α) (hν : ν ≪ μ) : VitaliFamily ν where - setsAt := v.setsAt - MeasurableSet' := v.MeasurableSet' - nonempty_interior := v.nonempty_interior - Nontrivial := v.Nontrivial - covering s f h h' := by - rcases v.covering s f h h' with ⟨t, ts, disj, mem_f, hμ⟩ - exact ⟨t, ts, disj, mem_f, hν hμ⟩ + __ := v + covering s f h h' := + let ⟨t, ts, disj, mem_f, hμ⟩ := v.covering s f h h' + ⟨t, ts, disj, mem_f, hν hμ⟩ #align vitali_family.mono VitaliFamily.mono /-- Given a Vitali family `v` for a measure `μ`, a family `f` is a fine subfamily on a set `s` if @@ -159,7 +163,7 @@ theorem index_countable [SecondCountableTopology α] : h.index.Countable := protected theorem measurableSet_u {p : α × Set α} (hp : p ∈ h.index) : MeasurableSet (h.covering p) := - v.MeasurableSet' p.1 _ (h.covering_mem_family hp) + v.measurableSet p.1 _ (h.covering_mem_family hp) #align vitali_family.fine_subfamily_on.measurable_set_u VitaliFamily.FineSubfamilyOn.measurableSet_u theorem measure_le_tsum_of_absolutelyContinuous [SecondCountableTopology α] {ρ : Measure α} @@ -185,15 +189,15 @@ contained in a `δ`-neighborhood on `x`. This does not change the local filter a can be convenient to get a nicer global behavior. -/ def enlarge (v : VitaliFamily μ) (δ : ℝ) (δpos : 0 < δ) : VitaliFamily μ where setsAt x := v.setsAt x ∪ { a | MeasurableSet a ∧ (interior a).Nonempty ∧ ¬a ⊆ closedBall x δ } - MeasurableSet' x a ha := by + measurableSet x a ha := by cases' ha with ha ha - exacts [v.MeasurableSet' _ _ ha, ha.1] + exacts [v.measurableSet _ _ ha, ha.1] nonempty_interior x a ha := by cases' ha with ha ha exacts [v.nonempty_interior _ _ ha, ha.2.1] - Nontrivial := by + nontrivial := by intro x ε εpos - rcases v.Nontrivial x ε εpos with ⟨a, ha, h'a⟩ + rcases v.nontrivial x ε εpos with ⟨a, ha, h'a⟩ exact ⟨a, mem_union_left _ ha, h'a⟩ covering := by intro s f fset ffine @@ -215,30 +219,24 @@ variable (v : VitaliFamily μ) /-- Given a vitali family `v`, then `v.filterAt x` is the filter on `Set α` made of those families that contain all sets of `v.setsAt x` of a sufficiently small diameter. This filter makes it possible to express limiting behavior when sets in `v.setsAt x` shrink to `x`. -/ -def filterAt (x : α) : Filter (Set α) := - ⨅ ε ∈ Ioi (0 : ℝ), 𝓟 ({ a ∈ v.setsAt x | a ⊆ closedBall x ε }) +def filterAt (x : α) : Filter (Set α) := (𝓝 x).smallSets ⊓ 𝓟 (v.setsAt x) #align vitali_family.filter_at VitaliFamily.filterAt +theorem _root_.Filter.HasBasis.vitaliFamily {ι : Sort*} {p : ι → Prop} {s : ι → Set α} {x : α} + (h : (𝓝 x).HasBasis p s) : (v.filterAt x).HasBasis p (fun i ↦ {t ∈ v.setsAt x | t ⊆ s i}) := by + simpa only [← Set.setOf_inter_eq_sep] using h.smallSets.inf_principal _ + +theorem filterAt_basis_closedBall (x : α) : + (v.filterAt x).HasBasis (0 < ·) ({a ∈ v.setsAt x | a ⊆ closedBall x ·}) := + nhds_basis_closedBall.vitaliFamily v + theorem mem_filterAt_iff {x : α} {s : Set (Set α)} : s ∈ v.filterAt x ↔ ∃ ε > (0 : ℝ), ∀ a ∈ v.setsAt x, a ⊆ closedBall x ε → a ∈ s := by - simp only [filterAt, exists_prop, gt_iff_lt] - rw [mem_biInf_of_directed] - · simp only [subset_def, and_imp, exists_prop, mem_sep_iff, mem_Ioi, mem_principal] - · simp only [DirectedOn, exists_prop, ge_iff_le, le_principal_iff, mem_Ioi, Order.Preimage, - mem_principal] - intro x hx y hy - refine' ⟨min x y, lt_min hx hy, - fun a ha => ⟨ha.1, ha.2.trans (closedBall_subset_closedBall (min_le_left _ _))⟩, - fun a ha => ⟨ha.1, ha.2.trans (closedBall_subset_closedBall (min_le_right _ _))⟩⟩ - · exact ⟨(1 : ℝ), mem_Ioi.2 zero_lt_one⟩ + simp only [(v.filterAt_basis_closedBall x).mem_iff, ← and_imp]; rfl #align vitali_family.mem_filter_at_iff VitaliFamily.mem_filterAt_iff -instance filterAt_neBot (x : α) : (v.filterAt x).NeBot := by - simp only [neBot_iff, ← empty_mem_iff_bot, mem_filterAt_iff, not_exists, exists_prop, - mem_empty_iff_false, and_true_iff, gt_iff_lt, not_and, Ne.def, not_false_iff, not_forall] - intro ε εpos - obtain ⟨w, w_sets, hw⟩ : ∃ w ∈ v.setsAt x, w ⊆ closedBall x ε := v.Nontrivial x ε εpos - exact ⟨w, w_sets, hw⟩ +instance filterAt_neBot (x : α) : (v.filterAt x).NeBot := + (v.filterAt_basis_closedBall x).neBot_iff.2 <| v.nontrivial _ _ #align vitali_family.filter_at_ne_bot VitaliFamily.filterAt_neBot theorem eventually_filterAt_iff {x : α} {P : Set α → Prop} : @@ -246,44 +244,34 @@ theorem eventually_filterAt_iff {x : α} {P : Set α → Prop} : v.mem_filterAt_iff #align vitali_family.eventually_filter_at_iff VitaliFamily.eventually_filterAt_iff -theorem eventually_filterAt_mem_sets (x : α) : ∀ᶠ a in v.filterAt x, a ∈ v.setsAt x := by - simp (config := { contextual := true }) only [eventually_filterAt_iff, exists_prop, and_true_iff, - gt_iff_lt, imp_true_iff] - exact ⟨1, zero_lt_one⟩ -#align vitali_family.eventually_filter_at_mem_sets VitaliFamily.eventually_filterAt_mem_sets - -theorem eventually_filterAt_subset_closedBall (x : α) {ε : ℝ} (hε : 0 < ε) : - ∀ᶠ a : Set α in v.filterAt x, a ⊆ closedBall x ε := by - simp only [v.eventually_filterAt_iff] - exact ⟨ε, hε, fun a _ ha' => ha'⟩ -#align vitali_family.eventually_filter_at_subset_closed_ball VitaliFamily.eventually_filterAt_subset_closedBall - theorem tendsto_filterAt_iff {ι : Type*} {l : Filter ι} {f : ι → Set α} {x : α} : Tendsto f l (v.filterAt x) ↔ (∀ᶠ i in l, f i ∈ v.setsAt x) ∧ ∀ ε > (0 : ℝ), ∀ᶠ i in l, f i ⊆ closedBall x ε := by - refine' ⟨fun H => ⟨H.eventually <| v.eventually_filterAt_mem_sets x, - fun ε hε => H.eventually <| v.eventually_filterAt_subset_closedBall x hε⟩, - fun H s hs => (_ : ∀ᶠ i in l, f i ∈ s)⟩ - obtain ⟨ε, εpos, hε⟩ := v.mem_filterAt_iff.mp hs - filter_upwards [H.1, H.2 ε εpos] with i hi hiε using hε _ hi hiε + simp only [filterAt, tendsto_inf, nhds_basis_closedBall.smallSets.tendsto_right_iff, + tendsto_principal, and_comm, mem_powerset_iff] #align vitali_family.tendsto_filter_at_iff VitaliFamily.tendsto_filterAt_iff +theorem eventually_filterAt_mem_setsAt (x : α) : ∀ᶠ a in v.filterAt x, a ∈ v.setsAt x := + (v.tendsto_filterAt_iff.mp tendsto_id).1 +#align vitali_family.eventually_filter_at_mem_sets VitaliFamily.eventually_filterAt_mem_setsAt + +theorem eventually_filterAt_subset_closedBall (x : α) {ε : ℝ} (hε : 0 < ε) : + ∀ᶠ a : Set α in v.filterAt x, a ⊆ closedBall x ε := + (v.tendsto_filterAt_iff.mp tendsto_id).2 ε hε +#align vitali_family.eventually_filter_at_subset_closed_ball VitaliFamily.eventually_filterAt_subset_closedBall + theorem eventually_filterAt_measurableSet (x : α) : ∀ᶠ a in v.filterAt x, MeasurableSet a := by - filter_upwards [v.eventually_filterAt_mem_sets x] with _ ha using v.MeasurableSet' _ _ ha + filter_upwards [v.eventually_filterAt_mem_setsAt x] with _ ha using v.measurableSet _ _ ha #align vitali_family.eventually_filter_at_measurable_set VitaliFamily.eventually_filterAt_measurableSet theorem frequently_filterAt_iff {x : α} {P : Set α → Prop} : (∃ᶠ a in v.filterAt x, P a) ↔ ∀ ε > (0 : ℝ), ∃ a ∈ v.setsAt x, a ⊆ closedBall x ε ∧ P a := by - simp only [Filter.Frequently, eventually_filterAt_iff, not_exists, exists_prop, not_and, - Classical.not_not, not_forall] + simp only [(v.filterAt_basis_closedBall x).frequently_iff, ← and_assoc]; rfl #align vitali_family.frequently_filter_at_iff VitaliFamily.frequently_filterAt_iff theorem eventually_filterAt_subset_of_nhds {x : α} {o : Set α} (hx : o ∈ 𝓝 x) : - ∀ᶠ a in v.filterAt x, a ⊆ o := by - rw [eventually_filterAt_iff] - rcases Metric.mem_nhds_iff.1 hx with ⟨ε, εpos, hε⟩ - exact ⟨ε / 2, half_pos εpos, - fun a _ ha => ha.trans ((closedBall_subset_ball (half_lt_self εpos)).trans hε)⟩ + ∀ᶠ a in v.filterAt x, a ⊆ o := + (eventually_smallSets_subset.2 hx).filter_mono inf_le_left #align vitali_family.eventually_filter_at_subset_of_nhds VitaliFamily.eventually_filterAt_subset_of_nhds theorem fineSubfamilyOn_of_frequently (v : VitaliFamily μ) (f : α → Set (Set α)) (s : Set α) diff --git a/Mathlib/MeasureTheory/Decomposition/Jordan.lean b/Mathlib/MeasureTheory/Decomposition/Jordan.lean index cdf829059c6bd..4e794463d15bf 100644 --- a/Mathlib/MeasureTheory/Decomposition/Jordan.lean +++ b/Mathlib/MeasureTheory/Decomposition/Jordan.lean @@ -298,6 +298,8 @@ theorem subset_negative_null_set (hu : MeasurableSet u) (hv : MeasurableSet v) exact this hw₁ hw₂ hwt #align measure_theory.signed_measure.subset_negative_null_set MeasureTheory.SignedMeasure.subset_negative_null_set +open scoped symmDiff + /-- If the symmetric difference of two positive sets is a null-set, then so are the differences between the two sets. -/ theorem of_diff_eq_zero_of_symmDiff_eq_zero_positive (hu : MeasurableSet u) (hv : MeasurableSet v) diff --git a/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean b/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean index 2da64473aadd6..e166c87a53e3d 100644 --- a/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kexing Ying -/ import Mathlib.MeasureTheory.Measure.Sub -import Mathlib.MeasureTheory.Decomposition.Jordan -import Mathlib.MeasureTheory.Measure.WithDensityVectorMeasure +import Mathlib.MeasureTheory.Decomposition.SignedHahn +import Mathlib.MeasureTheory.Function.AEEqOfIntegral #align_import measure_theory.decomposition.lebesgue from "leanprover-community/mathlib"@"b2ff9a3d7a15fd5b0f060b135421d6a89a999c2f" @@ -545,7 +545,7 @@ See also `rnDeriv_smul_right'`, which requires sigma-finite `ν` and `μ`. -/ theorem rnDeriv_smul_right (ν μ : Measure α) [IsFiniteMeasure ν] [ν.HaveLebesgueDecomposition μ] {r : ℝ≥0} (hr : r ≠ 0) : ν.rnDeriv (r • μ) =ᵐ[μ] r⁻¹ • ν.rnDeriv μ := by - refine (absolutelyContinuous_smul $ ENNReal.coe_ne_zero.2 hr).ae_le + refine (absolutelyContinuous_smul <| ENNReal.coe_ne_zero.2 hr).ae_le (?_ : ν.rnDeriv (r • μ) =ᵐ[r • μ] r⁻¹ • ν.rnDeriv μ) rw [← withDensity_eq_iff] rotate_left @@ -1015,7 +1015,7 @@ See also `rnDeriv_smul_right`, which has no hypothesis on `μ` but requires fini theorem rnDeriv_smul_right' (ν μ : Measure α) [SigmaFinite ν] [SigmaFinite μ] {r : ℝ≥0} (hr : r ≠ 0) : ν.rnDeriv (r • μ) =ᵐ[μ] r⁻¹ • ν.rnDeriv μ := by - refine (absolutelyContinuous_smul $ ENNReal.coe_ne_zero.2 hr).ae_le + refine (absolutelyContinuous_smul <| ENNReal.coe_ne_zero.2 hr).ae_le (?_ : ν.rnDeriv (r • μ) =ᵐ[r • μ] r⁻¹ • ν.rnDeriv μ) rw [← withDensity_eq_iff_of_sigmaFinite] · simp_rw [ENNReal.smul_def] diff --git a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean index 2548a786a2ba2..4e0a46c539ad0 100644 --- a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean +++ b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean @@ -416,6 +416,7 @@ theorem exists_isCompl_positive_negative (s : SignedMeasure α) : ⟨i, iᶜ, hi₁, hi₂, hi₁.compl, hi₃, isCompl_compl⟩ #align measure_theory.signed_measure.exists_is_compl_positive_negative MeasureTheory.SignedMeasure.exists_isCompl_positive_negative +open scoped symmDiff in /-- The symmetric difference of two Hahn decompositions has measure zero. -/ theorem of_symmDiff_compl_positive_negative {s : SignedMeasure α} {i j : Set α} (hi : MeasurableSet i) (hj : MeasurableSet j) (hi' : 0 ≤[i] s ∧ s ≤[iᶜ] 0) diff --git a/Mathlib/MeasureTheory/Decomposition/SignedLebesgue.lean b/Mathlib/MeasureTheory/Decomposition/SignedLebesgue.lean index d5d43fd1a86d3..a5b8a1c4047fd 100644 --- a/Mathlib/MeasureTheory/Decomposition/SignedLebesgue.lean +++ b/Mathlib/MeasureTheory/Decomposition/SignedLebesgue.lean @@ -5,6 +5,8 @@ Authors: Kexing Ying -/ import Mathlib.MeasureTheory.Decomposition.Lebesgue import Mathlib.MeasureTheory.Measure.Complex +import Mathlib.MeasureTheory.Decomposition.Jordan +import Mathlib.MeasureTheory.Measure.WithDensityVectorMeasure /-! # Lebesgue decomposition diff --git a/Mathlib/MeasureTheory/Function/AEEqFun.lean b/Mathlib/MeasureTheory/Function/AEEqFun.lean index 400c0d6e60bef..ff960ebb04af1 100644 --- a/Mathlib/MeasureTheory/Function/AEEqFun.lean +++ b/Mathlib/MeasureTheory/Function/AEEqFun.lean @@ -939,7 +939,7 @@ section Abs theorem coeFn_abs {β} [TopologicalSpace β] [Lattice β] [TopologicalLattice β] [AddGroup β] [TopologicalAddGroup β] (f : α →ₘ[μ] β) : ⇑|f| =ᵐ[μ] fun x => |f x| := by - simp_rw [abs_eq_sup_neg] + simp_rw [abs] filter_upwards [AEEqFun.coeFn_sup f (-f), AEEqFun.coeFn_neg f] with x hx_sup hx_neg rw [hx_sup, hx_neg, Pi.neg_apply] #align measure_theory.ae_eq_fun.coe_fn_abs MeasureTheory.AEEqFun.coeFn_abs diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean index 799b206df9975..8faf5f61cf0df 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean @@ -3,8 +3,10 @@ Copyright (c) 2021 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ -import Mathlib.MeasureTheory.Function.L2Space import Mathlib.MeasureTheory.Function.StronglyMeasurable.Lp +import Mathlib.MeasureTheory.Integral.Bochner +import Mathlib.Order.Filter.IndicatorFunction +import Mathlib.MeasureTheory.Function.StronglyMeasurable.Inner #align_import measure_theory.function.conditional_expectation.ae_measurable from "leanprover-community/mathlib"@"d8bbb04e2d2a44596798a9207ceefc0fb236e41e" @@ -568,8 +570,8 @@ variable {m m0 : MeasurableSpace α} {μ : Measure α} [Fact (1 ≤ p)] [NormedS theorem Lp.induction_stronglyMeasurable_aux (hm : m ≤ m0) (hp_ne_top : p ≠ ∞) (P : Lp F p μ → Prop) (h_ind : ∀ (c : F) {s : Set α} (hs : MeasurableSet[m] s) (hμs : μ s < ∞), P (Lp.simpleFunc.indicatorConst p (hm s hs) hμs.ne c)) - (h_add : ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, ∀ _ : AEStronglyMeasurable' m f μ, - ∀ _ : AEStronglyMeasurable' m g μ, Disjoint (Function.support f) (Function.support g) → + (h_add : ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, AEStronglyMeasurable' m f μ → + AEStronglyMeasurable' m g μ → Disjoint (Function.support f) (Function.support g) → P (hf.toLp f) → P (hg.toLp g) → P (hf.toLp f + hg.toLp g)) (h_closed : IsClosed {f : lpMeas F ℝ m p μ | P f}) : ∀ f : Lp F p μ, AEStronglyMeasurable' m f μ → P f := by @@ -621,15 +623,15 @@ sub-σ-algebra `m` in a normed space, it suffices to show that theorem Lp.induction_stronglyMeasurable (hm : m ≤ m0) (hp_ne_top : p ≠ ∞) (P : Lp F p μ → Prop) (h_ind : ∀ (c : F) {s : Set α} (hs : MeasurableSet[m] s) (hμs : μ s < ∞), P (Lp.simpleFunc.indicatorConst p (hm s hs) hμs.ne c)) - (h_add : ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, ∀ _ : StronglyMeasurable[m] f, - ∀ _ : StronglyMeasurable[m] g, Disjoint (Function.support f) (Function.support g) → + (h_add : ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, StronglyMeasurable[m] f → + StronglyMeasurable[m] g → Disjoint (Function.support f) (Function.support g) → P (hf.toLp f) → P (hg.toLp g) → P (hf.toLp f + hg.toLp g)) (h_closed : IsClosed {f : lpMeas F ℝ m p μ | P f}) : ∀ f : Lp F p μ, AEStronglyMeasurable' m f μ → P f := by intro f hf suffices h_add_ae : - ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, ∀ _ : AEStronglyMeasurable' m f μ, - ∀ _ : AEStronglyMeasurable' m g μ, Disjoint (Function.support f) (Function.support g) → + ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, AEStronglyMeasurable' m f μ → + AEStronglyMeasurable' m g μ → Disjoint (Function.support f) (Function.support g) → P (hf.toLp f) → P (hg.toLp g) → P (hf.toLp f + hg.toLp g) -- Porting note: `P` should be an explicit argument to `Lp.induction_stronglyMeasurable_aux`, but -- it isn't? diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean index 42eb31c58f50b..654b6ab8ab651 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean @@ -5,6 +5,7 @@ Authors: Rémy Degenne -/ import Mathlib.Analysis.InnerProductSpace.Projection import Mathlib.MeasureTheory.Function.ConditionalExpectation.Unique +import Mathlib.MeasureTheory.Function.L2Space #align_import measure_theory.function.conditional_expectation.condexp_L2 from "leanprover-community/mathlib"@"d8bbb04e2d2a44596798a9207ceefc0fb236e41e" diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index 6861a8904fe56..0edc072674d23 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -71,7 +71,7 @@ theorem snorm_one_condexp_le_snorm (f : α → ℝ) : snorm (μ[f|m]) 1 μ ≤ s (ae_of_all μ (fun x => le_abs_self (f x) : ∀ x, f x ≤ |f x|)), EventuallyLE.trans (condexp_neg f).symm.le (condexp_mono hf.neg hf.abs - (ae_of_all μ (fun x => neg_le_abs_self (f x): ∀ x, -f x ≤ |f x|)))] with x hx₁ hx₂ + (ae_of_all μ (fun x => neg_le_abs (f x): ∀ x, -f x ≤ |f x|)))] with x hx₁ hx₂ exact abs_le_abs hx₁ hx₂ _ = snorm f 1 μ := by rw [snorm_one_eq_lintegral_nnnorm, snorm_one_eq_lintegral_nnnorm, ← @@ -130,7 +130,7 @@ theorem set_integral_abs_condexp_le {s : Set α} (hs : MeasurableSet[m] s) (f : swap; · exact hnm _ hs refine' integral_congr_ae _ have : (fun x => |(μ[s.indicator f|m]) x|) =ᵐ[μ] fun x => |s.indicator (μ[f|m]) x| := - EventuallyEq.fun_comp (condexp_indicator hfint hs) _ + (condexp_indicator hfint hs).fun_comp abs refine' EventuallyEq.trans (eventually_of_forall fun x => _) this.symm rw [← Real.norm_eq_abs, norm_indicator_eq_indicator_norm] rfl diff --git a/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean b/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean index 697563e5e04fd..1ca984e4a6b22 100644 --- a/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean +++ b/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean @@ -208,7 +208,7 @@ theorem Memℒp.exists_hasCompactSupport_integral_rpow_sub_le rwa [(hf.sub g_mem).snorm_eq_integral_rpow_norm B ENNReal.coe_ne_top, ENNReal.ofReal_le_ofReal_iff I.le, one_div, ENNReal.toReal_ofReal hp.le, Real.rpow_le_rpow_iff _ hε.le (inv_pos.2 hp)] at hg - exact integral_nonneg fun x => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + exact integral_nonneg fun x => Real.rpow_nonneg (norm_nonneg _) _ #align measure_theory.mem_ℒp.exists_has_compact_support_integral_rpow_sub_le MeasureTheory.Memℒp.exists_hasCompactSupport_integral_rpow_sub_le /-- In a locally compact space, any integrable function can be approximated by compactly supported @@ -301,7 +301,7 @@ theorem Memℒp.exists_boundedContinuous_integral_rpow_sub_le [μ.WeaklyRegular] rwa [(hf.sub g_mem).snorm_eq_integral_rpow_norm B ENNReal.coe_ne_top, ENNReal.ofReal_le_ofReal_iff I.le, one_div, ENNReal.toReal_ofReal hp.le, Real.rpow_le_rpow_iff _ hε.le (inv_pos.2 hp)] at hg - exact integral_nonneg fun x => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + exact integral_nonneg fun x => Real.rpow_nonneg (norm_nonneg _) _ #align measure_theory.mem_ℒp.exists_bounded_continuous_integral_rpow_sub_le MeasureTheory.Memℒp.exists_boundedContinuous_integral_rpow_sub_le /-- Any integrable function can be approximated by bounded continuous functions, diff --git a/Mathlib/MeasureTheory/Function/Jacobian.lean b/Mathlib/MeasureTheory/Function/Jacobian.lean index 014e914c37edf..ac65d0c779cd7 100644 --- a/Mathlib/MeasureTheory/Function/Jacobian.lean +++ b/Mathlib/MeasureTheory/Function/Jacobian.lean @@ -4,12 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Analysis.Calculus.Deriv.Basic -import Mathlib.Analysis.Calculus.InverseFunctionTheorem.FDeriv import Mathlib.MeasureTheory.Constructions.BorelSpace.ContinuousLinearMap import Mathlib.MeasureTheory.Covering.BesicovitchVectorSpace import Mathlib.MeasureTheory.Measure.Lebesgue.EqHaar import Mathlib.Analysis.NormedSpace.Pointwise import Mathlib.MeasureTheory.Constructions.Polish +import Mathlib.Analysis.Calculus.InverseFunctionTheorem.ApproximatesLinearOn #align_import measure_theory.function.jacobian from "leanprover-community/mathlib"@"b84aee748341da06a6d78491367e2c0e9f15e8a5" diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index c727a24a5b14b..29ad3435d2a72 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -388,7 +388,7 @@ theorem HasFiniteIntegral.max_zero {f : α → ℝ} (hf : HasFiniteIntegral f μ theorem HasFiniteIntegral.min_zero {f : α → ℝ} (hf : HasFiniteIntegral f μ) : HasFiniteIntegral (fun a => min (f a) 0) μ := - hf.mono <| eventually_of_forall fun x => by simpa [abs_le] using neg_abs_le_self _ + hf.mono <| eventually_of_forall fun x => by simpa [abs_le] using neg_abs_le _ #align measure_theory.has_finite_integral.min_zero MeasureTheory.HasFiniteIntegral.min_zero end PosPart @@ -849,7 +849,7 @@ lemma Integrable.measure_le_lt_top {f : α → ℝ} (hf : Integrable f μ) {c : refine lt_of_le_of_lt (measure_mono ?_) (hf.measure_norm_ge_lt_top (show 0 < -c by linarith)) intro x hx simp only [Real.norm_eq_abs, Set.mem_setOf_eq] at hx ⊢ - exact (show -c ≤ - f x by linarith).trans (neg_le_abs_self _) + exact (show -c ≤ - f x by linarith).trans (neg_le_abs _) /-- If `f` is `ℝ`-valued and integrable, then for any `c > 0` the set `{x | f x > c}` has finite measure. -/ diff --git a/Mathlib/MeasureTheory/Function/LpOrder.lean b/Mathlib/MeasureTheory/Function/LpOrder.lean index cf8cc95723e8e..d9f7fee0bd76f 100644 --- a/Mathlib/MeasureTheory/Function/LpOrder.lean +++ b/Mathlib/MeasureTheory/Function/LpOrder.lean @@ -25,8 +25,7 @@ import Mathlib.MeasureTheory.Function.LpSpace set_option linter.uppercaseLean3 false -open TopologicalSpace MeasureTheory LatticeOrderedCommGroup - +open TopologicalSpace MeasureTheory open scoped ENNReal variable {α E : Type*} {m : MeasurableSpace α} {μ : Measure α} {p : ℝ≥0∞} diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm.lean b/Mathlib/MeasureTheory/Function/LpSeminorm.lean index 19bccb61537fc..74fe1e1abd51e 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne, Sébastien Gouëzel -/ import Mathlib.Analysis.NormedSpace.IndicatorFunction -import Mathlib.Analysis.SpecialFunctions.Pow.Continuity import Mathlib.MeasureTheory.Function.EssSup import Mathlib.MeasureTheory.Function.AEEqFun import Mathlib.MeasureTheory.Integral.MeanInequalities @@ -489,6 +488,7 @@ theorem snorm_congr_norm_ae {f : α → F} {g : α → G} (hfg : ∀ᵐ x ∂μ, snorm_congr_nnnorm_ae <| hfg.mono fun _x hx => NNReal.eq hx #align measure_theory.snorm_congr_norm_ae MeasureTheory.snorm_congr_norm_ae +open scoped symmDiff in theorem snorm_indicator_sub_indicator (s t : Set α) (f : α → E) : snorm (s.indicator f - t.indicator f) p μ = snorm ((s ∆ t).indicator f) p μ := snorm_congr_norm_ae <| ae_of_all _ fun x ↦ by @@ -512,7 +512,7 @@ theorem snorm'_norm_rpow (f : α → F) (p q : ℝ) (hq_pos : 0 < q) : congr ext1 x simp_rw [← ofReal_norm_eq_coe_nnnorm] - rw [Real.norm_eq_abs, abs_eq_self.mpr (Real.rpow_nonneg_of_nonneg (norm_nonneg _) _), mul_comm, ← + rw [Real.norm_eq_abs, abs_eq_self.mpr (Real.rpow_nonneg (norm_nonneg _) _), mul_comm, ← ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) hq_pos.le, ENNReal.rpow_mul] #align measure_theory.snorm'_norm_rpow MeasureTheory.snorm'_norm_rpow diff --git a/Mathlib/MeasureTheory/Function/LpSpace.lean b/Mathlib/MeasureTheory/Function/LpSpace.lean index 420cbb4b0bc1b..8964227a2d9ad 100644 --- a/Mathlib/MeasureTheory/Function/LpSpace.lean +++ b/Mathlib/MeasureTheory/Function/LpSpace.lean @@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne, Sébastien Gouëzel -/ import Mathlib.Analysis.Normed.Group.Hom +import Mathlib.Analysis.SpecialFunctions.Pow.Continuity +import Mathlib.Data.Set.Image import Mathlib.MeasureTheory.Function.LpSeminorm import Mathlib.MeasureTheory.Measure.OpenPos import Mathlib.Topology.ContinuousFunction.Compact @@ -1818,7 +1820,7 @@ theorem toLp_norm_le [NontriviallyNormedField 𝕜] [NormedSpace 𝕜 E] : theorem toLp_inj {f g : α →ᵇ E} [μ.IsOpenPosMeasure] [NormedField 𝕜] [NormedSpace 𝕜 E] : toLp (E := E) p μ 𝕜 f = toLp (E := E) p μ 𝕜 g ↔ f = g := by refine' ⟨fun h => _, by tauto⟩ - rw [← FunLike.coe_fn_eq, ← (map_continuous f).ae_eq_iff_eq μ (map_continuous g)] + rw [← DFunLike.coe_fn_eq, ← (map_continuous f).ae_eq_iff_eq μ (map_continuous g)] refine' (coeFn_toLp p μ 𝕜 f).symm.trans (EventuallyEq.trans _ <| coeFn_toLp p μ 𝕜 g) rw [h] #align bounded_continuous_function.to_Lp_inj BoundedContinuousFunction.toLp_inj diff --git a/Mathlib/MeasureTheory/Function/LpSpace/DomAct/Basic.lean b/Mathlib/MeasureTheory/Function/LpSpace/DomAct/Basic.lean index 5f18f67973e9d..cae39a424cecf 100644 --- a/Mathlib/MeasureTheory/Function/LpSpace/DomAct/Basic.lean +++ b/Mathlib/MeasureTheory/Function/LpSpace/DomAct/Basic.lean @@ -3,8 +3,8 @@ Copyright (c) 2023 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.MeasureTheory.Integral.Bochner import Mathlib.MeasureTheory.Function.AEEqFun.DomAct +import Mathlib.MeasureTheory.Function.LpSpace /-! # Action of `Mᵈᵐᵃ` on `Lᵖ` spaces diff --git a/Mathlib/MeasureTheory/Function/SimpleFunc.lean b/Mathlib/MeasureTheory/Function/SimpleFunc.lean index b0bb65acb19e3..03bcc570625b3 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFunc.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFunc.lean @@ -574,19 +574,24 @@ theorem map_mul [Mul β] [Mul γ] {g : β → γ} (hg : ∀ x y, g (x * y) = g x variable {K : Type*} +@[to_additive] instance instSMul [SMul K β] : SMul K (α →ₛ β) := ⟨fun k f => f.map (k • ·)⟩ #align measure_theory.simple_func.has_smul MeasureTheory.SimpleFunc.instSMul -@[simp] +@[to_additive (attr := simp)] theorem coe_smul [SMul K β] (c : K) (f : α →ₛ β) : ⇑(c • f) = c • ⇑f := rfl #align measure_theory.simple_func.coe_smul MeasureTheory.SimpleFunc.coe_smul +@[to_additive (attr := simp)] theorem smul_apply [SMul K β] (k : K) (f : α →ₛ β) (a : α) : (k • f) a = k • f a := rfl #align measure_theory.simple_func.smul_apply MeasureTheory.SimpleFunc.smul_apply +instance hasNatSMul [AddMonoid β] : SMul ℕ (α →ₛ β) := inferInstance + +@[to_additive existing hasNatSMul] instance hasNatPow [Monoid β] : Pow (α →ₛ β) ℕ := ⟨fun f n => f.map (· ^ n)⟩ #align measure_theory.simple_func.has_nat_pow MeasureTheory.SimpleFunc.hasNatPow @@ -1007,9 +1012,7 @@ theorem const_mul_lintegral (f : α →ₛ ℝ≥0∞) (x : ℝ≥0∞) : (const α x * f).lintegral μ = x * f.lintegral μ := calc (f.map fun a => x * a).lintegral μ = ∑ r in f.range, x * r * μ (f ⁻¹' {r}) := map_lintegral _ _ - _ = ∑ r in f.range, x * (r * μ (f ⁻¹' {r})) := - (Finset.sum_congr rfl fun _ _ => mul_assoc _ _ _) - _ = x * f.lintegral μ := Finset.mul_sum.symm + _ = x * ∑ r in f.range, r * μ (f ⁻¹' {r}) := by simp_rw [Finset.mul_sum, mul_assoc] #align measure_theory.simple_func.const_mul_lintegral MeasureTheory.SimpleFunc.const_mul_lintegral /-- Integral of a simple function `α →ₛ ℝ≥0∞` as a bilinear map. -/ diff --git a/Mathlib/MeasureTheory/Function/SpecialFunctions/IsROrC.lean b/Mathlib/MeasureTheory/Function/SpecialFunctions/IsROrC.lean index d1e18a60cd7e6..301b0d0bb3b90 100644 --- a/Mathlib/MeasureTheory/Function/SpecialFunctions/IsROrC.lean +++ b/Mathlib/MeasureTheory/Function/SpecialFunctions/IsROrC.lean @@ -3,8 +3,8 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.MeasureTheory.Function.SpecialFunctions.Basic import Mathlib.Data.IsROrC.Lemmas +import Mathlib.MeasureTheory.Constructions.BorelSpace.Complex #align_import measure_theory.function.special_functions.is_R_or_C from "leanprover-community/mathlib"@"83a66c8775fa14ee5180c85cab98e970956401ad" diff --git a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean index e13ac5df0b533..7569c2c1bfd94 100644 --- a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean +++ b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean @@ -3,10 +3,10 @@ Copyright (c) 2021 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne, Sébastien Gouëzel -/ -import Mathlib.Analysis.NormedSpace.FiniteDimension import Mathlib.Analysis.NormedSpace.BoundedLinearMaps import Mathlib.MeasureTheory.Measure.WithDensity import Mathlib.MeasureTheory.Function.SimpleFuncDense +import Mathlib.Topology.Algebra.Module.FiniteDimension #align_import measure_theory.function.strongly_measurable.basic from "leanprover-community/mathlib"@"ef95945cd48c932c9e034872bd25c3c220d9c946" @@ -425,6 +425,11 @@ theorem const_mul [Mul β] [ContinuousMul β] (hf : StronglyMeasurable f) (c : #align measure_theory.strongly_measurable.const_mul MeasureTheory.StronglyMeasurable.const_mul #align measure_theory.strongly_measurable.const_add MeasureTheory.StronglyMeasurable.const_add +@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable])) const_nsmul] +protected theorem pow [Monoid β] [ContinuousMul β] (hf : StronglyMeasurable f) (n : ℕ) : + StronglyMeasurable (f ^ n) := + ⟨fun k => hf.approx k ^ n, fun x => (hf.tendsto_approx x).pow n⟩ + @[to_additive (attr := measurability)] protected theorem inv [Inv β] [ContinuousInv β] (hf : StronglyMeasurable f) : StronglyMeasurable f⁻¹ := @@ -447,13 +452,13 @@ protected theorem smul {𝕜} [TopologicalSpace 𝕜] [SMul 𝕜 β] [Continuous #align measure_theory.strongly_measurable.smul MeasureTheory.StronglyMeasurable.smul #align measure_theory.strongly_measurable.vadd MeasureTheory.StronglyMeasurable.vadd -@[measurability] +@[to_additive (attr := measurability)] protected theorem const_smul {𝕜} [SMul 𝕜 β] [ContinuousConstSMul 𝕜 β] (hf : StronglyMeasurable f) (c : 𝕜) : StronglyMeasurable (c • f) := ⟨fun n => c • hf.approx n, fun x => (hf.tendsto_approx x).const_smul c⟩ #align measure_theory.strongly_measurable.const_smul MeasureTheory.StronglyMeasurable.const_smul -@[measurability] +@[to_additive (attr := measurability)] protected theorem const_smul' {𝕜} [SMul 𝕜 β] [ContinuousConstSMul 𝕜 β] (hf : StronglyMeasurable f) (c : 𝕜) : StronglyMeasurable fun x => c • f x := hf.const_smul c @@ -1340,13 +1345,18 @@ protected theorem smul {𝕜} [TopologicalSpace 𝕜] [SMul 𝕜 β] [Continuous #align measure_theory.ae_strongly_measurable.smul MeasureTheory.AEStronglyMeasurable.smul #align measure_theory.ae_strongly_measurable.vadd MeasureTheory.AEStronglyMeasurable.vadd -@[measurability] +@[to_additive (attr := aesop safe 20 apply (rule_sets [Measurable])) const_nsmul] +protected theorem pow [Monoid β] [ContinuousMul β] (hf : AEStronglyMeasurable f μ) (n : ℕ) : + AEStronglyMeasurable (f ^ n) μ := + ⟨hf.mk f ^ n, hf.stronglyMeasurable_mk.pow _, hf.ae_eq_mk.pow_const _⟩ + +@[to_additive (attr := measurability)] protected theorem const_smul {𝕜} [SMul 𝕜 β] [ContinuousConstSMul 𝕜 β] (hf : AEStronglyMeasurable f μ) (c : 𝕜) : AEStronglyMeasurable (c • f) μ := ⟨c • hf.mk f, hf.stronglyMeasurable_mk.const_smul c, hf.ae_eq_mk.const_smul c⟩ #align measure_theory.ae_strongly_measurable.const_smul MeasureTheory.AEStronglyMeasurable.const_smul -@[measurability] +@[to_additive (attr := measurability)] protected theorem const_smul' {𝕜} [SMul 𝕜 β] [ContinuousConstSMul 𝕜 β] (hf : AEStronglyMeasurable f μ) (c : 𝕜) : AEStronglyMeasurable (fun x => c • f x) μ := hf.const_smul c @@ -1648,14 +1658,10 @@ theorem _root_.Embedding.aestronglyMeasurable_comp_iff [PseudoMetrizableSpace β refine' ⟨fun H => aestronglyMeasurable_iff_aemeasurable_separable.2 ⟨_, _⟩, fun H => hg.continuous.comp_aestronglyMeasurable H⟩ - · let G : β → range g := codRestrict g (range g) mem_range_self + · let G : β → range g := rangeFactorization g have hG : ClosedEmbedding G := { hg.codRestrict _ _ with - closed_range := by - convert isClosed_univ (α := ↥(range g)) - apply eq_univ_of_forall - rintro ⟨-, ⟨x, rfl⟩⟩ - exact mem_range_self x } + closed_range := by rw [surjective_onto_range.range_eq]; exact isClosed_univ } have : AEMeasurable (G ∘ f) μ := AEMeasurable.subtype_mk H.aemeasurable exact hG.measurableEmbedding.aemeasurable_comp_iff.1 this · rcases (aestronglyMeasurable_iff_aemeasurable_separable.1 H).2 with ⟨t, ht, h't⟩ diff --git a/Mathlib/MeasureTheory/Function/UniformIntegrable.lean b/Mathlib/MeasureTheory/Function/UniformIntegrable.lean index 59a49dfd3cc87..d651bef8723f4 100644 --- a/Mathlib/MeasureTheory/Function/UniformIntegrable.lean +++ b/Mathlib/MeasureTheory/Function/UniformIntegrable.lean @@ -280,7 +280,7 @@ theorem Memℒp.snorm_indicator_norm_ge_le (hf : Memℒp f p μ) (hmeas : Strong nnnorm_indicator_eq_indicator_nnnorm] have hiff : M ^ (1 / p.toReal) ≤ ‖f x‖₊ ↔ M ≤ ‖‖f x‖ ^ p.toReal‖₊ := by rw [coe_nnnorm, coe_nnnorm, Real.norm_rpow_of_nonneg (norm_nonneg _), norm_norm, - ← Real.rpow_le_rpow_iff hM' (Real.rpow_nonneg_of_nonneg (norm_nonneg _) _) + ← Real.rpow_le_rpow_iff hM' (Real.rpow_nonneg (norm_nonneg _) _) (one_div_pos.2 <| ENNReal.toReal_pos hp_ne_zero hp_ne_top), ← Real.rpow_mul (norm_nonneg _), mul_one_div_cancel (ENNReal.toReal_pos hp_ne_zero hp_ne_top).ne.symm, Real.rpow_one] by_cases hx : x ∈ { x : α | M ^ (1 / p.toReal) ≤ ‖f x‖₊ } @@ -525,9 +525,7 @@ theorem tendsto_Lp_of_tendsto_ae_of_meas [IsFiniteMeasure μ] (hp : 1 ≤ p) (hp exact min_le_right _ _ have hlt : snorm (tᶜ.indicator (f n - g)) p μ ≤ ENNReal.ofReal (ε.toReal / 3) := by specialize hN n hn - have : 0 ≤ ε.toReal / (3 * measureUnivNNReal μ ^ (1 / p.toReal)) := by - rw [div_mul_eq_div_mul_one_div] - exact mul_nonneg hε'.le (one_div_nonneg.2 hpow.le) + have : 0 ≤ ε.toReal / (3 * measureUnivNNReal μ ^ (1 / p.toReal)) := by positivity have := snorm_sub_le_of_dist_bdd μ hp' htm.compl this fun x hx => (dist_comm (g x) (f n x) ▸ (hN x hx).le : dist (f n x) (g x) ≤ ε.toReal / (3 * measureUnivNNReal μ ^ (1 / p.toReal))) @@ -541,7 +539,7 @@ theorem tendsto_Lp_of_tendsto_ae_of_meas [IsFiniteMeasure μ] (hp : 1 ≤ p) (hp rw [ENNReal.ofReal_coe_nnreal, coe_measureUnivNNReal] exact measure_mono (Set.subset_univ _) · exact Real.rpow_pos_of_pos (measureUnivNNReal_pos hμ) _ - · refine' mul_nonneg hε'.le (one_div_nonneg.2 hpow.le) + · positivity have : ENNReal.ofReal (ε.toReal / 3) = ε / 3 := by rw [ENNReal.ofReal_div_of_pos (show (0 : ℝ) < 3 by norm_num), ENNReal.ofReal_toReal h.ne] simp diff --git a/Mathlib/MeasureTheory/Group/FundamentalDomain.lean b/Mathlib/MeasureTheory/Group/FundamentalDomain.lean index 2a7b5a44cdabc..a4fe63afa3537 100644 --- a/Mathlib/MeasureTheory/Group/FundamentalDomain.lean +++ b/Mathlib/MeasureTheory/Group/FundamentalDomain.lean @@ -681,9 +681,8 @@ variable [Countable G] [Group G] [MulAction G α] [MeasurableSpace α] {μ : Mea @[to_additive MeasureTheory.IsAddFundamentalDomain.measure_addFundamentalFrontier] theorem measure_fundamentalFrontier : μ (fundamentalFrontier G s) = 0 := by - simpa only [fundamentalFrontier, iUnion₂_inter, measure_iUnion_null_iff', one_smul, - measure_iUnion_null_iff, inter_comm s, Function.onFun] using fun g (hg : g ≠ 1) => - hs.aedisjoint hg + simpa only [fundamentalFrontier, iUnion₂_inter, one_smul, measure_iUnion_null_iff, inter_comm s, + Function.onFun] using fun g (hg : g ≠ 1) => hs.aedisjoint hg #align measure_theory.is_fundamental_domain.measure_fundamental_frontier MeasureTheory.IsFundamentalDomain.measure_fundamentalFrontier #align measure_theory.is_add_fundamental_domain.measure_add_fundamental_frontier MeasureTheory.IsAddFundamentalDomain.measure_addFundamentalFrontier diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index 2ff734fae1215..ad93f05faa58d 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -102,7 +102,7 @@ functions : 1. First go to the `L¹` space. - For example, if you see `ENNReal.toReal (∫⁻ a, ENNReal.ofReal $ ‖f a‖)`, that is the norm of + For example, if you see `ENNReal.toReal (∫⁻ a, ENNReal.ofReal <| ‖f a‖)`, that is the norm of `f` in `L¹` space. Rewrite using `L1.norm_of_fun_eq_lintegral_norm`. 2. Show that the set `{f ∈ L¹ | ∫ f = ∫⁻ f⁺ - ∫⁻ f⁻}` is closed in `L¹` using `isClosed_eq`. @@ -1335,7 +1335,7 @@ theorem Memℒp.snorm_eq_integral_rpow_norm {f : α → H} {p : ℝ≥0∞} (hp1 rw [← ofReal_rpow_of_nonneg (norm_nonneg _) toReal_nonneg, ofReal_norm_eq_coe_nnnorm] simp only [snorm_eq_lintegral_rpow_nnnorm hp1 hp2, one_div] rw [integral_eq_lintegral_of_nonneg_ae]; rotate_left - · exact eventually_of_forall fun x => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + · exact eventually_of_forall fun x => Real.rpow_nonneg (norm_nonneg _) _ · exact (hf.aestronglyMeasurable.norm.aemeasurable.pow_const _).aestronglyMeasurable rw [A, ← ofReal_rpow_of_nonneg toReal_nonneg (inv_nonneg.2 toReal_nonneg), ofReal_toReal] exact (lintegral_rpow_nnnorm_lt_top_of_snorm_lt_top hp1 hp2 hf.2).ne @@ -1730,9 +1730,9 @@ theorem integral_mul_norm_le_Lp_mul_Lq {E} [NormedAddCommGroup E] {f g : α → rw [integral_eq_lintegral_of_nonneg_ae, integral_eq_lintegral_of_nonneg_ae, integral_eq_lintegral_of_nonneg_ae] rotate_left - · exact eventually_of_forall fun x => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + · exact eventually_of_forall fun x => Real.rpow_nonneg (norm_nonneg _) _ · exact (hg.1.norm.aemeasurable.pow aemeasurable_const).aestronglyMeasurable - · exact eventually_of_forall fun x => Real.rpow_nonneg_of_nonneg (norm_nonneg _) _ + · exact eventually_of_forall fun x => Real.rpow_nonneg (norm_nonneg _) _ · exact (hf.1.norm.aemeasurable.pow aemeasurable_const).aestronglyMeasurable · exact eventually_of_forall fun x => mul_nonneg (norm_nonneg _) (norm_nonneg _) · exact hf.1.norm.mul hg.1.norm diff --git a/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean b/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean index 735bce0dda645..06fe1404a7cd1 100644 --- a/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean +++ b/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean @@ -8,6 +8,7 @@ import Mathlib.Analysis.BoxIntegral.Integrability import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.MeasureTheory.Constructions.Prod.Integral import Mathlib.MeasureTheory.Integral.IntervalIntegral +import Mathlib.Analysis.Calculus.FDeriv.Equiv #align_import measure_theory.integral.divergence_theorem from "leanprover-community/mathlib"@"3bce8d800a6f2b8f63fe1e588fd76a9ff4adcebe" @@ -376,7 +377,7 @@ See also * `interval_integral.integral_eq_sub_of_has_deriv_right_of_le` for a version that only assumes right differentiability of `f`; -* `MeasureTheory.integral_eq_of_has_deriv_within_at_off_countable` for a version that works both +* `MeasureTheory.integral_eq_of_hasDerivWithinAt_off_countable` for a version that works both for `a ≤ b` and `b ≤ a` at the expense of using unordered intervals instead of `Set.Icc`. -/ theorem integral_eq_of_hasDerivWithinAt_off_countable_of_le (f f' : ℝ → E) {a b : ℝ} (hle : a ≤ b) {s : Set ℝ} (hs : s.Countable) (Hc : ContinuousOn f (Icc a b)) @@ -415,7 +416,7 @@ interval and is differentiable off a countable set `s`. See also `measure_theory.interval_integral.integral_eq_sub_of_has_deriv_right` for a version that only assumes right differentiability of `f`. -/ -theorem integral_eq_of_has_deriv_within_at_off_countable (f f' : ℝ → E) {a b : ℝ} {s : Set ℝ} +theorem integral_eq_of_hasDerivWithinAt_off_countable (f f' : ℝ → E) {a b : ℝ} {s : Set ℝ} (hs : s.Countable) (Hc : ContinuousOn f [[a, b]]) (Hd : ∀ x ∈ Ioo (min a b) (max a b) \ s, HasDerivAt f (f' x) x) (Hi : IntervalIntegrable f' volume a b) : ∫ x in a..b, f' x = f b - f a := by @@ -425,7 +426,7 @@ theorem integral_eq_of_has_deriv_within_at_off_countable (f f' : ℝ → E) {a b · simp only [uIcc_of_ge hab, min_eq_right hab, max_eq_left hab] at * rw [intervalIntegral.integral_symm, neg_eq_iff_eq_neg, neg_sub] exact integral_eq_of_hasDerivWithinAt_off_countable_of_le f f' hab hs Hc Hd Hi.symm -#align measure_theory.integral_eq_of_has_deriv_within_at_off_countable MeasureTheory.integral_eq_of_has_deriv_within_at_off_countable +#align measure_theory.integral_eq_of_has_deriv_within_at_off_countable MeasureTheory.integral_eq_of_hasDerivWithinAt_off_countable /-- **Divergence theorem** for functions on the plane along rectangles. It is formulated in terms of two functions `f g : ℝ × ℝ → E` and an integral over `Icc a b = [a.1, b.1] × [a.2, b.2]`, where diff --git a/Mathlib/MeasureTheory/Integral/Gamma.lean b/Mathlib/MeasureTheory/Integral/Gamma.lean index 93ca3dcac3775..7609d35980d98 100644 --- a/Mathlib/MeasureTheory/Integral/Gamma.lean +++ b/Mathlib/MeasureTheory/Integral/Gamma.lean @@ -3,7 +3,8 @@ Copyright (c) 2023 Xavier Roblot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Xavier Roblot -/ -import Mathlib.Analysis.SpecialFunctions.Gamma.BohrMollerup +import Mathlib.Analysis.SpecialFunctions.PolarCoord +import Mathlib.Analysis.SpecialFunctions.Gamma.Basic /-! # Integrals involving the Gamma function diff --git a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean index e306c3ecb9730..0d050c2a11cec 100644 --- a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean +++ b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean @@ -932,7 +932,7 @@ theorem integral_comp_rpow_Ioi (g : ℝ → E) {p : ℝ} (hp : p ≠ 0) : rw [a3] at this; rw [this] refine' set_integral_congr measurableSet_Ioi _ intro x hx; dsimp only - rw [abs_mul, abs_of_nonneg (rpow_nonneg_of_nonneg (le_of_lt hx) _)] + rw [abs_mul, abs_of_nonneg (rpow_nonneg (le_of_lt hx) _)] #align measure_theory.integral_comp_rpow_Ioi MeasureTheory.integral_comp_rpow_Ioi theorem integral_comp_rpow_Ioi_of_pos {g : ℝ → E} {p : ℝ} (hp : 0 < p) : @@ -990,7 +990,7 @@ theorem integrableOn_Ioi_comp_rpow_iff [NormedSpace ℝ E] (f : ℝ → E) {p : rw [a3] at this rw [this] refine' integrableOn_congr_fun (fun x hx => _) measurableSet_Ioi - simp_rw [abs_mul, abs_of_nonneg (rpow_nonneg_of_nonneg (le_of_lt hx) _)] + simp_rw [abs_mul, abs_of_nonneg (rpow_nonneg (le_of_lt hx) _)] #align measure_theory.integrable_on_Ioi_comp_rpow_iff MeasureTheory.integrableOn_Ioi_comp_rpow_iff /-- The substitution `y = x ^ p` in integrals over `Ioi 0` preserves integrability (version diff --git a/Mathlib/MeasureTheory/Integral/Layercake.lean b/Mathlib/MeasureTheory/Integral/Layercake.lean index 285124b80072d..2f4f36fff22a7 100644 --- a/Mathlib/MeasureTheory/Integral/Layercake.lean +++ b/Mathlib/MeasureTheory/Integral/Layercake.lean @@ -479,7 +479,7 @@ theorem lintegral_rpow_eq_lintegral_meas_le_mul (μ : Measure α) (f_nn : 0 ≤ have g_nn : ∀ᵐ t ∂volume.restrict (Ioi (0 : ℝ)), 0 ≤ g t := by filter_upwards [self_mem_ae_restrict (measurableSet_Ioi : MeasurableSet (Ioi (0 : ℝ)))] intro t t_pos - exact Real.rpow_nonneg_of_nonneg (mem_Ioi.mp t_pos).le (p - 1) + exact Real.rpow_nonneg (mem_Ioi.mp t_pos).le (p - 1) have g_intble : ∀ t > 0, IntervalIntegrable g volume 0 t := fun _ _ => intervalIntegral.intervalIntegrable_rpow' one_lt_p have key := lintegral_comp_eq_lintegral_meas_le_mul μ f_nn f_mble g_intble g_nn diff --git a/Mathlib/MeasureTheory/Integral/Lebesgue.lean b/Mathlib/MeasureTheory/Integral/Lebesgue.lean index 284c1a8e47819..a2759a9bdda01 100644 --- a/Mathlib/MeasureTheory/Integral/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Integral/Lebesgue.lean @@ -815,15 +815,15 @@ theorem set_lintegral_eq_const {f : α → ℝ≥0∞} (hf : Measurable f) (r : #align measure_theory.set_lintegral_eq_const MeasureTheory.set_lintegral_eq_const theorem lintegral_indicator_one_le (s : Set α) : ∫⁻ a, s.indicator 1 a ∂μ ≤ μ s := - (lintegral_indicator_const_le _ _).trans $ (one_mul _).le + (lintegral_indicator_const_le _ _).trans <| (one_mul _).le @[simp] theorem lintegral_indicator_one₀ (hs : NullMeasurableSet s μ) : ∫⁻ a, s.indicator 1 a ∂μ = μ s := - (lintegral_indicator_const₀ hs _).trans $ one_mul _ + (lintegral_indicator_const₀ hs _).trans <| one_mul _ @[simp] theorem lintegral_indicator_one (hs : MeasurableSet s) : ∫⁻ a, s.indicator 1 a ∂μ = μ s := - (lintegral_indicator_const hs _).trans $ one_mul _ + (lintegral_indicator_const hs _).trans <| one_mul _ #align measure_theory.lintegral_indicator_one MeasureTheory.lintegral_indicator_one /-- A version of **Markov's inequality** for two functions. It doesn't follow from the standard @@ -883,8 +883,8 @@ theorem lintegral_eq_top_of_measure_eq_top_ne_zero {f : α → ℝ≥0∞} (hf : theorem setLintegral_eq_top_of_measure_eq_top_ne_zero (hf : AEMeasurable f (μ.restrict s)) (hμf : μ ({x ∈ s | f x = ∞}) ≠ 0) : ∫⁻ x in s, f x ∂μ = ∞ := - lintegral_eq_top_of_measure_eq_top_ne_zero hf $ - mt (eq_bot_mono $ by rw [← setOf_inter_eq_sep]; exact Measure.le_restrict_apply _ _) hμf + lintegral_eq_top_of_measure_eq_top_ne_zero hf <| + mt (eq_bot_mono <| by rw [← setOf_inter_eq_sep]; exact Measure.le_restrict_apply _ _) hμf #align measure_theory.set_lintegral_eq_top_of_measure_eq_top_ne_zero MeasureTheory.setLintegral_eq_top_of_measure_eq_top_ne_zero theorem measure_eq_top_of_lintegral_ne_top (hf : AEMeasurable f μ) (hμf : ∫⁻ x, f x ∂μ ≠ ∞) : @@ -894,7 +894,7 @@ theorem measure_eq_top_of_lintegral_ne_top (hf : AEMeasurable f μ) (hμf : ∫ theorem measure_eq_top_of_setLintegral_ne_top (hf : AEMeasurable f (μ.restrict s)) (hμf : ∫⁻ x in s, f x ∂μ ≠ ∞) : μ ({x ∈ s | f x = ∞}) = 0 := - of_not_not fun h => hμf $ setLintegral_eq_top_of_measure_eq_top_ne_zero hf h + of_not_not fun h => hμf <| setLintegral_eq_top_of_measure_eq_top_ne_zero hf h #align measure_theory.measure_eq_top_of_set_lintegral_ne_top MeasureTheory.measure_eq_top_of_setLintegral_ne_top /-- **Markov's inequality** also known as **Chebyshev's first inequality**. -/ diff --git a/Mathlib/MeasureTheory/Integral/RieszMarkovKakutani.lean b/Mathlib/MeasureTheory/Integral/RieszMarkovKakutani.lean index 7c7315d11bb87..3331277cb0676 100644 --- a/Mathlib/MeasureTheory/Integral/RieszMarkovKakutani.lean +++ b/Mathlib/MeasureTheory/Integral/RieszMarkovKakutani.lean @@ -51,7 +51,7 @@ section RieszMonotone functions f on X such that `f ≥ 1` on K. -/ theorem rieszContentAux_image_nonempty (K : Compacts X) : (Λ '' { f : X →ᵇ ℝ≥0 | ∀ x ∈ K, (1 : ℝ≥0) ≤ f x }).Nonempty := by - rw [nonempty_image_iff] + rw [image_nonempty] use (1 : X →ᵇ ℝ≥0) intro x _ simp only [BoundedContinuousFunction.coe_one, Pi.one_apply]; rfl diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean b/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean index 693bd732c56d4..e9dc7f409ced9 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean @@ -7,7 +7,6 @@ import Mathlib.Data.Finset.Update import Mathlib.Data.Prod.TProd import Mathlib.GroupTheory.Coset import Mathlib.Logic.Equiv.Fin -import Mathlib.Logic.Lemmas import Mathlib.MeasureTheory.MeasurableSpace.Defs import Mathlib.Order.Filter.SmallSets import Mathlib.Order.Filter.CountableSeparatingOn @@ -188,7 +187,7 @@ theorem le_map_comap : m ≤ (m.comap g).map g := end Functors @[simp] theorem map_const {m} (b : β) : MeasurableSpace.map (fun _a : α ↦ b) m = ⊤ := - eq_top_iff.2 $ λ s _ ↦ by by_cases b ∈ s <;> simp [*, map_def] <;> rw [Set.preimage_id'] <;> simp + eq_top_iff.2 <| λ s _ ↦ by by_cases b ∈ s <;> simp [*, map_def] <;> rw [Set.preimage_id'] <;> simp #align measurable_space.map_const MeasurableSpace.map_const @[simp] theorem comap_const {m} (b : β) : MeasurableSpace.comap (fun _a : α => b) m = ⊥ := @@ -1215,15 +1214,15 @@ lemma measurable_set_mem (a : α) : Measurable fun s : Set α ↦ a ∈ s := mea @[aesop safe 100 apply (rule_sets [Measurable])] lemma measurable_set_not_mem (a : α) : Measurable fun s : Set α ↦ a ∉ s := - (measurable_discrete Not).comp $ measurable_set_mem a + (measurable_discrete Not).comp <| measurable_set_mem a @[aesop safe 100 apply (rule_sets [Measurable])] lemma measurableSet_mem (a : α) : MeasurableSet {s : Set α | a ∈ s} := - measurableSet_setOf.2 $ measurable_set_mem _ + measurableSet_setOf.2 <| measurable_set_mem _ @[aesop safe 100 apply (rule_sets [Measurable])] lemma measurableSet_not_mem (a : α) : MeasurableSet {s : Set α | a ∉ s} := - measurableSet_setOf.2 $ measurable_set_not_mem _ + measurableSet_setOf.2 <| measurable_set_not_mem _ lemma measurable_compl : Measurable ((·ᶜ) : Set α → Set α) := measurable_set_iff.2 fun _ ↦ measurable_set_not_mem _ @@ -1368,7 +1367,7 @@ instance instEquivLike : EquivLike (α ≃ᵐ β) α β where inv e := e.toEquiv.symm left_inv e := e.toEquiv.left_inv right_inv e := e.toEquiv.right_inv - coe_injective' _ _ he _ := toEquiv_injective <| FunLike.ext' he + coe_injective' _ _ he _ := toEquiv_injective <| DFunLike.ext' he @[simp] theorem coe_toEquiv (e : α ≃ᵐ β) : (e.toEquiv : α → β) = e := @@ -1429,7 +1428,7 @@ def Simps.symm_apply (h : α ≃ᵐ β) : β → α := h.symm initialize_simps_projections MeasurableEquiv (toFun → apply, invFun → symm_apply) -@[ext] theorem ext {e₁ e₂ : α ≃ᵐ β} (h : (e₁ : α → β) = e₂) : e₁ = e₂ := FunLike.ext' h +@[ext] theorem ext {e₁ e₂ : α ≃ᵐ β} (h : (e₁ : α → β) = e₂) : e₁ = e₂ := DFunLike.ext' h #align measurable_equiv.ext MeasurableEquiv.ext @[simp] diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Card.lean b/Mathlib/MeasureTheory/MeasurableSpace/Card.lean index 6d080c5372c7a..f349b99cb3d10 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Card.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Card.lean @@ -48,7 +48,7 @@ def generateMeasurableRec (s : Set (Set α)) : (ω₁ : Type u) → Set (Set α) | i => let S := ⋃ j : Iio i, generateMeasurableRec s (j.1) s ∪ {∅} ∪ compl '' S ∪ Set.range fun f : ℕ → S => ⋃ n, (f n).1 - termination_by generateMeasurableRec s i => i + termination_by i => i decreasing_by exact j.2 #align measurable_space.generate_measurable_rec MeasurableSpace.generateMeasurableRec diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean b/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean index d44779419111a..31b1db9d8045f 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Data.Set.Countable -import Mathlib.Logic.Encodable.Lattice import Mathlib.Order.Disjointed import Mathlib.Tactic.Measurability @@ -76,6 +75,8 @@ open MeasureTheory section +open scoped symmDiff + @[simp, measurability] theorem MeasurableSet.empty [MeasurableSpace α] : MeasurableSet (∅ : Set α) := MeasurableSpace.measurableSet_empty _ @@ -453,11 +454,11 @@ theorem generateFrom_sup_generateFrom {s t : Set (Set α)} : #align measurable_space.generate_from_sup_generate_from MeasurableSpace.generateFrom_sup_generateFrom theorem generateFrom_singleton_empty : generateFrom {∅} = (⊥ : MeasurableSpace α) := - bot_unique $ generateFrom_le <| by simp [@MeasurableSet.empty α ⊥] + bot_unique <| generateFrom_le <| by simp [@MeasurableSet.empty α ⊥] #align measurable_space.generate_from_singleton_empty MeasurableSpace.generateFrom_singleton_empty theorem generateFrom_singleton_univ : generateFrom {Set.univ} = (⊥ : MeasurableSpace α) := - bot_unique $ generateFrom_le <| by simp + bot_unique <| generateFrom_le <| by simp #align measurable_space.generate_from_singleton_univ MeasurableSpace.generateFrom_singleton_univ @[simp] diff --git a/Mathlib/MeasureTheory/Measure/AddContent.lean b/Mathlib/MeasureTheory/Measure/AddContent.lean new file mode 100644 index 0000000000000..286fe3842df0f --- /dev/null +++ b/Mathlib/MeasureTheory/Measure/AddContent.lean @@ -0,0 +1,181 @@ +/- +Copyright (c) 2024 Rémy Degenne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Rémy Degenne, Peter Pfaffelhuber +-/ +import Mathlib.Data.ENNReal.Basic +import Mathlib.MeasureTheory.SetSemiring + +/-! +# Additive Contents + +An additive content `m` on a set of sets `C` is a set function with value 0 at the empty set which +is finitely additive on `C`. That means that for any finset `I` of pairwise disjoint sets in `C` +such that `⋃₀ I ∈ C`, `m (⋃₀ I) = ∑ s ∈ I, m s`. + +Mathlib also has a definition of contents over compact sets: see `MeasureTheory.Content`. +A `Content` is in particular an `AddContent` on the set of compact sets. + +## Main definitions + +* `MeasureTheory.AddContent C`: additive contents over the set of sets `C`. + +## Main statements + +Let `m` be an `AddContent C`. If `C` is a set semi-ring (`IsSetSemiring C`) we have the properties + +* `MeasureTheory.sum_addContent_le_of_subset`: if `I` is a finset of pairwise disjoint sets in `C` + and `⋃₀ I ⊆ t` for `t ∈ C`, then `∑ s in I, m s ≤ m t`. +* `MeasureTheory.addContent_mono`: if `s ⊆ t` for two sets in `C`, then `m s ≤ m t`. +* `MeasureTheory.addContent_union'`: if `s, t ∈ C` are disjoint and `s ∪ t ∈ C`, + then `m (s ∪ t) = m s + m t`. + If `C` is a set ring (`IsSetRing`), then `addContent_union` gives the same conclusion without the + hypothesis `s ∪ t ∈ C` (since it is a consequence of `IsSetRing C`). + +If `C` is a set ring (`MeasureTheory.IsSetRing C`), we have, for `s, t ∈ C`, + +* `MeasureTheory.addContent_union_le`: `m (s ∪ t) ≤ m s + m t` +* `MeasureTheory.addContent_le_diff`: `m s - m t ≤ m (s \ t)` + +-/ + +open Set Finset + +open scoped ENNReal BigOperators + +namespace MeasureTheory + +variable {α : Type*} {C : Set (Set α)} {s t : Set α} {I : Finset (Set α)} + +/-- An additive content is a set function with value 0 at the empty set which is finitely additive +on a given set of sets. -/ +structure AddContent (C : Set (Set α)) where + /-- The value of the content on a set. -/ + toFun : Set α → ℝ≥0∞ + empty' : toFun ∅ = 0 + sUnion' (I : Finset (Set α)) (_h_ss : ↑I ⊆ C) + (_h_dis : PairwiseDisjoint (I : Set (Set α)) id) (_h_mem : ⋃₀ ↑I ∈ C) : + toFun (⋃₀ I) = ∑ u in I, toFun u + +instance : Inhabited (AddContent C) := + ⟨{toFun := fun _ => 0 + empty' := by simp + sUnion' := by simp }⟩ + +instance : DFunLike (AddContent C) (Set α) (fun _ ↦ ℝ≥0∞) where + coe := fun m s ↦ m.toFun s + coe_injective' := by + intro m m' h + cases m + cases m' + congr + +variable {m m' : AddContent C} + +@[ext] protected lemma AddContent.ext (h : ∀ s, m s = m' s) : m = m' := + DFunLike.ext _ _ h + +protected lemma AddContent.ext_iff (m m' : AddContent C) : m = m' ↔ ∀ s, m s = m' s := + DFunLike.ext_iff + +@[simp] lemma addContent_empty : m ∅ = 0 := m.empty' + +lemma addContent_sUnion (h_ss : ↑I ⊆ C) + (h_dis : PairwiseDisjoint (I : Set (Set α)) id) (h_mem : ⋃₀ ↑I ∈ C) : + m (⋃₀ I) = ∑ u in I, m u := + m.sUnion' I h_ss h_dis h_mem + +lemma addContent_union' (hs : s ∈ C) (ht : t ∈ C) (hst : s ∪ t ∈ C) (h_dis : Disjoint s t) : + m (s ∪ t) = m s + m t := by + by_cases hs_empty : s = ∅ + · simp only [hs_empty, Set.empty_union, addContent_empty, zero_add] + classical + have h := addContent_sUnion (m := m) (I := {s, t}) ?_ ?_ ?_ + rotate_left + · simp only [coe_pair, Set.insert_subset_iff, hs, ht, Set.singleton_subset_iff, and_self_iff] + · simp only [coe_pair, Set.pairwiseDisjoint_insert, pairwiseDisjoint_singleton, + mem_singleton_iff, Ne.def, id.def, forall_eq, true_and_iff] + exact fun _ => h_dis + · simp only [coe_pair, sUnion_insert, sUnion_singleton] + exact hst + convert h + · simp only [coe_pair, sUnion_insert, sUnion_singleton] + · rw [sum_insert, sum_singleton] + simp only [Finset.mem_singleton] + refine fun hs_eq_t => hs_empty ?_ + rw [← hs_eq_t] at h_dis + exact Disjoint.eq_bot_of_self h_dis + +section IsSetSemiring + +lemma addContent_eq_add_diffFinset₀_of_subset (hC : IsSetSemiring C) + (hs : s ∈ C) (hI : ↑I ⊆ C) (hI_ss : ∀ t ∈ I, t ⊆ s) + (h_dis : PairwiseDisjoint (I : Set (Set α)) id) : + m s = ∑ i in I, m i + ∑ i in hC.diffFinset₀ hs hI, m i := by + classical + conv_lhs => rw [← hC.sUnion_union_diffFinset₀_of_subset hs hI hI_ss] + rw [addContent_sUnion] + · rw [sum_union] + exact hC.disjoint_diffFinset₀ hs hI + · rw [coe_union] + exact Set.union_subset hI (hC.diffFinset₀_subset hs hI) + · rw [coe_union] + exact hC.pairwiseDisjoint_union_diffFinset₀ hs hI h_dis + · rwa [hC.sUnion_union_diffFinset₀_of_subset hs hI hI_ss] + +lemma sum_addContent_le_of_subset (hC : IsSetSemiring C) + (h_ss : ↑I ⊆ C) (h_dis : PairwiseDisjoint (I : Set (Set α)) id) + (ht : t ∈ C) (hJt : ∀ s ∈ I, s ⊆ t) : + ∑ u in I, m u ≤ m t := by + classical + rw [addContent_eq_add_diffFinset₀_of_subset hC ht h_ss hJt h_dis] + exact le_add_right le_rfl + +lemma addContent_mono (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) + (hst : s ⊆ t) : + m s ≤ m t := by + have h := sum_addContent_le_of_subset (m := m) hC (I := {s}) ?_ ?_ ht ?_ + · simpa only [sum_singleton] using h + · rwa [singleton_subset_set_iff] + · simp only [coe_singleton, pairwiseDisjoint_singleton] + · simp [hst] + +end IsSetSemiring + +section IsSetRing + +lemma addContent_union (hC : IsSetRing C) (hs : s ∈ C) (ht : t ∈ C) + (h_dis : Disjoint s t) : + m (s ∪ t) = m s + m t := + addContent_union' hs ht (hC.union_mem hs ht) h_dis + +lemma addContent_union_le (hC : IsSetRing C) (hs : s ∈ C) (ht : t ∈ C) : + m (s ∪ t) ≤ m s + m t := by + rw [← union_diff_self, addContent_union hC hs (hC.diff_mem ht hs)] + · exact add_le_add le_rfl + (addContent_mono hC.isSetSemiring (hC.diff_mem ht hs) ht (diff_subset _ _)) + · rw [Set.disjoint_iff_inter_eq_empty, inter_diff_self] + +lemma addContent_biUnion_le {ι : Type*} (hC : IsSetRing C) {s : ι → Set α} + {S : Finset ι} (hs : ∀ n ∈ S, s n ∈ C) : + m (⋃ i ∈ S, s i) ≤ ∑ i in S, m (s i) := by + classical + induction' S using Finset.induction with i S hiS h hs + · simp + · rw [Finset.sum_insert hiS] + simp_rw [← Finset.mem_coe, Finset.coe_insert, Set.biUnion_insert] + simp only [Finset.mem_insert, forall_eq_or_imp] at hs + refine (addContent_union_le hC hs.1 (hC.biUnion_mem S hs.2)).trans ?_ + exact add_le_add le_rfl (h hs.2) + +lemma le_addContent_diff (m : AddContent C) (hC : IsSetRing C) (hs : s ∈ C) (ht : t ∈ C) : + m s - m t ≤ m (s \ t) := by + conv_lhs => rw [← inter_union_diff s t] + rw [addContent_union hC (hC.inter_mem hs ht) (hC.diff_mem hs ht) disjoint_inf_sdiff, add_comm] + refine add_tsub_le_assoc.trans_eq ?_ + rw [tsub_eq_zero_of_le + (addContent_mono hC.isSetSemiring (hC.inter_mem hs ht) ht (inter_subset_right _ _)), add_zero] + +end IsSetRing + +end MeasureTheory diff --git a/Mathlib/MeasureTheory/Measure/Content.lean b/Mathlib/MeasureTheory/Measure/Content.lean index c261ca165a967..435c5b18afab4 100644 --- a/Mathlib/MeasureTheory/Measure/Content.lean +++ b/Mathlib/MeasureTheory/Measure/Content.lean @@ -41,7 +41,9 @@ For `μ : Content G`, we define * `μ.outerMeasure` : the outer measure associated to `μ`. * `μ.measure` : the Borel measure associated to `μ`. -We prove that, on a locally compact space, the measure `μ.measure` is regular. +These definitions are given for spaces which are either T2, or locally compact and regular (which +covers possibly non-Hausdorff locally compact groups). The resulting measure `μ.measure` is always +outer regular by design. When the space is locally compact, `μ.measure` is also regular. ## References @@ -68,7 +70,8 @@ structure Content (G : Type w) [TopologicalSpace G] where toFun : Compacts G → ℝ≥0 mono' : ∀ K₁ K₂ : Compacts G, (K₁ : Set G) ⊆ K₂ → toFun K₁ ≤ toFun K₂ sup_disjoint' : - ∀ K₁ K₂ : Compacts G, Disjoint (K₁ : Set G) K₂ → toFun (K₁ ⊔ K₂) = toFun K₁ + toFun K₂ + ∀ K₁ K₂ : Compacts G, Disjoint (K₁ : Set G) K₂ → IsClosed (K₁ : Set G) → IsClosed (K₂ : Set G) + → toFun (K₁ ⊔ K₂) = toFun K₁ + toFun K₂ sup_le' : ∀ K₁ K₂ : Compacts G, toFun (K₁ ⊔ K₂) ≤ toFun K₁ + toFun K₂ #align measure_theory.content MeasureTheory.Content @@ -96,7 +99,8 @@ theorem mono (K₁ K₂ : Compacts G) (h : (K₁ : Set G) ⊆ K₂) : μ K₁ simp [apply_eq_coe_toFun, μ.mono' _ _ h] #align measure_theory.content.mono MeasureTheory.Content.mono -theorem sup_disjoint (K₁ K₂ : Compacts G) (h : Disjoint (K₁ : Set G) K₂) : +theorem sup_disjoint (K₁ K₂ : Compacts G) (h : Disjoint (K₁ : Set G) K₂) + (h₁ : IsClosed (K₁ : Set G)) (h₂ : IsClosed (K₂ : Set G)) : μ (K₁ ⊔ K₂) = μ K₁ + μ K₂ := by simp [apply_eq_coe_toFun, μ.sup_disjoint' _ _ h] #align measure_theory.content.sup_disjoint MeasureTheory.Content.sup_disjoint @@ -167,7 +171,7 @@ theorem innerContent_exists_compact {U : Opens G} (hU : μ.innerContent U ≠ #align measure_theory.content.inner_content_exists_compact MeasureTheory.Content.innerContent_exists_compact /-- The inner content of a supremum of opens is at most the sum of the individual inner contents. -/ -theorem innerContent_iSup_nat [T2Space G] (U : ℕ → Opens G) : +theorem innerContent_iSup_nat [T2OrLocallyCompactRegularSpace G] (U : ℕ → Opens G) : μ.innerContent (⨆ i : ℕ, U i) ≤ ∑' i : ℕ, μ.innerContent (U i) := by have h3 : ∀ (t : Finset ℕ) (K : ℕ → Compacts G), μ (t.sup K) ≤ t.sum fun i => μ (K i) := by intro t K @@ -196,7 +200,8 @@ theorem innerContent_iSup_nat [T2Space G] (U : ℕ → Opens G) : /-- The inner content of a union of sets is at most the sum of the individual inner contents. This is the "unbundled" version of `innerContent_iSup_nat`. It is required for the API of `inducedOuterMeasure`. -/ -theorem innerContent_iUnion_nat [T2Space G] ⦃U : ℕ → Set G⦄ (hU : ∀ i : ℕ, IsOpen (U i)) : +theorem innerContent_iUnion_nat [T2OrLocallyCompactRegularSpace G] ⦃U : ℕ → Set G⦄ + (hU : ∀ i : ℕ, IsOpen (U i)) : μ.innerContent ⟨⋃ i : ℕ, U i, isOpen_iUnion hU⟩ ≤ ∑' i : ℕ, μ.innerContent ⟨U i, hU i⟩ := by have := μ.innerContent_iSup_nat fun i => ⟨U i, hU i⟩ rwa [Opens.iSup_def] at this @@ -220,7 +225,8 @@ theorem is_mul_left_invariant_innerContent [Group G] [TopologicalGroup G] #align measure_theory.content.is_add_left_invariant_inner_content MeasureTheory.Content.is_add_left_invariant_innerContent @[to_additive] -theorem innerContent_pos_of_is_mul_left_invariant [T2Space G] [Group G] [TopologicalGroup G] +theorem innerContent_pos_of_is_mul_left_invariant [T2OrLocallyCompactRegularSpace G] [Group G] + [TopologicalGroup G] (h3 : ∀ (g : G) {K : Compacts G}, μ (K.map _ <| continuous_mul_left g) = μ K) (K : Compacts G) (hK : μ K ≠ 0) (U : Opens G) (hU : (U : Set G).Nonempty) : 0 < μ.innerContent U := by have : (interior (U : Set G)).Nonempty @@ -249,7 +255,7 @@ protected def outerMeasure : OuterMeasure G := inducedOuterMeasure (fun U hU => μ.innerContent ⟨U, hU⟩) isOpen_empty μ.innerContent_bot #align measure_theory.content.outer_measure MeasureTheory.Content.outerMeasure -variable [T2Space G] +variable [T2OrLocallyCompactRegularSpace G] theorem outerMeasure_opens (U : Opens G) : μ.outerMeasure U = μ.innerContent U := inducedOuterMeasure_eq' (fun _ => isOpen_iUnion) μ.innerContent_iUnion_nat μ.innerContent_mono U.2 @@ -358,22 +364,34 @@ theorem borel_le_caratheodory : S ≤ μ.outerMeasure.caratheodory := by rw [ENNReal.iSup_add] refine' iSup_le _ rintro ⟨L, hL⟩ + let L' : Compacts G := ⟨closure L, L.isCompact.closure⟩ + suffices μ L' + μ.outerMeasure (↑U' \ U) ≤ μ.outerMeasure U' by + have A : μ L ≤ μ L' := μ.mono _ _ subset_closure + exact (add_le_add_right A _).trans this simp only [subset_inter_iff] at hL - have : ↑U' \ U ⊆ U' \ L := diff_subset_diff_right hL.2 + have hL'U : (L' : Set G) ⊆ U := IsCompact.closure_subset_of_isOpen L.2 hU hL.2 + have hL'U' : (L' : Set G) ⊆ (U' : Set G) := IsCompact.closure_subset_of_isOpen L.2 U'.2 hL.1 + have : ↑U' \ U ⊆ U' \ L' := diff_subset_diff_right hL'U refine' le_trans (add_le_add_left (μ.outerMeasure.mono' this) _) _ - rw [μ.outerMeasure_of_isOpen (↑U' \ L) (IsOpen.sdiff U'.2 L.2.isClosed)] + rw [μ.outerMeasure_of_isOpen (↑U' \ L') (IsOpen.sdiff U'.2 isClosed_closure)] simp only [innerContent, iSup_subtype'] rw [Opens.coe_mk] - haveI : Nonempty { M : Compacts G // (M : Set G) ⊆ ↑U' \ L } := ⟨⟨⊥, empty_subset _⟩⟩ + haveI : Nonempty { M : Compacts G // (M : Set G) ⊆ ↑U' \ closure L } := ⟨⟨⊥, empty_subset _⟩⟩ rw [ENNReal.add_iSup] refine' iSup_le _ rintro ⟨M, hM⟩ - simp only [subset_diff] at hM - have : (↑(L ⊔ M) : Set G) ⊆ U' := by - simp only [union_subset_iff, Compacts.coe_sup, hM, hL, and_self_iff] + let M' : Compacts G := ⟨closure M, M.isCompact.closure⟩ + suffices μ L' + μ M' ≤ μ.outerMeasure U' by + have A : μ M ≤ μ M' := μ.mono _ _ subset_closure + exact (add_le_add_left A _).trans this + have hM' : (M' : Set G) ⊆ U' \ L' := + IsCompact.closure_subset_of_isOpen M.2 (IsOpen.sdiff U'.2 isClosed_closure) hM + have : (↑(L' ⊔ M') : Set G) ⊆ U' := by + simp only [Compacts.coe_sup, union_subset_iff, hL'U', true_and] + exact hM'.trans (diff_subset _ _ ) rw [μ.outerMeasure_of_isOpen (↑U') U'.2] refine' le_trans (ge_of_eq _) (μ.le_innerContent _ _ this) - exact μ.sup_disjoint _ _ hM.2.symm + exact μ.sup_disjoint L' M' (subset_diff.1 hM').2.symm isClosed_closure isClosed_closure #align measure_theory.content.borel_le_caratheodory MeasureTheory.Content.borel_le_caratheodory /-- The measure induced by the outer measure coming from a content, on the Borel sigma-algebra. -/ @@ -385,19 +403,21 @@ theorem measure_apply {s : Set G} (hs : MeasurableSet s) : μ.measure s = μ.out toMeasure_apply _ _ hs #align measure_theory.content.measure_apply MeasureTheory.Content.measure_apply +instance outerRegular : μ.measure.OuterRegular := by + refine ⟨fun A hA r (hr : _ < _) ↦ ?_⟩ + rw [μ.measure_apply hA, outerMeasure_eq_iInf] at hr + simp only [iInf_lt_iff] at hr + rcases hr with ⟨U, hUo, hAU, hr⟩ + rw [← μ.outerMeasure_of_isOpen U hUo, ← μ.measure_apply hUo.measurableSet] at hr + exact ⟨U, hAU, hUo, hr⟩ + /-- In a locally compact space, any measure constructed from a content is regular. -/ instance regular [WeaklyLocallyCompactSpace G] : μ.measure.Regular := by - have : μ.measure.OuterRegular := by - refine' ⟨fun A hA r (hr : _ < _) => _⟩ - rw [μ.measure_apply hA, outerMeasure_eq_iInf] at hr - simp only [iInf_lt_iff] at hr - rcases hr with ⟨U, hUo, hAU, hr⟩ - rw [← μ.outerMeasure_of_isOpen U hUo, ← μ.measure_apply hUo.measurableSet] at hr - exact ⟨U, hAU, hUo, hr⟩ have : IsFiniteMeasureOnCompacts μ.measure := by refine' ⟨fun K hK => _⟩ - rw [measure_apply _ hK.measurableSet] - exact μ.outerMeasure_lt_top_of_isCompact hK + apply (measure_mono subset_closure).trans_lt _ + rw [measure_apply _ isClosed_closure.measurableSet] + exact μ.outerMeasure_lt_top_of_isCompact hK.closure refine' ⟨fun U hU r hr => _⟩ rw [measure_apply _ hU.measurableSet, μ.outerMeasure_of_isOpen U hU] at hr simp only [innerContent, lt_iSup_iff] at hr @@ -430,7 +450,7 @@ theorem contentRegular_exists_compact (H : ContentRegular μ) (K : TopologicalSp (ENNReal.lt_add_right (ne_top_of_lt (μ.lt_top K)) (ENNReal.coe_ne_zero.mpr hε))) #align measure_theory.content.content_regular_exists_compact MeasureTheory.Content.contentRegular_exists_compact -variable [MeasurableSpace G] [T2Space G] [BorelSpace G] +variable [MeasurableSpace G] [T2OrLocallyCompactRegularSpace G] [BorelSpace G] /-- If `μ` is a regular content, then the measure induced by `μ` will agree with `μ` on compact sets. -/ @@ -441,16 +461,17 @@ theorem measure_eq_content_of_regular (H : MeasureTheory.Content.ContentRegular intro ε εpos _ obtain ⟨K', K'_hyp⟩ := contentRegular_exists_compact μ H K (ne_bot_of_gt εpos) calc - μ.measure ↑K ≤ μ.measure (interior ↑K') := by - rw [μ.measure_apply isOpen_interior.measurableSet, - μ.measure_apply K.isCompact.measurableSet] - exact μ.outerMeasure.mono K'_hyp.left + μ.measure ↑K ≤ μ.measure (interior ↑K') := measure_mono K'_hyp.1 _ ≤ μ K' := by rw [μ.measure_apply (IsOpen.measurableSet isOpen_interior)] exact μ.outerMeasure_interior_compacts K' _ ≤ μ K + ε := K'_hyp.right - · rw [μ.measure_apply (IsCompact.measurableSet K.isCompact)] - exact μ.le_outerMeasure_compacts K + · calc + μ K ≤ μ ⟨closure K, K.2.closure⟩ := μ.mono _ _ subset_closure + _ ≤ μ.measure (closure K) := by + rw [μ.measure_apply (isClosed_closure.measurableSet)] + exact μ.le_outerMeasure_compacts _ + _ = μ.measure K := Measure.OuterRegular.measure_closure_eq_of_isCompact K.2 #align measure_theory.content.measure_eq_content_of_regular MeasureTheory.Content.measure_eq_content_of_regular end RegularContents diff --git a/Mathlib/MeasureTheory/Measure/FiniteMeasure.lean b/Mathlib/MeasureTheory/Measure/FiniteMeasure.lean index 7c505edeee1df..e4259e7245bf7 100644 --- a/Mathlib/MeasureTheory/Measure/FiniteMeasure.lean +++ b/Mathlib/MeasureTheory/Measure/FiniteMeasure.lean @@ -571,7 +571,7 @@ lemma injective_toWeakDualBCNN : intro μ ν hμν apply ext_of_forall_lintegral_eq intro f - have key := congr_fun (congrArg FunLike.coe hμν) f + have key := congr_fun (congrArg DFunLike.coe hμν) f apply (ENNReal.toNNReal_eq_toNNReal_iff' ?_ ?_).mp key · exact (lintegral_lt_top_of_nnreal μ f).ne · exact (lintegral_lt_top_of_nnreal ν f).ne diff --git a/Mathlib/MeasureTheory/Measure/Haar/Basic.lean b/Mathlib/MeasureTheory/Measure/Haar/Basic.lean index ea0b2727ee528..e2dd509fee3e1 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Basic.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Basic.lean @@ -5,7 +5,6 @@ Authors: Floris van Doorn -/ import Mathlib.MeasureTheory.Measure.Content import Mathlib.MeasureTheory.Group.Prod -import Mathlib.GroupTheory.Divisible import Mathlib.Topology.Algebra.Group.Compact #align_import measure_theory.measure.haar.basic from "leanprover-community/mathlib"@"fd5edc43dc4f10b85abfe544b88f82cf13c5f844" @@ -375,7 +374,7 @@ theorem nonempty_iInter_clPrehaar (K₀ : PositiveCompacts G) : apply isCompact_univ_pi; intro K; apply isCompact_Icc refine' this.inter_iInter_nonempty (clPrehaar K₀) (fun s => isClosed_closure) fun t => _ let V₀ := ⋂ V ∈ t, (V : OpenNhdsOf (1 : G)).carrier - have h1V₀ : IsOpen V₀ := isOpen_biInter_finset $ by rintro ⟨⟨V, hV₁⟩, hV₂⟩ _; exact hV₁ + have h1V₀ : IsOpen V₀ := isOpen_biInter_finset <| by rintro ⟨⟨V, hV₁⟩, hV₂⟩ _; exact hV₁ have h2V₀ : (1 : G) ∈ V₀ := by simp only [mem_iInter]; rintro ⟨⟨V, hV₁⟩, hV₂⟩ _; exact hV₂ refine' ⟨prehaar K₀ V₀, _⟩ constructor @@ -482,9 +481,12 @@ theorem chaar_sup_le {K₀ : PositiveCompacts G} (K₁ K₂ : Compacts G) : #align measure_theory.measure.haar.add_chaar_sup_le MeasureTheory.Measure.haar.addCHaar_sup_le @[to_additive addCHaar_sup_eq] -theorem chaar_sup_eq [T2Space G] {K₀ : PositiveCompacts G} {K₁ K₂ : Compacts G} - (h : Disjoint K₁.1 K₂.1) : chaar K₀ (K₁ ⊔ K₂) = chaar K₀ K₁ + chaar K₀ K₂ := by - rcases isCompact_isCompact_separated K₁.2 K₂.2 h with ⟨U₁, U₂, h1U₁, h1U₂, h2U₁, h2U₂, hU⟩ +theorem chaar_sup_eq {K₀ : PositiveCompacts G} + {K₁ K₂ : Compacts G} (h : Disjoint K₁.1 K₂.1) (h₂ : IsClosed K₂.1) : + chaar K₀ (K₁ ⊔ K₂) = chaar K₀ K₁ + chaar K₀ K₂ := by + have : LocallyCompactSpace G := K₀.locallyCompactSpace_of_group + rcases separatedNhds_of_isCompact_isCompact_isClosed K₁.2 K₂.2 h₂ h + with ⟨U₁, U₂, h1U₁, h1U₂, h2U₁, h2U₂, hU⟩ rcases compact_open_separated_mul_right K₁.2 h1U₁ h2U₁ with ⟨L₁, h1L₁, h2L₁⟩ rcases mem_nhds_iff.mp h1L₁ with ⟨V₁, h1V₁, h2V₁, h3V₁⟩ replace h2L₁ := Subset.trans (mul_subset_mul_left h1V₁) h2L₁ @@ -530,8 +532,6 @@ theorem is_left_invariant_chaar {K₀ : PositiveCompacts G} (g : G) (K : Compact #align measure_theory.measure.haar.is_left_invariant_chaar MeasureTheory.Measure.haar.is_left_invariant_chaar #align measure_theory.measure.haar.is_left_invariant_add_chaar MeasureTheory.Measure.haar.is_left_invariant_addCHaar -variable [T2Space G] - -- Porting note: Even in `noncomputable section`, a definition with `to_additive` require -- `noncomputable` to generate an additive definition. -- Please refer to leanprover/lean4#2077. @@ -541,7 +541,7 @@ variable [T2Space G] noncomputable def haarContent (K₀ : PositiveCompacts G) : Content G where toFun K := ⟨chaar K₀ K, chaar_nonneg _ _⟩ mono' K₁ K₂ h := by simp only [← NNReal.coe_le_coe, NNReal.toReal, chaar_mono, h] - sup_disjoint' K₁ K₂ h := by simp only [chaar_sup_eq h]; rfl + sup_disjoint' K₁ K₂ h _h₁ h₂ := by simp only [chaar_sup_eq h]; rfl sup_le' K₁ K₂ := by simp only [← NNReal.coe_le_coe, NNReal.coe_add] simp only [NNReal.toReal, chaar_sup_le] @@ -575,8 +575,9 @@ theorem is_left_invariant_haarContent {K₀ : PositiveCompacts G} (g : G) (K : C #align measure_theory.measure.haar.is_left_invariant_add_haar_content MeasureTheory.Measure.haar.is_left_invariant_addHaarContent @[to_additive] -theorem haarContent_outerMeasure_self_pos {K₀ : PositiveCompacts G} : +theorem haarContent_outerMeasure_self_pos (K₀ : PositiveCompacts G) : 0 < (haarContent K₀).outerMeasure K₀ := by + have : LocallyCompactSpace G := K₀.locallyCompactSpace_of_group refine' zero_lt_one.trans_le _ rw [Content.outerMeasure_eq_iInf] refine' le_iInf₂ fun U hU => le_iInf fun hK₀ => le_trans _ <| le_iSup₂ K₀.toCompacts hK₀ @@ -584,6 +585,11 @@ theorem haarContent_outerMeasure_self_pos {K₀ : PositiveCompacts G} : #align measure_theory.measure.haar.haar_content_outer_measure_self_pos MeasureTheory.Measure.haar.haarContent_outerMeasure_self_pos #align measure_theory.measure.haar.add_haar_content_outer_measure_self_pos MeasureTheory.Measure.haar.addHaarContent_outerMeasure_self_pos +@[to_additive] +theorem haarContent_outerMeasure_closure_pos (K₀ : PositiveCompacts G) : + 0 < (haarContent K₀).outerMeasure (closure K₀) := + (haarContent_outerMeasure_self_pos K₀).trans_le (OuterMeasure.mono _ subset_closure) + end haar open haar @@ -593,7 +599,7 @@ open haar -/ -variable [TopologicalSpace G] [T2Space G] [TopologicalGroup G] [MeasurableSpace G] [BorelSpace G] +variable [TopologicalSpace G] [TopologicalGroup G] [MeasurableSpace G] [BorelSpace G] -- Porting note: Even in `noncomputable section`, a definition with `to_additive` require -- `noncomputable` to generate an additive definition. @@ -604,14 +610,16 @@ variable [TopologicalSpace G] [T2Space G] [TopologicalGroup G] [MeasurableSpace "The Haar measure on the locally compact additive group `G`, scaled so that `addHaarMeasure K₀ K₀ = 1`."] noncomputable def haarMeasure (K₀ : PositiveCompacts G) : Measure G := - ((haarContent K₀).outerMeasure K₀)⁻¹ • (haarContent K₀).measure + have : LocallyCompactSpace G := K₀.locallyCompactSpace_of_group + ((haarContent K₀).measure K₀)⁻¹ • (haarContent K₀).measure #align measure_theory.measure.haar_measure MeasureTheory.Measure.haarMeasure #align measure_theory.measure.add_haar_measure MeasureTheory.Measure.addHaarMeasure @[to_additive] -theorem haarMeasure_apply {K₀ : PositiveCompacts G} {s : Set G} (hs : MeasurableSet s) : - haarMeasure K₀ s = (haarContent K₀).outerMeasure s / (haarContent K₀).outerMeasure K₀ := by - change ((haarContent K₀).outerMeasure K₀)⁻¹ * (haarContent K₀).measure s = _ +theorem haarMeasure_apply [LocallyCompactSpace G] + {K₀ : PositiveCompacts G} {s : Set G} (hs : MeasurableSet s) : + haarMeasure K₀ s = (haarContent K₀).outerMeasure s / (haarContent K₀).measure K₀ := by + change ((haarContent K₀).measure K₀)⁻¹ * (haarContent K₀).measure s = _ simp only [hs, div_eq_mul_inv, mul_comm, Content.measure_apply] #align measure_theory.measure.haar_measure_apply MeasureTheory.Measure.haarMeasure_apply #align measure_theory.measure.add_haar_measure_apply MeasureTheory.Measure.addHaarMeasure_apply @@ -619,11 +627,12 @@ theorem haarMeasure_apply {K₀ : PositiveCompacts G} {s : Set G} (hs : Measurab @[to_additive] instance isMulLeftInvariant_haarMeasure (K₀ : PositiveCompacts G) : IsMulLeftInvariant (haarMeasure K₀) := by + have : LocallyCompactSpace G := K₀.locallyCompactSpace_of_group rw [← forall_measure_preimage_mul_iff] intro g A hA rw [haarMeasure_apply hA, haarMeasure_apply (measurable_const_mul g hA)] -- Porting note: Here was `congr 1`, but `to_additive` failed to generate a theorem. - refine congr_arg (fun x : ℝ≥0∞ => x / (haarContent K₀).outerMeasure K₀) ?_ + refine congr_arg (fun x : ℝ≥0∞ => x / (haarContent K₀).measure K₀) ?_ apply Content.is_mul_left_invariant_outerMeasure apply is_left_invariant_haarContent #align measure_theory.measure.is_mul_left_invariant_haar_measure MeasureTheory.Measure.isMulLeftInvariant_haarMeasure @@ -632,9 +641,12 @@ instance isMulLeftInvariant_haarMeasure (K₀ : PositiveCompacts G) : @[to_additive] theorem haarMeasure_self {K₀ : PositiveCompacts G} : haarMeasure K₀ K₀ = 1 := by haveI : LocallyCompactSpace G := K₀.locallyCompactSpace_of_group - rw [haarMeasure_apply K₀.isCompact.measurableSet, ENNReal.div_self] - · rw [← pos_iff_ne_zero]; exact haarContent_outerMeasure_self_pos - · exact (Content.outerMeasure_lt_top_of_isCompact _ K₀.isCompact).ne + simp only [haarMeasure, smul_toOuterMeasure, OuterMeasure.coe_smul, Pi.smul_apply, + smul_eq_mul] + rw [← OuterRegular.measure_closure_eq_of_isCompact K₀.isCompact, + Content.measure_apply _ isClosed_closure.measurableSet, ENNReal.inv_mul_cancel] + · exact (haarContent_outerMeasure_closure_pos K₀).ne' + · exact (Content.outerMeasure_lt_top_of_isCompact _ K₀.isCompact.closure).ne #align measure_theory.measure.haar_measure_self MeasureTheory.Measure.haarMeasure_self #align measure_theory.measure.add_haar_measure_self MeasureTheory.Measure.addHaarMeasure_self @@ -643,11 +655,16 @@ theorem haarMeasure_self {K₀ : PositiveCompacts G} : haarMeasure K₀ K₀ = 1 instance regular_haarMeasure {K₀ : PositiveCompacts G} : (haarMeasure K₀).Regular := by haveI : LocallyCompactSpace G := K₀.locallyCompactSpace_of_group apply Regular.smul - rw [ENNReal.inv_ne_top] - exact haarContent_outerMeasure_self_pos.ne' + rw [← OuterRegular.measure_closure_eq_of_isCompact K₀.isCompact, + Content.measure_apply _ isClosed_closure.measurableSet, ENNReal.inv_ne_top] + exact (haarContent_outerMeasure_closure_pos K₀).ne' #align measure_theory.measure.regular_haar_measure MeasureTheory.Measure.regular_haarMeasure #align measure_theory.measure.regular_add_haar_measure MeasureTheory.Measure.regular_addHaarMeasure +@[to_additive] +theorem haarMeasure_closure_self {K₀ : PositiveCompacts G} : haarMeasure K₀ (closure K₀) = 1 := by + rw [IsCompact.measure_closure_eq_of_group K₀.isCompact, haarMeasure_self] + /-- The Haar measure is sigma-finite in a second countable group. -/ @[to_additive "The additive Haar measure is sigma-finite in a second countable group."] instance sigmaFinite_haarMeasure [SecondCountableTopology G] {K₀ : PositiveCompacts G} : @@ -760,11 +777,14 @@ variable [SecondCountableTopology G] require `μ ≠ 0`). See also `isAddHaarMeasure_eq_smul_of_regular` for a statement not assuming second-countability."] theorem haarMeasure_unique (μ : Measure G) [SigmaFinite μ] [IsMulLeftInvariant μ] - (K₀ : PositiveCompacts G) : μ = μ K₀ • haarMeasure K₀ := - (measure_eq_div_smul μ (haarMeasure K₀) K₀.isCompact.measurableSet - (measure_pos_of_nonempty_interior _ K₀.interior_nonempty).ne' - K₀.isCompact.measure_lt_top.ne).trans - (by rw [haarMeasure_self, div_one]) + (K₀ : PositiveCompacts G) : μ = μ K₀ • haarMeasure K₀ := by + have : LocallyCompactSpace G := K₀.locallyCompactSpace_of_group + have A : Set.Nonempty (interior (closure (K₀ : Set G))) := + K₀.interior_nonempty.mono (interior_mono subset_closure) + have := measure_eq_div_smul μ (haarMeasure K₀) (isClosed_closure (s := K₀)).measurableSet + (measure_pos_of_nonempty_interior _ A).ne' K₀.isCompact.closure.measure_lt_top.ne + rwa [haarMeasure_closure_self, div_one, IsCompact.measure_closure_eq_of_group K₀.isCompact] + at this #align measure_theory.measure.haar_measure_unique MeasureTheory.Measure.haarMeasure_unique #align measure_theory.measure.add_haar_measure_unique MeasureTheory.Measure.addHaarMeasure_unique diff --git a/Mathlib/MeasureTheory/Measure/Haar/Disintegration.lean b/Mathlib/MeasureTheory/Measure/Haar/Disintegration.lean index c601787eaea0a..10033d18f9518 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Disintegration.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Disintegration.lean @@ -86,12 +86,18 @@ theorem LinearMap.exists_map_addHaar_eq_smul_addHaar' (h : Function.Surjective L ∃ c₀ : ℝ≥0∞, c₀ ≠ 0 ∧ c₀ ≠ ∞ ∧ μ.map M.symm = c₀ • μS.prod μT := by have : IsAddHaarMeasure (μ.map M.symm) := M.toContinuousLinearEquiv.symm.isAddHaarMeasure_map μ - exact isAddHaarMeasure_eq_smul _ _ + refine ⟨addHaarScalarFactor (μ.map M.symm) (μS.prod μT), ?_, ENNReal.coe_ne_top, + isAddHaarMeasure_eq_smul _ _⟩ + simpa only [ne_eq, ENNReal.coe_eq_zero] using + (addHaarScalarFactor_pos_of_isOpenPosMeasure (μ.map M.symm) (μS.prod μT)).ne' have J : (μS.prod μT).map P = (μS univ) • μT := map_snd_prod obtain ⟨c₁, c₁_pos, c₁_fin, h₁⟩ : ∃ c₁ : ℝ≥0∞, c₁ ≠ 0 ∧ c₁ ≠ ∞ ∧ μT.map L' = c₁ • ν := by have : IsAddHaarMeasure (μT.map L') := L'.toContinuousLinearEquiv.isAddHaarMeasure_map μT - exact isAddHaarMeasure_eq_smul _ _ + refine ⟨addHaarScalarFactor (μT.map L') ν, ?_, ENNReal.coe_ne_top, + isAddHaarMeasure_eq_smul _ _⟩ + simpa only [ne_eq, ENNReal.coe_eq_zero] using + (addHaarScalarFactor_pos_of_isOpenPosMeasure (μT.map L') ν).ne' refine ⟨c₀ * c₁, by simp [pos_iff_ne_zero, c₀_pos, c₁_pos], ENNReal.mul_lt_top c₀_fin c₁_fin, ?_⟩ simp only [I, h₀, Measure.map_smul, J, smul_smul, h₁] rw [mul_assoc, mul_comm _ c₁, ← mul_assoc] diff --git a/Mathlib/MeasureTheory/Measure/Haar/InnerProductSpace.lean b/Mathlib/MeasureTheory/Measure/Haar/InnerProductSpace.lean index 6de56e379a67b..5e53aa9dbb451 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/InnerProductSpace.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/InnerProductSpace.lean @@ -4,9 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Analysis.InnerProductSpace.Orientation -import Mathlib.Analysis.SpecialFunctions.Integrals import Mathlib.MeasureTheory.Measure.Lebesgue.EqHaar -import Mathlib.MeasureTheory.Measure.Lebesgue.Integral #align_import measure_theory.measure.haar.inner_product_space from "leanprover-community/mathlib"@"fd5edc43dc4f10b85abfe544b88f82cf13c5f844" diff --git a/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean b/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean index 1d60a9f49d75a..68f3194adafd5 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean @@ -188,7 +188,7 @@ def Basis.parallelepiped (b : Basis ι ℝ E) : PositiveCompacts E where rw [← pi_univ_Icc, interior_pi_set (@finite_univ ι _)] simp only [univ_pi_nonempty_iff, Pi.zero_apply, Pi.one_apply, interior_Icc, nonempty_Ioo, zero_lt_one, imp_true_iff] - rwa [← Homeomorph.image_interior, nonempty_image_iff] + rwa [← Homeomorph.image_interior, image_nonempty] #align basis.parallelepiped Basis.parallelepiped @[simp] diff --git a/Mathlib/MeasureTheory/Measure/Haar/Unique.lean b/Mathlib/MeasureTheory/Measure/Haar/Unique.lean index f876a640205d2..c754ecc6014dc 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Unique.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Unique.lean @@ -20,17 +20,15 @@ statements for left invariant measures (up to scalar multiplication): compact sets. * `isMulLeftInvariant_eq_smul_of_innerRegular`: two left invariant measures which are inner regular coincide up to a scalar. -* `isHaarMeasure_eq_smul_of_innerRegular`: two Haar measures which are inner regular coincide up - to a nonzero scalar. * `isMulLeftInvariant_eq_smul_of_regular`: two left invariant measure which are regular coincide up to a scalar. -* `isHaarMeasure_eq_smul_of_regular`: two Haar measures which are regular coincide up to a - nonzero scalar. * `isHaarMeasure_eq_smul`: in a second countable space, two Haar measures coincide up to a - nonzero scalar. + scalar. * `isMulLeftInvariant_eq_of_isProbabilityMeasure`: two left-invariant probability measures which are inner regular for finite measure sets with respect to compact sets coincide. +The scalar factor that appears in these identities is defined as `haarScalarFactor μ' μ`. + In general, uniqueness statements for Haar measures in the literature make some assumption of regularity, either regularity or inner regularity. We have tried to minimize the assumptions in the theorems above (notably in `integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport`, which doesn't @@ -110,7 +108,7 @@ namespace Measure section Group -variable {G : Type*} [TopologicalSpace G] [LocallyCompactSpace G] [Group G] [TopologicalGroup G] +variable {G : Type*} [TopologicalSpace G] [Group G] [TopologicalGroup G] [MeasurableSpace G] [BorelSpace G] /-- In a group with a left invariant measure `μ` and a right invariant measure `ν`, one can express @@ -124,6 +122,9 @@ lemma integral_isMulLeftInvariant_isMulRightInvariant_combo {f g : G → ℝ} (hf : Continuous f) (h'f : HasCompactSupport f) (hg : Continuous g) (h'g : HasCompactSupport g) (g_nonneg : 0 ≤ g) {x₀ : G} (g_pos : g x₀ ≠ 0) : ∫ x, f x ∂μ = (∫ y, f y * (∫ z, g (z⁻¹ * y) ∂ν)⁻¹ ∂ν) * ∫ x, g x ∂μ := by + -- The group has to be locally compact, otherwise all integrals vanish and the result is trivial. + rcases h'f.eq_zero_or_locallyCompactSpace_of_group hf with Hf|Hf + · simp [Hf] let D : G → ℝ := fun (x : G) ↦ ∫ y, g (y⁻¹ * x) ∂ν have D_cont : Continuous D := continuous_integral_apply_inv_mul hg h'g have D_pos : ∀ x, 0 < D x := by @@ -208,8 +209,8 @@ lemma integral_isMulLeftInvariant_isMulRightInvariant_combo /-- **Uniqueness of left-invariant measures**: Given two left-invariant measures which are finite on compacts, they coincide in the following sense: they give the same value to the integral of continuous compactly supported functions, up to a multiplicative constant. -/ -@[to_additive integral_isAddLeftInvariant_eq_smul_of_hasCompactSupport] -lemma integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport +@[to_additive exists_integral_isAddLeftInvariant_eq_smul_of_hasCompactSupport] +lemma exists_integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport (μ' μ : Measure G) [IsFiniteMeasureOnCompacts μ] [IsFiniteMeasureOnCompacts μ'] [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] [IsOpenPosMeasure μ] : ∃ (c : ℝ≥0), ∀ (f : G → ℝ), Continuous f → HasCompactSupport f → @@ -254,20 +255,74 @@ lemma integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport simp only [B, integral_smul_nnreal_measure] rfl +open Classical in +/-- Given two left-invariant measures which are finite on compacts, `haarScalarFactor μ' μ` is a +scalar such that `∫ f dμ' = (haarScalarFactor μ' μ) ∫ f dμ` for any compactly supported continuous +function `f`. -/ +@[to_additive "Given two left-invariant measures which are finite on compacts, +`addHaarScalarFactor μ' μ` is a scalar such that `∫ f dμ' = (addHaarScalarFactor μ' μ) ∫ f dμ` for +any compactly supported continuous function `f`."] +noncomputable def haarScalarFactor (μ' μ : Measure G) [IsFiniteMeasureOnCompacts μ] + [IsFiniteMeasureOnCompacts μ'] [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] + [IsOpenPosMeasure μ] : ℝ≥0 := + if ¬ LocallyCompactSpace G then 1 + else (exists_integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport μ' μ).choose + +@[to_additive integral_isAddLeftInvariant_eq_smul_of_hasCompactSupport] +lemma integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport + (μ' μ : Measure G) [IsFiniteMeasureOnCompacts μ] [IsFiniteMeasureOnCompacts μ'] + [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] [IsOpenPosMeasure μ] + {f : G → ℝ} (hf : Continuous f) (h'f : HasCompactSupport f) : + ∫ x, f x ∂μ' = ∫ x, f x ∂(haarScalarFactor μ' μ • μ) := by + classical + rcases h'f.eq_zero_or_locallyCompactSpace_of_group hf with Hf|Hf + · simp [Hf] + · simp only [haarScalarFactor, Hf, not_true_eq_false, ite_false] + exact (exists_integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport μ' μ).choose_spec + f hf h'f + +/-- The scalar factor between two left-invariant measures is non-zero when both measures are +positive on open sets. -/ +@[to_additive] +lemma haarScalarFactor_pos_of_isOpenPosMeasure (μ' μ : Measure G) [IsFiniteMeasureOnCompacts μ] + [IsFiniteMeasureOnCompacts μ'] [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] + [IsOpenPosMeasure μ] [IsOpenPosMeasure μ'] : 0 < haarScalarFactor μ' μ := by + rw [pos_iff_ne_zero] + intro H + -- The group has to be locally compact, otherwise the scalar factor is 1 by definition. + by_cases hG : LocallyCompactSpace G; swap + · simp [haarScalarFactor, hG] at H + -- Fix some nonzero continuous function with compact support `g`. + obtain ⟨g, g_cont, g_comp, g_nonneg, g_one⟩ : + ∃ (g : G → ℝ), Continuous g ∧ HasCompactSupport g ∧ 0 ≤ g ∧ g 1 ≠ 0 := by + rcases exists_compact_mem_nhds (1 : G) with ⟨k, hk, k_mem⟩ + rcases exists_continuous_one_zero_of_isCompact hk isClosed_empty (disjoint_empty k) + with ⟨⟨g, g_cont⟩, gk, -, g_comp, hg⟩ + refine ⟨g, g_cont, g_comp, fun x ↦ (hg x).1, ?_⟩ + have := gk (mem_of_mem_nhds k_mem) + simp only [ContinuousMap.coe_mk, Pi.one_apply] at this + simp [this] + have int_g_pos : 0 < ∫ x, g x ∂μ' := by + apply (integral_pos_iff_support_of_nonneg g_nonneg _).2 + · exact IsOpen.measure_pos μ' g_cont.isOpen_support ⟨1, g_one⟩ + · exact g_cont.integrable_of_hasCompactSupport g_comp + have := integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport μ' μ g_cont g_comp + simp only [H, zero_smul, integral_zero_measure] at this + linarith + /-- **Uniqueness of left-invariant measures**: Given two left-invariant measures which are finite on compacts and inner regular for finite measure sets with respect to compact sets, they coincide in the following sense: they give the same value to finite measure sets, up to a multiplicative constant. -/ @[to_additive] -lemma measure_isMulLeftInvariant_eq_smul_of_ne_top +lemma measure_isMulLeftInvariant_eq_smul_of_ne_top [LocallyCompactSpace G] (μ' μ : Measure G) [IsFiniteMeasureOnCompacts μ] [IsFiniteMeasureOnCompacts μ'] [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] [IsOpenPosMeasure μ] - [InnerRegularCompactLTTop μ] [InnerRegularCompactLTTop μ'] : - ∃ (c : ℝ≥0), ∀ (s : Set G), μ s < ∞ → μ' s < ∞ → μ' s = (c • μ) s := by + [InnerRegularCompactLTTop μ] [InnerRegularCompactLTTop μ'] {s : Set G} + (hs : μ s ≠ ∞) (h's : μ' s ≠ ∞) : μ' s = haarScalarFactor μ' μ • μ s := by /- We know that the measures integrate in the same way continuous compactly supported functions, - up to a constant `c`. We will use this constant `c`. -/ - rcases integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport μ' μ with ⟨c, hc⟩ - refine ⟨c, fun s hs h's ↦ ?_⟩ + up to the factor `c = haarScalarFactor μ' μ`. -/ + let c := haarScalarFactor μ' μ /- By regularity, every compact set may be approximated by a continuous compactly supported function. Therefore, the measures coincide on compact sets. -/ have A : ∀ k, IsCompact k → μ' k = (c • μ) k := by @@ -275,7 +330,7 @@ lemma measure_isMulLeftInvariant_eq_smul_of_ne_top rw [hk.measure_eq_biInf_integral_hasCompactSupport μ', hk.measure_eq_biInf_integral_hasCompactSupport (c • μ)] congr! 7 with f f_cont f_comp _fk _f_nonneg - exact hc f f_cont f_comp + exact integral_isMulLeftInvariant_eq_smul_of_hasCompactSupport μ' μ f_cont f_comp /- By regularity, every measurable set of finite measure may be approximated by compact sets. Therefore, the measures coincide on measurable sets of finite measure. -/ have B : ∀ s, MeasurableSet s → μ s < ∞ → μ' s < ∞ → μ' s = (c • μ) s := by @@ -301,78 +356,50 @@ lemma measure_isMulLeftInvariant_eq_smul_of_ne_top nnreal_smul_coe_apply] apply B · exact (measurableSet_toMeasurable _ _).inter (measurableSet_toMeasurable _ _) - · exact mu_t.le.trans_lt hs - · exact mu'_t.le.trans_lt h's + · exact mu_t.le.trans_lt hs.lt_top + · exact mu'_t.le.trans_lt h's.lt_top /-- **Uniqueness of left-invariant measures**: Given two left-invariant measures which are finite on compacts and inner regular, they coincide up to a multiplicative constant. -/ @[to_additive isAddLeftInvariant_eq_smul_of_innerRegular] -lemma isMulLeftInvariant_eq_smul_of_innerRegular +lemma isMulLeftInvariant_eq_smul_of_innerRegular [LocallyCompactSpace G] (μ' μ : Measure G) [IsFiniteMeasureOnCompacts μ] [IsFiniteMeasureOnCompacts μ'] [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] [IsOpenPosMeasure μ] [InnerRegular μ] [InnerRegular μ'] : - ∃ (c : ℝ≥0), μ' = c • μ := by - rcases measure_isMulLeftInvariant_eq_smul_of_ne_top μ' μ with ⟨c, hc⟩ - refine ⟨c, ?_⟩ + μ' = haarScalarFactor μ' μ • μ := by ext s hs rw [hs.measure_eq_iSup_isCompact, hs.measure_eq_iSup_isCompact] congr! 4 with K _Ks K_comp - exact hc K K_comp.measure_lt_top K_comp.measure_lt_top - -/-- **Uniqueness of left-invariant measures**: Two inner regular Haar measures coincide up to a -multiplicative constant. -/ -@[to_additive isAddHaarMeasure_eq_smul_of_innerRegular] -lemma isHaarMeasure_eq_smul_of_innerRegular - (μ' μ : Measure G) [IsHaarMeasure μ] [IsHaarMeasure μ'] [InnerRegular μ] [InnerRegular μ'] : - ∃ c : ℝ≥0∞, c ≠ 0 ∧ c ≠ ∞ ∧ μ' = c • μ := by - rcases isMulLeftInvariant_eq_smul_of_innerRegular μ' μ with ⟨c, hc⟩ - refine ⟨c, ?_, ENNReal.coe_ne_top, hc⟩ - intro h - simp only [ENNReal.coe_eq_zero.1 h, zero_smul] at hc - have : 0 < μ' univ := NeZero.pos (μ' univ) - simp [hc] at this + exact measure_isMulLeftInvariant_eq_smul_of_ne_top μ' μ K_comp.measure_lt_top.ne + K_comp.measure_lt_top.ne /-- **Uniqueness of left-invariant measures**: Given two left-invariant measures which are finite on compacts and regular, they coincide up to a multiplicative constant. -/ @[to_additive isAddLeftInvariant_eq_smul_of_regular] -lemma isMulLeftInvariant_eq_smul_of_regular +lemma isMulLeftInvariant_eq_smul_of_regular [LocallyCompactSpace G] (μ' μ : Measure G) [IsFiniteMeasureOnCompacts μ] [IsFiniteMeasureOnCompacts μ'] [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] [IsOpenPosMeasure μ] [Regular μ] [Regular μ'] : - ∃ (c : ℝ≥0), μ' = c • μ := by - rcases measure_isMulLeftInvariant_eq_smul_of_ne_top μ' μ with ⟨c, hc⟩ - refine ⟨c, ?_⟩ - have A : ∀ U, IsOpen U → μ' U = (c • μ) U := by + μ' = haarScalarFactor μ' μ • μ := by + have A : ∀ U, IsOpen U → μ' U = (haarScalarFactor μ' μ • μ) U := by intro U hU rw [hU.measure_eq_iSup_isCompact, hU.measure_eq_iSup_isCompact] congr! 4 with K _KU K_comp - exact hc K K_comp.measure_lt_top K_comp.measure_lt_top + exact measure_isMulLeftInvariant_eq_smul_of_ne_top μ' μ K_comp.measure_lt_top.ne + K_comp.measure_lt_top.ne ext s _hs rw [s.measure_eq_iInf_isOpen, s.measure_eq_iInf_isOpen] congr! 4 with U _sU U_open exact A U U_open -/-- **Uniqueness of left-invariant measures**: Two regular Haar measures coincide up to a -multiplicative constant. -/ -@[to_additive isAddHaarMeasure_eq_smul_of_regular] -lemma isHaarMeasure_eq_smul_of_regular - (μ' μ : Measure G) [IsHaarMeasure μ] [IsHaarMeasure μ'] [Regular μ] [Regular μ'] : - ∃ c : ℝ≥0∞, c ≠ 0 ∧ c ≠ ∞ ∧ μ' = c • μ := by - rcases isMulLeftInvariant_eq_smul_of_regular μ' μ with ⟨c, hc⟩ - refine ⟨c, ?_, ENNReal.coe_ne_top, hc⟩ - intro h - simp only [ENNReal.coe_eq_zero.1 h, zero_smul] at hc - have : 0 < μ' univ := NeZero.pos (μ' univ) - simp [hc] at this - /-- **Uniqueness of left-invariant measures**: Two Haar measures coincide up to a multiplicative constant in a second countable group. -/ @[to_additive isAddHaarMeasure_eq_smul] -lemma isHaarMeasure_eq_smul [SecondCountableTopology G] +lemma isHaarMeasure_eq_smul [LocallyCompactSpace G] [SecondCountableTopology G] (μ' μ : Measure G) [IsHaarMeasure μ] [IsHaarMeasure μ'] : - ∃ c : ℝ≥0∞, c ≠ 0 ∧ c ≠ ∞ ∧ μ' = c • μ := - isHaarMeasure_eq_smul_of_regular μ' μ - -- one could use as well `isHaarMeasure_eq_smul_isHaarMeasure_of_innerRegular μ' μ`, as in a + μ' = haarScalarFactor μ' μ • μ := + isMulLeftInvariant_eq_smul_of_regular μ' μ + -- one could use as well `isMulLeftInvariant_eq_smul_of_innerRegular`, as in a -- second countable topological space all Haar measures are regular and inner regular #align measure_theory.measure.is_haar_measure_eq_smul_is_haar_measure MeasureTheory.Measure.isHaarMeasure_eq_smul #align measure_theory.measure.is_add_haar_measure_eq_smul_is_add_haar_measure MeasureTheory.Measure.isAddHaarMeasure_eq_smul @@ -380,26 +407,25 @@ lemma isHaarMeasure_eq_smul [SecondCountableTopology G] /-- **Uniqueness of left-invariant measures**: Given two left-invariant probability measures which are inner regular for finite measure sets with respect to compact sets, they coincide. -/ @[to_additive] -lemma isMulLeftInvariant_eq_of_isProbabilityMeasure +lemma haarScalarFactor_eq_one_of_isProbabilityMeasure [LocallyCompactSpace G] (μ' μ : Measure G) [IsProbabilityMeasure μ] [IsProbabilityMeasure μ'] [InnerRegularCompactLTTop μ] [InnerRegularCompactLTTop μ'] - [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] : μ' = μ := by - rcases isMulLeftInvariant_eq_smul_of_regular μ' μ with ⟨c, hc⟩ - have : ((c : ℝ≥0∞) • μ) univ = μ' univ := by rw [hc]; rfl - simp only [smul_toOuterMeasure, OuterMeasure.coe_smul, Pi.smul_apply, measure_univ, smul_eq_mul, - mul_one, ENNReal.coe_eq_one] at this - simp [hc, this] + [IsMulLeftInvariant μ] [IsMulLeftInvariant μ'] : + haarScalarFactor μ' μ = 1 := by + have : μ' univ = (haarScalarFactor μ' μ : ℝ≥0∞) * μ univ := + measure_isMulLeftInvariant_eq_smul_of_ne_top _ _ (by simp) (by simp) + simpa [eq_comm] using this /-- An invariant σ-finite measure is absolutely continuous with respect to a Haar measure in a -second countable grop. -/ +second countable group. -/ @[to_additive "An invariant measure is absolutely continuous with respect to an additive Haar measure. "] -theorem absolutelyContinuous_isHaarMeasure [LocallyCompactSpace G] [T2Space G] +theorem absolutelyContinuous_isHaarMeasure [LocallyCompactSpace G] [SecondCountableTopology G] (μ ν : Measure G) [SigmaFinite μ] [IsMulLeftInvariant μ] [IsHaarMeasure ν] : μ ≪ ν := by have K : PositiveCompacts G := Classical.arbitrary _ - obtain ⟨c, -, -, h⟩ : ∃ c : ℝ≥0∞, c ≠ 0 ∧ c ≠ ∞ ∧ haarMeasure K = c • ν := - isHaarMeasure_eq_smul _ _ + have h : haarMeasure K = (haarScalarFactor (haarMeasure K) ν : ℝ≥0∞) • ν := + isHaarMeasure_eq_smul (haarMeasure K) ν rw [haarMeasure_unique μ K, h, smul_smul] exact AbsolutelyContinuous.smul (Eq.absolutelyContinuous rfl) _ @@ -418,9 +444,8 @@ instance (priority := 100) IsHaarMeasure.isInvInvariant_of_regular -- `c μ`. Applying again inversion, one gets the measure `c^2 μ`. But since inversion is an -- involution, this is also `μ`. Hence, `c^2 = 1`, which implies `c = 1`. constructor - have : IsHaarMeasure μ.inv := (MulEquiv.inv G).isHaarMeasure_map μ continuous_inv continuous_inv - obtain ⟨c, _, _, hc⟩ : ∃ c : ℝ≥0∞, c ≠ 0 ∧ c ≠ ∞ ∧ μ.inv = c • μ := - isHaarMeasure_eq_smul_of_regular _ _ + let c : ℝ≥0∞ := haarScalarFactor μ.inv μ + have hc : μ.inv = c • μ := isMulLeftInvariant_eq_smul_of_regular μ.inv μ have : map Inv.inv (map Inv.inv μ) = c ^ 2 • μ := by rw [← inv_def μ, hc, Measure.map_smul, ← inv_def μ, hc, smul_smul, pow_two] have μeq : μ = c ^ 2 • μ := by @@ -446,9 +471,8 @@ instance (priority := 100) IsHaarMeasure.isInvInvariant_of_innerRegular -- `c μ`. Applying again inversion, one gets the measure `c^2 μ`. But since inversion is an -- involution, this is also `μ`. Hence, `c^2 = 1`, which implies `c = 1`. constructor - have : IsHaarMeasure μ.inv := (MulEquiv.inv G).isHaarMeasure_map μ continuous_inv continuous_inv - obtain ⟨c, _, _, hc⟩ : ∃ c : ℝ≥0∞, c ≠ 0 ∧ c ≠ ∞ ∧ μ.inv = c • μ := - isHaarMeasure_eq_smul_of_innerRegular _ _ + let c : ℝ≥0∞ := haarScalarFactor μ.inv μ + have hc : μ.inv = c • μ := isMulLeftInvariant_eq_smul_of_innerRegular μ.inv μ have : map Inv.inv (map Inv.inv μ) = c ^ 2 • μ := by rw [← inv_def μ, hc, Measure.map_smul, ← inv_def μ, hc, smul_smul, pow_two] have μeq : μ = c ^ 2 • μ := by @@ -475,7 +499,8 @@ theorem measurePreserving_zpow [CompactSpace G] [RootableBy G ℤ] have : (μ.map f).IsHaarMeasure := isHaarMeasure_map_of_isFiniteMeasure μ f hf (RootableBy.surjective_pow G ℤ hn) have : InnerRegular (μ.map f) := InnerRegular.map_of_continuous hf - obtain ⟨C, -, -, hC⟩ := isHaarMeasure_eq_smul_of_innerRegular (μ.map f) μ + let C : ℝ≥0∞ := haarScalarFactor (μ.map f) μ + have hC : μ.map f = C • μ := isMulLeftInvariant_eq_smul_of_innerRegular _ _ suffices C = 1 by rwa [this, one_smul] at hC have h_univ : (μ.map f) univ = μ univ := by rw [map_apply_of_aemeasurable hf.measurable.aemeasurable MeasurableSet.univ, diff --git a/Mathlib/MeasureTheory/Measure/Hausdorff.lean b/Mathlib/MeasureTheory/Measure/Hausdorff.lean index 119d8d03cadef..d0d407724e834 100644 --- a/Mathlib/MeasureTheory/Measure/Hausdorff.lean +++ b/Mathlib/MeasureTheory/Measure/Hausdorff.lean @@ -5,7 +5,6 @@ Authors: Yury Kudryashov -/ import Mathlib.Analysis.Convex.Between import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic -import Mathlib.MeasureTheory.Measure.Haar.InnerProductSpace import Mathlib.MeasureTheory.Measure.Lebesgue.Basic import Mathlib.Topology.MetricSpace.Holder import Mathlib.Topology.MetricSpace.MetricSeparated @@ -761,7 +760,7 @@ theorem hausdorffMeasure_image_le (h : HolderOnWith C r f s) (hr : 0 < r) {d : · rw [← image_iUnion, ← iUnion_inter] exact image_subset _ (subset_inter hst Subset.rfl) · refine' ENNReal.tsum_le_tsum fun n => _ - simp only [iSup_le_iff, nonempty_image_iff] + simp only [iSup_le_iff, image_nonempty] intro hft simp only [Nonempty.mono ((t n).inter_subset_left s) hft, ciSup_pos] rw [ENNReal.rpow_mul, ← ENNReal.mul_rpow_of_nonneg _ _ hd] diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/Complex.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/Complex.lean index ae937e6d566f8..010cd84c2fed4 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/Complex.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/Complex.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.MeasureTheory.Measure.Haar.InnerProductSpace +import Mathlib.MeasureTheory.Constructions.BorelSpace.Complex #align_import measure_theory.measure.lebesgue.complex from "leanprover-community/mathlib"@"fd5edc43dc4f10b85abfe544b88f82cf13c5f844" diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/VolumeOfBalls.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/VolumeOfBalls.lean index 722ea369f324d..b48cd373d9435 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/VolumeOfBalls.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/VolumeOfBalls.lean @@ -6,6 +6,7 @@ Authors: Xavier Roblot import Mathlib.MeasureTheory.Constructions.HaarToSphere import Mathlib.MeasureTheory.Integral.Gamma import Mathlib.MeasureTheory.Integral.Pi +import Mathlib.Analysis.SpecialFunctions.Gamma.BohrMollerup /-! # Volume of balls @@ -168,7 +169,7 @@ theorem MeasureTheory.volume_sum_rpow_lt_one : have h₁ : 0 < p := by linarith have h₂ : ∀ x : ι → ℝ, 0 ≤ ∑ i, |x i| ^ p := by refine fun _ => Finset.sum_nonneg' ?_ - exact fun i => (fun _ => rpow_nonneg_of_nonneg (abs_nonneg _) _) _ + exact fun i => (fun _ => rpow_nonneg (abs_nonneg _) _) _ -- We collect facts about `Lp` norms that will be used in `measure_lt_one_eq_integral_div_gamma` have eq_norm := fun x : ι → ℝ => (PiLp.norm_eq_sum (p := .ofReal p) (f := x) ((toReal_ofReal (le_of_lt h₁)).symm ▸ h₁)) @@ -187,7 +188,7 @@ theorem MeasureTheory.volume_sum_rpow_lt_one : (g := fun x => (∑ i, |x i| ^ p) ^ (1 / p)) nm_zero nm_neg nm_add (eq_zero _).mp (fun r x => nm_smul r x) (by linarith : 0 < p)) using 4 · rw [rpow_lt_one_iff' _ (one_div_pos.mpr h₁)] - exact Finset.sum_nonneg' (fun _ => rpow_nonneg_of_nonneg (abs_nonneg _) _) + exact Finset.sum_nonneg' (fun _ => rpow_nonneg (abs_nonneg _) _) · simp_rw [← rpow_mul (h₂ _), div_mul_cancel _ (ne_of_gt h₁), Real.rpow_one, ← Finset.sum_neg_distrib, exp_sum] rw [integral_fintype_prod_eq_pow ι fun x : ℝ => exp (- |x| ^ p), integral_comp_abs @@ -199,8 +200,8 @@ theorem MeasureTheory.volume_sum_rpow_lt [Nonempty ι] {p : ℝ} (hp : 1 ≤ p) .ofReal ((2 * Gamma (1 / p + 1)) ^ card ι / Gamma (card ι / p + 1)) := by have h₁ : ∀ x : ι → ℝ, 0 ≤ ∑ i, |x i| ^ p := by refine fun _ => Finset.sum_nonneg' ?_ - exact fun i => (fun _ => rpow_nonneg_of_nonneg (abs_nonneg _) _) _ - have h₂ : ∀ x : ι → ℝ, 0 ≤ (∑ i, |x i| ^ p) ^ (1 / p) := fun x => rpow_nonneg_of_nonneg (h₁ x) _ + exact fun i => (fun _ => rpow_nonneg (abs_nonneg _) _) _ + have h₂ : ∀ x : ι → ℝ, 0 ≤ (∑ i, |x i| ^ p) ^ (1 / p) := fun x => rpow_nonneg (h₁ x) _ obtain hr | hr := le_or_lt r 0 · have : {x : ι → ℝ | (∑ i, |x i| ^ p) ^ (1 / p) < r} = ∅ := by ext x @@ -213,7 +214,7 @@ theorem MeasureTheory.volume_sum_rpow_lt [Nonempty ι] {p : ℝ} (hp : 1 ≤ p) smul_eq_mul, abs_mul, mul_rpow (abs_nonneg _) (abs_nonneg _), abs_inv, inv_rpow (abs_nonneg _), ← Finset.mul_sum, abs_eq_self.mpr (le_of_lt hr), inv_mul_lt_iff (rpow_pos_of_pos hr _), mul_one, ← rpow_lt_rpow_iff - (rpow_nonneg_of_nonneg (h₁ _) _) (le_of_lt hr) (by linarith : 0 < p), ← rpow_mul + (rpow_nonneg (h₁ _) _) (le_of_lt hr) (by linarith : 0 < p), ← rpow_mul (h₁ _), div_mul_cancel _ (ne_of_gt (by linarith) : p ≠ 0), Real.rpow_one] theorem MeasureTheory.volume_sum_rpow_le [Nonempty ι] {p : ℝ} (hp : 1 ≤ p) (r : ℝ) : @@ -242,7 +243,7 @@ theorem Complex.volume_sum_rpow_lt_one {p : ℝ} (hp : 1 ≤ p) : have h₁ : 0 < p := by linarith have h₂ : ∀ x : ι → ℂ, 0 ≤ ∑ i, ‖x i‖ ^ p := by refine fun _ => Finset.sum_nonneg' ?_ - exact fun i => (fun _ => rpow_nonneg_of_nonneg (norm_nonneg _) _) _ + exact fun i => (fun _ => rpow_nonneg (norm_nonneg _) _) _ -- We collect facts about `Lp` norms that will be used in `measure_lt_one_eq_integral_div_gamma` have eq_norm := fun x : ι → ℂ => (PiLp.norm_eq_sum (p := .ofReal p) (f := x) ((toReal_ofReal (le_of_lt h₁)).symm ▸ h₁)) @@ -261,7 +262,7 @@ theorem Complex.volume_sum_rpow_lt_one {p : ℝ} (hp : 1 ≤ p) : (g := fun x => (∑ i, ‖x i‖ ^ p) ^ (1 / p)) nm_zero nm_neg nm_add (eq_zero _).mp (fun r x => nm_smul r x) (by linarith : 0 < p) using 4 · rw [rpow_lt_one_iff' _ (one_div_pos.mpr h₁)] - exact Finset.sum_nonneg' (fun _ => rpow_nonneg_of_nonneg (norm_nonneg _) _) + exact Finset.sum_nonneg' (fun _ => rpow_nonneg (norm_nonneg _) _) · simp_rw [← rpow_mul (h₂ _), div_mul_cancel _ (ne_of_gt h₁), Real.rpow_one, ← Finset.sum_neg_distrib, Real.exp_sum] rw [integral_fintype_prod_eq_pow ι fun x : ℂ => Real.exp (- ‖x‖ ^ p), @@ -274,8 +275,8 @@ theorem Complex.volume_sum_rpow_lt [Nonempty ι] {p : ℝ} (hp : 1 ≤ p) (r : .ofReal ((π * Real.Gamma (2 / p + 1)) ^ card ι / Real.Gamma (2 * card ι / p + 1)) := by have h₁ : ∀ x : ι → ℂ, 0 ≤ ∑ i, ‖x i‖ ^ p := by refine fun _ => Finset.sum_nonneg' ?_ - exact fun i => (fun _ => rpow_nonneg_of_nonneg (norm_nonneg _) _) _ - have h₂ : ∀ x : ι → ℂ, 0 ≤ (∑ i, ‖x i‖ ^ p) ^ (1 / p) := fun x => rpow_nonneg_of_nonneg (h₁ x) _ + exact fun i => (fun _ => rpow_nonneg (norm_nonneg _) _) _ + have h₂ : ∀ x : ι → ℂ, 0 ≤ (∑ i, ‖x i‖ ^ p) ^ (1 / p) := fun x => rpow_nonneg (h₁ x) _ obtain hr | hr := le_or_lt r 0 · have : {x : ι → ℂ | (∑ i, ‖x i‖ ^ p) ^ (1 / p) < r} = ∅ := by ext x @@ -287,7 +288,7 @@ theorem Complex.volume_sum_rpow_lt [Nonempty ι] {p : ℝ} (hp : 1 ≤ p) (r : simp_rw [← Set.preimage_smul_inv₀ (ne_of_gt hr), Set.preimage_setOf_eq, Pi.smul_apply, norm_smul, mul_rpow (norm_nonneg _) (norm_nonneg _), Real.norm_eq_abs, abs_inv, inv_rpow (abs_nonneg _), ← Finset.mul_sum, abs_eq_self.mpr (le_of_lt hr), inv_mul_lt_iff - (rpow_pos_of_pos hr _), mul_one, ← rpow_lt_rpow_iff (rpow_nonneg_of_nonneg (h₁ _) _) + (rpow_pos_of_pos hr _), mul_one, ← rpow_lt_rpow_iff (rpow_nonneg (h₁ _) _) (le_of_lt hr) (by linarith : 0 < p), ← rpow_mul (h₁ _), div_mul_cancel _ (ne_of_gt (by linarith) : p ≠ 0), Real.rpow_one, finrank_pi, finrank_pi_fintype ℝ, Complex.finrank_real_complex, Finset.sum_const, smul_eq_mul, mul_comm, Fintype.card] diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean index e87733ebb9ebf..92e499905c56b 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean @@ -136,13 +136,15 @@ theorem measure_union_add_inter' (hs : MeasurableSet s) (t : Set α) : rw [union_comm, inter_comm, measure_union_add_inter t hs, add_comm] #align measure_theory.measure_union_add_inter' MeasureTheory.measure_union_add_inter' +open scoped symmDiff in lemma measure_symmDiff_eq (hs : MeasurableSet s) (ht : MeasurableSet t) : μ (s ∆ t) = μ (s \ t) + μ (t \ s) := by simpa only [symmDiff_def, sup_eq_union] using measure_union disjoint_sdiff_sdiff (ht.diff hs) +open scoped symmDiff in lemma measure_symmDiff_le (s t u : Set α) : μ (s ∆ u) ≤ μ (s ∆ t) + μ (t ∆ u) := - le_trans (μ.mono $ symmDiff_triangle s t u) (measure_union_le (s ∆ t) (t ∆ u)) + le_trans (μ.mono <| symmDiff_triangle s t u) (measure_union_le (s ∆ t) (t ∆ u)) theorem measure_add_measure_compl (h : MeasurableSet s) : μ s + μ sᶜ = μ univ := measure_add_measure_compl₀ h.nullMeasurableSet @@ -608,7 +610,7 @@ theorem measure_limsup_eq_zero {s : ℕ → Set α} (hs : (∑' i, μ (s i)) ≠ exact fun ⟨i, hi⟩ => ⟨i + (m - n), by simpa only [add_assoc, tsub_add_cancel_of_le hnm] using hi⟩ #align measure_theory.measure_limsup_eq_zero MeasureTheory.measure_limsup_eq_zero -theorem measure_liminf_eq_zero {s : ℕ → Set α} (h : (∑' i, μ (s i)) ≠ ⊤) : +theorem measure_liminf_eq_zero {s : ℕ → Set α} (h : (∑' i, μ (s i)) ≠ ∞) : μ (liminf s atTop) = 0 := by rw [← le_zero_iff] have : liminf s atTop ≤ limsup s atTop := liminf_le_limsup diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean b/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean index dc80e03812b97..c4c68e51f44a3 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean @@ -64,7 +64,7 @@ open Function MeasurableSpace open Classical Topology BigOperators Filter ENNReal NNReal -variable {α β γ δ ι : Type*} +variable {α β γ δ : Type*} {ι : Sort*} namespace MeasureTheory @@ -203,10 +203,10 @@ theorem measure_mono_top (h : s₁ ⊆ s₂) (h₁ : μ s₁ = ∞) : μ s₂ = #align measure_theory.measure_mono_top MeasureTheory.measure_mono_top @[simp, mono] -theorem measure_le_measure_union_left : μ s ≤ μ (s ∪ t) := μ.mono $ subset_union_left s t +theorem measure_le_measure_union_left : μ s ≤ μ (s ∪ t) := μ.mono <| subset_union_left s t @[simp, mono] -theorem measure_le_measure_union_right : μ t ≤ μ (s ∪ t) := μ.mono $ subset_union_right s t +theorem measure_le_measure_union_right : μ t ≤ μ (s ∪ t) := μ.mono <| subset_union_right s t /-- For every set there exists a measurable superset of the same measure. -/ theorem exists_measurable_superset (μ : Measure α) (s : Set α) : @@ -216,7 +216,7 @@ theorem exists_measurable_superset (μ : Measure α) (s : Set α) : /-- For every set `s` and a countable collection of measures `μ i` there exists a measurable superset `t ⊇ s` such that each measure `μ i` takes the same value on `s` and `t`. -/ -theorem exists_measurable_superset_forall_eq {ι} [Countable ι] (μ : ι → Measure α) (s : Set α) : +theorem exists_measurable_superset_forall_eq [Countable ι] (μ : ι → Measure α) (s : Set α) : ∃ t, s ⊆ t ∧ MeasurableSet t ∧ ∀ i, μ i t = μ i s := by simpa only [← measure_eq_trim] using OuterMeasure.exists_measurable_superset_forall_eq_trim (fun i => (μ i).toOuterMeasure) s @@ -267,7 +267,7 @@ theorem measure_biUnion_lt_top {s : Set β} {f : β → Set α} (hs : s.Finite) apply ENNReal.sum_lt_top; simpa only [Finite.mem_toFinset] #align measure_theory.measure_bUnion_lt_top MeasureTheory.measure_biUnion_lt_top -theorem measure_iUnion_null [Countable β] {s : β → Set α} : (∀ i, μ (s i) = 0) → μ (⋃ i, s i) = 0 := +theorem measure_iUnion_null [Countable ι] {s : ι → Set α} : (∀ i, μ (s i) = 0) → μ (⋃ i, s i) = 0 := μ.toOuterMeasure.iUnion_null #align measure_theory.measure_Union_null MeasureTheory.measure_iUnion_null @@ -277,15 +277,12 @@ theorem measure_iUnion_null_iff [Countable ι] {s : ι → Set α} : μ.toOuterMeasure.iUnion_null_iff #align measure_theory.measure_Union_null_iff MeasureTheory.measure_iUnion_null_iff -/-- A version of `measure_iUnion_null_iff` for unions indexed by Props -TODO: in the long run it would be better to combine this with `measure_iUnion_null_iff` by -generalising to `Sort`. -/ --- @[simp] -- Porting note: simp can prove this +@[deprecated] -- Deprecated since 14 January 2024 theorem measure_iUnion_null_iff' {ι : Prop} {s : ι → Set α} : μ (⋃ i, s i) = 0 ↔ ∀ i, μ (s i) = 0 := - μ.toOuterMeasure.iUnion_null_iff' + measure_iUnion_null_iff #align measure_theory.measure_Union_null_iff' MeasureTheory.measure_iUnion_null_iff' -theorem measure_biUnion_null_iff {s : Set ι} (hs : s.Countable) {t : ι → Set α} : +theorem measure_biUnion_null_iff {ι : Type*} {s : Set ι} (hs : s.Countable) {t : ι → Set α} : μ (⋃ i ∈ s, t i) = 0 ↔ ∀ i ∈ s, μ (t i) = 0 := μ.toOuterMeasure.biUnion_null_iff hs #align measure_theory.measure_bUnion_null_iff MeasureTheory.measure_biUnion_null_iff @@ -328,6 +325,7 @@ theorem measure_union_ne_top (hs : μ s ≠ ∞) (ht : μ t ≠ ∞) : μ (s ∪ (measure_union_lt_top hs.lt_top ht.lt_top).ne #align measure_theory.measure_union_ne_top MeasureTheory.measure_union_ne_top +open scoped symmDiff in theorem measure_symmDiff_ne_top (hs : μ s ≠ ∞) (ht : μ t ≠ ∞) : μ (s ∆ t) ≠ ∞ := ne_top_of_le_ne_top (measure_union_ne_top hs ht) <| measure_mono symmDiff_subset_union @@ -336,7 +334,7 @@ theorem measure_union_eq_top_iff : μ (s ∪ t) = ∞ ↔ μ s = ∞ ∨ μ t = not_iff_not.1 <| by simp only [← lt_top_iff_ne_top, ← Ne.def, not_or, measure_union_lt_top_iff] #align measure_theory.measure_union_eq_top_iff MeasureTheory.measure_union_eq_top_iff -theorem exists_measure_pos_of_not_measure_iUnion_null [Countable β] {s : β → Set α} +theorem exists_measure_pos_of_not_measure_iUnion_null [Countable ι] {s : ι → Set α} (hs : μ (⋃ n, s n) ≠ 0) : ∃ n, 0 < μ (s n) := by contrapose! hs exact measure_iUnion_null fun n => nonpos_iff_eq_zero.1 (hs n) @@ -416,12 +414,11 @@ instance instCountableInterFilter : CountableInterFilter μ.ae := by unfold Measure.ae; infer_instance #align measure_theory.measure.ae.countable_Inter_filter MeasureTheory.instCountableInterFilter -theorem ae_all_iff {ι : Sort*} [Countable ι] {p : α → ι → Prop} : - (∀ᵐ a ∂μ, ∀ i, p a i) ↔ ∀ i, ∀ᵐ a ∂μ, p a i := +theorem ae_all_iff [Countable ι] {p : α → ι → Prop} : (∀ᵐ a ∂μ, ∀ i, p a i) ↔ ∀ i, ∀ᵐ a ∂μ, p a i := eventually_countable_forall #align measure_theory.ae_all_iff MeasureTheory.ae_all_iff -theorem all_ae_of {ι : Sort _} {p : α → ι → Prop} (hp : ∀ᵐ a ∂μ, ∀ i, p a i) (i : ι) : +theorem all_ae_of {p : α → ι → Prop} (hp : ∀ᵐ a ∂μ, ∀ i, p a i) (i : ι) : ∀ᵐ a ∂μ, p a i := by filter_upwards [hp] with a ha using ha i @@ -429,7 +426,7 @@ lemma ae_iff_of_countable [Countable α] {p : α → Prop} : (∀ᵐ x ∂μ, p rw [ae_iff, measure_null_iff_singleton] exacts [forall_congr' fun _ ↦ not_imp_comm, Set.to_countable _] -theorem ae_ball_iff {S : Set ι} (hS : S.Countable) {p : α → ∀ i ∈ S, Prop} : +theorem ae_ball_iff {ι : Type*} {S : Set ι} (hS : S.Countable) {p : α → ∀ i ∈ S, Prop} : (∀ᵐ x ∂μ, ∀ i (hi : i ∈ S), p x i hi) ↔ ∀ i (hi : i ∈ S), ∀ᵐ x ∂μ, p x i hi := eventually_countable_ball hS #align measure_theory.ae_ball_iff MeasureTheory.ae_ball_iff @@ -496,6 +493,7 @@ theorem ae_eq_set {s t : Set α} : s =ᵐ[μ] t ↔ μ (s \ t) = 0 ∧ μ (t \ s simp [eventuallyLE_antisymm_iff, ae_le_set] #align measure_theory.ae_eq_set MeasureTheory.ae_eq_set +open scoped symmDiff in @[simp] theorem measure_symmDiff_eq_zero_iff {s t : Set α} : μ (s ∆ t) = 0 ↔ s =ᵐ[μ] t := by simp [ae_eq_set, symmDiff_def] diff --git a/Mathlib/MeasureTheory/Measure/OuterMeasure.lean b/Mathlib/MeasureTheory/Measure/OuterMeasure.lean index ba56568145bd5..556b9d1093a76 100644 --- a/Mathlib/MeasureTheory/Measure/OuterMeasure.lean +++ b/Mathlib/MeasureTheory/Measure/OuterMeasure.lean @@ -91,6 +91,7 @@ theorem empty' (m : OuterMeasure α) : m ∅ = 0 := m.empty #align measure_theory.outer_measure.empty' MeasureTheory.OuterMeasure.empty' +@[gcongr] theorem mono' (m : OuterMeasure α) {s₁ s₂} (h : s₁ ⊆ s₂) : m s₁ ≤ m s₂ := m.mono h #align measure_theory.outer_measure.mono' MeasureTheory.OuterMeasure.mono' @@ -109,36 +110,32 @@ protected theorem iUnion (m : OuterMeasure α) {β} [Countable β] (s : β → S rel_iSup_tsum m m.empty (· ≤ ·) m.iUnion_nat s #align measure_theory.outer_measure.Union MeasureTheory.OuterMeasure.iUnion -theorem iUnion_null [Countable β] (m : OuterMeasure α) {s : β → Set α} (h : ∀ i, m (s i) = 0) : - m (⋃ i, s i) = 0 := by simpa [h] using m.iUnion s -#align measure_theory.outer_measure.Union_null MeasureTheory.OuterMeasure.iUnion_null - -@[simp] -theorem iUnion_null_iff [Countable β] (m : OuterMeasure α) {s : β → Set α} : - m (⋃ i, s i) = 0 ↔ ∀ i, m (s i) = 0 := - ⟨fun h _ => m.mono_null (subset_iUnion _ _) h, m.iUnion_null⟩ -#align measure_theory.outer_measure.Union_null_iff MeasureTheory.OuterMeasure.iUnion_null_iff - -/-- A version of `iUnion_null_iff` for unions indexed by Props. -TODO: in the long run it would be better to combine this with `iUnion_null_iff` by -generalising to `Sort`. -/ -@[simp] -theorem iUnion_null_iff' (m : OuterMeasure α) {ι : Prop} {s : ι → Set α} : - m (⋃ i, s i) = 0 ↔ ∀ i, m (s i) = 0 := - ⟨ fun h i => mono_null m (subset_iUnion s i) h, - by by_cases i : ι <;> simp [i]⟩ -#align measure_theory.outer_measure.Union_null_iff' MeasureTheory.OuterMeasure.iUnion_null_iff' - theorem biUnion_null_iff (m : OuterMeasure α) {s : Set β} (hs : s.Countable) {t : β → Set α} : m (⋃ i ∈ s, t i) = 0 ↔ ∀ i ∈ s, m (t i) = 0 := by - haveI := hs.toEncodable - rw [biUnion_eq_iUnion, iUnion_null_iff, SetCoe.forall'] + refine ⟨fun h i hi ↦ m.mono_null (subset_biUnion_of_mem hi) h, fun h ↦ ?_⟩ + have _ := hs.toEncodable + simpa [h] using m.iUnion fun x : s ↦ t x #align measure_theory.outer_measure.bUnion_null_iff MeasureTheory.OuterMeasure.biUnion_null_iff theorem sUnion_null_iff (m : OuterMeasure α) {S : Set (Set α)} (hS : S.Countable) : m (⋃₀ S) = 0 ↔ ∀ s ∈ S, m s = 0 := by rw [sUnion_eq_biUnion, m.biUnion_null_iff hS] #align measure_theory.outer_measure.sUnion_null_iff MeasureTheory.OuterMeasure.sUnion_null_iff +@[simp] +theorem iUnion_null_iff {ι : Sort*} [Countable ι] (m : OuterMeasure α) {s : ι → Set α} : + m (⋃ i, s i) = 0 ↔ ∀ i, m (s i) = 0 := by + rw [← sUnion_range, m.sUnion_null_iff (countable_range s), forall_range_iff] +#align measure_theory.outer_measure.Union_null_iff MeasureTheory.OuterMeasure.iUnion_null_iff + +alias ⟨_, iUnion_null⟩ := iUnion_null_iff +#align measure_theory.outer_measure.Union_null MeasureTheory.OuterMeasure.iUnion_null + +@[deprecated] -- Deprecated since 14 January 2024 +theorem iUnion_null_iff' (m : OuterMeasure α) {ι : Prop} {s : ι → Set α} : + m (⋃ i, s i) = 0 ↔ ∀ i, m (s i) = 0 := + m.iUnion_null_iff +#align measure_theory.outer_measure.Union_null_iff' MeasureTheory.OuterMeasure.iUnion_null_iff' + protected theorem iUnion_finset (m : OuterMeasure α) (s : β → Set α) (t : Finset β) : m (⋃ i ∈ t, s i) ≤ ∑ i in t, m (s i) := rel_iSup_sum m m.empty (· ≤ ·) m.iUnion_nat s t @@ -188,8 +185,8 @@ theorem iUnion_of_tendsto_zero {ι} (m : OuterMeasure α) {s : ι → Set α} (l /-- If `s : ℕ → Set α` is a monotone sequence of sets such that `∑' k, m (s (k + 1) \ s k) ≠ ∞`, then `m (⋃ n, s n) = ⨆ n, m (s n)`. -/ theorem iUnion_nat_of_monotone_of_tsum_ne_top (m : OuterMeasure α) {s : ℕ → Set α} - (h_mono : ∀ n, s n ⊆ s (n + 1)) (h0 : (∑' k, m (s (k + 1) \ s k)) ≠ ∞) - [∀ i:ℕ, DecidablePred (· ∈ s i)] : m (⋃ n, s n) = ⨆ n, m (s n) := by + (h_mono : ∀ n, s n ⊆ s (n + 1)) (h0 : (∑' k, m (s (k + 1) \ s k)) ≠ ∞) : + m (⋃ n, s n) = ⨆ n, m (s n) := by refine' m.iUnion_of_tendsto_zero atTop _ refine' tendsto_nhds_bot_mono' (ENNReal.tendsto_sum_nat_add _ h0) fun n => _ refine' (m.mono _).trans (m.iUnion _) @@ -427,7 +424,7 @@ theorem smul_iSup [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] { end Supremum -@[mono] +@[mono, gcongr] theorem mono'' {m₁ m₂ : OuterMeasure α} {s₁ s₂ : Set α} (hm : m₁ ≤ m₂) (hs : s₁ ⊆ s₂) : m₁ s₁ ≤ m₂ s₂ := (hm s₁).trans (m₂.mono hs) @@ -901,7 +898,7 @@ theorem comap_boundedBy {β} (f : β → α) exact (@H ⟨s, hs⟩ ⟨t, ht⟩ hst).trans (le_iSup (fun _ : t.Nonempty => m t) ht) · dsimp only [boundedBy] congr with s : 1 - rw [nonempty_image_iff] + rw [image_nonempty] #align measure_theory.outer_measure.comap_bounded_by MeasureTheory.OuterMeasure.comap_boundedBy /-- If `m u = ∞` for any set `u` that has nonempty intersection both with `s` and `t`, then diff --git a/Mathlib/MeasureTheory/Measure/Regular.lean b/Mathlib/MeasureTheory/Measure/Regular.lean index f425a92eedefc..96d8e09144bdf 100644 --- a/Mathlib/MeasureTheory/Measure/Regular.lean +++ b/Mathlib/MeasureTheory/Measure/Regular.lean @@ -320,7 +320,7 @@ class InnerRegularCompactLTTop (μ : Measure α) : Prop where -- see Note [lower instance priority] /-- A regular measure is weakly regular in a T2 space or in a regular space. -/ -instance (priority := 100) Regular.weaklyRegular [ClosableCompactSubsetOpenSpace α] [Regular μ] : +instance (priority := 100) Regular.weaklyRegular [T2OrLocallyCompactRegularSpace α] [Regular μ] : WeaklyRegular μ := by constructor intro U hU r hr @@ -423,7 +423,7 @@ lemma of_restrict [OpensMeasurableSpace α] {μ : Measure α} {s : ℕ → Set have : ∀ n, ∃ (U : _) (_ : U ⊇ A n), IsOpen U ∧ μ U < μ (A n) + δ n := by intro n have H₁ : ∀ t, μ.restrict (s n) t = μ (t ∩ s n) := fun t => restrict_apply' (hm n) - have Ht : μ.restrict (s n) (A n) ≠ ⊤ := by + have Ht : μ.restrict (s n) (A n) ≠ ∞ := by rw [H₁] exact ((measure_mono ((inter_subset_left _ _).trans (subset_iUnion A n))).trans_lt HA).ne rcases (A n).exists_isOpen_lt_add Ht (δ0 n).ne' with ⟨U, hAU, hUo, hU⟩ @@ -438,6 +438,13 @@ lemma of_restrict [OpensMeasurableSpace α] {μ : Measure α} {s : ℕ → Set _ = μ (⋃ n, A n) + ∑' n, δ n := (congr_arg₂ (· + ·) (measure_iUnion hAd hAm).symm rfl) _ < r := hδε +lemma measure_closure_eq_of_isCompact [T2OrLocallyCompactRegularSpace α] [OuterRegular μ] + {k : Set α} (hk : IsCompact k) : μ (closure k) = μ k := by + apply le_antisymm ?_ (measure_mono subset_closure) + simp only [measure_eq_iInf_isOpen k, le_iInf_iff] + intro u ku u_open + exact measure_mono (hk.closure_subset_of_isOpen u_open ku) + end OuterRegular /-- If a measure `μ` admits finite spanning open sets such that the restriction of `μ` to each set @@ -486,7 +493,7 @@ open Finset in sets. Then the measure is weakly regular. -/ theorem weaklyRegular_of_finite [BorelSpace α] (μ : Measure α) [IsFiniteMeasure μ] (H : InnerRegularWRT μ IsClosed IsOpen) : WeaklyRegular μ := by - have hfin : ∀ {s}, μ s ≠ ⊤ := @(measure_ne_top μ) + have hfin : ∀ {s}, μ s ≠ ∞ := @(measure_ne_top μ) suffices ∀ s, MeasurableSet s → ∀ ε, ε ≠ 0 → ∃ F, F ⊆ s ∧ ∃ U, U ⊇ s ∧ IsClosed F ∧ IsOpen U ∧ μ s ≤ μ F + ε ∧ μ U ≤ μ s + ε by refine' @@ -665,7 +672,7 @@ instance smul_nnreal [InnerRegular μ] (c : ℝ≥0) : InnerRegular (c • μ) : instance (priority := 100) [InnerRegular μ] : InnerRegularCompactLTTop μ := ⟨fun _s hs r hr ↦ InnerRegular.innerRegular hs.1 r hr⟩ -lemma innerRegularWRT_isClosed_isOpen [ClosableCompactSubsetOpenSpace α] [OpensMeasurableSpace α] +lemma innerRegularWRT_isClosed_isOpen [T2OrLocallyCompactRegularSpace α] [OpensMeasurableSpace α] [h : InnerRegular μ] : InnerRegularWRT μ IsClosed IsOpen := by intro U hU r hr rcases h.innerRegular hU.measurableSet r hr with ⟨K, KU, K_comp, hK⟩ @@ -759,12 +766,12 @@ instance (priority := 50) [h : InnerRegularCompactLTTop μ] [IsFiniteMeasure μ] convert h.innerRegular with s simp [measure_ne_top μ s] -instance (priority := 50) [BorelSpace α] [ClosableCompactSubsetOpenSpace α] +instance (priority := 50) [BorelSpace α] [T2OrLocallyCompactRegularSpace α] [InnerRegularCompactLTTop μ] [IsFiniteMeasure μ] : WeaklyRegular μ := by apply InnerRegularWRT.weaklyRegular_of_finite exact InnerRegular.innerRegularWRT_isClosed_isOpen -instance (priority := 50) [BorelSpace α] [ClosableCompactSubsetOpenSpace α] +instance (priority := 50) [BorelSpace α] [T2OrLocallyCompactRegularSpace α] [h : InnerRegularCompactLTTop μ] [IsFiniteMeasure μ] : Regular μ := by constructor apply InnerRegularWRT.trans h.innerRegular @@ -999,7 +1006,7 @@ protected theorem smul [Regular μ] {x : ℝ≥0∞} (hx : x ≠ ∞) : (x • instance smul_nnreal [Regular μ] (c : ℝ≥0) : Regular (c • μ) := Regular.smul coe_ne_top /-- The restriction of a regular measure to a set of finite measure is regular. -/ -theorem restrict_of_measure_ne_top [ClosableCompactSubsetOpenSpace α] [BorelSpace α] [Regular μ] +theorem restrict_of_measure_ne_top [T2OrLocallyCompactRegularSpace α] [BorelSpace α] [Regular μ] {A : Set α} (h'A : μ A ≠ ∞) : Regular (μ.restrict A) := by have : WeaklyRegular (μ.restrict A) := WeaklyRegular.restrict_of_measure_ne_top h'A constructor diff --git a/Mathlib/MeasureTheory/Measure/Typeclasses.lean b/Mathlib/MeasureTheory/Measure/Typeclasses.lean index fcc5f1ddc700f..60c95b55fdb5a 100644 --- a/Mathlib/MeasureTheory/Measure/Typeclasses.lean +++ b/Mathlib/MeasureTheory/Measure/Typeclasses.lean @@ -185,6 +185,8 @@ theorem ae_mem_iff_measure_eq [IsFiniteMeasure μ] {s : Set α} (hs : NullMeasur ae_iff_measure_eq hs #align measure_theory.ae_mem_iff_measure_eq MeasureTheory.ae_mem_iff_measure_eq +open scoped symmDiff + theorem abs_toReal_measure_sub_le_measure_symmDiff' (hs : MeasurableSet s) (ht : MeasurableSet t) (hs' : μ s ≠ ∞) (ht' : μ t ≠ ∞) : |(μ s).toReal - (μ t).toReal| ≤ (μ (s ∆ t)).toReal := by @@ -291,10 +293,10 @@ theorem prob_compl_eq_one_sub (hs : MeasurableSet s) : μ sᶜ = 1 - μ s := #align measure_theory.prob_compl_eq_one_iff MeasureTheory.prob_compl_eq_one_iff lemma mem_ae_iff_prob_eq_one₀ (hs : NullMeasurableSet s μ) : s ∈ μ.ae ↔ μ s = 1 := - mem_ae_iff.trans $ prob_compl_eq_zero_iff₀ hs + mem_ae_iff.trans <| prob_compl_eq_zero_iff₀ hs lemma mem_ae_iff_prob_eq_one (hs : MeasurableSet s) : s ∈ μ.ae ↔ μ s = 1 := - mem_ae_iff.trans $ prob_compl_eq_zero_iff hs + mem_ae_iff.trans <| prob_compl_eq_zero_iff hs lemma ae_iff_prob_eq_one (hp : Measurable p) : (∀ᵐ a ∂μ, p a) ↔ μ {a | p a} = 1 := mem_ae_iff_prob_eq_one hp.setOf @@ -979,7 +981,7 @@ end FiniteSpanningSetsIn theorem sigmaFinite_of_countable {S : Set (Set α)} (hc : S.Countable) (hμ : ∀ s ∈ S, μ s < ∞) (hU : ⋃₀ S = univ) : SigmaFinite μ := by obtain ⟨s, hμ, hs⟩ : ∃ s : ℕ → Set α, (∀ n, μ (s n) < ∞) ∧ ⋃ n, s n = univ - exact (@exists_seq_cover_iff_countable _ (fun x => μ x < ⊤) ⟨∅, by simp⟩).2 ⟨S, hc, hμ, hU⟩ + exact (@exists_seq_cover_iff_countable _ (fun x => μ x < ∞) ⟨∅, by simp⟩).2 ⟨S, hc, hμ, hU⟩ exact ⟨⟨⟨fun n => s n, fun _ => trivial, hμ, hs⟩⟩⟩ #align measure_theory.measure.sigma_finite_of_countable MeasureTheory.Measure.sigmaFinite_of_countable diff --git a/Mathlib/MeasureTheory/Measure/WithDensity.lean b/Mathlib/MeasureTheory/Measure/WithDensity.lean index 8c8df663099f7..3a68858bbee67 100644 --- a/Mathlib/MeasureTheory/Measure/WithDensity.lean +++ b/Mathlib/MeasureTheory/Measure/WithDensity.lean @@ -540,7 +540,7 @@ lemma SigmaFinite.withDensity [SigmaFinite μ] {f : α → ℝ≥0} (hf : AEMeas norm_cast exact (hs i).2.2 x hxs _ = i * μ (s i) := by rw [set_lintegral_const] - _ < ⊤ := ENNReal.mul_lt_top (by simp) (hs i).2.1.ne + _ < ∞ := ENNReal.mul_lt_top (by simp) (hs i).2.1.ne lemma SigmaFinite.withDensity_of_ne_top' [SigmaFinite μ] {f : α → ℝ≥0∞} (hf : AEMeasurable f μ) (hf_ne_top : ∀ x, f x ≠ ∞) : diff --git a/Mathlib/MeasureTheory/SetSemiring.lean b/Mathlib/MeasureTheory/SetSemiring.lean index e8f0ab12c8fe3..7fb6d6b03f609 100644 --- a/Mathlib/MeasureTheory/SetSemiring.lean +++ b/Mathlib/MeasureTheory/SetSemiring.lean @@ -4,10 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne, Peter Pfaffelhuber -/ import Mathlib.Data.Set.Pairwise.Lattice -import Mathlib.Data.Real.ENNReal import Mathlib.MeasureTheory.PiSystem -/-! # Semirings of sets +/-! # Semirings and rings of sets A semi-ring of sets `C` (in the sense of measure theory) is a family of sets containing `∅`, stable by intersection and such that for all `s, t ∈ C`, `t \ s` is equal to a disjoint union of @@ -18,6 +17,8 @@ is an interval (possibly empty). The union of two intervals may not be an interv The set difference of two intervals may not be an interval, but it will be a disjoint union of two intervals. +A ring of sets is a set of sets containing `∅`, stable by union, set difference and intersection. + ## Main definitions * `MeasureTheory.IsSetSemiring C`: property of being a semi-ring of sets. @@ -28,6 +29,8 @@ two intervals. (with `hI : ↑I ⊆ C`), this is a `Finset` of pairwise disjoint sets such that `s \ ⋃₀ I = ⋃₀ hC.diffFinset₀ hs hI`. +* `MeasureTheory.IsSetRing`: property of being a ring of sets. + ## Main statements * `MeasureTheory.IsSetSemiring.exists_disjoint_finset_diff_eq`: the existence of the `Finset` given @@ -37,8 +40,6 @@ two intervals. open Finset Set -open scoped ENNReal BigOperators - namespace MeasureTheory variable {α : Type*} {C : Set (Set α)} {s t : Set α} @@ -260,12 +261,13 @@ lemma pairwiseDisjoint_union_diffFinset₀ (hC : IsSetSemiring C) (hs : s ∈ C) (hC.disjoint_sUnion_diffFinset₀ hs hI) lemma sUnion_union_sUnion_diffFinset₀_of_subset (hC : IsSetSemiring C) (hs : s ∈ C) - (hI : ↑I ⊆ C) (hI_ss : ⋃₀ ↑I ⊆ s) : + (hI : ↑I ⊆ C) (hI_ss : ∀ t ∈ I, t ⊆ s) : ⋃₀ I ∪ ⋃₀ hC.diffFinset₀ hs hI = s := by - conv_rhs => rw [← union_diff_cancel hI_ss, hC.diff_sUnion_eq_sUnion_diffFinset₀ hs hI] + conv_rhs => rw [← union_diff_cancel (Set.sUnion_subset hI_ss : ⋃₀ ↑I ⊆ s), + hC.diff_sUnion_eq_sUnion_diffFinset₀ hs hI] lemma sUnion_union_diffFinset₀_of_subset (hC : IsSetSemiring C) (hs : s ∈ C) - (hI : ↑I ⊆ C) (hI_ss : ⋃₀ ↑I ⊆ s) [DecidableEq (Set α)] : + (hI : ↑I ⊆ C) (hI_ss : ∀ t ∈ I, t ⊆ s) [DecidableEq (Set α)] : ⋃₀ ↑(I ∪ hC.diffFinset₀ hs hI) = s := by conv_rhs => rw [← sUnion_union_sUnion_diffFinset₀_of_subset hC hs hI hI_ss] simp_rw [coe_union] @@ -275,4 +277,49 @@ end diffFinset₀ end IsSetSemiring +/-- A ring of sets `C` is a family of sets containing `∅`, stable by union and set difference. +It is then also stable by intersection (see `IsSetRing.inter_mem`). -/ +structure IsSetRing (C : Set (Set α)) : Prop where + empty_mem : ∅ ∈ C + union_mem ⦃s t⦄ : s ∈ C → t ∈ C → s ∪ t ∈ C + diff_mem ⦃s t⦄ : s ∈ C → t ∈ C → s \ t ∈ C + +namespace IsSetRing + +lemma inter_mem (hC : IsSetRing C) (hs : s ∈ C) (ht : t ∈ C) : s ∩ t ∈ C := by + rw [← diff_diff_right_self]; exact hC.diff_mem hs (hC.diff_mem hs ht) + +lemma isSetSemiring (hC : IsSetRing C) : IsSetSemiring C where + empty_mem := hC.empty_mem + inter_mem := fun s hs t ht => hC.inter_mem hs ht + diff_eq_Union' := by + refine fun s hs t ht => ⟨{s \ t}, ?_, ?_, ?_⟩ + · simp only [coe_singleton, Set.singleton_subset_iff] + exact hC.diff_mem hs ht + · simp only [coe_singleton, pairwiseDisjoint_singleton] + · simp only [coe_singleton, sUnion_singleton] + +lemma biUnion_mem {ι : Type*} (hC : IsSetRing C) {s : ι → Set α} + (S : Finset ι) (hs : ∀ n ∈ S, s n ∈ C) : + ⋃ i ∈ S, s i ∈ C := by + classical + induction' S using Finset.induction with i S _ h hs + · simp [hC.empty_mem] + · simp_rw [← Finset.mem_coe, Finset.coe_insert, Set.biUnion_insert] + refine hC.union_mem (hs i (mem_insert_self i S)) ?_ + exact h (fun n hnS ↦ hs n (mem_insert_of_mem hnS)) + +lemma biInter_mem {ι : Type*} (hC : IsSetRing C) {s : ι → Set α} + (S : Finset ι) (hS : S.Nonempty) (hs : ∀ n ∈ S, s n ∈ C) : + ⋂ i ∈ S, s i ∈ C := by + classical + induction' hS using Finset.Nonempty.cons_induction with _ i S hiS _ h hs + · simpa using hs + · simp_rw [← Finset.mem_coe, Finset.coe_cons, Set.biInter_insert] + simp only [cons_eq_insert, Finset.mem_insert, forall_eq_or_imp] at hs + refine hC.inter_mem hs.1 ?_ + exact h (fun n hnS ↦ hs.2 n hnS) + +end IsSetRing + end MeasureTheory diff --git a/Mathlib/ModelTheory/Basic.lean b/Mathlib/ModelTheory/Basic.lean index 24b4de9f95466..89a1fd87066d9 100644 --- a/Mathlib/ModelTheory/Basic.lean +++ b/Mathlib/ModelTheory/Basic.lean @@ -456,7 +456,7 @@ end Structure /-- `HomClass L F M N` states that `F` is a type of `L`-homomorphisms. You should extend this typeclass when you extend `FirstOrder.Language.Hom`. -/ class HomClass (L : outParam Language) (F : Type*) (M N : outParam <| Type*) - [FunLike F M fun _ => N] [L.Structure M] [L.Structure N] : Prop where + [FunLike F M N] [L.Structure M] [L.Structure N] : Prop where map_fun : ∀ (φ : F) {n} (f : L.Functions n) (x), φ (funMap f x) = funMap f (φ ∘ x) map_rel : ∀ (φ : F) {n} (r : L.Relations n) (x), RelMap r x → RelMap r (φ ∘ x) #align first_order.language.hom_class FirstOrder.Language.HomClass @@ -464,26 +464,26 @@ class HomClass (L : outParam Language) (F : Type*) (M N : outParam <| Type*) /-- `StrongHomClass L F M N` states that `F` is a type of `L`-homomorphisms which preserve relations in both directions. -/ class StrongHomClass (L : outParam Language) (F : Type*) (M N : outParam <| Type*) - [FunLike F M fun _ => N] [L.Structure M] [L.Structure N] : Prop where + [FunLike F M N] [L.Structure M] [L.Structure N] : Prop where map_fun : ∀ (φ : F) {n} (f : L.Functions n) (x), φ (funMap f x) = funMap f (φ ∘ x) map_rel : ∀ (φ : F) {n} (r : L.Relations n) (x), RelMap r (φ ∘ x) ↔ RelMap r x #align first_order.language.strong_hom_class FirstOrder.Language.StrongHomClass --Porting note: using implicit brackets for `Structure` arguments instance (priority := 100) StrongHomClass.homClass [L.Structure M] - [L.Structure N] [FunLike F M fun _ => N] [StrongHomClass L F M N] : HomClass L F M N where + [L.Structure N] [FunLike F M N] [StrongHomClass L F M N] : HomClass L F M N where map_fun := StrongHomClass.map_fun map_rel φ _ R x := (StrongHomClass.map_rel φ R x).2 #align first_order.language.strong_hom_class.hom_class FirstOrder.Language.StrongHomClass.homClass /-- Not an instance to avoid a loop. -/ theorem HomClass.strongHomClassOfIsAlgebraic [L.IsAlgebraic] {F M N} [L.Structure M] [L.Structure N] - [FunLike F M fun _ => N] [HomClass L F M N] : StrongHomClass L F M N where + [FunLike F M N] [HomClass L F M N] : StrongHomClass L F M N where map_fun := HomClass.map_fun map_rel _ n R _ := (IsAlgebraic.empty_relations n).elim R #align first_order.language.hom_class.strong_hom_class_of_is_algebraic FirstOrder.Language.HomClass.strongHomClassOfIsAlgebraic -theorem HomClass.map_constants {F M N} [L.Structure M] [L.Structure N] [FunLike F M fun _ => N] +theorem HomClass.map_constants {F M N} [L.Structure M] [L.Structure N] [FunLike F M N] [HomClass L F M N] (φ : F) (c : L.Constants) : φ c = c := (HomClass.map_fun φ c default).trans (congr rfl (funext default)) #align first_order.language.hom_class.map_constants FirstOrder.Language.HomClass.map_constants @@ -498,10 +498,10 @@ attribute [inherit_doc FirstOrder.Language.Hom.map_rel'] FirstOrder.Language.Emb namespace Hom -instance funLike : FunLike (M →[L] N) M fun _ => N where +instance instFunLike : FunLike (M →[L] N) M N where coe := Hom.toFun coe_injective' f g h := by cases f; cases g; cases h; rfl -#align first_order.language.hom.fun_like FirstOrder.Language.Hom.funLike +#align first_order.language.hom.fun_like FirstOrder.Language.Hom.instFunLike instance homClass : HomClass L (M →[L] N) M N where map_fun := map_fun' @@ -512,7 +512,7 @@ instance [L.IsAlgebraic] : StrongHomClass L (M →[L] N) M N := HomClass.strongHomClassOfIsAlgebraic instance hasCoeToFun : CoeFun (M →[L] N) fun _ => M → N := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun #align first_order.language.hom.has_coe_to_fun FirstOrder.Language.Hom.hasCoeToFun @[simp] @@ -522,11 +522,11 @@ theorem toFun_eq_coe {f : M →[L] N} : f.toFun = (f : M → N) := @[ext] theorem ext ⦃f g : M →[L] N⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align first_order.language.hom.ext FirstOrder.Language.Hom.ext theorem ext_iff {f g : M →[L] N} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align first_order.language.hom.ext_iff FirstOrder.Language.Hom.ext_iff @[simp] @@ -588,7 +588,7 @@ theorem comp_assoc (f : M →[L] N) (g : N →[L] P) (h : P →[L] Q) : end Hom /-- Any element of a `HomClass` can be realized as a first_order homomorphism. -/ -def HomClass.toHom {F M N} [L.Structure M] [L.Structure N] [FunLike F M fun _ => N] +def HomClass.toHom {F M N} [L.Structure M] [L.Structure N] [FunLike F M N] [HomClass L F M N] : F → M →[L] N := fun φ => ⟨φ, HomClass.map_fun φ, HomClass.map_rel φ⟩ #align first_order.language.hom_class.to_hom FirstOrder.Language.HomClass.toHom @@ -612,7 +612,7 @@ instance strongHomClass : StrongHomClass L (M ↪[L] N) M N where #align first_order.language.embedding.strong_hom_class FirstOrder.Language.Embedding.strongHomClass instance hasCoeToFun : CoeFun (M ↪[L] N) fun _ => M → N := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun #align first_order.language.embedding.has_coe_to_fun FirstOrder.Language.Embedding.hasCoeToFun @[simp] @@ -764,15 +764,15 @@ def symm (f : M ≃[L] N) : N ≃[L] M := simp only [Equiv.toFun_as_coe] rw [Equiv.symm_apply_eq] refine' Eq.trans _ (f.map_fun' f' (f.toEquiv.symm ∘ x)).symm - rw [← Function.comp.assoc, Equiv.toFun_as_coe, Equiv.self_comp_symm, Function.comp.left_id] + rw [← Function.comp.assoc, Equiv.toFun_as_coe, Equiv.self_comp_symm, Function.id_comp] map_rel' := fun n r {x} => by simp only [Equiv.toFun_as_coe] refine' (f.map_rel' r (f.toEquiv.symm ∘ x)).symm.trans _ - rw [← Function.comp.assoc, Equiv.toFun_as_coe, Equiv.self_comp_symm, Function.comp.left_id] } + rw [← Function.comp.assoc, Equiv.toFun_as_coe, Equiv.self_comp_symm, Function.id_comp] } #align first_order.language.equiv.symm FirstOrder.Language.Equiv.symm instance hasCoeToFun : CoeFun (M ≃[L] N) fun _ => M → N := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun #align first_order.language.equiv.has_coe_to_fun FirstOrder.Language.Equiv.hasCoeToFun @[simp] @@ -828,7 +828,7 @@ theorem coe_toEmbedding (f : M ≃[L] N) : (f.toEmbedding : M → N) = (f : M #align first_order.language.equiv.coe_to_embedding FirstOrder.Language.Equiv.coe_toEmbedding theorem coe_injective : @Function.Injective (M ≃[L] N) (M → N) (↑) := - FunLike.coe_injective + DFunLike.coe_injective #align first_order.language.equiv.coe_injective FirstOrder.Language.Equiv.coe_injective @[ext] @@ -968,7 +968,7 @@ instance : Unique (Language.empty.Structure M) := ⟨⟨Language.emptyStructure⟩, fun a => by ext _ f <;> exact Empty.elim f⟩ -instance (priority := 100) strongHomClassEmpty {F M N} [FunLike F M fun _ => N] : +instance (priority := 100) strongHomClassEmpty {F M N} [FunLike F M N] : StrongHomClass Language.empty F M N := ⟨fun _ _ f => Empty.elim f, fun _ _ r => Empty.elim r⟩ #align first_order.language.strong_hom_class_empty FirstOrder.Language.strongHomClassEmpty @@ -1043,14 +1043,14 @@ theorem toEquiv_inducedStructureEquiv (e : M ≃ N) : @[simp] theorem toFun_inducedStructureEquiv (e : M ≃ N) : - FunLike.coe (@inducedStructureEquiv L M N _ e) = e := + DFunLike.coe (@inducedStructureEquiv L M N _ e) = e := rfl @[simp] theorem toFun_inducedStructureEquiv_Symm (e : M ≃ N) : (by letI : L.Structure N := inducedStructure e - exact FunLike.coe (@inducedStructureEquiv L M N _ e).symm) = (e.symm : N → M) := + exact DFunLike.coe (@inducedStructureEquiv L M N _ e).symm) = (e.symm : N → M) := rfl end Equiv diff --git a/Mathlib/ModelTheory/Definability.lean b/Mathlib/ModelTheory/Definability.lean index 96c5a31a9241f..195c878b5f0b7 100644 --- a/Mathlib/ModelTheory/Definability.lean +++ b/Mathlib/ModelTheory/Definability.lean @@ -121,7 +121,7 @@ theorem Definable.union {f g : Set (α → M)} (hf : A.Definable L f) (hg : A.De rw [hφ, hθ, mem_setOf_eq, Formula.realize_sup, mem_union, mem_setOf_eq, mem_setOf_eq] #align set.definable.union Set.Definable.union -theorem definable_finset_inf {ι : Type*} {f : ∀ _ : ι, Set (α → M)} (hf : ∀ i, A.Definable L (f i)) +theorem definable_finset_inf {ι : Type*} {f : ι → Set (α → M)} (hf : ∀ i, A.Definable L (f i)) (s : Finset ι) : A.Definable L (s.inf f) := by classical refine' Finset.induction definable_univ (fun i s _ h => _) s @@ -129,7 +129,7 @@ theorem definable_finset_inf {ι : Type*} {f : ∀ _ : ι, Set (α → M)} (hf : exact (hf i).inter h #align set.definable_finset_inf Set.definable_finset_inf -theorem definable_finset_sup {ι : Type*} {f : ∀ _ : ι, Set (α → M)} (hf : ∀ i, A.Definable L (f i)) +theorem definable_finset_sup {ι : Type*} {f : ι → Set (α → M)} (hf : ∀ i, A.Definable L (f i)) (s : Finset ι) : A.Definable L (s.sup f) := by classical refine' Finset.induction definable_empty (fun i s _ h => _) s @@ -137,13 +137,13 @@ theorem definable_finset_sup {ι : Type*} {f : ∀ _ : ι, Set (α → M)} (hf : exact (hf i).union h #align set.definable_finset_sup Set.definable_finset_sup -theorem definable_finset_biInter {ι : Type*} {f : ∀ _ : ι, Set (α → M)} +theorem definable_finset_biInter {ι : Type*} {f : ι → Set (α → M)} (hf : ∀ i, A.Definable L (f i)) (s : Finset ι) : A.Definable L (⋂ i ∈ s, f i) := by rw [← Finset.inf_set_eq_iInter] exact definable_finset_inf hf s #align set.definable_finset_bInter Set.definable_finset_biInter -theorem definable_finset_biUnion {ι : Type*} {f : ∀ _ : ι, Set (α → M)} +theorem definable_finset_biUnion {ι : Type*} {f : ι → Set (α → M)} (hf : ∀ i, A.Definable L (f i)) (s : Finset ι) : A.Definable L (⋃ i ∈ s, f i) := by rw [← Finset.sup_set_eq_biUnion] exact definable_finset_sup hf s @@ -216,7 +216,7 @@ theorem Definable.image_comp_sum_inl_fin (m : ℕ) {s : Set (Sum α (Fin m) → refine' ⟨(BoundedFormula.relabel id φ).exs, _⟩ ext x simp only [Set.mem_image, mem_setOf_eq, BoundedFormula.realize_exs, - BoundedFormula.realize_relabel, Function.comp.right_id, Fin.castAdd_zero, Fin.cast_refl] + BoundedFormula.realize_relabel, Function.comp_id, Fin.castAdd_zero, Fin.cast_refl] constructor · rintro ⟨y, hy, rfl⟩ exact diff --git a/Mathlib/ModelTheory/DirectLimit.lean b/Mathlib/ModelTheory/DirectLimit.lean index 619565843eb96..2b08a42227b1e 100644 --- a/Mathlib/ModelTheory/DirectLimit.lean +++ b/Mathlib/ModelTheory/DirectLimit.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Aaron Anderson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ +import Mathlib.Init.Align import Mathlib.Data.Fintype.Order import Mathlib.Algebra.DirectLimit import Mathlib.ModelTheory.Quotients @@ -73,7 +74,7 @@ theorem coe_natLERec (m n : ℕ) (h : m ≤ n) : #align first_order.language.directed_system.coe_nat_le_rec FirstOrder.Language.DirectedSystem.coe_natLERec instance natLERec.directedSystem : DirectedSystem G' fun i j h => natLERec f' i j h := - ⟨fun i x h => congr (congr rfl (Nat.leRecOn_self _)) rfl, + ⟨fun i x _ => congr (congr rfl (Nat.leRecOn_self _)) rfl, fun hij hjk => by simp [Nat.leRecOn_trans hij hjk]⟩ #align first_order.language.directed_system.nat_le_rec.directed_system FirstOrder.Language.DirectedSystem.natLERec.directedSystem @@ -148,12 +149,12 @@ noncomputable def sigmaStructure [IsDirected ι (· ≤ ·)] [Nonempty ι] : L.S funMap F x := ⟨_, funMap F - (unify f x (Classical.choose (Fintype.bddAbove_range fun a => (x a).1)) - (Classical.choose_spec (Fintype.bddAbove_range fun a => (x a).1)))⟩ + (unify f x (Classical.choose (Finite.bddAbove_range fun a => (x a).1)) + (Classical.choose_spec (Finite.bddAbove_range fun a => (x a).1)))⟩ RelMap R x := RelMap R - (unify f x (Classical.choose (Fintype.bddAbove_range fun a => (x a).1)) - (Classical.choose_spec (Fintype.bddAbove_range fun a => (x a).1))) + (unify f x (Classical.choose (Finite.bddAbove_range fun a => (x a).1)) + (Classical.choose_spec (Finite.bddAbove_range fun a => (x a).1))) #align first_order.language.direct_limit.sigma_structure FirstOrder.Language.DirectLimit.sigmaStructure end DirectLimit @@ -210,7 +211,7 @@ variable [Nonempty ι] theorem exists_unify_eq {α : Type*} [Fintype α] {x y : α → Σˣ f} (xy : x ≈ y) : ∃ (i : ι)(hx : i ∈ upperBounds (range (Sigma.fst ∘ x)))(hy : i ∈ upperBounds (range (Sigma.fst ∘ y))), unify f x i hx = unify f y i hy := by - obtain ⟨i, hi⟩ := Fintype.bddAbove_range (Sum.elim (fun a => (x a).1) fun a => (y a).1) + obtain ⟨i, hi⟩ := Finite.bddAbove_range (Sum.elim (fun a => (x a).1) fun a => (y a).1) rw [Sum.elim_range, upperBounds_union] at hi simp_rw [← Function.comp_apply (f := Sigma.fst)] at hi exact ⟨i, hi.1, hi.2, funext fun a => (equiv_iff G f _ _).1 (xy a)⟩ @@ -219,13 +220,13 @@ theorem exists_unify_eq {α : Type*} [Fintype α] {x y : α → Σˣ f} (xy : x theorem funMap_equiv_unify {n : ℕ} (F : L.Functions n) (x : Fin n → Σˣ f) (i : ι) (hi : i ∈ upperBounds (range (Sigma.fst ∘ x))) : funMap F x ≈ .mk f _ (funMap F (unify f x i hi)) := - funMap_unify_equiv G f F x (Classical.choose (Fintype.bddAbove_range fun a => (x a).1)) i _ hi + funMap_unify_equiv G f F x (Classical.choose (Finite.bddAbove_range fun a => (x a).1)) i _ hi #align first_order.language.direct_limit.fun_map_equiv_unify FirstOrder.Language.DirectLimit.funMap_equiv_unify theorem relMap_equiv_unify {n : ℕ} (R : L.Relations n) (x : Fin n → Σˣ f) (i : ι) (hi : i ∈ upperBounds (range (Sigma.fst ∘ x))) : RelMap R x = RelMap R (unify f x i hi) := - relMap_unify_equiv G f R x (Classical.choose (Fintype.bddAbove_range fun a => (x a).1)) i _ hi + relMap_unify_equiv G f R x (Classical.choose (Finite.bddAbove_range fun a => (x a).1)) i _ hi #align first_order.language.direct_limit.rel_map_equiv_unify FirstOrder.Language.DirectLimit.relMap_equiv_unify /-- The direct limit `setoid` respects the structure `sigmaStructure`, so quotienting by it @@ -256,7 +257,7 @@ theorem funMap_quotient_mk'_sigma_mk' {n : ℕ} {F : L.Functions n} {i : ι} {x funMap F (fun a => (⟦.mk f i (x a)⟧ : DirectLimit G f)) = ⟦.mk f i (funMap F x)⟧ := by simp only [funMap_quotient_mk', Quotient.eq] obtain ⟨k, ik, jk⟩ := - directed_of (· ≤ ·) i (Classical.choose (Fintype.bddAbove_range fun _ : Fin n => i)) + directed_of (· ≤ ·) i (Classical.choose (Finite.bddAbove_range fun _ : Fin n => i)) refine' ⟨k, jk, ik, _⟩ simp only [Embedding.map_fun, comp_unify] rfl @@ -267,14 +268,14 @@ theorem relMap_quotient_mk'_sigma_mk' {n : ℕ} {R : L.Relations n} {i : ι} {x RelMap R (fun a => (⟦.mk f i (x a)⟧ : DirectLimit G f)) = RelMap R x := by rw [relMap_quotient_mk'] obtain ⟨k, _, _⟩ := - directed_of (· ≤ ·) i (Classical.choose (Fintype.bddAbove_range fun _ : Fin n => i)) + directed_of (· ≤ ·) i (Classical.choose (Finite.bddAbove_range fun _ : Fin n => i)) rw [relMap_equiv_unify G f R (fun a => .mk f i (x a)) i] rw [unify_sigma_mk_self] #align first_order.language.direct_limit.rel_map_quotient_mk_sigma_mk FirstOrder.Language.DirectLimit.relMap_quotient_mk'_sigma_mk' theorem exists_quotient_mk'_sigma_mk'_eq {α : Type*} [Fintype α] (x : α → DirectLimit G f) : ∃ (i : ι) (y : α → G i), x = fun a => ⟦.mk f i (y a)⟧ := by - obtain ⟨i, hi⟩ := Fintype.bddAbove_range fun a => (x a).out.1 + obtain ⟨i, hi⟩ := Finite.bddAbove_range fun a => (x a).out.1 refine' ⟨i, unify f (Quotient.out ∘ x) i hi, _⟩ ext a rw [Quotient.eq_mk_iff_out, unify] diff --git a/Mathlib/ModelTheory/ElementaryMaps.lean b/Mathlib/ModelTheory/ElementaryMaps.lean index 43552824b69dd..45c28aa907b28 100644 --- a/Mathlib/ModelTheory/ElementaryMaps.lean +++ b/Mathlib/ModelTheory/ElementaryMaps.lean @@ -63,7 +63,7 @@ namespace ElementaryEmbedding attribute [coe] toFun -instance funLike : FunLike (M ↪ₑ[L] N) M fun _ => N where +instance instFunLike : FunLike (M ↪ₑ[L] N) M N where coe f := f.toFun coe_injective' f g h := by cases f @@ -71,10 +71,10 @@ instance funLike : FunLike (M ↪ₑ[L] N) M fun _ => N where simp only [ElementaryEmbedding.mk.injEq] ext x exact Function.funext_iff.1 h x -#align first_order.language.elementary_embedding.fun_like FirstOrder.Language.ElementaryEmbedding.funLike +#align first_order.language.elementary_embedding.fun_like FirstOrder.Language.ElementaryEmbedding.instFunLike instance : CoeFun (M ↪ₑ[L] N) fun _ => M → N := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[simp] theorem map_boundedFormula (f : M ↪ₑ[L] N) {α : Type*} {n : ℕ} (φ : L.BoundedFormula α n) @@ -87,10 +87,10 @@ theorem map_boundedFormula (f : M ↪ₑ[L] N) {α : Type*} {n : ℕ} (φ : L.Bo simp only [Formula.realize_relabel, BoundedFormula.realize_toFormula, iff_eq_eq] at h rw [← Function.comp.assoc _ _ (Fintype.equivFin _).symm, Function.comp.assoc _ (Fintype.equivFin _).symm (Fintype.equivFin _), Equiv.symm_comp_self, - Function.comp.right_id, Function.comp.assoc, Sum.elim_comp_inl, + Function.comp_id, Function.comp.assoc, Sum.elim_comp_inl, Function.comp.assoc _ _ Sum.inr, Sum.elim_comp_inr, ← Function.comp.assoc] at h refine' h.trans _ - erw [Function.comp.assoc _ _ (Fintype.equivFin _), Equiv.symm_comp_self, Function.comp.right_id, + erw [Function.comp.assoc _ _ (Fintype.equivFin _), Equiv.symm_comp_self, Function.comp_id, Sum.elim_comp_inl, Sum.elim_comp_inr (v ∘ Subtype.val) xs, ← Set.inclusion_eq_id (s := (BoundedFormula.freeVarFinset φ : Set α)) Set.Subset.rfl, BoundedFormula.realize_restrictFreeVar Set.Subset.rfl] @@ -127,7 +127,7 @@ theorem injective (φ : M ↪ₑ[L] N) : Function.Injective φ := by #align first_order.language.elementary_embedding.injective FirstOrder.Language.ElementaryEmbedding.injective instance embeddingLike : EmbeddingLike (M ↪ₑ[L] N) M N := - { show FunLike (M ↪ₑ[L] N) M fun _ => N from inferInstance with injective' := injective } + { show FunLike (M ↪ₑ[L] N) M N from inferInstance with injective' := injective } #align first_order.language.elementary_embedding.embedding_like FirstOrder.Language.ElementaryEmbedding.embeddingLike @[simp] @@ -186,16 +186,16 @@ theorem coe_toEmbedding (f : M ↪ₑ[L] N) : (f.toEmbedding : M → N) = (f : M #align first_order.language.elementary_embedding.coe_to_embedding FirstOrder.Language.ElementaryEmbedding.coe_toEmbedding theorem coe_injective : @Function.Injective (M ↪ₑ[L] N) (M → N) (↑) := - FunLike.coe_injective + DFunLike.coe_injective #align first_order.language.elementary_embedding.coe_injective FirstOrder.Language.ElementaryEmbedding.coe_injective @[ext] theorem ext ⦃f g : M ↪ₑ[L] N⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align first_order.language.elementary_embedding.ext FirstOrder.Language.ElementaryEmbedding.ext theorem ext_iff {f g : M ↪ₑ[L] N} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align first_order.language.elementary_embedding.ext_iff FirstOrder.Language.ElementaryEmbedding.ext_iff variable (L) (M) diff --git a/Mathlib/ModelTheory/Graph.lean b/Mathlib/ModelTheory/Graph.lean index 6d98943527ba2..f2d85afffbd44 100644 --- a/Mathlib/ModelTheory/Graph.lean +++ b/Mathlib/ModelTheory/Graph.lean @@ -9,7 +9,7 @@ import Mathlib.Combinatorics.SimpleGraph.Basic #align_import model_theory.graph from "leanprover-community/mathlib"@"e56b8fea84d60fe434632b9d3b829ee685fb0c8f" /-! -# First-Ordered Structures in Graph Theory +# First-Order Structures in Graph Theory This file defines first-order languages, structures, and theories in graph theory. ## Main Definitions @@ -19,7 +19,6 @@ adjacency. * `FirstOrder.Language.Theory.simpleGraph` is the theory of simple graphs. * `FirstOrder.Language.simpleGraphOfStructure` gives the simple graph corresponding to a model of the theory of simple graphs. - -/ diff --git a/Mathlib/ModelTheory/Semantics.lean b/Mathlib/ModelTheory/Semantics.lean index 0e7a27fb3dab4..b6ff0ebfcceb4 100644 --- a/Mathlib/ModelTheory/Semantics.lean +++ b/Mathlib/ModelTheory/Semantics.lean @@ -5,6 +5,7 @@ Authors: Aaron Anderson, Jesse Michael Han, Floris van Doorn -/ import Mathlib.Data.Finset.Basic import Mathlib.ModelTheory.Syntax +import Mathlib.Data.List.ProdSigma #align_import model_theory.semantics from "leanprover-community/mathlib"@"d565b3df44619c1498326936be16f1a935df0728" @@ -182,7 +183,7 @@ theorem realize_varsToConstants [L[[α]].Structure M] [(lhomWithConstants L α). induction' t with ab n f ts ih · cases' ab with a b --Porting note: both cases were `simp [Language.con]` - · simp [Language.con, realize, constantMap, funMap_eq_coe_constants] + · simp [Language.con, realize, funMap_eq_coe_constants] · simp [realize, constantMap] · simp only [realize, constantsOn, mk₂_Functions, ih] --Porting note: below lemma does not work with simp for some reason @@ -355,7 +356,7 @@ theorem realize_iff : (φ.iff ψ).Realize v xs ↔ (φ.Realize v xs ↔ ψ.Reali theorem realize_castLE_of_eq {m n : ℕ} (h : m = n) {h' : m ≤ n} {φ : L.BoundedFormula α m} {v : α → M} {xs : Fin n → M} : (φ.castLE h').Realize v xs ↔ φ.Realize v (xs ∘ cast h) := by subst h - simp only [castLE_rfl, cast_refl, OrderIso.coe_refl, Function.comp.right_id] + simp only [castLE_rfl, cast_refl, OrderIso.coe_refl, Function.comp_id] #align first_order.language.bounded_formula.realize_cast_le_of_eq FirstOrder.Language.BoundedFormula.realize_castLE_of_eq theorem realize_mapTermRel_id [L'.Structure M] @@ -680,7 +681,7 @@ theorem realize_relabel {φ : L.Formula α} {g : α → β} {v : β → M} : theorem realize_relabel_sum_inr (φ : L.Formula (Fin n)) {v : Empty → M} {x : Fin n → M} : (BoundedFormula.relabel Sum.inr φ).Realize v x ↔ φ.Realize x := by rw [BoundedFormula.realize_relabel, Formula.Realize, Sum.elim_comp_inr, Fin.castAdd_zero, - cast_refl, Function.comp.right_id, + cast_refl, Function.comp_id, Subsingleton.elim (x ∘ (natAdd n : Fin 0 → Fin n)) default] #align first_order.language.formula.realize_relabel_sum_inr FirstOrder.Language.Formula.realize_relabel_sum_inr diff --git a/Mathlib/ModelTheory/Syntax.lean b/Mathlib/ModelTheory/Syntax.lean index 4be8ea708d2c9..96e2185c3526a 100644 --- a/Mathlib/ModelTheory/Syntax.lean +++ b/Mathlib/ModelTheory/Syntax.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Aaron Anderson, Jesse Michael Han, Floris van Doorn. All righ Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson, Jesse Michael Han, Floris van Doorn -/ -import Mathlib.Data.List.ProdSigma import Mathlib.Data.Set.Prod import Mathlib.Logic.Equiv.Fin import Mathlib.ModelTheory.LanguageMap @@ -73,7 +72,7 @@ open Structure Fin /-- A term on `α` is either a variable indexed by an element of `α` or a function symbol applied to simpler terms. -/ inductive Term (α : Type u') : Type max u u' - | var : ∀ _a : α, Term α + | var : α → Term α | func : ∀ {l : ℕ} (_f : L.Functions l) (_ts : Fin l → Term α), Term α #align first_order.language.term FirstOrder.Language.Term export Term (var func) diff --git a/Mathlib/NumberTheory/ArithmeticFunction.lean b/Mathlib/NumberTheory/ArithmeticFunction.lean index 8bbcf8a4cc114..2f609beee217d 100644 --- a/Mathlib/NumberTheory/ArithmeticFunction.lean +++ b/Mathlib/NumberTheory/ArithmeticFunction.lean @@ -88,15 +88,15 @@ section Zero variable [Zero R] -- porting note: used to be `CoeFun` -instance : FunLike (ArithmeticFunction R) ℕ fun _ ↦ R := - inferInstanceAs (FunLike (ZeroHom ℕ R) ℕ fun _ ↦ R) +instance : FunLike (ArithmeticFunction R) ℕ R := + inferInstanceAs (FunLike (ZeroHom ℕ R) ℕ R) @[simp] theorem toFun_eq (f : ArithmeticFunction R) : f.toFun = f := rfl #align nat.arithmetic_function.to_fun_eq Nat.ArithmeticFunction.toFun_eq @[simp] -theorem coe_mk (f : ℕ → R) (hf) : @FunLike.coe (ArithmeticFunction R) _ _ _ +theorem coe_mk (f : ℕ → R) (hf) : @DFunLike.coe (ArithmeticFunction R) _ _ _ (ZeroHom.mk f hf) = f := rfl @[simp] @@ -105,7 +105,7 @@ theorem map_zero {f : ArithmeticFunction R} : f 0 = 0 := #align nat.arithmetic_function.map_zero Nat.ArithmeticFunction.map_zero theorem coe_inj {f g : ArithmeticFunction R} : (f : ℕ → R) = g ↔ f = g := - FunLike.coe_fn_eq + DFunLike.coe_fn_eq #align nat.arithmetic_function.coe_inj Nat.ArithmeticFunction.coe_inj @[simp] @@ -119,7 +119,7 @@ theorem ext ⦃f g : ArithmeticFunction R⦄ (h : ∀ x, f x = g x) : f = g := #align nat.arithmetic_function.ext Nat.ArithmeticFunction.ext theorem ext_iff {f g : ArithmeticFunction R} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align nat.arithmetic_function.ext_iff Nat.ArithmeticFunction.ext_iff section One @@ -632,7 +632,7 @@ theorem map_prod_of_prime [CommSemiring R] {f : ArithmeticFunction R} theorem map_prod_of_subset_primeFactors [CommSemiring R] {f : ArithmeticFunction R} (h_mult : ArithmeticFunction.IsMultiplicative f) (l : ℕ) (t : Finset ℕ) (ht : t ⊆ l.primeFactors) : - f (∏ a in t, a) = ∏ a : ℕ in t, f a := + f (∏ a in t, a) = ∏ a : ℕ in t, f a := map_prod_of_prime h_mult t fun _ a => prime_of_mem_primeFactors (ht a) theorem nat_cast {f : ArithmeticFunction ℕ} [Semiring R] (h : f.IsMultiplicative) : @@ -652,7 +652,7 @@ theorem mul [CommSemiring R] {f g : ArithmeticFunction R} (hf : f.IsMultiplicati refine ⟨by simp [hf.1, hg.1], ?_⟩ simp only [mul_apply] intro m n cop - rw [sum_mul_sum] + rw [sum_mul_sum, ← sum_product'] symm apply sum_nbij fun ((i, j), k, l) ↦ (i * k, j * l) · rintro ⟨⟨a1, a2⟩, ⟨b1, b2⟩⟩ h @@ -764,7 +764,7 @@ theorem prodPrimeFactors [CommMonoidWithZero R] (f : ℕ → R) : rw [iff_ne_zero] refine ⟨prodPrimeFactors_apply one_ne_zero, ?_⟩ intro x y hx hy hxy - have hxy₀: x*y ≠ 0 := by exact Nat.mul_ne_zero hx hy + have hxy₀ : x * y ≠ 0 := mul_ne_zero hx hy rw [prodPrimeFactors_apply hxy₀, prodPrimeFactors_apply hx, prodPrimeFactors_apply hy, Nat.primeFactors_mul hx hy, ← Finset.prod_union hxy.disjoint_primeFactors] @@ -778,7 +778,8 @@ theorem prodPrimeFactors_add_of_squarefree [CommSemiring R] {f g : ArithmeticFun factors_eq] apply Finset.sum_congr rfl intro t ht - erw [t.prod_val, ← prod_primeFactors_sdiff_of_squarefree hn (Finset.mem_powerset.mp ht), + rw [t.prod_val, Function.id_def, + ← prod_primeFactors_sdiff_of_squarefree hn (Finset.mem_powerset.mp ht), hf.map_prod_of_subset_primeFactors n t (Finset.mem_powerset.mp ht), ← hg.map_prod_of_subset_primeFactors n (_ \ t) (Finset.sdiff_subset _ t)] @@ -1080,7 +1081,7 @@ theorem IsMultiplicative.prodPrimeFactors_one_add_of_squarefree [CommSemiring R] trans (∏ᵖ p ∣ n, ((ζ:ArithmeticFunction R) + f) p) · simp_rw [prodPrimeFactors_apply hn.ne_zero, add_apply, natCoe_apply] apply Finset.prod_congr rfl; intro p hp; - rw [zeta_apply_ne (prime_of_mem_factors $ List.mem_toFinset.mp hp).ne_zero, cast_one] + rw [zeta_apply_ne (prime_of_mem_factors <| List.mem_toFinset.mp hp).ne_zero, cast_one] rw [isMultiplicative_zeta.nat_cast.prodPrimeFactors_add_of_squarefree h_mult hn, coe_zeta_mul_apply] @@ -1251,7 +1252,7 @@ theorem sum_eq_iff_sum_smul_moebius_eq_on [AddCommGroup R] {f g : ℕ → R} suffices ∑ d in n.divisors, μ (n/d) • G d = f n from by rw [Nat.sum_divisorsAntidiagonal' (f := fun x y => μ x • g y), ← this, sum_congr rfl] intro d hd - rw [← h d (Nat.pos_of_mem_divisors hd) $ hs d n (Nat.dvd_of_mem_divisors hd) hnP] + rw [← h d (Nat.pos_of_mem_divisors hd) <| hs d n (Nat.dvd_of_mem_divisors hd) hnP] rw [← Nat.sum_divisorsAntidiagonal' (f := fun x y => μ x • G y)] apply sum_eq_iff_sum_smul_moebius_eq.mp _ n hn intro _ _; rfl @@ -1261,7 +1262,7 @@ theorem sum_eq_iff_sum_smul_moebius_eq_on [AddCommGroup R] {f g : ℕ → R} suffices ∑ d in n.divisors, F d = g n from by rw [← this, sum_congr rfl] intro d hd - rw [← h d (Nat.pos_of_mem_divisors hd) $ hs d n (Nat.dvd_of_mem_divisors hd) hnP] + rw [← h d (Nat.pos_of_mem_divisors hd) <| hs d n (Nat.dvd_of_mem_divisors hd) hnP] apply sum_eq_iff_sum_smul_moebius_eq.mpr _ n hn intro _ _; rfl diff --git a/Mathlib/NumberTheory/Bertrand.lean b/Mathlib/NumberTheory/Bertrand.lean index 090713e349960..de69ad3733fef 100644 --- a/Mathlib/NumberTheory/Bertrand.lean +++ b/Mathlib/NumberTheory/Bertrand.lean @@ -4,10 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Stevens, Bolton Bailey -/ import Mathlib.Data.Nat.Choose.Factorization -import Mathlib.Data.Nat.PrimeNormNum import Mathlib.NumberTheory.Primorial import Mathlib.Analysis.Convex.SpecificFunctions.Basic import Mathlib.Analysis.Convex.SpecificFunctions.Deriv +import Mathlib.Tactic.NormNum.Prime #align_import number_theory.bertrand from "leanprover-community/mathlib"@"a16665637b378379689c566204817ae792ac8b39" @@ -88,26 +88,20 @@ theorem real_main_inequality {x : ℝ} (n_large : (512 : ℝ) ≤ x) : exact (h.right_le_of_le_left'' h1 ((h1.trans h2).trans_le h0) h2 h0 (h4.trans h3)).trans h4 refine' ⟨18, 512, by norm_num1, by norm_num1, n_large, _, _⟩ · have : sqrt (2 * 18) = 6 := (sqrt_eq_iff_mul_self_eq_of_pos (by norm_num1)).mpr (by norm_num1) - rw [hf, log_nonneg_iff, this] - rw [one_le_div] <;> norm_num1 - apply le_trans _ (le_mul_of_one_le_left _ _) <;> norm_num1 - apply Real.rpow_le_rpow <;> norm_num1 - apply rpow_nonneg_of_nonneg; norm_num1 - apply rpow_pos_of_pos; norm_num1 - apply hf' 18; norm_num1 + rw [hf _ (by norm_num1), log_nonneg_iff (by positivity), this, one_le_div (by norm_num1)] norm_num1 · have : sqrt (2 * 512) = 32 := (sqrt_eq_iff_mul_self_eq_of_pos (by norm_num1)).mpr (by norm_num1) - rw [hf, log_nonpos_iff (hf' _ _), this, div_le_one] <;> norm_num1 - · conv in 512 => equals 2 ^ 9 => norm_num1 - conv in 1024 => equals 2 ^ 10 => norm_num1 - conv in 32 => rw [← Nat.cast_ofNat] - rw [rpow_nat_cast, ← pow_mul, ← pow_add] - conv in 4 => equals 2 ^ (2 : ℝ) => rw [rpow_two]; norm_num1 - rw [← rpow_mul, ← rpow_nat_cast] - apply rpow_le_rpow_of_exponent_le - all_goals norm_num1 - · apply rpow_pos_of_pos four_pos + rw [hf _ (by norm_num1), log_nonpos_iff (hf' _ (by norm_num1)), this, + div_le_one (by positivity)] + conv in 512 => equals 2 ^ 9 => norm_num1 + conv in 2 * 512 => equals 2 ^ 10 => norm_num1 + conv in 32 => rw [← Nat.cast_ofNat] + rw [rpow_nat_cast, ← pow_mul, ← pow_add] + conv in 4 => equals 2 ^ (2 : ℝ) => rw [rpow_two]; norm_num1 + rw [← rpow_mul, ← rpow_nat_cast] + apply rpow_le_rpow_of_exponent_le + all_goals norm_num1 #align bertrand.real_main_inequality Bertrand.real_main_inequality end Bertrand diff --git a/Mathlib/NumberTheory/Cyclotomic/Basic.lean b/Mathlib/NumberTheory/Cyclotomic/Basic.lean index 1f07282403dca..9048927ed868a 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Basic.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Riccardo Brasca. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Riccardo Brasca -/ +import Mathlib.Init.Core import Mathlib.RingTheory.Polynomial.Cyclotomic.Roots import Mathlib.NumberTheory.NumberField.Basic import Mathlib.FieldTheory.Galois diff --git a/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean b/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean index 542071bb1898d..bdd64a6a3a8ee 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean @@ -159,22 +159,32 @@ theorem discr_prime_pow [hcycl : IsCyclotomicExtension {p ^ k} K L] [hp : Fact ( replace hk := eq_of_prime_pow_eq (prime_iff.1 hp.out) (prime_iff.1 Nat.prime_two) (succ_pos _) hk rwa [coe_two, PNat.coe_inj] at hk - rw [hp, ← PNat.coe_inj, PNat.pow_coe] at hk + subst hp + rw [← PNat.coe_inj, PNat.pow_coe] at hk nth_rw 2 [← pow_one 2] at hk replace hk := Nat.pow_right_injective rfl.le hk rw [add_left_eq_self] at hk - rw [hp, hk] at hζ; norm_num at hζ; rw [← coe_two] at hζ - rw [coe_basis, powerBasis_gen]; simp only [hp, hk]; norm_num - -- Porting note: the goal at this point is `(discr K fun i ↦ ζ ^ ↑i) = 1`. - -- This `simp_rw` is needed so the next `rw` can rewrite the type of `i` from - -- `Fin (natDegree (minpoly K ζ))` to `Fin 1` + subst hk + rw [← Nat.one_eq_succ_zero, pow_one] at hζ hcycl + have : natDegree (minpoly K ζ) = 1 := by + rw [hζ.eq_neg_one_of_two_right, show (-1 : L) = algebraMap K L (-1) by simp, + minpoly.eq_X_sub_C_of_algebraMap_inj _ (NoZeroSMulDivisors.algebraMap_injective K L)] + exact natDegree_X_sub_C (-1) + rcases Fin.equiv_iff_eq.2 this with ⟨e⟩ + rw [← Algebra.discr_reindex K (hζ.powerBasis K).basis e, coe_basis, powerBasis_gen]; norm_num simp_rw [hζ.eq_neg_one_of_two_right, show (-1 : L) = algebraMap K L (-1) by simp] - rw [hζ.eq_neg_one_of_two_right, show (-1 : L) = algebraMap K L (-1) by simp, - minpoly.eq_X_sub_C_of_algebraMap_inj _ (algebraMap K L).injective, natDegree_X_sub_C] - simp only [discr, traceMatrix_apply, Matrix.det_unique, Fin.default_eq_zero, Fin.val_zero, - _root_.pow_zero, traceForm_apply, mul_one] - rw [← (algebraMap K L).map_one, trace_algebraMap, finrank _ hirr, hp, hk]; norm_num - simp [← coe_two, Even.neg_pow (by decide : Even (1 / 2))] + convert_to (discr K fun i : Fin 1 ↦ (algebraMap K L) (-1) ^ ↑i) = _ + · congr + ext i + simp only [map_neg, map_one, Function.comp_apply, Fin.coe_fin_one, _root_.pow_zero] + suffices (e.symm i : ℕ) = 0 by simp [this] + rw [← Nat.lt_one_iff] + convert (e.symm i).2 + rw [this] + · simp only [discr, traceMatrix_apply, Matrix.det_unique, Fin.default_eq_zero, Fin.val_zero, + _root_.pow_zero, traceForm_apply, mul_one] + rw [← (algebraMap K L).map_one, trace_algebraMap, finrank _ hirr]; norm_num + simp [← coe_two, Even.neg_pow (by decide : Even (1 / 2))] · exact discr_prime_pow_ne_two hζ hirr hk #align is_cyclotomic_extension.discr_prime_pow IsCyclotomicExtension.discr_prime_pow diff --git a/Mathlib/NumberTheory/Dioph.lean b/Mathlib/NumberTheory/Dioph.lean index cf6e5336a7743..16dae4de66341 100644 --- a/Mathlib/NumberTheory/Dioph.lean +++ b/Mathlib/NumberTheory/Dioph.lean @@ -98,14 +98,14 @@ namespace Poly section -instance funLike : FunLike (Poly α) (α → ℕ) fun _ => ℤ := +instance instFunLike : FunLike (Poly α) (α → ℕ) ℤ := ⟨Subtype.val, Subtype.val_injective⟩ -#align poly.fun_like Poly.funLike +#align poly.fun_like Poly.instFunLike -- Porting note: This instance is not necessary anymore --- /-- Helper instance for when there are too many metavariables to apply `fun_like.has_coe_to_fun` +-- /-- Helper instance for when there are too many metavariables to apply `DFunLike.hasCoeToFun` -- directly. -/ --- instance : CoeFun (Poly α) fun _ => (α → ℕ) → ℤ := FunLike.hasCoeToFun +-- instance : CoeFun (Poly α) fun _ => (α → ℕ) → ℤ := DFunLike.hasCoeToFun /-- The underlying function of a `Poly` is a polynomial -/ protected theorem isPoly (f : Poly α) : IsPoly f := f.2 @@ -113,7 +113,7 @@ protected theorem isPoly (f : Poly α) : IsPoly f := f.2 /-- Extensionality for `Poly α` -/ @[ext] -theorem ext {f g : Poly α} : (∀ x, f x = g x) → f = g := FunLike.ext _ _ +theorem ext {f g : Poly α} : (∀ x, f x = g x) → f = g := DFunLike.ext _ _ #align poly.ext Poly.ext /-- The `i`th projection function, `x_i`. -/ @@ -341,7 +341,7 @@ theorem inject_dummies (f : β → γ) (g : γ → Option β) (inv : ∀ x, g (f variable (β) -theorem reindex_dioph (f : α → β) : ∀ _ : Dioph S, Dioph {v | v ∘ f ∈ S} +theorem reindex_dioph (f : α → β) : Dioph S → Dioph {v | v ∘ f ∈ S} | ⟨γ, p, pe⟩ => ⟨γ, p.map (inl ∘ f ⊗ inr), fun v => (pe _).trans <| exists_congr fun t => @@ -765,7 +765,7 @@ theorem pow_dioph : DiophFn fun v => f v ^ g v := by let D_pell := pell_dioph.reindex_dioph (Fin2 9) [&4, &8, &1, &0] (D&2 D= D.0 D∧ D&0 D= D.1) D∨ (D.0 D< D&2 D∧ ((D&1 D= D.0 D∧ D&0 D= D.0) D∨ (D.0 D< D&1 D∧ - ((D∃) 3 <| (D∃) 4 <| (D∃) 5 <| (D∃) 6 $ (D∃) 7 <| (D∃) 8 <| D_pell D∧ + ((D∃) 3 <| (D∃) 4 <| (D∃) 5 <| (D∃) 6 <| (D∃) 7 <| (D∃) 8 <| D_pell D∧ (D≡ (D&1) (D&0 D* (D&4 D- D&7) D+ D&6) (D&3)) D∧ D.2 D* D&4 D* D&7 D= D&3 D+ (D&7 D* D&7 D+ D.1) D∧ D&6 D< D&3 D∧ D&7 D≤ D&5 D∧ D&8 D≤ D&5 D∧ diff --git a/Mathlib/NumberTheory/DiophantineApproximation.lean b/Mathlib/NumberTheory/DiophantineApproximation.lean index f5af3c4ba8849..91e76bdc10c91 100644 --- a/Mathlib/NumberTheory/DiophantineApproximation.lean +++ b/Mathlib/NumberTheory/DiophantineApproximation.lean @@ -5,7 +5,6 @@ Authors: Michael Geißer, Michael Stoll -/ import Mathlib.Algebra.ContinuedFractions.Computation.ApproximationCorollaries import Mathlib.Algebra.ContinuedFractions.Computation.Translations -import Mathlib.Combinatorics.Pigeonhole import Mathlib.Data.Int.Units import Mathlib.Data.Real.Irrational import Mathlib.RingTheory.Coprime.Lemmas diff --git a/Mathlib/NumberTheory/DirichletCharacter/Basic.lean b/Mathlib/NumberTheory/DirichletCharacter/Basic.lean index b308b3f28d3b2..c2cadaef1b099 100644 --- a/Mathlib/NumberTheory/DirichletCharacter/Basic.lean +++ b/Mathlib/NumberTheory/DirichletCharacter/Basic.lean @@ -4,10 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Ashvni Narayanan, Moritz Firsching, Michael Stoll -/ import Mathlib.Algebra.Periodic -import Mathlib.Data.ZMod.Algebra -import Mathlib.NumberTheory.LegendreSymbol.MulCharacter -import Mathlib.Data.ZMod.Algebra import Mathlib.Data.ZMod.Units +import Mathlib.NumberTheory.LegendreSymbol.MulCharacter /-! # Dirichlet Characters diff --git a/Mathlib/NumberTheory/Divisors.lean b/Mathlib/NumberTheory/Divisors.lean index cff3ebc327baa..ba79462e0470c 100644 --- a/Mathlib/NumberTheory/Divisors.lean +++ b/Mathlib/NumberTheory/Divisors.lean @@ -126,7 +126,8 @@ theorem mem_divisorsAntidiagonal {x : ℕ × ℕ} : simp only [succ_le_of_lt (Nat.pos_of_ne_zero h.1), succ_le_of_lt (Nat.pos_of_ne_zero h.2), true_and_iff] exact - ⟨le_mul_of_pos_right (Nat.pos_of_ne_zero h.2), le_mul_of_pos_left (Nat.pos_of_ne_zero h.1)⟩ + ⟨Nat.le_mul_of_pos_right _ (Nat.pos_of_ne_zero h.2), + Nat.le_mul_of_pos_left _ (Nat.pos_of_ne_zero h.1)⟩ #align nat.mem_divisors_antidiagonal Nat.mem_divisorsAntidiagonal -- Porting note: Redundant binder annotation update diff --git a/Mathlib/NumberTheory/EllipticDivisibilitySequence.lean b/Mathlib/NumberTheory/EllipticDivisibilitySequence.lean new file mode 100644 index 0000000000000..a94a4f9d6fa9f --- /dev/null +++ b/Mathlib/NumberTheory/EllipticDivisibilitySequence.lean @@ -0,0 +1,231 @@ +/- +Copyright (c) 2024 David Kurniadi Angdinata. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: David Kurniadi Angdinata +-/ + +import Mathlib.Data.Nat.Parity +import Mathlib.Tactic.Linarith +import Mathlib.Tactic.LinearCombination + +/-! +# Elliptic divisibility sequences + +This file defines the type of an elliptic divisibility sequence (EDS) and a few examples. + +## Mathematical background + +Let $R$ be a commutative ring. An elliptic sequence is a sequence $W : \mathbb{Z} \to R$ satisfying +$$ W(m + n)W(m - n)W(r)^2 = W(m + r)W(m - r)W(n)^2 - W(n + r)W(n - r)W(m)^2, $$ +for any $m, n, r \in \mathbb{Z}$. A divisibility sequence is a sequence $W : \mathbb{Z} \to R$ +satisfying $W(m) \mid W(n)$ for any $m, n \in \mathbb{Z}$ such that $m \mid n$. + +Some examples of EDSs include + * the identity sequence, + * certain terms of Lucas sequences, and + * division polynomials of elliptic curves. + +## Main definitions + + * `IsEllSequence`: a sequence indexed by integers is an elliptic sequence. + * `IsDivSequence`: a sequence indexed by integers is a divisibility sequence. + * `IsEllDivSequence`: a sequence indexed by integers is an EDS. + * `normEDS'`: the canonical example of a normalised EDS indexed by `ℕ`. + * `normEDS`: the canonical example of a normalised EDS indexed by `ℤ`. + +## Main statements + + * TODO: prove that `normEDS` satisfies `IsEllDivSequence`. + * TODO: prove that a normalised sequence satisfying `IsEllDivSequence` can be given by `normEDS`. + +## Implementation notes + +`IsEllDivSequence' b c d n` is defined in terms of the private `IsEllDivSequence'' b c d n`, +which are equal when `n` is odd and differ by a factor of `b` when `n` is even. This coincides with +the reference since both agree for `IsEllDivSequence' b c d 2` and for `IsEllDivSequence' b c d 4`, +and the correct factors of `b` are removed in `IsEllDivSequence' b c d (2 * (m + 2) + 1)` and in +`IsEllDivSequence' b c d (2 * (m + 3))`. This is done to avoid the necessity for ring division by +`b` in the inductive definition of `IsEllDivSequence' b c d (2 * (m + 3))`. The idea is that, an +easy lemma shows that `IsEllDivSequence' b c d (2 * (m + 3))` always contains a factor of `b`, so it +is possible to remove a factor of `b` a posteriori, but stating this lemma requires first defining +`IsEllDivSequence' b c d (2 * (m + 3))`, which requires having this factor of `b` a priori. + +## References + +M Ward, *Memoir on Elliptic Divisibility Sequences* + +## Tags + +elliptic, divisibility, sequence +-/ + +universe u v w + +variable {R : Type u} [CommRing R] + +/-- The proposition that a sequence indexed by integers is an elliptic sequence. -/ +def IsEllSequence (W : ℤ → R) : Prop := + ∀ m n r : ℤ, W (m + n) * W (m - n) * W r ^ 2 = + W (m + r) * W (m - r) * W n ^ 2 - W (n + r) * W (n - r) * W m ^ 2 + +/-- The proposition that a sequence indexed by integers is a divisibility sequence. -/ +def IsDivSequence (W : ℤ → R) : Prop := + ∀ m n : ℕ, m ∣ n → W m ∣ W n + +/-- The proposition that a sequence indexed by integers is an EDS. -/ +def IsEllDivSequence (W : ℤ → R) : Prop := + IsEllSequence W ∧ IsDivSequence W + +lemma IsEllSequence_id : IsEllSequence id := + fun _ _ _ => by simp only [id_eq]; ring1 + +lemma IsDivSequence_id : IsDivSequence id := + fun _ _ => Int.ofNat_dvd.mpr + +/-- The identity sequence is an EDS. -/ +theorem IsEllDivSequence_id : IsEllDivSequence id := + ⟨IsEllSequence_id, IsDivSequence_id⟩ + +lemma IsEllSequence_mul (x : R) {W : ℤ → R} (h : IsEllSequence W) : IsEllSequence (x • W) := + fun m n r => by + linear_combination (norm := (simp only [Pi.smul_apply, smul_eq_mul]; ring1)) x ^ 4 * h m n r + +lemma IsDivSequence_mul (x : R) {W : ℤ → R} (h : IsDivSequence W) : IsDivSequence (x • W) := + fun m n r => mul_dvd_mul_left x <| h m n r + +lemma IsEllDivSequence_mul (x : R) {W : ℤ → R} (h : IsEllDivSequence W) : + IsEllDivSequence (x • W) := + ⟨IsEllSequence_mul x h.left, IsDivSequence_mul x h.right⟩ + +private def normEDS'' (b c d : R) : ℕ → R + | 0 => 0 + | 1 => 1 + | 2 => 1 + | 3 => c + | 4 => d + | (n + 5) => let m := n / 2 + have h4 : m + 4 < n + 5 := Nat.lt_succ.mpr <| add_le_add_right (n.div_le_self 2) 4 + have h3 : m + 3 < n + 5 := (lt_add_one _).trans h4 + have h2 : m + 2 < n + 5 := (lt_add_one _).trans h3 + have h1 : m + 1 < n + 5 := (lt_add_one _).trans h2 + if hn : Even n then + normEDS'' b c d (m + 4) * normEDS'' b c d (m + 2) ^ 3 * (if Even m then b ^ 4 else 1) - + normEDS'' b c d (m + 1) * normEDS'' b c d (m + 3) ^ 3 * (if Even m then 1 else b ^ 4) + else + have h5 : m + 5 < n + 5 := add_lt_add_right + (Nat.div_lt_self (Nat.odd_iff_not_even.mpr hn).pos <| Nat.lt_succ_self 1) 5 + normEDS'' b c d (m + 2) ^ 2 * normEDS'' b c d (m + 3) * normEDS'' b c d (m + 5) - + normEDS'' b c d (m + 1) * normEDS'' b c d (m + 3) * normEDS'' b c d (m + 4) ^ 2 + +variable (b c d : R) + +/-- The canonical example of a normalised EDS `W : ℕ → R`, +with initial values `W(0) = 0`, `W(1) = 1`, `W(2) = b`, `W(3) = c`, and `W(4) = b * d`. + +This is defined in terms of a truncated sequence whose even terms differ by a factor of `b`. -/ +def normEDS' (n : ℕ) : R := + normEDS'' b c d n * if Even n then b else 1 + +@[simp] +lemma normEDS'_zero : normEDS' b c d 0 = 0 := by + rw [normEDS', normEDS'', zero_mul] + +@[simp] +lemma normEDS'_one : normEDS' b c d 1 = 1 := by + rw [normEDS', normEDS'', one_mul, if_neg Nat.not_even_one] + +@[simp] +lemma normEDS'_two : normEDS' b c d 2 = b := by + rw [normEDS', normEDS'', one_mul, if_pos even_two] + +@[simp] +lemma normEDS'_three : normEDS' b c d 3 = c := by + rw [normEDS', normEDS'', if_neg <| by decide, mul_one] + +@[simp] +lemma normEDS'_four : normEDS' b c d 4 = d * b := by + rw [normEDS', normEDS'', if_pos <| by decide] + +lemma normEDS'_odd (m : ℕ) : normEDS' b c d (2 * (m + 2) + 1) = + normEDS' b c d (m + 4) * normEDS' b c d (m + 2) ^ 3 - + normEDS' b c d (m + 1) * normEDS' b c d (m + 3) ^ 3 := by + rw [normEDS', if_neg <| fun h => Nat.even_add_one.mp h <| even_two_mul _, + show 2 * (m + 2) + 1 = 2 * m + 5 by rfl, normEDS'', dif_pos <| even_two_mul m] + simp only [normEDS', Nat.mul_div_right _ zero_lt_two] + by_cases hm : Even m + · have hm1 : ¬Even (m + 1) := fun h => Nat.even_add_one.mp h hm + have hm2 : Even (m + 2) := Nat.even_add_one.mpr hm1 + have hm3 : ¬Even (m + 3) := fun h => Nat.even_add_one.mp h hm2 + have hm4 : Even (m + 4) := Nat.even_add_one.mpr hm3 + rw [if_pos hm, if_pos hm, if_pos hm4, if_pos hm2, if_neg hm1, if_neg hm3] + ring1 + · have hm1 : Even (m + 1) := Nat.even_add_one.mpr hm + have hm2 : ¬Even (m + 2) := fun h => Nat.even_add_one.mp h hm1 + have hm3 : Even (m + 3) := Nat.even_add_one.mpr hm2 + have hm4 : ¬Even (m + 4) := fun h => Nat.even_add_one.mp h hm3 + rw [if_neg hm, if_neg hm, if_neg hm4, if_neg hm2, if_pos hm1, if_pos hm3] + ring1 + +lemma normEDS'_even (m : ℕ) : normEDS' b c d (2 * (m + 3)) * b = + normEDS' b c d (m + 2) ^ 2 * normEDS' b c d (m + 3) * normEDS' b c d (m + 5) - + normEDS' b c d (m + 1) * normEDS' b c d (m + 3) * normEDS' b c d (m + 4) ^ 2 := by + rw [normEDS', if_pos <| even_two_mul _, show 2 * (m + 3) = 2 * m + 1 + 5 by rfl, + normEDS'', dif_neg <| fun h => Nat.even_add_one.mp h <| even_two_mul _] + simp only [normEDS', Nat.mul_add_div two_pos, show 1 / 2 = 0 by rfl] + by_cases hm : Even m + · have hm1 : ¬Even (m + 1) := fun h => Nat.even_add_one.mp h hm + have hm2 : Even (m + 2) := Nat.even_add_one.mpr hm1 + have hm3 : ¬Even (m + 3) := fun h => Nat.even_add_one.mp h hm2 + have hm4 : Even (m + 4) := Nat.even_add_one.mpr hm3 + have hm5 : ¬Even (m + 5) := fun h => Nat.even_add_one.mp h hm4 + rw [if_pos hm2, if_neg hm3, if_neg hm5, if_neg hm1, if_pos hm4] + ring1 + · have hm1 : Even (m + 1) := Nat.even_add_one.mpr hm + have hm2 : ¬Even (m + 2) := fun h => Nat.even_add_one.mp h hm1 + have hm3 : Even (m + 3) := Nat.even_add_one.mpr hm2 + have hm4 : ¬Even (m + 4) := fun h => Nat.even_add_one.mp h hm3 + have hm5 : Even (m + 5) := Nat.even_add_one.mpr hm4 + rw [if_neg hm2, if_pos hm3, if_pos hm5, if_pos hm1, if_neg hm4] + ring1 + +/-- The canonical example of a normalised EDS `W : ℤ → R`, +with initial values `W(0) = 0`, `W(1) = 1`, `W(2) = b`, `W(3) = c`, and `W(4) = b * d`. + +This extends `normEDS'` by defining its values at negative integers. -/ +def normEDS (n : ℤ) : R := n.sign * normEDS' b c d n.natAbs + +@[simp] +lemma normEDS_zero : normEDS b c d 0 = 0 := by + erw [normEDS, Int.cast_zero, zero_mul] + +@[simp] +lemma normEDS_one : normEDS b c d 1 = 1 := by + erw [normEDS, Int.cast_one, one_mul, normEDS'_one] + +@[simp] +lemma normEDS_two : normEDS b c d 2 = b := by + erw [normEDS, Int.cast_one, one_mul, normEDS'_two] + +@[simp] +lemma normEDS_three : normEDS b c d 3 = c := by + erw [normEDS, Int.cast_one, one_mul, normEDS'_three] + +@[simp] +lemma normEDS_four : normEDS b c d 4 = d * b := by + erw [normEDS, Int.cast_one, one_mul, normEDS'_four] + +lemma normEDS_odd (m : ℕ) : normEDS b c d (2 * (m + 2) + 1) = + normEDS b c d (m + 4) * normEDS b c d (m + 2) ^ 3 - + normEDS b c d (m + 1) * normEDS b c d (m + 3) ^ 3 := by + repeat erw [normEDS, Int.cast_one, one_mul] + exact normEDS'_odd b c d m + +lemma normEDS_even (m : ℕ) : normEDS b c d (2 * (m + 3)) * b = + normEDS b c d (m + 2) ^ 2 * normEDS b c d (m + 3) * normEDS b c d (m + 5) - + normEDS b c d (m + 1) * normEDS b c d (m + 3) * normEDS b c d (m + 4) ^ 2 := by + repeat erw [normEDS, Int.cast_one, one_mul] + exact normEDS'_even b c d m + +@[simp] +lemma normEDS_neg (n : ℕ) : normEDS b c d (-n) = -normEDS b c d n := by + simp [normEDS] diff --git a/Mathlib/NumberTheory/FLT/Basic.lean b/Mathlib/NumberTheory/FLT/Basic.lean index 8838c2a2a4236..5afd98c0a3b89 100644 --- a/Mathlib/NumberTheory/FLT/Basic.lean +++ b/Mathlib/NumberTheory/FLT/Basic.lean @@ -5,7 +5,7 @@ Authors: Kevin Buzzard, Yaël Dillies -/ import Mathlib.Data.Nat.Parity import Mathlib.Data.Rat.Defs -import Mathlib.Tactic.Positivity +import Mathlib.Tactic.Positivity.Basic import Mathlib.Tactic.TFAE /-! @@ -65,7 +65,7 @@ lemma fermatLastTheoremWith_nat_int_rat_tfae (n : ℕ) : (Int.coe_nat_inj'.1 _) push_cast simp only [abs_of_neg, neg_pow a, neg_pow b, neg_pow c, ← mul_add, habc, *] - · exact (by positivity : 0 < c ^ n).not_lt $ habc.symm.trans_lt $ add_neg (hn.pow_neg ha) $ + · exact (by positivity : 0 < c ^ n).not_lt <| habc.symm.trans_lt <| add_neg (hn.pow_neg ha) <| hn.pow_neg hb · refine' h b.natAbs c.natAbs a.natAbs (by positivity) (by positivity) (by positivity) (Int.coe_nat_inj'.1 _) @@ -87,7 +87,7 @@ lemma fermatLastTheoremWith_nat_int_rat_tfae (n : ℕ) : push_cast simp only [abs_of_pos, abs_of_neg, hn.neg_pow, habc, add_neg_eq_iff_eq_add, eq_add_neg_iff_add_eq, *] - · exact (by positivity : 0 < a ^ n + b ^ n).not_lt $ habc.trans_lt $ hn.pow_neg hc + · exact (by positivity : 0 < a ^ n + b ^ n).not_lt <| habc.trans_lt <| hn.pow_neg hc · refine' h a.natAbs b.natAbs c.natAbs (by positivity) (by positivity) (by positivity) (Int.coe_nat_inj'.1 _) push_cast @@ -101,7 +101,7 @@ lemma fermatLastTheoremWith_nat_int_rat_tfae (n : ℕ) : refine' h (a.num * b.den * c.den) (a.den * b.num * c.den) (a.den * b.den * c.num) (by positivity) (by positivity) (by positivity) _ have : (a.den * b.den * c.den : ℚ) ^ n ≠ 0 := by positivity - refine' Int.cast_injective $ (div_left_inj' this).1 _ + refine' Int.cast_injective <| (div_left_inj' this).1 _ push_cast simp only [add_div, ← div_pow, mul_div_mul_comm, div_self (by positivity : (a.den : ℚ) ≠ 0), div_self (by positivity : (b.den : ℚ) ≠ 0), div_self (by positivity : (c.den : ℚ) ≠ 0), diff --git a/Mathlib/NumberTheory/FLT/Four.lean b/Mathlib/NumberTheory/FLT/Four.lean index 6d7723ec6966f..e56e2937c3935 100644 --- a/Mathlib/NumberTheory/FLT/Four.lean +++ b/Mathlib/NumberTheory/FLT/Four.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Paul van Wamelen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Paul van Wamelen -/ +import Mathlib.Algebra.GroupPower.Lemmas import Mathlib.NumberTheory.FLT.Basic import Mathlib.NumberTheory.PythagoreanTriples import Mathlib.RingTheory.Coprime.Lemmas diff --git a/Mathlib/NumberTheory/FermatPsp.lean b/Mathlib/NumberTheory/FermatPsp.lean index 7a2db88a60b5d..77081d44e4abc 100644 --- a/Mathlib/NumberTheory/FermatPsp.lean +++ b/Mathlib/NumberTheory/FermatPsp.lean @@ -216,7 +216,7 @@ private theorem psp_from_prime_psp {b : ℕ} (b_ge_two : 2 ≤ b) {p : ℕ} (p_p have hi_bpowpsubone : 1 ≤ b ^ (p - 1) := Nat.one_le_pow (p - 1) b hi_b -- Other useful facts have p_odd : Odd p := p_prime.odd_of_ne_two p_gt_two.ne.symm - have AB_not_prime : ¬Nat.Prime (A * B) := Nat.not_prime_mul hi_A hi_B + have AB_not_prime : ¬Nat.Prime (A * B) := Nat.not_prime_mul hi_A.ne' hi_B.ne' have AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1) := AB_id_helper _ _ b_ge_two p_odd have hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1 := by simpa only [one_pow, pow_mul] using nat_sub_dvd_pow_sub_pow _ 1 p @@ -318,7 +318,7 @@ private theorem psp_from_prime_gt_p {b : ℕ} (b_ge_two : 2 ≤ b) {p : ℕ} (p_ suffices h : p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2 · apply gt_of_ge_of_gt · exact tsub_le_tsub_left (one_le_of_lt p_gt_two) ((b ^ 2) ^ (p - 1) * b ^ 2) - · have : p ≤ p * b ^ 2 := Nat.le_mul_of_pos_right (show 0 < b ^ 2 by nlinarith) + · have : p ≤ p * b ^ 2 := Nat.le_mul_of_pos_right _ (show 0 < b ^ 2 by nlinarith) exact tsub_lt_tsub_right_of_le this h suffices h : p < (b ^ 2) ^ (p - 1) · have : 4 ≤ b ^ 2 := by nlinarith @@ -352,7 +352,7 @@ theorem exists_infinite_pseudoprimes {b : ℕ} (h : 1 ≤ b) (m : ℕ) : have h₄ : 0 < b * (b ^ 2 - 1) := mul_pos h₁ h₃ have h₅ : b * (b ^ 2 - 1) < p := by linarith have h₆ : ¬p ∣ b * (b ^ 2 - 1) := Nat.not_dvd_of_pos_of_lt h₄ h₅ - have h₇ : b ≤ b * (b ^ 2 - 1) := Nat.le_mul_of_pos_right h₃ + have h₇ : b ≤ b * (b ^ 2 - 1) := Nat.le_mul_of_pos_right _ h₃ have h₈ : 2 ≤ b * (b ^ 2 - 1) := le_trans b_ge_two h₇ have h₉ : 2 < p := gt_of_gt_of_ge h₅ h₈ have h₁₀ := psp_from_prime_gt_p b_ge_two hp₂ h₉ diff --git a/Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean b/Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean index 783acaa6f2fc5..63cf26685dc99 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean @@ -98,8 +98,8 @@ open Multiplicative /-- Define coercion to a function so that it includes the move from `R` to `Multiplicative R`. After we have proved the API lemmas below, we don't need to worry about writing `ofAdd a` when we want to apply an additive character. -/ -instance instFunLike : FunLike (AddChar R R') R fun _ ↦ R' := - inferInstanceAs (FunLike (Multiplicative R →* R') R fun _ ↦ R') +instance instFunLike : FunLike (AddChar R R') R R' := + inferInstanceAs (FunLike (Multiplicative R →* R') R R') #noalign add_char.has_coe_to_fun theorem coe_to_fun_apply (ψ : AddChar R R') (a : R) : ψ a = ψ.toMonoidHom (ofAdd a) := @@ -190,7 +190,7 @@ def IsNontrivial (ψ : AddChar R R') : Prop := /-- An additive character is nontrivial iff it is not the trivial character. -/ theorem isNontrivial_iff_ne_trivial (ψ : AddChar R R') : IsNontrivial ψ ↔ ψ ≠ 1 := by refine' not_forall.symm.trans (Iff.not _) - rw [FunLike.ext_iff] + rw [DFunLike.ext_iff] rfl #align add_char.is_nontrivial_iff_ne_trivial AddChar.isNontrivial_iff_ne_trivial diff --git a/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean b/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean index f672a452c7d8e..a61841e5fe5fc 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean @@ -3,7 +3,8 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.NumberTheory.LegendreSymbol.QuadraticReciprocity +import Mathlib.NumberTheory.LegendreSymbol.Basic +import Mathlib.Analysis.Normed.Field.Basic #align_import number_theory.legendre_symbol.gauss_eisenstein_lemmas from "leanprover-community/mathlib"@"8818fdefc78642a7e6afcd20be5c184f3c7d9699" @@ -126,7 +127,7 @@ private theorem eisenstein_lemma_aux₁ (p : ℕ) [Fact p.Prime] [hp2 : Fact (p _ = (∑ x in Ico 1 (p / 2).succ, ((a * x : ℕ) : ZMod p).val : ℕ) + (∑ x in Ico 1 (p / 2).succ, a * x / p : ℕ) := by simp only [val_nat_cast] - simp [sum_add_distrib, mul_sum.symm, Nat.cast_add, Nat.cast_mul, Nat.cast_sum, hp2] + simp [sum_add_distrib, ← mul_sum, Nat.cast_add, Nat.cast_mul, Nat.cast_sum, hp2] _ = _ := congr_arg₂ (· + ·) (calc @@ -148,7 +149,7 @@ theorem eisenstein_lemma_aux (p : ℕ) [Fact p.Prime] [Fact (p % 2 = 1)] {a : ∑ x in Ico 1 (p / 2).succ, x * a / p [MOD 2] := have ha2 : (a : ZMod 2) = (1 : ℕ) := (eq_iff_modEq_nat _).2 ha2 (eq_iff_modEq_nat 2).1 <| sub_eq_zero.1 <| by - simpa [add_left_comm, sub_eq_add_neg, Finset.mul_sum.symm, mul_comm, ha2, Nat.cast_sum, + simpa [add_left_comm, sub_eq_add_neg, ← mul_sum, mul_comm, ha2, Nat.cast_sum, add_neg_eq_iff_eq_add.symm, neg_eq_self_mod_two, add_assoc] using Eq.symm (eisenstein_lemma_aux₁ p hap) #align zmod.eisenstein_lemma_aux ZMod.eisenstein_lemma_aux diff --git a/Mathlib/NumberTheory/LegendreSymbol/MulCharacter.lean b/Mathlib/NumberTheory/LegendreSymbol/MulCharacter.lean index 4bc6b10688607..f7c6c6c64005e 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/MulCharacter.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/MulCharacter.lean @@ -71,7 +71,7 @@ structure MulChar extends MonoidHom R R' where map_nonunit' : ∀ a : R, ¬IsUnit a → toFun a = 0 #align mul_char MulChar -instance MulChar.instFunLike : FunLike (MulChar R R') R (fun _ => R') := +instance MulChar.instFunLike : FunLike (MulChar R R') R R' := ⟨fun χ => χ.toFun, fun χ₀ χ₁ h => by cases χ₀; cases χ₁; congr; apply MonoidHom.ext (fun _ => congr_fun h _)⟩ diff --git a/Mathlib/NumberTheory/LucasLehmer.lean b/Mathlib/NumberTheory/LucasLehmer.lean index fc1c347c693ec..b7863a3897868 100644 --- a/Mathlib/NumberTheory/LucasLehmer.lean +++ b/Mathlib/NumberTheory/LucasLehmer.lean @@ -4,11 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Scott Morrison, Ainsley Pahljina -/ import Mathlib.Data.Nat.Parity -import Mathlib.Data.PNat.Interval import Mathlib.Data.ZMod.Basic import Mathlib.GroupTheory.OrderOfElement import Mathlib.RingTheory.Fintype import Mathlib.Tactic.IntervalCases +import Mathlib.Algebra.GroupPower.Order #align_import number_theory.lucas_lehmer from "leanprover-community/mathlib"@"10b4e499f43088dd3bb7b5796184ad5216648ab1" @@ -153,7 +153,7 @@ theorem residue_eq_zero_iff_sMod_eq_zero (p : ℕ) (w : 1 < p) : intro h simp? [ZMod.int_cast_zmod_eq_zero_iff_dvd] at h says simp only [ZMod.int_cast_zmod_eq_zero_iff_dvd, gt_iff_lt, zero_lt_two, pow_pos, cast_pred, - cast_pow, cast_ofNat] at h + cast_pow, cast_ofNat, Int.isPosValue] at h apply Int.eq_zero_of_dvd_of_nonneg_of_lt _ _ h <;> clear h · exact sMod_nonneg _ (by positivity) _ · exact sMod_lt _ (by positivity) _ @@ -426,7 +426,7 @@ theorem ω_pow_formula (p' : ℕ) (h : lucasLehmerResidue (p' + 2) = 0) : rw [sZMod_eq_s p'] at h simp? [ZMod.int_cast_zmod_eq_zero_iff_dvd] at h says simp only [add_tsub_cancel_right, ZMod.int_cast_zmod_eq_zero_iff_dvd, gt_iff_lt, zero_lt_two, - pow_pos, cast_pred, cast_pow, cast_ofNat] at h + pow_pos, cast_pred, cast_pow, cast_ofNat, Int.isPosValue] at h cases' h with k h use k replace h := congr_arg (fun n : ℤ => (n : X (q (p' + 2)))) h diff --git a/Mathlib/NumberTheory/MaricaSchoenheim.lean b/Mathlib/NumberTheory/MaricaSchoenheim.lean index a9d9220e50076..b09f683e6c2c3 100644 --- a/Mathlib/NumberTheory/MaricaSchoenheim.lean +++ b/Mathlib/NumberTheory/MaricaSchoenheim.lean @@ -37,7 +37,7 @@ lemma grahamConjecture_of_squarefree {n : ℕ} (f : ℕ → ℕ) (hf' : ∀ k < by_contra! set 𝒜 := (Iio n).image fun n ↦ primeFactors (f n) have hf'' : ∀ i < n, ∀ j, Squarefree (f i / (f i).gcd (f j)) := - fun i hi j ↦ (hf' _ hi).squarefree_of_dvd $ div_dvd_of_dvd $ gcd_dvd_left _ _ + fun i hi j ↦ (hf' _ hi).squarefree_of_dvd <| div_dvd_of_dvd <| gcd_dvd_left _ _ refine lt_irrefl n ?_ calc n = 𝒜.card := ?_ @@ -50,9 +50,9 @@ lemma grahamConjecture_of_squarefree {n : ℕ} (f : ℕ → ℕ) (hf' : ∀ k < · simp only [forall_mem_diffs, forall_image, mem_Ioo, mem_Iio] rintro i hi j hj rw [← primeFactors_div_gcd (hf' _ hi) (hf' _ hj).ne_zero, - prod_primeFactors_of_squarefree $ hf'' _ hi _] - exact ⟨Nat.div_pos (gcd_le_left _ (hf' _ hi).ne_zero.bot_lt) $ - Nat.gcd_pos_of_pos_left _ (hf' _ hi).ne_zero.bot_lt, Nat.div_lt_of_lt_mul $ this _ hi _ hj⟩ + prod_primeFactors_of_squarefree <| hf'' _ hi _] + exact ⟨Nat.div_pos (gcd_le_left _ (hf' _ hi).ne_zero.bot_lt) <| + Nat.gcd_pos_of_pos_left _ (hf' _ hi).ne_zero.bot_lt, Nat.div_lt_of_lt_mul <| this _ hi _ hj⟩ · simp only [forall_mem_diffs, forall_image, mem_Ioo, mem_Iio] rintro a ha b hb c hc d hd rw [← primeFactors_div_gcd (hf' _ ha) (hf' _ hb).ne_zero, ← primeFactors_div_gcd diff --git a/Mathlib/NumberTheory/Modular.lean b/Mathlib/NumberTheory/Modular.lean index 5c242407700e9..b694635f7fa05 100644 --- a/Mathlib/NumberTheory/Modular.lean +++ b/Mathlib/NumberTheory/Modular.lean @@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Alex Kontorovich, Heather Macbeth, Marc Masdeu -/ import Mathlib.Analysis.Complex.UpperHalfPlane.Basic -import Mathlib.Analysis.NormedSpace.FiniteDimension import Mathlib.LinearAlgebra.GeneralLinearGroup import Mathlib.LinearAlgebra.Matrix.GeneralLinearGroup +import Mathlib.Topology.Instances.Matrix +import Mathlib.Topology.Algebra.Module.FiniteDimension #align_import number_theory.modular from "leanprover-community/mathlib"@"2196ab363eb097c008d4497125e0dde23fb36db2" @@ -147,7 +148,7 @@ theorem tendsto_normSq_coprime_pair : dsimp only [Pi.smul_apply, LinearMap.pi_apply, smul_eq_mul] fin_cases i · show (z : ℂ).im⁻¹ * (f c).im = c 0 - rw [f_def, add_im, ofReal_mul_im, ofReal_im, add_zero, mul_left_comm, inv_mul_cancel hz, + rw [f_def, add_im, im_ofReal_mul, ofReal_im, add_zero, mul_left_comm, inv_mul_cancel hz, mul_one] · show (z : ℂ).im⁻¹ * ((z : ℂ) * conj (f c)).im = c 1 rw [f_def, RingHom.map_add, RingHom.map_mul, mul_add, mul_left_comm, mul_conj, conj_ofReal, diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index ff53fe5380695..dcc3c7782fcb6 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ import Mathlib.Algebra.DirectSum.Algebra -import Mathlib.Algebra.GradedMonoid import Mathlib.Analysis.Complex.UpperHalfPlane.FunctionsBoundedAtInfty import Mathlib.Analysis.Complex.UpperHalfPlane.Manifold +import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions import Mathlib.NumberTheory.ModularForms.SlashInvariantForms #align_import number_theory.modular_forms.basic from "leanprover-community/mathlib"@"57f9349f2fe19d2de7207e99b0341808d977cdcf" @@ -79,7 +79,7 @@ class CuspFormClass (F : Type*) (Γ : outParam <| Subgroup (SL(2, ℤ))) (k : ou instance (priority := 100) ModularFormClass.modularForm : ModularFormClass (ModularForm Γ k) Γ k where coe f := f.toFun - coe_injective' f g h := by cases f; cases g; congr; exact FunLike.ext' h + coe_injective' f g h := by cases f; cases g; congr; exact DFunLike.ext' h slash_action_eq f := f.slash_action_eq' holo := ModularForm.holo' bdd_at_infty := ModularForm.bdd_at_infty' @@ -87,7 +87,7 @@ instance (priority := 100) ModularFormClass.modularForm : instance (priority := 100) CuspFormClass.cuspForm : CuspFormClass (CuspForm Γ k) Γ k where coe f := f.toFun - coe_injective' f g h := by cases f; cases g; congr; exact FunLike.ext' h + coe_injective' f g h := by cases f; cases g; congr; exact DFunLike.ext' h slash_action_eq f := f.slash_action_eq' holo := CuspForm.holo' zero_at_infty := CuspForm.zero_at_infty' @@ -112,12 +112,12 @@ theorem CuspForm.toSlashInvariantForm_coe (f : CuspForm Γ k) : ⇑f.1 = f := rf @[ext] theorem ModularForm.ext {f g : ModularForm Γ k} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align modular_form.ext ModularForm.ext @[ext] theorem CuspForm.ext {f g : CuspForm Γ k} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align cusp_form.ext CuspForm.ext /-- Copy of a `ModularForm` with a new `toFun` equal to the old one. Useful to fix @@ -233,7 +233,7 @@ theorem sub_apply (f g : ModularForm Γ k) (z : ℍ) : (f - g) z = f z - g z := #align modular_form.sub_apply ModularForm.sub_apply instance : AddCommGroup (ModularForm Γ k) := - FunLike.coe_injective.addCommGroup _ rfl coe_add coe_neg coe_sub coe_smul coe_smul + DFunLike.coe_injective.addCommGroup _ rfl coe_add coe_neg coe_sub coe_smul coe_smul /-- Additive coercion from `ModularForm` to `ℍ → ℂ`. -/ @[simps] @@ -244,7 +244,7 @@ def coeHom : ModularForm Γ k →+ ℍ → ℂ where #align modular_form.coe_hom ModularForm.coeHom instance : Module ℂ (ModularForm Γ k) := - Function.Injective.module ℂ coeHom FunLike.coe_injective fun _ _ => rfl + Function.Injective.module ℂ coeHom DFunLike.coe_injective fun _ _ => rfl instance : Inhabited (ModularForm Γ k) := ⟨0⟩ @@ -401,7 +401,7 @@ theorem sub_apply (f g : CuspForm Γ k) (z : ℍ) : (f - g) z = f z - g z := #align cusp_form.sub_apply CuspForm.sub_apply instance : AddCommGroup (CuspForm Γ k) := - FunLike.coe_injective.addCommGroup _ rfl coe_add coe_neg coe_sub coe_smul coe_smul + DFunLike.coe_injective.addCommGroup _ rfl coe_add coe_neg coe_sub coe_smul coe_smul /-- Additive coercion from `CuspForm` to `ℍ → ℂ`. -/ @[simps] @@ -412,14 +412,14 @@ def coeHom : CuspForm Γ k →+ ℍ → ℂ where #align cusp_form.coe_hom CuspForm.coeHom instance : Module ℂ (CuspForm Γ k) := - Function.Injective.module ℂ coeHom FunLike.coe_injective fun _ _ => rfl + Function.Injective.module ℂ coeHom DFunLike.coe_injective fun _ _ => rfl instance : Inhabited (CuspForm Γ k) := ⟨0⟩ instance (priority := 99) [CuspFormClass F Γ k] : ModularFormClass F Γ k where - coe := FunLike.coe - coe_injective' := FunLike.coe_injective' + coe := DFunLike.coe + coe_injective' := DFunLike.coe_injective' slash_action_eq := SlashInvariantFormClass.slash_action_eq holo := CuspFormClass.holo bdd_at_infty _ _ := (CuspFormClass.zero_at_infty _ _).boundedAtFilter diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean new file mode 100644 index 0000000000000..ed94627cb7fb7 --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2024 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck, David Loeffler +-/ +import Mathlib.NumberTheory.ModularForms.SlashInvariantForms +import Mathlib.NumberTheory.ModularForms.CongruenceSubgroups + +/-! +# Eisenstein Series + +## Main definitions + +* We define Eisenstein series of level `Γ(N)` for any `N : ℕ` and weight `k : ℤ` as the infinite sum + `∑' v : (Fin 2 → ℤ), (1 / (v 0 * z + v 1) ^ k)`, where `z : ℍ` and `v` ranges over all pairs of + coprime integers congruent to a fixed pair `(a, b)` modulo `N`. Note that by using `(Fin 2 → ℤ)` + instead of `ℤ × ℤ` we can state all of the required equivalences using matrices and vectors, which + makes working with them more convenient. + +* We show that they define a slash invariant form of level `Γ(N)` and weight `k`. + +## References +* [F. Diamond and J. Shurman, *A First Course in Modular Forms*][diamondshurman2005] +-/ + +noncomputable section + +open ModularForm UpperHalfPlane Complex Matrix + +open scoped MatrixGroups + +namespace EisensteinSeries + +variable (N : ℕ) (a : Fin 2 → ZMod N) + +section gammaSet_def + +/-- The set of pairs of coprime integers congruent to `a` mod `N`. -/ +def gammaSet := {v : Fin 2 → ℤ | (↑) ∘ v = a ∧ IsCoprime (v 0) (v 1)} + +lemma pairwise_disjoint_gammaSet : Pairwise (Disjoint on gammaSet N) := by + refine fun u v huv ↦ ?_ + contrapose! huv + obtain ⟨f, hf⟩ := Set.not_disjoint_iff.mp huv + exact hf.1.1.symm.trans hf.2.1 + +/-- For level `N = 1`, the gamma sets are all equal. -/ +lemma gammaSet_one_eq (a a' : Fin 2 → ZMod 1) : gammaSet 1 a = gammaSet 1 a' := + congr_arg _ (Subsingleton.elim _ _) + +/-- For level `N = 1`, the gamma sets are all equivalent; this is the equivalence. -/ +def gammaSet_one_equiv (a a' : Fin 2 → ZMod 1) : gammaSet 1 a ≃ gammaSet 1 a' := + Equiv.Set.ofEq (gammaSet_one_eq a a') + +end gammaSet_def + +variable {N a} + +section gamma_action + +/-- Right-multiplying by `γ ∈ SL(2, ℤ)` sends `gammaSet N a` to `gammaSet N (vecMul a γ)`. -/ +lemma vecMul_SL2_mem_gammaSet {v : Fin 2 → ℤ} (hv : v ∈ gammaSet N a) (γ : SL(2, ℤ)) : + vecMul v γ ∈ gammaSet N (vecMul a γ) := by + refine ⟨?_, hv.2.vecMulSL γ⟩ + have := RingHom.map_vecMul (m := Fin 2) (n := Fin 2) (Int.castRingHom (ZMod N)) γ v + simp only [eq_intCast, Int.coe_castRingHom] at this + simp_rw [Function.comp, this, hv.1] + simp + +variable (a) in +/-- The bijection between `GammaSets` given by multiplying by an element of `SL(2, ℤ)`. -/ +def gammaSetEquiv (γ : SL(2, ℤ)) : gammaSet N a ≃ gammaSet N (vecMul a γ) where + toFun v := ⟨vecMul v.1 γ, vecMul_SL2_mem_gammaSet v.2 γ⟩ + invFun v := ⟨vecMul v.1 ↑(γ⁻¹), by + have := vecMul_SL2_mem_gammaSet v.2 γ⁻¹ + rw [vecMul_vecMul, ← SpecialLinearGroup.coe_mul] at this + simpa only [SpecialLinearGroup.map_apply_coe, RingHom.mapMatrix_apply, Int.coe_castRingHom, + map_inv, mul_right_inv, SpecialLinearGroup.coe_one, vecMul_one]⟩ + left_inv v := by simp_rw [vecMul_vecMul, ← SpecialLinearGroup.coe_mul, mul_inv_self, + SpecialLinearGroup.coe_one, vecMul_one] + right_inv v := by simp_rw [vecMul_vecMul, ← SpecialLinearGroup.coe_mul, inv_mul_self, + SpecialLinearGroup.coe_one, vecMul_one] + +end gamma_action + +section eisSummand + +/-- The function on `(Fin 2 → ℤ)` whose sum defines an Eisenstein series.-/ +def eisSummand (k : ℤ) (v : Fin 2 → ℤ) (z : ℍ) : ℂ := 1 / (v 0 * z.1 + v 1) ^ k + +/-- How the `eisSummand` function changes under the Moebius action. -/ +theorem eisSummand_SL2_apply (k : ℤ) (i : (Fin 2 → ℤ)) (A : SL(2, ℤ)) (z : ℍ) : + eisSummand k i (A • z) = (z.denom A) ^ k * eisSummand k (vecMul i A) z := by + simp only [eisSummand, specialLinearGroup_apply, algebraMap_int_eq, eq_intCast, ofReal_int_cast, + one_div, vecMul, vec2_dotProduct, Int.cast_add, Int.cast_mul] + have h (a b c d u v : ℂ) (hc : c * z + d ≠ 0) : ((u * ((a * z + b) / (c * z + d)) + v) ^ k)⁻¹ = + (c * z + d) ^ k * (((u * a + v * c) * z + (u * b + v * d)) ^ k)⁻¹ + · field_simp [hc] + ring_nf + apply h (hc := z.denom_ne_zero A) + +end eisSummand + +variable (a) + +/-- An Eisenstein series of weight `k` and level `Γ(N)`, with congruence condition `a`. -/ +def eisensteinSeries (k : ℤ) (z : ℍ) : ℂ := ∑' x : gammaSet N a, eisSummand k x z + +lemma eisensteinSeries_slash_apply (k : ℤ) (γ : SL(2, ℤ)) : + eisensteinSeries a k ∣[k] γ = eisensteinSeries (vecMul a γ) k := by + ext1 z + simp_rw [SL_slash, slash_def, slash, det_coe', ofReal_one, one_zpow, mul_one, zpow_neg, + mul_inv_eq_iff_eq_mul₀ (zpow_ne_zero _ <| z.denom_ne_zero _), mul_comm, + eisensteinSeries, ← UpperHalfPlane.sl_moeb, eisSummand_SL2_apply, tsum_mul_left] + erw [(gammaSetEquiv a γ).tsum_eq (eisSummand k · z)] + +/-- The SlashInvariantForm defined by an Eisenstein series of weight `k : ℤ`, level `Γ(N)`, + and congruence condition given by `a : Fin 2 → ZMod N`. -/ +def eisensteinSeries_SIF (k : ℤ) : SlashInvariantForm (Gamma N) k where + toFun := eisensteinSeries a k + slash_action_eq' A := by rw [subgroup_slash, ← SL_slash, eisensteinSeries_slash_apply, + (Gamma_mem' N A).mp A.2, SpecialLinearGroup.coe_one, vecMul_one] diff --git a/Mathlib/NumberTheory/ModularForms/JacobiTheta/Manifold.lean b/Mathlib/NumberTheory/ModularForms/JacobiTheta/Manifold.lean index 693117d66c766..75e8a3cdf843c 100644 --- a/Mathlib/NumberTheory/ModularForms/JacobiTheta/Manifold.lean +++ b/Mathlib/NumberTheory/ModularForms/JacobiTheta/Manifold.lean @@ -3,8 +3,9 @@ Copyright (c) 2023 David Loeffler. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Loeffler -/ -import Mathlib.NumberTheory.ModularForms.JacobiTheta.Basic import Mathlib.Analysis.Complex.UpperHalfPlane.Manifold +import Mathlib.Geometry.Manifold.MFDeriv.FDeriv +import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable #align_import number_theory.modular_forms.jacobi_theta.manifold from "leanprover-community/mathlib"@"57f9349f2fe19d2de7207e99b0341808d977cdcf" diff --git a/Mathlib/NumberTheory/ModularForms/JacobiTheta/Basic.lean b/Mathlib/NumberTheory/ModularForms/JacobiTheta/OneVariable.lean similarity index 50% rename from Mathlib/NumberTheory/ModularForms/JacobiTheta/Basic.lean rename to Mathlib/NumberTheory/ModularForms/JacobiTheta/OneVariable.lean index dd26ade756470..fc6fd6a83827a 100644 --- a/Mathlib/NumberTheory/ModularForms/JacobiTheta/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/JacobiTheta/OneVariable.lean @@ -3,16 +3,14 @@ Copyright (c) 2023 David Loeffler. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Loeffler -/ -import Mathlib.Analysis.SpecialFunctions.Gaussian -import Mathlib.Analysis.Complex.LocallyUniformLimit -import Mathlib.Analysis.Complex.UpperHalfPlane.FunctionsBoundedAtInfty -import Mathlib.Analysis.Complex.UpperHalfPlane.Topology +import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable +import Mathlib.Analysis.Complex.UpperHalfPlane.Basic #align_import number_theory.modular_forms.jacobi_theta.basic from "leanprover-community/mathlib"@"57f9349f2fe19d2de7207e99b0341808d977cdcf" /-! # Jacobi's theta function -This file defines the Jacobi theta function +This file defines the one-variable Jacobi theta function $$\theta(\tau) = \sum_{n \in \mathbb{Z}} \exp (i \pi n ^ 2 \tau),$$ @@ -21,25 +19,52 @@ and proves the modular transformation properties `θ (τ + 2) = θ τ` and show that `θ` is differentiable on `ℍ`, and `θ(τ) - 1` has exponential decay as `im τ → ∞`. -/ - -open Complex Real Asymptotics Filter +open Complex Real Asymptotics Filter Topology open scoped Real BigOperators UpperHalfPlane -/-- Jacobi's theta function `∑' (n : ℤ), exp (π * I * n ^ 2 * τ)`. -/ -noncomputable def jacobiTheta (z : ℂ) : ℂ := - ∑' n : ℤ, cexp (π * I * (n : ℂ) ^ 2 * z) +/-- Jacobi's one-variable theta function `∑' (n : ℤ), exp (π * I * n ^ 2 * τ)`. -/ +noncomputable def jacobiTheta (τ : ℂ) : ℂ := ∑' n : ℤ, cexp (π * I * (n : ℂ) ^ 2 * τ) #align jacobi_theta jacobiTheta -theorem norm_exp_mul_sq_le {z : ℂ} (hz : 0 < z.im) (n : ℤ) : - ‖cexp (π * I * (n : ℂ) ^ 2 * z)‖ ≤ rexp (-π * z.im) ^ n.natAbs := by - let y := rexp (-π * z.im) - have h : y < 1 := exp_lt_one_iff.mpr (mul_neg_of_neg_of_pos (neg_lt_zero.mpr pi_pos) hz) +lemma jacobiTheta_eq_jacobiTheta₂ (τ : ℂ) : jacobiTheta τ = jacobiTheta₂ 0 τ := tsum_congr (by simp) + +theorem jacobiTheta_two_add (τ : ℂ) : jacobiTheta (2 + τ) = jacobiTheta τ := by + simp_rw [jacobiTheta_eq_jacobiTheta₂, add_comm, jacobiTheta₂_add_right] +#align jacobi_theta_two_add jacobiTheta_two_add + +theorem jacobiTheta_T_sq_smul (τ : ℍ) : jacobiTheta (ModularGroup.T ^ 2 • τ :) = jacobiTheta τ := by + suffices (ModularGroup.T ^ 2 • τ :) = (2 : ℂ) + ↑τ by simp_rw [this, jacobiTheta_two_add] + have : ModularGroup.T ^ (2 : ℕ) = ModularGroup.T ^ (2 : ℤ) := rfl + simp_rw [this, UpperHalfPlane.modular_T_zpow_smul, UpperHalfPlane.coe_vadd] + norm_cast +set_option linter.uppercaseLean3 false in +#align jacobi_theta_T_sq_smul jacobiTheta_T_sq_smul + +theorem jacobiTheta_S_smul (τ : ℍ) : + jacobiTheta ↑(ModularGroup.S • τ) = (-I * τ) ^ (1 / 2 : ℂ) * jacobiTheta τ := by + have h0 : (τ : ℂ) ≠ 0 := ne_of_apply_ne im (zero_im.symm ▸ ne_of_gt τ.2) + simp_rw [UpperHalfPlane.modular_S_smul, jacobiTheta_eq_jacobiTheta₂] + conv_rhs => erw [← ofReal_zero, jacobiTheta₂_functional_equation 0 τ.2] + rw [zero_pow two_pos, mul_zero, zero_div, Complex.exp_zero, mul_one, ← mul_assoc, + mul_one_div] + erw [div_self] + rw [one_mul, UpperHalfPlane.coe_mk, inv_neg, neg_div, one_div] + · rfl + · rw [Ne.def, cpow_eq_zero_iff, not_and_or] + exact Or.inl <| mul_ne_zero (neg_ne_zero.mpr I_ne_zero) h0 +set_option linter.uppercaseLean3 false in +#align jacobi_theta_S_smul jacobiTheta_S_smul + +theorem norm_exp_mul_sq_le {τ : ℂ} (hτ : 0 < τ.im) (n : ℤ) : + ‖cexp (π * I * (n : ℂ) ^ 2 * τ)‖ ≤ rexp (-π * τ.im) ^ n.natAbs := by + let y := rexp (-π * τ.im) + have h : y < 1 := exp_lt_one_iff.mpr (mul_neg_of_neg_of_pos (neg_lt_zero.mpr pi_pos) hτ) refine' (le_of_eq _).trans (_ : y ^ n ^ 2 ≤ _) · rw [Complex.norm_eq_abs, Complex.abs_exp] - have : (π * I * n ^ 2 * z : ℂ).re = -π * z.im * (n : ℝ) ^ 2 := by - rw [(by push_cast; ring : (π * I * n ^ 2 * z : ℂ) = (π * n ^ 2 : ℝ) * (z * I)), - ofReal_mul_re, mul_I_re] + have : (π * I * n ^ 2 * τ : ℂ).re = -π * τ.im * (n : ℝ) ^ 2 := by + rw [(by push_cast; ring : (π * I * n ^ 2 * τ : ℂ) = (π * n ^ 2 : ℝ) * (τ * I)), + re_ofReal_mul, mul_I_re] ring obtain ⟨m, hm⟩ := Int.eq_ofNat_of_zero_le (sq_nonneg n) rw [this, exp_mul, ← Int.cast_pow, rpow_int_cast, hm, zpow_ofNat] @@ -63,58 +88,15 @@ theorem exists_summable_bound_exp_mul_sq {R : ℝ} (hR : 0 < R) : summable_geometric_of_lt_1 (Real.exp_pos _).le h #align exists_summable_bound_exp_mul_sq exists_summable_bound_exp_mul_sq -theorem summable_exp_mul_sq {z : ℂ} (hz : 0 < z.im) : - Summable fun n : ℤ => cexp (π * I * (n : ℂ) ^ 2 * z) := - let ⟨_, h, h'⟩ := exists_summable_bound_exp_mul_sq hz +theorem summable_exp_mul_sq {τ : ℂ} (hτ : 0 < τ.im) : + Summable fun n : ℤ => cexp (π * I * (n : ℂ) ^ 2 * τ) := + let ⟨_, h, h'⟩ := exists_summable_bound_exp_mul_sq hτ .of_norm_bounded _ h (h' <| le_refl _) #align summable_exp_mul_sq summable_exp_mul_sq -theorem jacobiTheta_two_add (z : ℂ) : jacobiTheta (2 + z) = jacobiTheta z := by - refine' tsum_congr fun n => _ - suffices cexp (π * I * n ^ 2 * 2 : ℂ) = 1 by rw [mul_add, Complex.exp_add, this, one_mul] - rw [(by push_cast; ring : (π * I * n ^ 2 * 2 : ℂ) = (n ^ 2 :) * (2 * π * I)), Complex.exp_int_mul, - Complex.exp_two_pi_mul_I, one_zpow] -#align jacobi_theta_two_add jacobiTheta_two_add - -theorem jacobiTheta_T_sq_smul (τ : ℍ) : jacobiTheta (ModularGroup.T ^ 2 • τ :) = jacobiTheta τ := by - suffices (ModularGroup.T ^ 2 • τ :) = (2 : ℂ) + ↑τ by simp_rw [this, jacobiTheta_two_add] - have : ModularGroup.T ^ (2 : ℕ) = ModularGroup.T ^ (2 : ℤ) := rfl - simp_rw [this, UpperHalfPlane.modular_T_zpow_smul, UpperHalfPlane.coe_vadd] - norm_cast -set_option linter.uppercaseLean3 false in -#align jacobi_theta_T_sq_smul jacobiTheta_T_sq_smul - -theorem jacobiTheta_S_smul (τ : ℍ) : - jacobiTheta ↑(ModularGroup.S • τ) = (-I * τ) ^ (1 / 2 : ℂ) * jacobiTheta τ := by - unfold jacobiTheta - rw [UpperHalfPlane.modular_S_smul, UpperHalfPlane.coe_mk] - have ha : 0 < (-I * τ).re := by - rw [neg_mul, neg_re, mul_re, I_re, I_im, zero_mul, one_mul, zero_sub, neg_neg] - exact τ.im_pos - have ha' : (-I * τ) ^ (1 / 2 : ℂ) ≠ 0 := by - rw [Ne.def, cpow_eq_zero_iff] - contrapose! ha - rw [ha.1, zero_re] - have hτ : (τ : ℂ) ≠ 0 := τ.ne_zero - have := Complex.tsum_exp_neg_mul_int_sq ha - rw [mul_comm ((1 : ℂ) / _) _, mul_one_div, eq_div_iff ha', mul_comm _ (_ ^ _), eq_comm] at this - have expo1 : ∀ n : ℤ, -↑π / (-I * ↑τ) * (n : ℂ) ^ 2 = ↑π * I * (n : ℂ) ^ 2 * (-↑τ)⁻¹ := by - intro n - field_simp [hτ, I_ne_zero] - ring_nf - rw [I_sq, mul_neg, mul_one, neg_neg] - simp_rw [expo1] at this - have expo2 : ∀ n : ℤ, -↑π * (-I * ↑τ) * (n : ℂ) ^ 2 = ↑π * I * (n : ℂ) ^ 2 * ↑τ := by - intro n - ring_nf - simp_rw [expo2] at this - exact this -set_option linter.uppercaseLean3 false in -#align jacobi_theta_S_smul jacobiTheta_S_smul - -theorem hasSum_nat_jacobiTheta {z : ℂ} (hz : 0 < im z) : - HasSum (fun n : ℕ => cexp (π * I * ((n : ℂ) + 1) ^ 2 * z)) ((jacobiTheta z - 1) / 2) := by - have := (summable_exp_mul_sq hz).hasSum.sum_nat_of_sum_int +theorem hasSum_nat_jacobiTheta {τ : ℂ} (hτ : 0 < im τ) : + HasSum (fun n : ℕ => cexp (π * I * ((n : ℂ) + 1) ^ 2 * τ)) ((jacobiTheta τ - 1) / 2) := by + have := (summable_exp_mul_sq hτ).hasSum.sum_nat_of_sum_int rw [← @hasSum_nat_add_iff' ℂ _ _ _ _ 1] at this simp_rw [Finset.sum_range_one, Int.cast_neg, Int.cast_ofNat, Nat.cast_zero, neg_zero, Int.cast_zero, sq (0 : ℂ), mul_zero, zero_mul, neg_sq, ← mul_two, @@ -124,32 +106,32 @@ theorem hasSum_nat_jacobiTheta {z : ℂ} (hz : 0 < im z) : simp_rw [mul_div_cancel (G₀ := ℂ) _ two_ne_zero] #align has_sum_nat_jacobi_theta hasSum_nat_jacobiTheta -theorem jacobiTheta_eq_tsum_nat {z : ℂ} (hz : 0 < im z) : - jacobiTheta z = ↑1 + ↑2 * ∑' n : ℕ, cexp (π * I * ((n : ℂ) + 1) ^ 2 * z) := by - rw [(hasSum_nat_jacobiTheta hz).tsum_eq, mul_div_cancel' _ (two_ne_zero' ℂ), ← add_sub_assoc, +theorem jacobiTheta_eq_tsum_nat {τ : ℂ} (hτ : 0 < im τ) : + jacobiTheta τ = ↑1 + ↑2 * ∑' n : ℕ, cexp (π * I * ((n : ℂ) + 1) ^ 2 * τ) := by + rw [(hasSum_nat_jacobiTheta hτ).tsum_eq, mul_div_cancel' _ (two_ne_zero' ℂ), ← add_sub_assoc, add_sub_cancel'] #align jacobi_theta_eq_tsum_nat jacobiTheta_eq_tsum_nat /-- An explicit upper bound for `‖jacobiTheta τ - 1‖`. -/ -theorem norm_jacobiTheta_sub_one_le {z : ℂ} (hz : 0 < im z) : - ‖jacobiTheta z - 1‖ ≤ 2 / (1 - rexp (-π * z.im)) * rexp (-π * z.im) := by - suffices ‖∑' n : ℕ, cexp (π * I * ((n : ℂ) + 1) ^ 2 * z)‖ ≤ - rexp (-π * z.im) / (1 - rexp (-π * z.im)) by +theorem norm_jacobiTheta_sub_one_le {τ : ℂ} (hτ : 0 < im τ) : + ‖jacobiTheta τ - 1‖ ≤ 2 / (1 - rexp (-π * τ.im)) * rexp (-π * τ.im) := by + suffices ‖∑' n : ℕ, cexp (π * I * ((n : ℂ) + 1) ^ 2 * τ)‖ ≤ + rexp (-π * τ.im) / (1 - rexp (-π * τ.im)) by calc - ‖jacobiTheta z - 1‖ = ↑2 * ‖∑' n : ℕ, cexp (π * I * ((n : ℂ) + 1) ^ 2 * z)‖ := by - rw [sub_eq_iff_eq_add'.mpr (jacobiTheta_eq_tsum_nat hz), norm_mul, Complex.norm_eq_abs, + ‖jacobiTheta τ - 1‖ = ↑2 * ‖∑' n : ℕ, cexp (π * I * ((n : ℂ) + 1) ^ 2 * τ)‖ := by + rw [sub_eq_iff_eq_add'.mpr (jacobiTheta_eq_tsum_nat hτ), norm_mul, Complex.norm_eq_abs, Complex.abs_two] - _ ≤ 2 * (rexp (-π * z.im) / (1 - rexp (-π * z.im))) := by gcongr - _ = 2 / (1 - rexp (-π * z.im)) * rexp (-π * z.im) := by rw [div_mul_comm, mul_comm] - have : ∀ n : ℕ, ‖cexp (π * I * ((n : ℂ) + 1) ^ 2 * z)‖ ≤ rexp (-π * z.im) ^ (n + 1) := by + _ ≤ 2 * (rexp (-π * τ.im) / (1 - rexp (-π * τ.im))) := by gcongr + _ = 2 / (1 - rexp (-π * τ.im)) * rexp (-π * τ.im) := by rw [div_mul_comm, mul_comm] + have : ∀ n : ℕ, ‖cexp (π * I * ((n : ℂ) + 1) ^ 2 * τ)‖ ≤ rexp (-π * τ.im) ^ (n + 1) := by intro n - simpa only [Int.cast_add, Int.cast_one] using norm_exp_mul_sq_le hz (n + 1) + simpa only [Int.cast_add, Int.cast_one] using norm_exp_mul_sq_le hτ (n + 1) have s : HasSum (fun n : ℕ => - rexp (-π * z.im) ^ (n + 1)) (rexp (-π * z.im) / (1 - rexp (-π * z.im))) := by + rexp (-π * τ.im) ^ (n + 1)) (rexp (-π * τ.im) / (1 - rexp (-π * τ.im))) := by simp_rw [pow_succ, div_eq_mul_inv, hasSum_mul_left_iff (Real.exp_ne_zero _)] - exact hasSum_geometric_of_lt_1 (exp_pos (-π * z.im)).le - (exp_lt_one_iff.mpr <| mul_neg_of_neg_of_pos (neg_lt_zero.mpr pi_pos) hz) - have aux : Summable fun n : ℕ => ‖cexp (π * I * ((n : ℂ) + 1) ^ 2 * z)‖ := + exact hasSum_geometric_of_lt_1 (exp_pos (-π * τ.im)).le + (exp_lt_one_iff.mpr <| mul_neg_of_neg_of_pos (neg_lt_zero.mpr pi_pos) hτ) + have aux : Summable fun n : ℕ => ‖cexp (π * I * ((n : ℂ) + 1) ^ 2 * τ)‖ := .of_nonneg_of_le (fun n => norm_nonneg _) this s.summable exact (norm_tsum_le_tsum_norm aux).trans ((tsum_mono aux s.summable this).trans_eq s.tsum_eq) #align norm_jacobi_theta_sub_one_le norm_jacobiTheta_sub_one_le @@ -158,34 +140,24 @@ theorem norm_jacobiTheta_sub_one_le {z : ℂ} (hz : 0 < im z) : theorem isBigO_at_im_infty_jacobiTheta_sub_one : (fun τ => jacobiTheta τ - 1) =O[comap im atTop] fun τ => rexp (-π * τ.im) := by simp_rw [IsBigO, IsBigOWith, Filter.eventually_comap, Filter.eventually_atTop] - refine' ⟨2 / (1 - rexp (-π)), 1, fun y hy z hz => - (norm_jacobiTheta_sub_one_le (hz.symm ▸ zero_lt_one.trans_le hy : 0 < im z)).trans _⟩ + refine' ⟨2 / (1 - rexp (-π)), 1, fun y hy τ hτ => + (norm_jacobiTheta_sub_one_le (hτ.symm ▸ zero_lt_one.trans_le hy : 0 < im τ)).trans _⟩ rw [Real.norm_eq_abs, Real.abs_exp] refine' mul_le_mul_of_nonneg_right _ (exp_pos _).le rw [div_le_div_left (zero_lt_two' ℝ), sub_le_sub_iff_left, exp_le_exp, neg_mul, neg_le_neg_iff] - · exact le_mul_of_one_le_right pi_pos.le (hz.symm ▸ hy) + · exact le_mul_of_one_le_right pi_pos.le (hτ.symm ▸ hy) · rw [sub_pos, exp_lt_one_iff, neg_mul, neg_lt_zero] - exact mul_pos pi_pos (hz.symm ▸ zero_lt_one.trans_le hy) + exact mul_pos pi_pos (hτ.symm ▸ zero_lt_one.trans_le hy) · rw [sub_pos, exp_lt_one_iff, neg_lt_zero]; exact pi_pos set_option linter.uppercaseLean3 false in #align is_O_at_im_infty_jacobi_theta_sub_one isBigO_at_im_infty_jacobiTheta_sub_one -theorem differentiableAt_jacobiTheta {z : ℂ} (hz : 0 < im z) : - DifferentiableAt ℂ jacobiTheta z := by - suffices ∀ (y : ℝ) (_ : 0 < y), - DifferentiableOn ℂ (fun z => ∑' n : ℤ, cexp (π * I * (n : ℂ) ^ 2 * z)) {w : ℂ | y < im w} by - let ⟨y, hy, hy'⟩ := exists_between hz - exact (this y hy).differentiableAt - ((Complex.continuous_im.isOpen_preimage _ isOpen_Ioi).mem_nhds hy') - intro y hy - have h1 : ∀ (n : ℤ) (w : ℂ) (_ : y < im w), - DifferentiableWithinAt ℂ (fun v : ℂ => cexp (π * I * (n : ℂ) ^ 2 * v)) {z : ℂ | y < im z} w := - fun n w _ => (differentiableAt_id.const_mul _).cexp.differentiableWithinAt - have h2 : IsOpen {w : ℂ | y < im w} := continuous_im.isOpen_preimage _ isOpen_Ioi - obtain ⟨bd, bd_s, le_bd⟩ := exists_summable_bound_exp_mul_sq hy - exact differentiableOn_tsum_of_summable_norm bd_s h1 h2 fun i w hw => le_bd (le_of_lt hw) i +theorem differentiableAt_jacobiTheta {τ : ℂ} (hτ : 0 < im τ) : + DifferentiableAt ℂ jacobiTheta τ := by + simp_rw [funext jacobiTheta_eq_jacobiTheta₂] + exact differentiableAt_jacobiTheta₂ 0 hτ #align differentiable_at_jacobi_theta differentiableAt_jacobiTheta -theorem continuousAt_jacobiTheta {z : ℂ} (hz : 0 < im z) : ContinuousAt jacobiTheta z := - (differentiableAt_jacobiTheta hz).continuousAt +theorem continuousAt_jacobiTheta {τ : ℂ} (hτ : 0 < im τ) : ContinuousAt jacobiTheta τ := + (differentiableAt_jacobiTheta hτ).continuousAt #align continuous_at_jacobi_theta continuousAt_jacobiTheta diff --git a/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean b/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean new file mode 100644 index 0000000000000..70ceb63efc1bb --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean @@ -0,0 +1,132 @@ +/- +Copyright (c) 2023 David Loeffler. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: David Loeffler +-/ +import Mathlib.Analysis.SpecialFunctions.Gaussian +import Mathlib.Analysis.Complex.LocallyUniformLimit + +/-! +# The two-variable Jacobi theta function + +This file defines the two-variable Jacobi theta function + +$$\theta(z, \tau) = \sum_{n \in \mathbb{Z}} \exp (2 i \pi n z + i \pi n ^ 2 \tau),$$ + +and proves the functional equation relating the values at `(z, τ)` and `(z / τ, -1 / τ)`, +using Poisson's summation formula. We also show holomorphy (in both variables individually, +not jointly). +-/ + +open Complex Real Asymptotics Filter Topology + +open scoped Real BigOperators + +/-- The two-variable Jacobi theta function, +`θ z τ = ∑' (n : ℤ), cexp (2 * π * I * n * z + π * I * n ^ 2 * τ)`. + +The sum is only convergent for `0 < im τ`; we are implictly extending it by 0 for other values of +`τ`. -/ +noncomputable def jacobiTheta₂ (z τ : ℂ) : ℂ := + ∑' n : ℤ, cexp (2 * π * I * n * z + π * I * n ^ 2 * τ) + +/-- A uniform bound for the summands in the Jacobi theta function on compact subsets. -/ +lemma jacobiTheta₂_term_bound {S T : ℝ} (hT : 0 < T) {z τ : ℂ} + (hz : |im z| ≤ S) (hτ : T ≤ im τ) (n : ℤ) : + ‖cexp (2 * π * I * n * z + π * I * n ^ 2 * τ)‖ ≤ Real.exp (-π * (T * n ^ 2 - 2 * S * |n|)) := by + rw [Complex.norm_eq_abs, Complex.abs_exp, (by push_cast; ring : + 2 * π * I * n * z + π * I * n ^ 2 * τ = (π * (2 * n) :) * z * I + (π * n ^ 2 :) * τ * I), + add_re, mul_I_re, im_ofReal_mul, mul_I_re, im_ofReal_mul, Real.exp_le_exp, neg_mul, ← neg_add, + neg_le_neg_iff, mul_assoc π, mul_assoc π, ← mul_add, mul_le_mul_left pi_pos, add_comm, + mul_comm T] + refine add_le_add (mul_le_mul le_rfl hτ hT.le (sq_nonneg _)) ?_ + rw [← mul_neg, mul_assoc, mul_assoc, mul_le_mul_left two_pos, mul_comm, neg_mul, ← mul_neg] + refine le_trans ?_ (neg_abs_le _) + rw [mul_neg, neg_le_neg_iff, abs_mul, Int.cast_abs] + exact mul_le_mul_of_nonneg_left hz (abs_nonneg _) + +lemma summable_jacobiTheta₂_term_bound (S : ℝ) {T : ℝ} (hT : 0 < T) : + Summable (fun n : ℤ ↦ Real.exp (-π * (T * n ^ 2 - 2 * S * |n|))) := by + suffices : Summable (fun n : ℕ ↦ Real.exp (-π * (T * n ^ 2 - 2 * S * n))) + · apply summable_int_of_summable_nat <;> + simpa only [Int.cast_neg, neg_sq, abs_neg, Int.cast_ofNat, Nat.abs_cast] + apply summable_of_isBigO_nat summable_exp_neg_nat + refine Real.isBigO_exp_comp_exp_comp.mpr (Tendsto.isBoundedUnder_le_atBot ?_) + rw [← tendsto_neg_atTop_iff] + simp only [neg_mul, Pi.sub_apply, sub_neg_eq_add, neg_add_rev, neg_neg] + suffices : Tendsto (fun n ↦ n * (π * T * n - (2 * π * S + 1)) : ℕ → ℝ) atTop atTop + · convert this using 2 with n; ring + refine tendsto_nat_cast_atTop_atTop.atTop_mul_atTop (tendsto_atTop_add_const_right _ _ ?_) + exact tendsto_nat_cast_atTop_atTop.const_mul_atTop (mul_pos pi_pos hT) + +/-- Differentiability of `Θ z τ` in `τ`, for fixed `z`. (This is weaker than differentiability +in both variables simultaneously, but we do not have a version of +`differentiableOn_tsum_of_summable_norm` in multiple variables yet.) -/ +lemma differentiableAt_jacobiTheta₂ (z : ℂ) {τ : ℂ} (hτ : 0 < im τ) : + DifferentiableAt ℂ (jacobiTheta₂ z) τ := by + obtain ⟨T, hT⟩ := exists_between hτ + let V := {b | T < im b} + have : V ∈ 𝓝 τ := continuous_im.continuousAt.preimage_mem_nhds (Ioi_mem_nhds hT.2) + refine DifferentiableOn.differentiableAt ?_ this + apply differentiableOn_tsum_of_summable_norm + · exact summable_jacobiTheta₂_term_bound |im z| hT.1 + · refine fun i ↦ (Complex.differentiable_exp.comp ?_).differentiableOn + exact (differentiable_const _).add ((differentiable_const _).mul differentiable_id) + · exact continuous_im.isOpen_preimage _ isOpen_Ioi + · exact fun i ξ (hξ : T < im ξ) ↦ jacobiTheta₂_term_bound hT.1 (le_refl _) hξ.le i + +/-- The two-variable Jacobi theta function is periodic in `τ` with period 2. -/ +lemma jacobiTheta₂_add_right (z τ : ℂ) : jacobiTheta₂ z (τ + 2) = jacobiTheta₂ z τ := by + refine tsum_congr (fun n ↦ ?_) + simp_rw [Complex.exp_add] + suffices cexp (π * I * n ^ 2 * 2 : ℂ) = 1 by rw [mul_add, Complex.exp_add, this, mul_one] + rw [(by push_cast; ring : (π * I * n ^ 2 * 2 : ℂ) = (n ^ 2 :) * (2 * π * I)), exp_int_mul, + exp_two_pi_mul_I, one_zpow] + +/-- The two-variable Jacobi theta function is periodic in `z` with period 1. -/ +lemma jacobiTheta₂_add_left (z τ : ℂ) : jacobiTheta₂ (z + 1) τ = jacobiTheta₂ z τ := by + refine tsum_congr (fun n ↦ ?_) + simp_rw [mul_add, mul_one, Complex.exp_add] + suffices cexp (2 * ↑π * I * n) = 1 by rw [this, mul_one] + simpa only [mul_comm] using exp_int_mul_two_pi_mul_I n + +/-- The two-variable Jacobi theta function is quasi-periodic in `z` with period `τ`. -/ +lemma jacobiTheta₂_add_left' (z τ : ℂ) : + jacobiTheta₂ (z + τ) τ = cexp (-π * I * (τ + 2 * z)) * jacobiTheta₂ z τ := by + conv_rhs => erw [← tsum_mul_left, ← (Equiv.addRight (1 : ℤ)).tsum_eq] + refine tsum_congr (fun n ↦ ?_) + rw [← Complex.exp_add, Equiv.coe_addRight, Int.cast_add] + ring_nf + +/-- The two-variable Jacobi theta function is even in `z`. -/ +lemma jacobiTheta₂_neg_left (z τ : ℂ) : jacobiTheta₂ (-z) τ = jacobiTheta₂ z τ := by + conv_lhs => rw [jacobiTheta₂, ← Equiv.tsum_eq (Equiv.neg ℤ)] + refine tsum_congr (fun n ↦ ?_) + rw [Equiv.neg_apply, Int.cast_neg, neg_sq] + ring_nf + +/-- The functional equation for the Jacobi theta function: `jacobiTheta₂ x τ` is an explict factor +times `jacobiTheta₂ (x / τ) (-1 / τ)`. This is the key lemma behind the proof of the functional +equation for Dirichlet L-series. -/ +theorem jacobiTheta₂_functional_equation (z : ℂ) {τ : ℂ} (hτ : 0 < im τ) : + jacobiTheta₂ z τ = + 1 / (-I * τ) ^ (1 / 2 : ℂ) * cexp (-π * I * z ^ 2 / τ) * jacobiTheta₂ (z / τ) (-1 / τ) := by + have h0 : τ ≠ 0; contrapose! hτ; rw [hτ, zero_im] + have h2 : 0 < (-I * τ).re + · simpa only [neg_mul, neg_re, mul_re, I_re, zero_mul, I_im, one_mul, zero_sub, neg_neg] using hτ + calc + _ = ∑' n : ℤ, cexp (-π * (-I * τ) * ↑n ^ 2 + 2 * π * (I * z) * ↑n) := + tsum_congr (fun n ↦ by ring_nf) + _ = 1 / (-I * τ) ^ (1 / 2 : ℂ) * ∑' (n : ℤ), cexp (-π / (-I * τ) * (n + I * (I * z)) ^ 2) := by + rw [tsum_exp_neg_quadratic h2] + _ = 1 / (-I * τ) ^ (1 / 2 : ℂ) * cexp (π * I * (-1 / τ) * z ^ 2) * + ∑' (n : ℤ), cexp (2 * π * I * n * (z / τ) + π * I * n ^ 2 * (-1 / τ)) := by + simp_rw [mul_assoc _ (cexp _), ← tsum_mul_left (a := cexp _), ← Complex.exp_add] + congr 2 with n : 1; congr 1 + field_simp [I_ne_zero] + ring_nf + simp_rw [I_sq, I_pow_four] + ring_nf + _ = _ := by + congr 3 + ring diff --git a/Mathlib/NumberTheory/ModularForms/SlashInvariantForms.lean b/Mathlib/NumberTheory/ModularForms/SlashInvariantForms.lean index f81e304b46da1..9562b71b19697 100644 --- a/Mathlib/NumberTheory/ModularForms/SlashInvariantForms.lean +++ b/Mathlib/NumberTheory/ModularForms/SlashInvariantForms.lean @@ -46,7 +46,7 @@ structure SlashInvariantForm where /-- `SlashInvariantFormClass F Γ k` asserts `F` is a type of bundled functions that are invariant under the `SlashAction`. -/ -class SlashInvariantFormClass extends FunLike F ℍ fun _ => ℂ where +class SlashInvariantFormClass extends DFunLike F ℍ fun _ => ℂ where slash_action_eq : ∀ (f : F) (γ : Γ), (f : ℍ → ℂ) ∣[k] γ = f #align slash_invariant_form_class SlashInvariantFormClass @@ -60,7 +60,7 @@ instance (priority := 100) SlashInvariantFormClass.slashInvariantForm : variable {F Γ k} instance : CoeFun (SlashInvariantForm Γ k) fun _ => ℍ → ℂ := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[simp] theorem SlashInvariantForm.toFun_eq_coe {f : SlashInvariantForm Γ k} : f.toFun = (f : ℍ → ℂ) := @@ -72,7 +72,7 @@ theorem SlashInvariantForm.coe_mk (f : ℍ → ℂ) (hf : ∀ γ : Γ, f ∣[k] @[ext] theorem SlashInvariantForm.ext {f g : SlashInvariantForm Γ k} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align slash_invariant_form_ext SlashInvariantForm.ext /-- Copy of a `SlashInvariantForm` with a new `toFun` equal to the old one. @@ -192,7 +192,7 @@ theorem sub_apply (f g : SlashInvariantForm Γ k) (z : ℍ) : (f - g) z = f z - #align slash_invariant_form.sub_apply SlashInvariantForm.sub_apply instance : AddCommGroup (SlashInvariantForm Γ k) := - FunLike.coe_injective.addCommGroup _ rfl coe_add coe_neg coe_sub coe_smul coe_smul + DFunLike.coe_injective.addCommGroup _ rfl coe_add coe_neg coe_sub coe_smul coe_smul /-- Additive coercion from `SlashInvariantForm` to `ℍ → ℂ`.-/ def coeHom : SlashInvariantForm Γ k →+ ℍ → ℂ where @@ -202,7 +202,7 @@ def coeHom : SlashInvariantForm Γ k →+ ℍ → ℂ where #align slash_invariant_form.coe_hom SlashInvariantForm.coeHom theorem coeHom_injective : Function.Injective (@coeHom Γ k) := - FunLike.coe_injective + DFunLike.coe_injective #align slash_invariant_form.coe_hom_injective SlashInvariantForm.coeHom_injective instance : Module ℂ (SlashInvariantForm Γ k) := diff --git a/Mathlib/NumberTheory/Multiplicity.lean b/Mathlib/NumberTheory/Multiplicity.lean index 97ce4daa73e39..1dee8ef49017d 100644 --- a/Mathlib/NumberTheory/Multiplicity.lean +++ b/Mathlib/NumberTheory/Multiplicity.lean @@ -5,10 +5,9 @@ Authors: Tian Chen, Mantas Bakšys -/ import Mathlib.Algebra.GeomSum import Mathlib.Data.Int.Parity -import Mathlib.Data.ZMod.Basic import Mathlib.NumberTheory.Padics.PadicVal -import Mathlib.RingTheory.Ideal.QuotientOperations -import Mathlib.Init.Meta.WellFoundedTactics +import Mathlib.Algebra.GroupPower.Order +import Mathlib.RingTheory.Ideal.Quotient #align_import number_theory.multiplicity from "leanprover-community/mathlib"@"e8638a0fcaf73e4500469f368ef9494e495099b3" diff --git a/Mathlib/NumberTheory/NumberField/Basic.lean b/Mathlib/NumberTheory/NumberField/Basic.lean index fc9a2847b6041..94b395bdda7c8 100644 --- a/Mathlib/NumberTheory/NumberField/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Ashvni Narayanan. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Ashvni Narayanan, Anne Baanen -/ -import Mathlib.Algebra.CharP.Algebra +import Mathlib.Data.Int.Parity import Mathlib.RingTheory.DedekindDomain.IntegralClosure #align_import number_theory.number_field.basic from "leanprover-community/mathlib"@"f0c8bf9245297a541f468be517f1bde6195105e9" @@ -60,6 +60,9 @@ protected theorem isAlgebraic : Algebra.IsAlgebraic ℚ K := Algebra.IsAlgebraic.of_finite _ _ #align number_field.is_algebraic NumberField.isAlgebraic +instance [NumberField L] [Algebra K L] : FiniteDimensional K L := + Module.Finite.of_restrictScalars_finite ℚ K L + /-- The ring of integers (or number ring) corresponding to a number field is the integral closure of ℤ in the number field. -/ def ringOfIntegers := diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding.lean index 62d0862730210..d6a73b652fb79 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding.lean @@ -8,6 +8,7 @@ import Mathlib.MeasureTheory.Group.GeometryOfNumbers import Mathlib.MeasureTheory.Measure.Lebesgue.VolumeOfBalls import Mathlib.NumberTheory.NumberField.Embeddings import Mathlib.RingTheory.Discriminant +import Mathlib.Topology.Bornology.Constructions #align_import number_theory.number_field.canonical_embedding from "leanprover-community/mathlib"@"60da01b41bbe4206f05d34fd70c8dd7498717a30" @@ -576,8 +577,8 @@ theorem convexBodySumFun_eq_zero_iff (x : E K) : Finset.sum_eq_zero_iff_of_nonneg (fun _ _ => norm_nonneg _)] at h ext : 2 · exact norm_eq_zero.mp (h.1 _ (Finset.mem_univ _)) - · exact norm_eq_zero.mp ((smul_eq_zero_iff_eq' two_ne_zero (α := ℝ)).mp - (h.2 _ (Finset.mem_univ _))) + · exact norm_eq_zero.1 <| eq_zero_of_ne_zero_of_mul_left_eq_zero two_ne_zero <| h.2 _ <| + Finset.mem_univ _ · simp only [convexBodySumFun, h, Prod.fst_zero, Pi.zero_apply, norm_zero, Finset.sum_const_zero, Prod.snd_zero, mul_zero, add_zero] @@ -799,7 +800,7 @@ theorem exists_ne_zero_mem_ringOfIntegers_of_norm_le {B : ℝ} · rw [ne_eq, AddSubgroup.mk_eq_zero_iff, map_eq_zero, ← ne_eq] at h_nzr exact Subtype.ne_of_val_ne h_nzr · rw [← rpow_nat_cast, ← rpow_le_rpow_iff (by simp only [Rat.cast_abs, abs_nonneg]) - (rpow_nonneg_of_nonneg h2 _) h1, ← rpow_mul h2, mul_inv_cancel (Nat.cast_ne_zero.mpr + (rpow_nonneg h2 _) h1, ← rpow_mul h2, mul_inv_cancel (Nat.cast_ne_zero.mpr (ne_of_gt finrank_pos)), rpow_one, le_div_iff' (Nat.cast_pos.mpr finrank_pos)] refine le_trans ?_ ((convexBodySum_mem K B).mp h_mem) rw [← le_div_iff' (Nat.cast_pos.mpr finrank_pos), ← sum_mult_eq, Nat.cast_sum] diff --git a/Mathlib/NumberTheory/NumberField/Discriminant.lean b/Mathlib/NumberTheory/NumberField/Discriminant.lean index f7ab06d0e7103..5a226f24ab7c8 100644 --- a/Mathlib/NumberTheory/NumberField/Discriminant.lean +++ b/Mathlib/NumberTheory/NumberField/Discriminant.lean @@ -106,7 +106,7 @@ theorem exists_ne_zero_mem_ringOfIntegers_of_norm_le_mul_sqrt_discr : (finrank ℚ K).factorial / (finrank ℚ K) ^ (finrank ℚ K) * Real.sqrt |discr K| := by -- The smallest possible value for `exists_ne_zero_mem_ringOfIntegers_of_norm_le` let B := (minkowskiBound K * (convexBodySumFactor K)⁻¹).toReal ^ (1 / (finrank ℚ K : ℝ)) - have hB : 0 ≤ B := Real.rpow_nonneg_of_nonneg toReal_nonneg _ + have hB : 0 ≤ B := Real.rpow_nonneg toReal_nonneg _ have h_le : (minkowskiBound K) ≤ volume (convexBodySum K B) := by refine le_of_eq ?_ rw [convexBodySum_volume, ← ENNReal.ofReal_pow hB, ← Real.rpow_nat_cast, ← Real.rpow_mul @@ -166,10 +166,9 @@ theorem abs_discr_ge (h : 1 < finrank ℚ K) : let a : ℕ → ℝ := fun n => (n:ℝ) ^ (n * 2) / ((4 / π) ^ n * (n.factorial:ℝ) ^ 2) suffices ∀ n, 2 ≤ n → (4 / 9 : ℝ) * (3 * π / 4) ^ n ≤ a n by refine le_trans (this (finrank ℚ K) h) ?_ - refine div_le_div_of_le_left (by positivity) (by positivity) ?_ - refine mul_le_mul_of_nonneg_right (pow_le_pow_right ?_ ?_) (by positivity) - · rw [_root_.le_div_iff Real.pi_pos, one_mul] - exact Real.pi_le_four + simp only -- unfold `a` and beta-reduce + gcongr + · exact (one_le_div Real.pi_pos).2 Real.pi_le_four · rw [← card_add_two_mul_card_eq_rank, mul_comm] exact Nat.le_add_left _ _ intro n hn diff --git a/Mathlib/NumberTheory/NumberField/Embeddings.lean b/Mathlib/NumberTheory/NumberField/Embeddings.lean index fa4ddb33c813f..d115d3d93473a 100644 --- a/Mathlib/NumberTheory/NumberField/Embeddings.lean +++ b/Mathlib/NumberTheory/NumberField/Embeddings.lean @@ -278,7 +278,7 @@ namespace NumberField.InfinitePlace open NumberField -instance {K : Type*} [Field K] : FunLike (InfinitePlace K) K (fun _ => ℝ) := +instance {K : Type*} [Field K] : FunLike (InfinitePlace K) K ℝ := { coe := fun w x => w.1 x coe_injective' := fun _ _ h => Subtype.eq (AbsoluteValue.ext fun x => congr_fun h x)} @@ -308,7 +308,7 @@ theorem mk_embedding (w : InfinitePlace K) : mk (embedding w) = w := Subtype.ext @[simp] theorem mk_conjugate_eq (φ : K →+* ℂ) : mk (ComplexEmbedding.conjugate φ) = mk φ := by - refine FunLike.ext _ _ (fun x => ?_) + refine DFunLike.ext _ _ (fun x => ?_) rw [apply, apply, ComplexEmbedding.conjugate_coe_eq, Complex.abs_conj] #align number_field.infinite_place.mk_conjugate_eq NumberField.InfinitePlace.mk_conjugate_eq @@ -571,6 +571,8 @@ def comap (w : InfinitePlace K) (f : k →+* K) : InfinitePlace k := @[simp] lemma comap_mk (φ : K →+* ℂ) (f : k →+* K) : (mk φ).comap f = mk (φ.comp f) := rfl +lemma comap_id (w : InfinitePlace K) : w.comap (RingHom.id K) = w := rfl + lemma comap_comp (w : InfinitePlace K) (f : F →+* K) (g : k →+* F) : w.comap (f.comp g) = (w.comap f).comap g := rfl @@ -589,7 +591,23 @@ lemma comap_surjective [Algebra k K] (h : Algebra.IsAlgebraic k K) : letI := w.embedding.toAlgebra ⟨mk (IsAlgClosed.lift (M := ℂ) h), by simp [comap_mk, RingHom.algebraMap_toAlgebra]⟩ -variable [Algebra k K] (σ : K ≃ₐ[k] K) (w : InfinitePlace K) +lemma mult_comap_le (f : k →+* K) (w : InfinitePlace K) : mult (w.comap f) ≤ mult w := by + rw [mult, mult] + split_ifs with h₁ h₂ h₂ + pick_goal 3; exact (h₁ (h₂.comap _)).elim + all_goals decide + +variable [Algebra k K] [Algebra k F] [Algebra K F] [IsScalarTower k K F] +variable (σ : K ≃ₐ[k] K) (w : InfinitePlace K) + +variable (k K) + +lemma card_mono [NumberField k] [NumberField K] : + card (InfinitePlace k) ≤ card (InfinitePlace K) := + have := Module.Finite.of_restrictScalars_finite ℚ k K + Fintype.card_le_of_surjective _ (comap_surjective (Algebra.IsAlgebraic.of_finite k K)) + +variable {k K} /-- The action of the galois group on infinite places. -/ @[simps! smul_coe_apply] @@ -669,7 +687,37 @@ An infinite place is unramified in a field extension if the restriction has the -/ def IsUnramified : Prop := mult (w.comap (algebraMap k K)) = mult w -variable {k w} +variable {k} + +lemma isUnramified_self : IsUnramified K w := rfl + +variable {w} + +lemma IsUnramified.eq (h : IsUnramified k w) : mult (w.comap (algebraMap k K)) = mult w := h + +lemma isUnramified_iff_mult_le : + IsUnramified k w ↔ mult w ≤ mult (w.comap (algebraMap k K)) := by + rw [IsUnramified, le_antisymm_iff, and_iff_right] + exact mult_comap_le _ _ + +lemma IsUnramified.comap_algHom {w : InfinitePlace F} (h : IsUnramified k w) (f : K →ₐ[k] F) : + IsUnramified k (w.comap (f : K →+* F)) := by + rw [InfinitePlace.isUnramified_iff_mult_le, ← InfinitePlace.comap_comp, f.comp_algebraMap, h.eq] + exact InfinitePlace.mult_comap_le _ _ + +variable (K) + +lemma IsUnramified.of_restrictScalars {w : InfinitePlace F} (h : IsUnramified k w) : + IsUnramified K w := by + rw [InfinitePlace.isUnramified_iff_mult_le, ← h.eq, IsScalarTower.algebraMap_eq k K F, + InfinitePlace.comap_comp] + exact InfinitePlace.mult_comap_le _ _ + +lemma IsUnramified.comap {w : InfinitePlace F} (h : IsUnramified k w) : + IsUnramified k (w.comap (algebraMap K F)) := + h.comap_algHom (IsScalarTower.toAlgHom k K F) + +variable {K} lemma not_isUnramified_iff : ¬ IsUnramified k w ↔ IsComplex w ∧ IsReal (w.comap (algebraMap k K)) := by @@ -885,4 +933,63 @@ lemma card_eq_card_isUnramifiedIn [NumberField k] [IsGalois k K] : end NumberField.InfinitePlace +variable (k K F) +variable [Algebra k K] [Algebra k F] [Algebra K F] [IsScalarTower k K F] + +/-- A field extension is unramified at infinite places if every infinite place is unramified. -/ +class IsUnramifiedAtInfinitePlaces : Prop where + isUnramified : ∀ w : InfinitePlace K, w.IsUnramified k + +instance IsUnramifiedAtInfinitePlaces.id : IsUnramifiedAtInfinitePlaces K K where + isUnramified w := w.isUnramified_self + +lemma IsUnramifiedAtInfinitePlaces.trans + [h₁ : IsUnramifiedAtInfinitePlaces k K] [h₂ : IsUnramifiedAtInfinitePlaces K F] : + IsUnramifiedAtInfinitePlaces k F where + isUnramified w := + Eq.trans (IsScalarTower.algebraMap_eq k K F ▸ h₁.1 (w.comap (algebraMap _ _))) (h₂.1 w) + +lemma IsUnramifiedAtInfinitePlaces.top [h : IsUnramifiedAtInfinitePlaces k F] : + IsUnramifiedAtInfinitePlaces K F where + isUnramified w := (h.1 w).of_restrictScalars K + +lemma IsUnramifiedAtInfinitePlaces.bot [h₁ : IsUnramifiedAtInfinitePlaces k F] + (h : Algebra.IsAlgebraic K F) : + IsUnramifiedAtInfinitePlaces k K where + isUnramified w := by + obtain ⟨w, rfl⟩ := InfinitePlace.comap_surjective h w + exact (h₁.1 w).comap K + +variable {K} + +lemma NumberField.InfinitePlace.isUnramified [IsUnramifiedAtInfinitePlaces k K] + (w : InfinitePlace K) : IsUnramified k w := IsUnramifiedAtInfinitePlaces.isUnramified w + +variable {k} (K) + +lemma NumberField.InfinitePlace.isUnramifiedIn [IsUnramifiedAtInfinitePlaces k K] + (w : InfinitePlace k) : IsUnramifiedIn K w := fun v _ ↦ v.isUnramified k + +variable {K} + +lemma IsUnramifiedAtInfinitePlaces_of_odd_card_aut [IsGalois k K] [FiniteDimensional k K] + (h : Odd (Fintype.card <| K ≃ₐ[k] K)) : IsUnramifiedAtInfinitePlaces k K := + ⟨fun _ ↦ not_not.mp (Nat.odd_iff_not_even.mp h ∘ InfinitePlace.even_card_aut_of_not_isUnramified)⟩ + +lemma IsUnramifiedAtInfinitePlaces_of_odd_finrank [IsGalois k K] + (h : Odd (FiniteDimensional.finrank k K)) : IsUnramifiedAtInfinitePlaces k K := + ⟨fun _ ↦ not_not.mp (Nat.odd_iff_not_even.mp h ∘ InfinitePlace.even_finrank_of_not_isUnramified)⟩ + +variable (k K) + +open FiniteDimensional in +lemma IsUnramifiedAtInfinitePlaces.card_infinitePlace [NumberField k] [NumberField K] + [IsGalois k K] [IsUnramifiedAtInfinitePlaces k K] : + Fintype.card (InfinitePlace K) = Fintype.card (InfinitePlace k) * finrank k K := by + rw [InfinitePlace.card_eq_card_isUnramifiedIn (k := k) (K := K), Finset.filter_true_of_mem, + Finset.card_univ, Finset.card_eq_zero.mpr, zero_mul, add_zero] + · exact Finset.compl_univ + simp only [Finset.mem_univ, forall_true_left, Finset.filter_eq_empty_iff] + exact InfinitePlace.isUnramifiedIn K + end InfinitePlace diff --git a/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean b/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean new file mode 100644 index 0000000000000..43aaed4959617 --- /dev/null +++ b/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean @@ -0,0 +1,115 @@ +/- +Copyright (c) 2024 Xavier Roblot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Xavier Roblot +-/ +import Mathlib.NumberTheory.NumberField.Basic +import Mathlib.RingTheory.FractionalIdeal.Norm +import Mathlib.RingTheory.FractionalIdeal.Operations + +/-! + +# Fractional ideals of number fields + +Prove some results on the fractional ideals of number fields. + +## Main definitions and results + + * `NumberField.basisOfFractionalIdeal`: A `ℚ`-basis of `K` that spans `I` over `ℤ` where `I` is + a fractional ideal of a number field `K`. + * `NumberField.det_basisOfFractionalIdeal_eq_absNorm`: for `I` a fractional ideal of a number + field `K`, the absolute value of the determinant of the base change from `integralBasis` to + `basisOfFractionalIdeal I` is equal to the norm of `I`. +-/ + +variable (K : Type*) [Field K] [NumberField K] + +namespace NumberField + +open scoped nonZeroDivisors + +section Basis + +open Module + +-- This is necessary to avoid several timeouts +attribute [local instance 2000] Submodule.module + +instance (I : FractionalIdeal (𝓞 K)⁰ K) : Module.Free ℤ I := by + refine Free.of_equiv (LinearEquiv.restrictScalars ℤ (I.equivNum ?_)).symm + exact nonZeroDivisors.coe_ne_zero I.den + +instance (I : FractionalIdeal (𝓞 K)⁰ K) : Module.Finite ℤ I := by + refine Module.Finite.of_surjective + (LinearEquiv.restrictScalars ℤ (I.equivNum ?_)).symm.toLinearMap (LinearEquiv.surjective _) + exact nonZeroDivisors.coe_ne_zero I.den + +instance (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) : + IsLocalizedModule ℤ⁰ ((Submodule.subtype (I : Submodule (𝓞 K) K)).restrictScalars ℤ) where + map_units x := by + rw [← (Algebra.lmul _ _).commutes, Algebra.lmul_isUnit_iff, isUnit_iff_ne_zero, eq_intCast, + Int.cast_ne_zero] + exact nonZeroDivisors.coe_ne_zero x + surj' x := by + obtain ⟨⟨a, _, d, hd, rfl⟩, h⟩ := IsLocalization.surj (Algebra.algebraMapSubmonoid (𝓞 K) ℤ⁰) x + refine ⟨⟨⟨Ideal.absNorm I.1.num * a, I.1.num_le ?_⟩, d * Ideal.absNorm I.1.num, ?_⟩ , ?_⟩ + · simp_rw [FractionalIdeal.val_eq_coe, FractionalIdeal.coe_coeIdeal] + refine (IsLocalization.mem_coeSubmodule _ _).mpr ⟨Ideal.absNorm I.1.num * a, ?_, ?_⟩ + · exact Ideal.mul_mem_right _ _ I.1.num.absNorm_mem + · rw [map_mul, map_natCast]; rfl + · refine Submonoid.mul_mem _ hd (mem_nonZeroDivisors_of_ne_zero ?_) + rw [Nat.cast_ne_zero, ne_eq, Ideal.absNorm_eq_zero_iff] + exact FractionalIdeal.num_eq_zero_iff.not.mpr <| Units.ne_zero I + · simp_rw [LinearMap.coe_restrictScalars, Submodule.coeSubtype] at h ⊢ + rw [show (a : K) = algebraMap (𝓞 K) K a by rfl, ← h] + simp only [Submonoid.mk_smul, zsmul_eq_mul, Int.cast_mul, Int.cast_ofNat, algebraMap_int_eq, + eq_intCast, map_intCast] + ring + exists_of_eq h := + ⟨1, by rwa [one_smul, one_smul, ← (Submodule.injective_subtype I.1.coeToSubmodule).eq_iff]⟩ + +/-- A `ℤ`-basis of a fractional ideal. -/ +noncomputable def fractionalIdealBasis (I : FractionalIdeal (𝓞 K)⁰ K) : + Basis (Free.ChooseBasisIndex ℤ I) ℤ I := Free.chooseBasis ℤ I + +/-- A `ℚ`-basis of `K` that spans `I` over `ℤ`, see `mem_span_basisOfFractionalIdeal` below. -/ +noncomputable def basisOfFractionalIdeal (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) : + Basis (Free.ChooseBasisIndex ℤ I) ℚ K := + (fractionalIdealBasis K I.1).ofIsLocalizedModule ℚ ℤ⁰ + ((Submodule.subtype (I : Submodule (𝓞 K) K)).restrictScalars ℤ) + +theorem basisOfFractionalIdeal_apply (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) + (i : Free.ChooseBasisIndex ℤ I) : + basisOfFractionalIdeal K I i = fractionalIdealBasis K I.1 i := + (fractionalIdealBasis K I.1).ofIsLocalizedModule_apply ℚ ℤ⁰ _ i + +theorem mem_span_basisOfFractionalIdeal {I : (FractionalIdeal (𝓞 K)⁰ K)ˣ} {x : K} : + x ∈ Submodule.span ℤ (Set.range (basisOfFractionalIdeal K I)) ↔ x ∈ (I : Set K) := by + rw [basisOfFractionalIdeal, (fractionalIdealBasis K I.1).ofIsLocalizedModule_span ℚ ℤ⁰ _] + simp + +open FiniteDimensional in +theorem fractionalIdeal_rank (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) : + finrank ℤ I = finrank ℤ (𝓞 K) := by + rw [finrank_eq_card_chooseBasisIndex, RingOfIntegers.rank, + finrank_eq_card_basis (basisOfFractionalIdeal K I)] + +end Basis + +section Norm + +open Module + +/-- The absolute value of the determinant of the base change from `integralBasis` to +`basisOfFractionalIdeal I` is equal to the norm of `I`. -/ +theorem det_basisOfFractionalIdeal_eq_absNorm (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) + (e : (Free.ChooseBasisIndex ℤ (𝓞 K)) ≃ (Free.ChooseBasisIndex ℤ I)) : + |(integralBasis K).det ((basisOfFractionalIdeal K I).reindex e.symm)| = + FractionalIdeal.absNorm I.1 := by + rw [← FractionalIdeal.abs_det_basis_change (RingOfIntegers.basis K) I.1 + ((fractionalIdealBasis K I.1).reindex e.symm)] + congr + ext + simpa using basisOfFractionalIdeal_apply K I _ + +end Norm diff --git a/Mathlib/NumberTheory/NumberField/Norm.lean b/Mathlib/NumberTheory/NumberField/Norm.lean index c25e78ca793f3..bc123be3de395 100644 --- a/Mathlib/NumberTheory/NumberField/Norm.lean +++ b/Mathlib/NumberTheory/NumberField/Norm.lean @@ -101,6 +101,7 @@ theorem norm_norm [IsSeparable K L] [Algebra F L] [IsSeparable F L] [FiniteDimen variable {F} +set_option synthInstance.maxHeartbeats 60000 in theorem isUnit_norm [CharZero K] {x : 𝓞 F} : IsUnit (norm K x) ↔ IsUnit x := by letI : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K let L := normalClosure K F (AlgebraicClosure F) diff --git a/Mathlib/NumberTheory/NumberField/Units.lean b/Mathlib/NumberTheory/NumberField/Units.lean index e60329ec1eeb2..b994e81135f49 100644 --- a/Mathlib/NumberTheory/NumberField/Units.lean +++ b/Mathlib/NumberTheory/NumberField/Units.lean @@ -34,7 +34,7 @@ as an additive `ℤ`-module. places `w` of `K`. * `NumberField.Units.exist_unique_eq_mul_prod`: **Dirichlet Unit Theorem**. Any unit `x` of `𝓞 K` -can be written uniquely as the product of a root of unity and powers of the units of of the +can be written uniquely as the product of a root of unity and powers of the units of the fundamental system `fundSystem`. ## Tags @@ -107,15 +107,14 @@ def torsion : Subgroup (𝓞 K)ˣ := CommGroup.torsion (𝓞 K)ˣ theorem mem_torsion {x : (𝓞 K)ˣ} [NumberField K] : x ∈ torsion K ↔ ∀ w : InfinitePlace K, w x = 1 := by - rw [eq_iff_eq (x : K) 1, torsion, CommGroup.mem_torsion, isOfFinOrder_iff_pow_eq_one] - refine ⟨fun ⟨n, h_pos, h_eq⟩ φ => ?_, fun h => ?_⟩ - · refine norm_map_one_of_pow_eq_one φ.toMonoidHom (k := ⟨n, h_pos⟩) ?_ - rw [PNat.mk_coe, ← coe_pow, h_eq, coe_one] - · obtain ⟨n, hn, hx⟩ := Embeddings.pow_eq_one_of_norm_eq_one K ℂ x.val.prop h - exact ⟨n, hn, by ext; rw [coe_pow, hx, coe_one]⟩ + rw [eq_iff_eq (x : K) 1, torsion, CommGroup.mem_torsion] + refine ⟨fun hx φ ↦ (((φ.comp $ algebraMap (𝓞 K) K).toMonoidHom.comp $ + Units.coeHom _).isOfFinOrder hx).norm_eq_one, fun h ↦ isOfFinOrder_iff_pow_eq_one.2 ?_⟩ + obtain ⟨n, hn, hx⟩ := Embeddings.pow_eq_one_of_norm_eq_one K ℂ x.val.prop h + exact ⟨n, hn, by ext; rw [coe_pow, hx, coe_one]⟩ /-- Shortcut instance because Lean tends to time out before finding the general instance. -/ -instance : Nonempty (torsion K) := One.nonempty +instance : Nonempty (torsion K) := One.instNonempty /-- The torsion subgroup is finite. -/ instance [NumberField K] : Fintype (torsion K) := by @@ -493,7 +492,6 @@ theorem unitLattice_rank : rw [← Units.finrank_eq_rank] exact Zlattice.rank ℝ (unitLattice_span_eq_top K) -set_option synthInstance.maxHeartbeats 27000 in /-- The linear equivalence between `unitLattice` and `(𝓞 K)ˣ ⧸ (torsion K)` as an additive `ℤ`-module. -/ def unitLatticeEquiv : (unitLattice K) ≃ₗ[ℤ] Additive ((𝓞 K)ˣ ⧸ (torsion K)) := by diff --git a/Mathlib/NumberTheory/Padics/Harmonic.lean b/Mathlib/NumberTheory/Padics/Harmonic.lean index 43b0b5308621f..cd0572ddc1cff 100644 --- a/Mathlib/NumberTheory/Padics/Harmonic.lean +++ b/Mathlib/NumberTheory/Padics/Harmonic.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Koundinya Vajjha, Thomas Browning -/ -import Mathlib.NumberTheory.Padics.PadicIntegers -import Mathlib.Data.Int.Log +import Mathlib.Algebra.CharP.Basic +import Mathlib.NumberTheory.Padics.PadicNumbers /-! diff --git a/Mathlib/NumberTheory/Padics/Hensel.lean b/Mathlib/NumberTheory/Padics/Hensel.lean index 669022ec9bed8..04945f8510007 100644 --- a/Mathlib/NumberTheory/Padics/Hensel.lean +++ b/Mathlib/NumberTheory/Padics/Hensel.lean @@ -351,15 +351,8 @@ private theorem bound' : Tendsto (fun n : ℕ => ‖F.derivative.eval a‖ * T ^ (Nat.tendsto_pow_atTop_atTop_of_one_lt (by norm_num))) private theorem bound : - ∀ {ε}, ε > 0 → ∃ N : ℕ, ∀ {n}, n ≥ N → ‖F.derivative.eval a‖ * T ^ 2 ^ n < ε := by - have := bound' hnorm - simp? [Tendsto, nhds] at this says - simp only [Tendsto, nhds_def, Set.mem_setOf_eq, le_iInf_iff, le_principal_iff, mem_map, - mem_atTop_sets, ge_iff_le, Set.mem_preimage, and_imp] at this - intro ε hε - cases' this (ball 0 ε) (mem_ball_self hε) isOpen_ball with N hN - exists N; intro n hn - simpa [abs_of_nonneg T_nonneg] using hN _ hn + ∀ {ε}, ε > 0 → ∃ N : ℕ, ∀ {n}, n ≥ N → ‖F.derivative.eval a‖ * T ^ 2 ^ n < ε := fun hε ↦ + eventually_atTop.1 <| (bound' hnorm).eventually <| gt_mem_nhds hε private theorem bound'_sq : Tendsto (fun n : ℕ => ‖F.derivative.eval a‖ ^ 2 * T ^ 2 ^ n) atTop (𝓝 0) := by @@ -370,15 +363,8 @@ private theorem bound'_sq : · apply bound' assumption -private theorem newton_seq_is_cauchy : IsCauSeq norm newton_seq := by - intro ε hε - cases' bound hnorm hε with N hN - exists N - intro j hj - apply lt_of_le_of_lt - · apply newton_seq_dist hnorm hj - · apply hN - exact le_rfl +private theorem newton_seq_is_cauchy : IsCauSeq norm newton_seq := fun _ε hε ↦ + (bound hnorm hε).imp fun _N hN _j hj ↦ (newton_seq_dist hnorm hj).trans_lt <| hN le_rfl private def newton_cau_seq : CauSeq ℤ_[p] norm := ⟨_, newton_seq_is_cauchy hnorm⟩ @@ -412,11 +398,7 @@ private theorem soln_dist_to_a : ‖soln - a‖ = ‖F.eval a‖ / ‖F.derivati tendsto_nhds_unique (newton_seq_dist_tendsto' hnorm) (newton_seq_dist_tendsto hnorm hnsol) private theorem soln_dist_to_a_lt_deriv : ‖soln - a‖ < ‖F.derivative.eval a‖ := by - rw [soln_dist_to_a, div_lt_iff] - · rwa [sq] at hnorm - · apply deriv_norm_pos - assumption - · exact hnsol + rw [soln_dist_to_a, div_lt_iff (deriv_norm_pos _), ← sq] <;> assumption private theorem eval_soln : F.eval soln = 0 := limit_zero_of_norm_tendsto_zero (newton_seq_norm_tendsto_zero hnorm) diff --git a/Mathlib/NumberTheory/PellMatiyasevic.lean b/Mathlib/NumberTheory/PellMatiyasevic.lean index bbb4b2542dba6..3149a8c9b3444 100644 --- a/Mathlib/NumberTheory/PellMatiyasevic.lean +++ b/Mathlib/NumberTheory/PellMatiyasevic.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Star.Unitary import Mathlib.Data.Nat.ModEq import Mathlib.NumberTheory.Zsqrtd.Basic import Mathlib.Tactic.Monotonicity +import Mathlib.Algebra.GroupPower.Order #align_import number_theory.pell_matiyasevic from "leanprover-community/mathlib"@"795b501869b9fa7aa716d5fdadd00c03f983a605" diff --git a/Mathlib/NumberTheory/PythagoreanTriples.lean b/Mathlib/NumberTheory/PythagoreanTriples.lean index 2c1577443bb03..3fec79e582c14 100644 --- a/Mathlib/NumberTheory/PythagoreanTriples.lean +++ b/Mathlib/NumberTheory/PythagoreanTriples.lean @@ -9,6 +9,7 @@ import Mathlib.Tactic.Ring import Mathlib.Tactic.FieldSimp import Mathlib.Data.Int.NatPrime import Mathlib.Data.ZMod.Basic +import Mathlib.Algebra.GroupPower.Order #align_import number_theory.pythagorean_triples from "leanprover-community/mathlib"@"e8638a0fcaf73e4500469f368ef9494e495099b3" @@ -218,8 +219,8 @@ theorem isClassified_of_normalize_isPrimitiveClassified (hc : h.normalize.IsPrim convert h.normalize.mul_isClassified (Int.gcd x y) (isClassified_of_isPrimitiveClassified h.normalize hc) <;> rw [Int.mul_ediv_cancel'] - · exact Int.gcd_dvd_left x y - · exact Int.gcd_dvd_right x y + · exact Int.gcd_dvd_left + · exact Int.gcd_dvd_right · exact h.gcd_dvd #align pythagorean_triple.is_classified_of_normalize_is_primitive_classified PythagoreanTriple.isClassified_of_normalize_isPrimitiveClassified diff --git a/Mathlib/NumberTheory/Rayleigh.lean b/Mathlib/NumberTheory/Rayleigh.lean index d13686eda8a97..17e7613714c3f 100644 --- a/Mathlib/NumberTheory/Rayleigh.lean +++ b/Mathlib/NumberTheory/Rayleigh.lean @@ -127,6 +127,8 @@ theorem compl_beattySeq' {r s : ℝ} (hrs : r.IsConjugateExponent s) : {beattySeq' r k | k}ᶜ = {beattySeq s k | k} := by rw [← compl_beattySeq hrs.symm, compl_compl] +open scoped symmDiff + /-- Generalization of Rayleigh's theorem on Beatty sequences. Let `r` be a real number greater than 1, and `1/r + 1/s = 1`. Then `B⁺_r` and `B⁺'_s` partition the positive integers. -/ theorem beattySeq_symmDiff_beattySeq'_pos {r s : ℝ} (hrs : r.IsConjugateExponent s) : diff --git a/Mathlib/NumberTheory/SumFourSquares.lean b/Mathlib/NumberTheory/SumFourSquares.lean index df9d144eff129..450f063b5e938 100644 --- a/Mathlib/NumberTheory/SumFourSquares.lean +++ b/Mathlib/NumberTheory/SumFourSquares.lean @@ -3,7 +3,6 @@ Copyright (c) 2019 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.GroupPower.Identities import Mathlib.Data.ZMod.Basic import Mathlib.FieldTheory.Finite.Basic import Mathlib.Data.Int.Parity @@ -58,6 +57,7 @@ theorem sq_add_sq_of_two_mul_sq_add_sq {m x y : ℤ} (h : 2 * m = x ^ 2 + y ^ 2) rw [even_iff_two_dvd] at hxsuby hxaddy rw [Int.mul_ediv_cancel' hxsuby, Int.mul_ediv_cancel' hxaddy] _ = 2 * 2 * (((x - y) / 2) ^ 2 + ((x + y) / 2) ^ 2) := by + set_option simprocs false in simp [mul_add, pow_succ, mul_comm, mul_assoc, mul_left_comm] #align int.sq_add_sq_of_two_mul_sq_add_sq Int.sq_add_sq_of_two_mul_sq_add_sq diff --git a/Mathlib/NumberTheory/SumTwoSquares.lean b/Mathlib/NumberTheory/SumTwoSquares.lean index 11f672e903dc2..1f3c1978358a7 100644 --- a/Mathlib/NumberTheory/SumTwoSquares.lean +++ b/Mathlib/NumberTheory/SumTwoSquares.lean @@ -3,6 +3,7 @@ Copyright (c) 2019 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Michael Stoll -/ +import Mathlib.Data.Nat.Squarefree import Mathlib.NumberTheory.Zsqrtd.QuadraticReciprocity import Mathlib.Tactic.LinearCombination diff --git a/Mathlib/NumberTheory/WellApproximable.lean b/Mathlib/NumberTheory/WellApproximable.lean index c0123ff19b8da..703424d2d2348 100644 --- a/Mathlib/NumberTheory/WellApproximable.lean +++ b/Mathlib/NumberTheory/WellApproximable.lean @@ -366,7 +366,7 @@ lemma _root_.NormedAddCommGroup.exists_norm_nsmul_le {A : Type*} replace hδ : 0 ≤ δ/2 := by by_contra contra suffices : μ (closedBall 0 (δ/2)) = 0 - · apply isOpen_univ.measure_ne_zero μ univ_nonempty $ le_zero_iff.mp $ le_trans hδ _ + · apply isOpen_univ.measure_ne_zero μ univ_nonempty <| le_zero_iff.mp <| le_trans hδ _ simp [this] rw [not_le, ← closedBall_eq_empty (x := (0 : A))] at contra simp [contra] @@ -380,7 +380,7 @@ lemma exists_norm_nsmul_le (ξ : 𝕊) {n : ℕ} (hn : 0 < n) : ∃ j ∈ Icc 1 n, ‖j • ξ‖ ≤ T / ↑(n + 1) := by apply NormedAddCommGroup.exists_norm_nsmul_le (μ := volume) ξ hn rw [AddCircle.measure_univ, volume_closedBall, ← ENNReal.ofReal_nsmul, - mul_div_cancel' _ two_ne_zero, min_eq_right (div_le_self hT.out.le $ by simp), nsmul_eq_mul, + mul_div_cancel' _ two_ne_zero, min_eq_right (div_le_self hT.out.le <| by simp), nsmul_eq_mul, mul_div_cancel' _ (Nat.cast_ne_zero.mpr n.succ_ne_zero)] end AddCircle diff --git a/Mathlib/NumberTheory/ZetaFunction.lean b/Mathlib/NumberTheory/ZetaFunction.lean index 17cc453b3d2e2..9fb7f9fd07cec 100644 --- a/Mathlib/NumberTheory/ZetaFunction.lean +++ b/Mathlib/NumberTheory/ZetaFunction.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: David Loeffler -/ import Mathlib.Analysis.SpecialFunctions.Gamma.Beta -import Mathlib.NumberTheory.ModularForms.JacobiTheta.Basic +import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable import Mathlib.NumberTheory.ZetaValues #align_import number_theory.zeta_function from "leanprover-community/mathlib"@"57f9349f2fe19d2de7207e99b0341808d977cdcf" @@ -113,7 +113,7 @@ theorem riemannZeta_zero : riemannZeta 0 = -1 / 2 := by /-- The sum defining `zetaKernel₁` is convergent. -/ theorem summable_exp_neg_pi_mul_nat_sq {t : ℝ} (ht : 0 < t) : Summable fun n : ℕ => rexp (-π * t * ((n : ℝ) + 1) ^ 2) := by - have : 0 < (↑t * I).im := by rwa [ofReal_mul_im, I_im, mul_one] + have : 0 < (↑t * I).im := by rwa [im_ofReal_mul, I_im, mul_one] convert (hasSum_nat_jacobiTheta this).summable.norm using 1 ext1 n rw [Complex.norm_eq_abs, Complex.abs_exp] @@ -292,7 +292,7 @@ theorem isBigO_zero_zetaKernel₁ : IsBigO (𝓝[>] 0) zetaKernel₁ fun t => t · refine isBigO_iff.mpr ⟨‖(1 / 2 : ℂ)‖, ?_⟩ refine eventually_of_mem (Ioc_mem_nhdsWithin_Ioi <| left_mem_Ico.mpr zero_lt_one) fun t ht => ?_ refine le_mul_of_one_le_right (norm_nonneg _) ?_ - rw [norm_of_nonneg (rpow_nonneg_of_nonneg ht.1.le _), rpow_neg ht.1.le] + rw [norm_of_nonneg (rpow_nonneg ht.1.le _), rpow_neg ht.1.le] exact one_le_inv (rpow_pos_of_pos ht.1 _) (rpow_le_one ht.1.le ht.2 one_half_pos.le) set_option linter.uppercaseLean3 false in #align is_O_zero_zeta_kernel₁ isBigO_zero_zetaKernel₁ @@ -470,7 +470,7 @@ theorem completed_zeta_eq_mellin_of_one_lt_re {s : ℂ} (hs : 1 < re s) : riemannCompletedZeta s = mellin zetaKernel₁ (s / 2) := by have : 1 / 2 < (s / 2).re := by rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl] - rwa [ofReal_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)] + rwa [re_ofReal_mul, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)] rw [riemannCompletedZeta, riemannCompletedZeta₀, mellin_zetaKernel₂_eq_of_lt_re this, sub_add, sub_sub, ← add_sub] conv_rhs => rw [← add_zero (mellin zetaKernel₁ <| s / 2)] @@ -559,7 +559,7 @@ theorem completed_zeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) : rw [completed_zeta_eq_mellin_of_one_lt_re hs, mellin_zetaKernel₁_eq_tsum, neg_div, mul_div_cancel' _ (two_ne_zero' ℂ)] rw [show s / 2 = ↑(2⁻¹ : ℝ) * s by push_cast; rw [mul_comm]; rfl] - rwa [ofReal_mul_re, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)] + rwa [re_ofReal_mul, ← div_eq_inv_mul, div_lt_div_right (zero_lt_two' ℝ)] #align completed_zeta_eq_tsum_of_one_lt_re completed_zeta_eq_tsum_of_one_lt_re /-- The Riemann zeta function agrees with the naive Dirichlet-series definition when the latter @@ -571,7 +571,7 @@ theorem zeta_eq_tsum_one_div_nat_add_one_cpow {s : ℂ} (hs : 1 < re s) : rw [riemannZeta, Function.update_noteq this, completed_zeta_eq_tsum_of_one_lt_re hs, ← mul_assoc, neg_div, cpow_neg, mul_inv_cancel_left₀, mul_div_cancel_left] · apply Gamma_ne_zero_of_re_pos - rw [div_eq_mul_inv, mul_comm, show (2⁻¹ : ℂ) = (2⁻¹ : ℝ) by norm_num, ofReal_mul_re] + rw [div_eq_mul_inv, mul_comm, show (2⁻¹ : ℂ) = (2⁻¹ : ℝ) by norm_num, re_ofReal_mul] exact mul_pos (inv_pos_of_pos two_pos) (zero_lt_one.trans hs) · rw [Ne.def, cpow_eq_zero_iff, not_and_or, ← Ne.def, ofReal_ne_zero] exact Or.inl pi_pos.ne' diff --git a/Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean b/Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean index 818b9ff2287b5..290c82cdf77e9 100644 --- a/Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean +++ b/Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ import Mathlib.NumberTheory.Zsqrtd.Basic -import Mathlib.Data.Complex.Abs import Mathlib.RingTheory.PrincipalIdealDomain +import Mathlib.Data.Complex.Basic +import Mathlib.Data.Real.Archimedean #align_import number_theory.zsqrtd.gaussian_int from "leanprover-community/mathlib"@"5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9" diff --git a/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean b/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean index 942d1502dad18..64cd25d8af791 100644 --- a/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean +++ b/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ import Mathlib.NumberTheory.Zsqrtd.GaussianInt -import Mathlib.NumberTheory.LegendreSymbol.QuadraticReciprocity +import Mathlib.NumberTheory.LegendreSymbol.Basic +import Mathlib.Analysis.Normed.Field.Basic #align_import number_theory.zsqrtd.quadratic_reciprocity from "leanprover-community/mathlib"@"5b2fe80501ff327b9109fb09b7cc8c325cd0d7d9" diff --git a/Mathlib/Order/Atoms.lean b/Mathlib/Order/Atoms.lean index 7ab1fbb46c5a0..a71a3932f9807 100644 --- a/Mathlib/Order/Atoms.lean +++ b/Mathlib/Order/Atoms.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Aaron Anderson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ +import Mathlib.Data.Set.Image import Mathlib.Order.ModularLattice import Mathlib.Order.WellFounded import Mathlib.Tactic.Nontriviality @@ -95,20 +96,20 @@ theorem IsAtom.le_iff (h : IsAtom a) : x ≤ a ↔ x = ⊥ ∨ x = a := by rw [l #align is_atom.le_iff IsAtom.le_iff lemma IsAtom.le_iff_eq (ha : IsAtom a) (hb : b ≠ ⊥) : b ≤ a ↔ b = a := - ha.le_iff.trans $ or_iff_right hb + ha.le_iff.trans <| or_iff_right hb theorem IsAtom.Iic_eq (h : IsAtom a) : Set.Iic a = {⊥, a} := Set.ext fun _ => h.le_iff #align is_atom.Iic_eq IsAtom.Iic_eq @[simp] -theorem bot_covby_iff : ⊥ ⋖ a ↔ IsAtom a := by - simp only [Covby, bot_lt_iff_ne_bot, IsAtom, not_imp_not] -#align bot_covby_iff bot_covby_iff +theorem bot_covBy_iff : ⊥ ⋖ a ↔ IsAtom a := by + simp only [CovBy, bot_lt_iff_ne_bot, IsAtom, not_imp_not] +#align bot_covby_iff bot_covBy_iff -alias ⟨Covby.is_atom, IsAtom.bot_covby⟩ := bot_covby_iff -#align covby.is_atom Covby.is_atom -#align is_atom.bot_covby IsAtom.bot_covby +alias ⟨CovBy.is_atom, IsAtom.bot_covBy⟩ := bot_covBy_iff +#align covby.is_atom CovBy.is_atom +#align is_atom.bot_covby IsAtom.bot_covBy end PartialOrder @@ -192,13 +193,13 @@ theorem IsCoatom.Ici_eq (h : IsCoatom a) : Set.Ici a = {⊤, a} := #align is_coatom.Ici_eq IsCoatom.Ici_eq @[simp] -theorem covby_top_iff : a ⋖ ⊤ ↔ IsCoatom a := - toDual_covby_toDual_iff.symm.trans bot_covby_iff -#align covby_top_iff covby_top_iff +theorem covBy_top_iff : a ⋖ ⊤ ↔ IsCoatom a := + toDual_covBy_toDual_iff.symm.trans bot_covBy_iff +#align covby_top_iff covBy_top_iff -alias ⟨Covby.is_coatom, IsCoatom.covby_top⟩ := covby_top_iff -#align covby.is_coatom Covby.is_coatom -#align is_coatom.covby_top IsCoatom.covby_top +alias ⟨CovBy.isCoatom, IsCoatom.covBy_top⟩ := covBy_top_iff +#align covby.is_coatom CovBy.isCoatom +#align is_coatom.covby_top IsCoatom.covBy_top end PartialOrder @@ -214,23 +215,23 @@ variable [PartialOrder α] {a b : α} @[simp] theorem Set.Ici.isAtom_iff {b : Set.Ici a} : IsAtom b ↔ a ⋖ b := by - rw [← bot_covby_iff] - refine' (Set.OrdConnected.apply_covby_apply_iff (OrderEmbedding.subtype fun c => a ≤ c) _).symm + rw [← bot_covBy_iff] + refine' (Set.OrdConnected.apply_covBy_apply_iff (OrderEmbedding.subtype fun c => a ≤ c) _).symm simpa only [OrderEmbedding.subtype_apply, Subtype.range_coe_subtype] using Set.ordConnected_Ici #align set.Ici.is_atom_iff Set.Ici.isAtom_iff @[simp] theorem Set.Iic.isCoatom_iff {a : Set.Iic b} : IsCoatom a ↔ ↑a ⋖ b := by - rw [← covby_top_iff] - refine' (Set.OrdConnected.apply_covby_apply_iff (OrderEmbedding.subtype fun c => c ≤ b) _).symm + rw [← covBy_top_iff] + refine' (Set.OrdConnected.apply_covBy_apply_iff (OrderEmbedding.subtype fun c => c ≤ b) _).symm simpa only [OrderEmbedding.subtype_apply, Subtype.range_coe_subtype] using Set.ordConnected_Iic #align set.Iic.is_coatom_iff Set.Iic.isCoatom_iff -theorem covby_iff_atom_Ici (h : a ≤ b) : a ⋖ b ↔ IsAtom (⟨b, h⟩ : Set.Ici a) := by simp -#align covby_iff_atom_Ici covby_iff_atom_Ici +theorem covBy_iff_atom_Ici (h : a ≤ b) : a ⋖ b ↔ IsAtom (⟨b, h⟩ : Set.Ici a) := by simp +#align covby_iff_atom_Ici covBy_iff_atom_Ici -theorem covby_iff_coatom_Iic (h : a ≤ b) : a ⋖ b ↔ IsCoatom (⟨a, h⟩ : Set.Iic b) := by simp -#align covby_iff_coatom_Iic covby_iff_coatom_Iic +theorem covBy_iff_coatom_Iic (h : a ≤ b) : a ⋖ b ↔ IsCoatom (⟨a, h⟩ : Set.Iic b) := by simp +#align covby_iff_coatom_Iic covBy_iff_coatom_Iic end PartialOrder @@ -583,9 +584,9 @@ theorem isCoatom_bot : IsCoatom (⊥ : α) := isAtom_dual_iff_isCoatom.1 isAtom_top #align is_coatom_bot isCoatom_bot -theorem bot_covby_top : (⊥ : α) ⋖ ⊤ := - isAtom_top.bot_covby -#align bot_covby_top bot_covby_top +theorem bot_covBy_top : (⊥ : α) ⋖ ⊤ := + isAtom_top.bot_covBy +#align bot_covby_top bot_covBy_top end IsSimpleOrder @@ -789,8 +790,8 @@ variable [PartialOrder α] [PartialOrder β] theorem isAtom_of_map_bot_of_image [OrderBot α] [OrderBot β] (f : β ↪o α) (hbot : f ⊥ = ⊥) {b : β} (hb : IsAtom (f b)) : IsAtom b := by - simp only [← bot_covby_iff] at hb ⊢ - exact Covby.of_image f (hbot.symm ▸ hb) + simp only [← bot_covBy_iff] at hb ⊢ + exact CovBy.of_image f (hbot.symm ▸ hb) #align order_embedding.is_atom_of_map_bot_of_image OrderEmbedding.isAtom_of_map_bot_of_image theorem isCoatom_of_map_top_of_image [OrderTop α] [OrderTop β] (f : β ↪o α) (htop : f ⊤ = ⊤) diff --git a/Mathlib/Order/Basic.lean b/Mathlib/Order/Basic.lean index b4194380150e7..0997b67b64dc5 100644 --- a/Mathlib/Order/Basic.lean +++ b/Mathlib/Order/Basic.lean @@ -11,6 +11,7 @@ import Mathlib.Tactic.Convert import Mathlib.Tactic.SimpRw import Mathlib.Tactic.Classical import Mathlib.Tactic.Cases +import Mathlib.Order.Notation #align_import order.basic from "leanprover-community/mathlib"@"90df25ded755a2cf9651ea850d1abe429b1e4eb1" @@ -35,9 +36,6 @@ classes and allows to transfer order instances. ### Extra class -* `Sup`: type class for the `⊔` notation -* `Inf`: type class for the `⊓` notation -* `HasCompl`: type class for the `ᶜ` notation * `DenselyOrdered`: An order with no gap, i.e. for any two elements `a < b` there exists `c` such that `a < c < b`. @@ -238,7 +236,6 @@ theorem not_gt (h : x = y) : ¬y < x := end Eq - section variable [Preorder α] {a b : α} @@ -676,8 +673,124 @@ instance Order.Preimage.decidable {α β} (f : α → β) (s : β → β → Pro DecidableRel (f ⁻¹'o s) := fun _ _ ↦ H _ _ #align order.preimage.decidable Order.Preimage.decidable -/-! ### Order dual -/ +section ltByCases + +variable [LinearOrder α] {P : Sort*} {x y : α} + +@[simp] +lemma ltByCases_lt (h : x < y) {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} : + ltByCases x y h₁ h₂ h₃ = h₁ h := dif_pos h + +@[simp] +lemma ltByCases_gt (h : y < x) {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} : + ltByCases x y h₁ h₂ h₃ = h₃ h := (dif_neg h.not_lt).trans (dif_pos h) + +@[simp] +lemma ltByCases_eq (h : x = y) {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} : + ltByCases x y h₁ h₂ h₃ = h₂ h := (dif_neg h.not_lt).trans (dif_neg h.not_gt) + +lemma ltByCases_not_lt (h : ¬ x < y) {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} + (p : ¬ y < x → x = y := fun h' => (le_antisymm (le_of_not_gt h') (le_of_not_gt h))) : + ltByCases x y h₁ h₂ h₃ = if h' : y < x then h₃ h' else h₂ (p h') := dif_neg h + +lemma ltByCases_not_gt (h : ¬ y < x) {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} + (p : ¬ x < y → x = y := fun h' => (le_antisymm (le_of_not_gt h) (le_of_not_gt h'))) : + ltByCases x y h₁ h₂ h₃ = if h' : x < y then h₁ h' else h₂ (p h') := + dite_congr rfl (fun _ => rfl) (fun _ => dif_neg h) + +lemma ltByCases_ne (h : x ≠ y) {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} + (p : ¬ x < y → y < x := fun h' => h.lt_or_lt.resolve_left h') : + ltByCases x y h₁ h₂ h₃ = if h' : x < y then h₁ h' else h₃ (p h') := + dite_congr rfl (fun _ => rfl) (fun _ => dif_pos _) + +lemma ltByCases_comm {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} + (p : y = x → x = y := fun h' => h'.symm) : + ltByCases x y h₁ h₂ h₃ = ltByCases y x h₃ (h₂ ∘ p) h₁ := by + refine ltByCases x y (fun h => ?_) (fun h => ?_) (fun h => ?_) + · rw [ltByCases_lt h, ltByCases_gt h] + · rw [ltByCases_eq h, ltByCases_eq h.symm, comp_apply] + · rw [ltByCases_lt h, ltByCases_gt h] + +lemma eq_iff_eq_of_lt_iff_lt_of_gt_iff_gt {x' y' : α} + (ltc : (x < y) ↔ (x' < y')) (gtc : (y < x) ↔ (y' < x')) : + x = y ↔ x' = y' := by simp_rw [eq_iff_le_not_lt, ← not_lt, ltc, gtc] + +lemma ltByCases_rec {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} (p : P) + (hlt : (h : x < y) → h₁ h = p) (heq : (h : x = y) → h₂ h = p) + (hgt : (h : y < x) → h₃ h = p) : + ltByCases x y h₁ h₂ h₃ = p := + ltByCases x y + (fun h => ltByCases_lt h ▸ hlt h) + (fun h => ltByCases_eq h ▸ heq h) + (fun h => ltByCases_gt h ▸ hgt h) + +lemma ltByCases_eq_iff {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} {p : P} : + ltByCases x y h₁ h₂ h₃ = p ↔ (∃ h, h₁ h = p) ∨ (∃ h, h₂ h = p) ∨ (∃ h, h₃ h = p) := by + refine ltByCases x y (fun h => ?_) (fun h => ?_) (fun h => ?_) + · simp only [ltByCases_lt, exists_prop_of_true, h, h.not_lt, not_false_eq_true, + exists_prop_of_false, or_false, h.ne] + · simp only [h, lt_self_iff_false, ltByCases_eq, not_false_eq_true, + exists_prop_of_false, exists_prop_of_true, or_false, false_or] + · simp only [ltByCases_gt, exists_prop_of_true, h, h.not_lt, not_false_eq_true, + exists_prop_of_false, false_or, h.ne'] + +lemma ltByCases_congr {x' y' : α} {h₁ : x < y → P} {h₂ : x = y → P} {h₃ : y < x → P} + {h₁' : x' < y' → P} {h₂' : x' = y' → P} {h₃' : y' < x' → P} (ltc : (x < y) ↔ (x' < y')) + (gtc : (y < x) ↔ (y' < x')) (hh'₁ : ∀ (h : x' < y'), h₁ (ltc.mpr h) = h₁' h) + (hh'₂ : ∀ (h : x' = y'), h₂ ((eq_iff_eq_of_lt_iff_lt_of_gt_iff_gt ltc gtc).mpr h) = h₂' h) + (hh'₃ : ∀ (h : y' < x'), h₃ (gtc.mpr h) = h₃' h) : + ltByCases x y h₁ h₂ h₃ = ltByCases x' y' h₁' h₂' h₃' := by + refine ltByCases_rec _ (fun h => ?_) (fun h => ?_) (fun h => ?_) + · rw [ltByCases_lt (ltc.mp h), hh'₁] + · rw [eq_iff_eq_of_lt_iff_lt_of_gt_iff_gt ltc gtc] at h + rw [ltByCases_eq h, hh'₂] + · rw [ltByCases_gt (gtc.mp h), hh'₃] + +/-- Perform a case-split on the ordering of `x` and `y` in a decidable linear order, +non-dependently. -/ +abbrev ltTrichotomy (x y : α) (p q r : P) := ltByCases x y (fun _ => p) (fun _ => q) (fun _ => r) + +variable {p q r s : P} + +@[simp] +lemma ltTrichotomy_lt (h : x < y) : ltTrichotomy x y p q r = p := ltByCases_lt h + +@[simp] +lemma ltTrichotomy_gt (h : y < x) : ltTrichotomy x y p q r = r := ltByCases_gt h + +@[simp] +lemma ltTrichotomy_eq (h : x = y) : ltTrichotomy x y p q r = q := ltByCases_eq h + +lemma ltTrichotomy_not_lt (h : ¬ x < y) : + ltTrichotomy x y p q r = if y < x then r else q := ltByCases_not_lt h + +lemma ltTrichotomy_not_gt (h : ¬ y < x) : + ltTrichotomy x y p q r = if x < y then p else q := ltByCases_not_gt h + +lemma ltTrichotomy_ne (h : x ≠ y) : + ltTrichotomy x y p q r = if x < y then p else r := ltByCases_ne h + +lemma ltTrichotomy_comm : ltTrichotomy x y p q r = ltTrichotomy y x r q p := ltByCases_comm +lemma ltTrichotomy_self {p : P} : ltTrichotomy x y p p p = p := + ltByCases_rec p (fun _ => rfl) (fun _ => rfl) (fun _ => rfl) + +lemma ltTrichotomy_eq_iff : ltTrichotomy x y p q r = s ↔ + (x < y ∧ p = s) ∨ (x = y ∧ q = s) ∨ (y < x ∧ r = s) := by + refine ltByCases x y (fun h => ?_) (fun h => ?_) (fun h => ?_) + · simp only [ltTrichotomy_lt, false_and, true_and, or_false, h, h.not_lt, h.ne] + · simp only [ltTrichotomy_eq, false_and, true_and, or_false, false_or, h, lt_irrefl] + · simp only [ltTrichotomy_gt, false_and, true_and, false_or, h, h.not_lt, h.ne'] + +lemma ltTrichotomy_congr {x' y' : α} {p' q' r' : P} (ltc : (x < y) ↔ (x' < y')) + (gtc : (y < x) ↔ (y' < x')) (hh'₁ : x' < y' → p = p') + (hh'₂ : x' = y' → q = q') (hh'₃ : y' < x' → r = r') : + ltTrichotomy x y p q r = ltTrichotomy x' y' p' q' r' := + ltByCases_congr ltc gtc hh'₁ hh'₂ hh'₃ + +end ltByCases + +/-! ### Order dual -/ /-- Type synonym to equip a type with the dual order: `≤` means `≥` and `<` means `>`. `αᵒᵈ` is notation for `OrderDual α`. -/ @@ -743,18 +856,6 @@ end OrderDual /-! ### `HasCompl` -/ -/-- Set / lattice complement -/ -@[notation_class] -class HasCompl (α : Type*) where - /-- Set / lattice complement -/ - compl : α → α -#align has_compl HasCompl - -export HasCompl (compl) - -@[inherit_doc] -postfix:1024 "ᶜ" => compl - instance Prop.hasCompl : HasCompl Prop := ⟨Not⟩ #align Prop.has_compl Prop.hasCompl @@ -961,32 +1062,8 @@ theorem max_def_lt (x y : α) : max x y = if x < y then y else x := by end MinMaxRec -/-! ### `Sup` and `Inf` -/ - - -/-- Typeclass for the `⊔` (`\lub`) notation -/ -@[notation_class, ext] -class Sup (α : Type u) where - /-- Least upper bound (`\lub` notation) -/ - sup : α → α → α -#align has_sup Sup - -/-- Typeclass for the `⊓` (`\glb`) notation -/ -@[notation_class, ext] -class Inf (α : Type u) where - /-- Greatest lower bound (`\glb` notation) -/ - inf : α → α → α -#align has_inf Inf - -@[inherit_doc] -infixl:68 " ⊔ " => Sup.sup - -@[inherit_doc] -infixl:69 " ⊓ " => Inf.inf - /-! ### Lifts of order instances -/ - /-- Transfer a `Preorder` on `β` to a `Preorder` on `α` using a function `f : α → β`. See note [reducible non-instances]. -/ @[reducible] diff --git a/Mathlib/Order/Birkhoff.lean b/Mathlib/Order/Birkhoff.lean index 38a9573d1dd19..16b2a805764af 100644 --- a/Mathlib/Order/Birkhoff.lean +++ b/Mathlib/Order/Birkhoff.lean @@ -53,15 +53,15 @@ variable [SemilatticeInf α] {s : UpperSet α} {a : α} refine ⟨fun h ↦ Ici_ne_top h.eq_top, fun s t hst ↦ ?_⟩ have := mem_Ici_iff.2 (le_refl a) rw [← hst] at this - exact this.imp (fun ha ↦ le_antisymm (le_Ici.2 ha) $ hst.ge.trans inf_le_left) fun ha ↦ - le_antisymm (le_Ici.2 ha) $ hst.ge.trans inf_le_right + exact this.imp (fun ha ↦ le_antisymm (le_Ici.2 ha) <| hst.ge.trans inf_le_left) fun ha ↦ + le_antisymm (le_Ici.2 ha) <| hst.ge.trans inf_le_right variable [Finite α] @[simp] lemma infIrred_iff_of_finite : InfIrred s ↔ ∃ a, Ici a = s := by refine' ⟨fun hs ↦ _, _⟩ · obtain ⟨a, ha, has⟩ := (s : Set α).toFinite.exists_minimal_wrt id _ (coe_nonempty.2 hs.ne_top) - exact ⟨a, (hs.2 $ erase_inf_Ici ha $ by simpa [eq_comm] using has).resolve_left + exact ⟨a, (hs.2 <| erase_inf_Ici ha <| by simpa [eq_comm] using has).resolve_left (lt_erase.2 ha).ne'⟩ · rintro ⟨a, rfl⟩ exact infIrred_Ici _ @@ -75,15 +75,15 @@ variable [SemilatticeSup α] {s : LowerSet α} {a : α} refine' ⟨fun h ↦ Iic_ne_bot h.eq_bot, fun s t hst ↦ _⟩ have := mem_Iic_iff.2 (le_refl a) rw [← hst] at this - exact this.imp (fun ha ↦ (le_sup_left.trans_eq hst).antisymm $ Iic_le.2 ha) fun ha ↦ - (le_sup_right.trans_eq hst).antisymm $ Iic_le.2 ha + exact this.imp (fun ha ↦ (le_sup_left.trans_eq hst).antisymm <| Iic_le.2 ha) fun ha ↦ + (le_sup_right.trans_eq hst).antisymm <| Iic_le.2 ha variable [Finite α] @[simp] lemma supIrred_iff_of_finite : SupIrred s ↔ ∃ a, Iic a = s := by refine' ⟨fun hs ↦ _, _⟩ · obtain ⟨a, ha, has⟩ := (s : Set α).toFinite.exists_maximal_wrt id _ (coe_nonempty.2 hs.ne_bot) - exact ⟨a, (hs.2 $ erase_sup_Iic ha $ by simpa [eq_comm] using has).resolve_left + exact ⟨a, (hs.2 <| erase_sup_Iic ha <| by simpa [eq_comm] using has).resolve_left (erase_lt.2 ha).ne⟩ · rintro ⟨a, rfl⟩ exact supIrred_Iic _ @@ -108,7 +108,7 @@ noncomputable def OrderIso.lowerSetSupIrred : α ≃o LowerSet {a : α // SupIrr refine' le_antisymm (Finset.sup_le fun b ↦ Set.mem_toFinset.1) _ obtain ⟨s, rfl, hs⟩ := exists_supIrred_decomposition a exact Finset.sup_le fun i hi ↦ - le_sup_of_le (b := ⟨i, hs hi⟩) (Set.mem_toFinset.2 $ le_sup (f := id) hi) le_rfl + le_sup_of_le (b := ⟨i, hs hi⟩) (Set.mem_toFinset.2 <| le_sup (f := id) hi) le_rfl right_inv := fun s ↦ by ext a dsimp @@ -117,7 +117,7 @@ noncomputable def OrderIso.lowerSetSupIrred : α ≃o LowerSet {a : α // SupIrr exact s.lower ha (Set.mem_toFinset.1 hi) · dsimp exact le_sup (Set.mem_toFinset.2 ha) } - (fun b c hbc d ↦ le_trans' hbc) fun s t hst ↦ Finset.sup_mono $ Set.toFinset_mono hst + (fun b c hbc d ↦ le_trans' hbc) fun s t hst ↦ Finset.sup_mono <| Set.toFinset_mono hst -- We remove this instance locally to let `Set.toFinset_Iic` fire. When the instance is present, -- `simp` refuses to use that lemma because TC inference synthesizes `Set.fintypeIic`, which is not @@ -139,7 +139,7 @@ noncomputable def OrderIso.supIrredLowerSet : α ≃o {s : LowerSet α // SupIrr rintro ⟨s, hs⟩ obtain ⟨a, rfl⟩ := LowerSet.supIrred_iff_of_finite.1 hs simp } - (fun b c hbc d ↦ le_trans' hbc) fun s t hst ↦ Finset.sup_mono $ Set.toFinset_mono hst + (fun b c hbc d ↦ le_trans' hbc) fun s t hst ↦ Finset.sup_mono <| Set.toFinset_mono hst end Fintype diff --git a/Mathlib/Order/BooleanAlgebra.lean b/Mathlib/Order/BooleanAlgebra.lean index 38649d81ed097..82b5c7aa2df64 100644 --- a/Mathlib/Order/BooleanAlgebra.lean +++ b/Mathlib/Order/BooleanAlgebra.lean @@ -773,11 +773,11 @@ theorem codisjoint_himp_self_right : Codisjoint x (x ⇨ y) := #align codisjoint_himp_self_right codisjoint_himp_self_right theorem himp_le : x ⇨ y ≤ z ↔ y ≤ z ∧ Codisjoint x z := - (@le_sdiff αᵒᵈ _ _ _ _).trans <| and_congr_right' $ @Codisjoint_comm _ (_) _ _ _ + (@le_sdiff αᵒᵈ _ _ _ _).trans <| and_congr_right' <| @Codisjoint_comm _ (_) _ _ _ #align himp_le himp_le @[simp] lemma himp_le_iff : x ⇨ y ≤ x ↔ x = ⊤ := - ⟨fun h ↦ codisjoint_self.1 $ codisjoint_himp_self_right.mono_right h, fun h ↦ le_top.trans h.ge⟩ + ⟨fun h ↦ codisjoint_self.1 <| codisjoint_himp_self_right.mono_right h, fun h ↦ le_top.trans h.ge⟩ @[simp] lemma himp_eq_left : x ⇨ y = x ↔ x = ⊤ ∧ y = ⊤ := by rw [codisjoint_himp_self_left.eq_iff]; aesop diff --git a/Mathlib/Order/Booleanisation.lean b/Mathlib/Order/Booleanisation.lean index aca7208e4417c..ea2c65574335e 100644 --- a/Mathlib/Order/Booleanisation.lean +++ b/Mathlib/Order/Booleanisation.lean @@ -170,10 +170,10 @@ instance instPreorder : Preorder (Booleanisation α) where | lift a => LE.lift le_rfl | comp a => LE.comp le_rfl le_trans x y z hxy hyz := match x, y, z, hxy, hyz with - | lift a, lift b, lift c, LE.lift hab, LE.lift hbc => LE.lift $ hab.trans hbc - | lift a, lift b, comp c, LE.lift hab, LE.sep hbc => LE.sep $ hbc.mono_left hab - | lift a, comp b, comp c, LE.sep hab, LE.comp hcb => LE.sep $ hab.mono_right hcb - | comp a, comp b, comp c, LE.comp hba, LE.comp hcb => LE.comp $ hcb.trans hba + | lift a, lift b, lift c, LE.lift hab, LE.lift hbc => LE.lift <| hab.trans hbc + | lift a, lift b, comp c, LE.lift hab, LE.sep hbc => LE.sep <| hbc.mono_left hab + | lift a, comp b, comp c, LE.sep hab, LE.comp hcb => LE.sep <| hab.mono_right hcb + | comp a, comp b, comp c, LE.comp hba, LE.comp hcb => LE.comp <| hcb.trans hba instance instPartialOrder : PartialOrder (Booleanisation α) where le_antisymm x y hxy hyx := match x, y, hxy, hyx with @@ -194,11 +194,11 @@ instance instSemilatticeSup : SemilatticeSup (Booleanisation α) where | comp a, lift b => LE.sep disjoint_sdiff_self_right | comp a, comp b => LE.comp inf_le_right sup_le x y z hxz hyz := match x, y, z, hxz, hyz with - | lift a, lift b, lift c, LE.lift hac, LE.lift hbc => LE.lift $ sup_le hac hbc - | lift a, lift b, comp c, LE.sep hac, LE.sep hbc => LE.sep $ hac.sup_left hbc - | lift a, comp b, comp c, LE.sep hac, LE.comp hcb => LE.comp $ le_sdiff.2 ⟨hcb, hac.symm⟩ - | comp a, lift b, comp c, LE.comp hca, LE.sep hbc => LE.comp $ le_sdiff.2 ⟨hca, hbc.symm⟩ - | comp a, comp b, comp c, LE.comp hca, LE.comp hcb => LE.comp $ le_inf hca hcb + | lift a, lift b, lift c, LE.lift hac, LE.lift hbc => LE.lift <| sup_le hac hbc + | lift a, lift b, comp c, LE.sep hac, LE.sep hbc => LE.sep <| hac.sup_left hbc + | lift a, comp b, comp c, LE.sep hac, LE.comp hcb => LE.comp <| le_sdiff.2 ⟨hcb, hac.symm⟩ + | comp a, lift b, comp c, LE.comp hca, LE.sep hbc => LE.comp <| le_sdiff.2 ⟨hca, hbc.symm⟩ + | comp a, comp b, comp c, LE.comp hca, LE.comp hcb => LE.comp <| le_inf hca hcb -- The linter significantly hinders readability here. set_option linter.unusedVariables false in @@ -214,11 +214,11 @@ instance instSemilatticeInf : SemilatticeInf (Booleanisation α) where | comp a, lift b => LE.lift sdiff_le | comp a, comp b => LE.comp le_sup_right le_inf x y z hxz hyz := match x, y, z, hxz, hyz with - | lift a, lift b, lift c, LE.lift hab, LE.lift hac => LE.lift $ le_inf hab hac - | lift a, lift b, comp c, LE.lift hab, LE.sep hac => LE.lift $ le_sdiff.2 ⟨hab, hac⟩ - | lift a, comp b, lift c, LE.sep hab, LE.lift hac => LE.lift $ le_sdiff.2 ⟨hac, hab⟩ - | lift a, comp b, comp c, LE.sep hab, LE.sep hac => LE.sep $ hab.sup_right hac - | comp a, comp b, comp c, LE.comp hba, LE.comp hca => LE.comp $ sup_le hba hca + | lift a, lift b, lift c, LE.lift hab, LE.lift hac => LE.lift <| le_inf hab hac + | lift a, lift b, comp c, LE.lift hab, LE.sep hac => LE.lift <| le_sdiff.2 ⟨hab, hac⟩ + | lift a, comp b, lift c, LE.sep hab, LE.lift hac => LE.lift <| le_sdiff.2 ⟨hac, hab⟩ + | lift a, comp b, comp c, LE.sep hab, LE.sep hac => LE.sep <| hab.sup_right hac + | comp a, comp b, comp c, LE.comp hba, LE.comp hca => LE.comp <| sup_le hba hca instance instDistribLattice : DistribLattice (Booleanisation α) where inf_le_left _ _ := inf_le_left @@ -226,12 +226,12 @@ instance instDistribLattice : DistribLattice (Booleanisation α) where le_inf _ _ _ := le_inf le_sup_inf x y z := match x, y, z with | lift a, lift b, lift c => LE.lift le_sup_inf - | lift a, lift b, comp c => LE.lift $ by simp [sup_left_comm, sup_comm] - | lift a, comp b, lift c => LE.lift $ by simp [sup_left_comm, sup_comm (a := b \ a)] - | lift a, comp b, comp c => LE.comp $ by rw [sup_sdiff] - | comp a, lift b, lift c => LE.comp $ by rw [sdiff_inf] - | comp a, lift b, comp c => LE.comp $ by rw [sdiff_sdiff_right'] - | comp a, comp b, lift c => LE.comp $ by rw [sdiff_sdiff_right', sup_comm] + | lift a, lift b, comp c => LE.lift <| by simp [sup_left_comm, sup_comm] + | lift a, comp b, lift c => LE.lift <| by simp [sup_left_comm, sup_comm (a := b \ a)] + | lift a, comp b, comp c => LE.comp <| by rw [sup_sdiff] + | comp a, lift b, lift c => LE.comp <| by rw [sdiff_inf] + | comp a, lift b, comp c => LE.comp <| by rw [sdiff_sdiff_right'] + | comp a, comp b, lift c => LE.comp <| by rw [sdiff_sdiff_right', sup_comm] | comp a, comp b, comp c => LE.comp inf_sup_left.le -- The linter significantly hinders readability here. diff --git a/Mathlib/Order/BoundedOrder.lean b/Mathlib/Order/BoundedOrder.lean index 1afaa1bad8978..a0548fa44b865 100644 --- a/Mathlib/Order/BoundedOrder.lean +++ b/Mathlib/Order/BoundedOrder.lean @@ -3,7 +3,6 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ -import Mathlib.Data.Option.Basic import Mathlib.Order.Lattice import Mathlib.Order.ULift import Mathlib.Tactic.PushNeg @@ -40,37 +39,6 @@ variable {α : Type u} {β : Type v} {γ δ : Type*} /-! ### Top, bottom element -/ - -/-- Typeclass for the `⊤` (`\top`) notation -/ -@[notation_class, ext] -class Top (α : Type u) where - /-- The top (`⊤`, `\top`) element -/ - top : α -#align has_top Top - -/-- Typeclass for the `⊥` (`\bot`) notation -/ -@[notation_class, ext] -class Bot (α : Type u) where - /-- The bot (`⊥`, `\bot`) element -/ - bot : α -#align has_bot Bot - -/-- The top (`⊤`, `\top`) element -/ -notation "⊤" => Top.top - -/-- The bot (`⊥`, `\bot`) element -/ -notation "⊥" => Bot.bot - -instance (priority := 100) top_nonempty (α : Type u) [Top α] : Nonempty α := - ⟨⊤⟩ -#align has_top_nonempty top_nonempty - -instance (priority := 100) bot_nonempty (α : Type u) [Bot α] : Nonempty α := - ⟨⊥⟩ -#align has_bot_nonempty bot_nonempty - -attribute [match_pattern] Bot.bot Top.top - /-- An order is an `OrderTop` if it has a greatest element. We state this using a data mixin, holding the value of `⊤` and the greatest element constraint. -/ class OrderTop (α : Type u) [LE α] extends Top α where diff --git a/Mathlib/Order/Bounds/Basic.lean b/Mathlib/Order/Bounds/Basic.lean index efd60bd90b38d..cbb129e5ad458 100644 --- a/Mathlib/Order/Bounds/Basic.lean +++ b/Mathlib/Order/Bounds/Basic.lean @@ -1561,6 +1561,54 @@ end AntitoneMonotone end Image2 +section Prod + +variable {α β : Type*} [Preorder α] [Preorder β] + +lemma bddAbove_prod {s : Set (α × β)} : + BddAbove s ↔ BddAbove (Prod.fst '' s) ∧ BddAbove (Prod.snd '' s) := + ⟨fun ⟨p, hp⟩ ↦ ⟨⟨p.1, ball_image_of_ball fun _q hq ↦ (hp hq).1⟩, + ⟨p.2, ball_image_of_ball fun _q hq ↦ (hp hq).2⟩⟩, + fun ⟨⟨x, hx⟩, ⟨y, hy⟩⟩ ↦ ⟨⟨x, y⟩, fun _p hp ↦ + ⟨hx <| mem_image_of_mem _ hp, hy <| mem_image_of_mem _ hp⟩⟩⟩ + +lemma bddBelow_prod {s : Set (α × β)} : + BddBelow s ↔ BddBelow (Prod.fst '' s) ∧ BddBelow (Prod.snd '' s) := + bddAbove_prod (α := αᵒᵈ) (β := βᵒᵈ) + +lemma bddAbove_range_prod {F : ι → α × β} : + BddAbove (range F) ↔ BddAbove (range <| Prod.fst ∘ F) ∧ BddAbove (range <| Prod.snd ∘ F) := by + simp only [bddAbove_prod, ← range_comp] + +lemma bddBelow_range_prod {F : ι → α × β} : + BddBelow (range F) ↔ BddBelow (range <| Prod.fst ∘ F) ∧ BddBelow (range <| Prod.snd ∘ F) := + bddAbove_range_prod (α := αᵒᵈ) (β := βᵒᵈ) + +theorem isLUB_prod [Preorder α] [Preorder β] {s : Set (α × β)} (p : α × β) : + IsLUB s p ↔ IsLUB (Prod.fst '' s) p.1 ∧ IsLUB (Prod.snd '' s) p.2 := by + refine' + ⟨fun H => + ⟨⟨monotone_fst.mem_upperBounds_image H.1, fun a ha => _⟩, + ⟨monotone_snd.mem_upperBounds_image H.1, fun a ha => _⟩⟩, + fun H => ⟨_, _⟩⟩ + · suffices h : (a, p.2) ∈ upperBounds s from (H.2 h).1 + exact fun q hq => ⟨ha <| mem_image_of_mem _ hq, (H.1 hq).2⟩ + · suffices h : (p.1, a) ∈ upperBounds s from (H.2 h).2 + exact fun q hq => ⟨(H.1 hq).1, ha <| mem_image_of_mem _ hq⟩ + · exact fun q hq => ⟨H.1.1 <| mem_image_of_mem _ hq, H.2.1 <| mem_image_of_mem _ hq⟩ + · exact fun q hq => + ⟨H.1.2 <| monotone_fst.mem_upperBounds_image hq, + H.2.2 <| monotone_snd.mem_upperBounds_image hq⟩ +#align is_lub_prod isLUB_prod + +theorem isGLB_prod [Preorder α] [Preorder β] {s : Set (α × β)} (p : α × β) : + IsGLB s p ↔ IsGLB (Prod.fst '' s) p.1 ∧ IsGLB (Prod.snd '' s) p.2 := + @isLUB_prod αᵒᵈ βᵒᵈ _ _ _ _ +#align is_glb_prod isGLB_prod + +end Prod + + section Pi variable {π : α → Type*} [∀ a, Preorder (π a)] @@ -1614,27 +1662,26 @@ theorem IsLUB.of_image [Preorder α] [Preorder β] {f : α → β} (hf : ∀ {x hf.1 <| hx.2 <| Monotone.mem_upperBounds_image (fun _ _ => hf.2) hy⟩ #align is_lub.of_image IsLUB.of_image -theorem isLUB_prod [Preorder α] [Preorder β] {s : Set (α × β)} (p : α × β) : - IsLUB s p ↔ IsLUB (Prod.fst '' s) p.1 ∧ IsLUB (Prod.snd '' s) p.2 := by - refine' - ⟨fun H => - ⟨⟨monotone_fst.mem_upperBounds_image H.1, fun a ha => _⟩, - ⟨monotone_snd.mem_upperBounds_image H.1, fun a ha => _⟩⟩, - fun H => ⟨_, _⟩⟩ - · suffices h : (a, p.2) ∈ upperBounds s from (H.2 h).1 - exact fun q hq => ⟨ha <| mem_image_of_mem _ hq, (H.1 hq).2⟩ - · suffices h : (p.1, a) ∈ upperBounds s from (H.2 h).2 - exact fun q hq => ⟨(H.1 hq).1, ha <| mem_image_of_mem _ hq⟩ - · exact fun q hq => ⟨H.1.1 <| mem_image_of_mem _ hq, H.2.1 <| mem_image_of_mem _ hq⟩ - · exact fun q hq => - ⟨H.1.2 <| monotone_fst.mem_upperBounds_image hq, - H.2.2 <| monotone_snd.mem_upperBounds_image hq⟩ -#align is_lub_prod isLUB_prod - -theorem isGLB_prod [Preorder α] [Preorder β] {s : Set (α × β)} (p : α × β) : - IsGLB s p ↔ IsGLB (Prod.fst '' s) p.1 ∧ IsGLB (Prod.snd '' s) p.2 := - @isLUB_prod αᵒᵈ βᵒᵈ _ _ _ _ -#align is_glb_prod isGLB_prod +lemma BddAbove.range_mono [Preorder β] {f : α → β} (g : α → β) (h : ∀ a, f a ≤ g a) + (hbdd : BddAbove (range g)) : BddAbove (range f) := by + obtain ⟨C, hC⟩ := hbdd + use C + rintro - ⟨x, rfl⟩ + exact (h x).trans (hC <| mem_range_self x) + +lemma BddBelow.range_mono [Preorder β] (f : α → β) {g : α → β} (h : ∀ a, f a ≤ g a) + (hbdd : BddBelow (range f)) : BddBelow (range g) := + BddAbove.range_mono (β := βᵒᵈ) f h hbdd + +lemma BddAbove.range_comp {γ : Type*} [Preorder β] [Preorder γ] {f : α → β} {g : β → γ} + (hf : BddAbove (range f)) (hg : Monotone g) : BddAbove (range (fun x => g (f x))) := by + change BddAbove (range (g ∘ f)) + simpa only [Set.range_comp] using hg.map_bddAbove hf + +lemma BddBelow.range_comp {γ : Type*} [Preorder β] [Preorder γ] {f : α → β} {g : β → γ} + (hf : BddBelow (range f)) (hg : Monotone g) : BddBelow (range (fun x => g (f x))) := by + change BddBelow (range (g ∘ f)) + simpa only [Set.range_comp] using hg.map_bddBelow hf section ScottContinuous variable [Preorder α] [Preorder β] {f : α → β} {a : α} diff --git a/Mathlib/Order/Category/BddLat.lean b/Mathlib/Order/Category/BddLat.lean index 7ba3c253cfee5..afb266ac4b7cf 100644 --- a/Mathlib/Order/Category/BddLat.lean +++ b/Mathlib/Order/Category/BddLat.lean @@ -64,14 +64,14 @@ instance : LargeCategory.{u} BddLat where assoc _ _ _ := BoundedLatticeHom.comp_assoc _ _ _ -- Porting note: added. -instance instFunLike (X Y : BddLat) : FunLike (X ⟶ Y) X (fun _ => Y) := - show FunLike (BoundedLatticeHom X Y) X (fun _ => Y) from inferInstance +instance instFunLike (X Y : BddLat) : FunLike (X ⟶ Y) X Y := + show FunLike (BoundedLatticeHom X Y) X Y from inferInstance instance : ConcreteCategory BddLat where forget := { obj := (↑) - map := FunLike.coe } - forget_faithful := ⟨(FunLike.coe_injective ·)⟩ + map := DFunLike.coe } + forget_faithful := ⟨(DFunLike.coe_injective ·)⟩ instance hasForgetToBddOrd : HasForget₂ BddLat BddOrd where forget₂ := diff --git a/Mathlib/Order/Category/BddOrd.lean b/Mathlib/Order/Category/BddOrd.lean index b8fe4627256cd..265341df97311 100644 --- a/Mathlib/Order/Category/BddOrd.lean +++ b/Mathlib/Order/Category/BddOrd.lean @@ -63,14 +63,14 @@ instance largeCategory : LargeCategory.{u} BddOrd where -- Porting note: added. -- see https://github.com/leanprover-community/mathlib4/issues/5017 -instance instFunLike (X Y : BddOrd) : FunLike (X ⟶ Y) X (fun _ => Y) := - show FunLike (BoundedOrderHom X Y) X (fun _ => Y) from inferInstance +instance instFunLike (X Y : BddOrd) : FunLike (X ⟶ Y) X Y := + show FunLike (BoundedOrderHom X Y) X Y from inferInstance instance concreteCategory : ConcreteCategory BddOrd where forget := { obj := (↥) - map := FunLike.coe } - forget_faithful := ⟨(FunLike.coe_injective ·)⟩ + map := DFunLike.coe } + forget_faithful := ⟨(DFunLike.coe_injective ·)⟩ #align BddOrd.concrete_category BddOrd.concreteCategory instance hasForgetToPartOrd : HasForget₂ BddOrd PartOrd where diff --git a/Mathlib/Order/Category/CompleteLat.lean b/Mathlib/Order/Category/CompleteLat.lean index 495b8cb82c58d..e5fd83d5aa018 100644 --- a/Mathlib/Order/Category/CompleteLat.lean +++ b/Mathlib/Order/Category/CompleteLat.lean @@ -50,7 +50,7 @@ instance : BundledHom @CompleteLatticeHom where toFun _ _ f := f.toFun id := @CompleteLatticeHom.id comp := @CompleteLatticeHom.comp - hom_ext _ _ _ _ h := FunLike.coe_injective h + hom_ext _ _ _ _ h := DFunLike.coe_injective h deriving instance LargeCategory for CompleteLat diff --git a/Mathlib/Order/Category/FinBoolAlg.lean b/Mathlib/Order/Category/FinBoolAlg.lean index 6f265d00010c5..df078c7c8d208 100644 --- a/Mathlib/Order/Category/FinBoolAlg.lean +++ b/Mathlib/Order/Category/FinBoolAlg.lean @@ -113,12 +113,12 @@ instance forgetToFinPartOrdFaithful : Faithful (forget₂ FinBoolAlg FinPartOrd) -- Porting note: original code -- ⟨fun {X Y} f g h => -- haveI := congr_arg (coeFn : _ → X → Y) h - -- FunLike.coe_injective this⟩ + -- DFunLike.coe_injective this⟩ -- Porting note: the coercions to functions for the various bundled order categories -- are quite inconsistent. We need to go back through and make all these files uniform. ⟨fun {X Y} f g h => by dsimp at * - apply FunLike.coe_injective + apply DFunLike.coe_injective dsimp ext x apply_fun (fun f => f x) at h diff --git a/Mathlib/Order/Category/Frm.lean b/Mathlib/Order/Category/Frm.lean index e4be664f3f255..1571eec274bbb 100644 --- a/Mathlib/Order/Category/Frm.lean +++ b/Mathlib/Order/Category/Frm.lean @@ -62,7 +62,7 @@ instance bundledHom : BundledHom Hom where toFun {α β} _ _ := ((↑) : FrameHom α β → α → β) id {α} _ := FrameHom.id α comp _ _ _ := FrameHom.comp - hom_ext _ _ := FunLike.coe_injective + hom_ext _ _ := DFunLike.coe_injective #align Frm.bundled_hom Frm.bundledHom -- Porting note: Originally `deriving instance LargeCategory, ConcreteCategory for Frm` diff --git a/Mathlib/Order/Category/HeytAlg.lean b/Mathlib/Order/Category/HeytAlg.lean index 5ff616983170e..b9c66d422db64 100644 --- a/Mathlib/Order/Category/HeytAlg.lean +++ b/Mathlib/Order/Category/HeytAlg.lean @@ -47,10 +47,10 @@ instance : Inhabited HeytAlg := ⟨of PUnit⟩ instance bundledHom : BundledHom HeytingHom where - toFun α β [HeytingAlgebra α] [HeytingAlgebra β] := (FunLike.coe : HeytingHom α β → α → β) + toFun α β [HeytingAlgebra α] [HeytingAlgebra β] := (DFunLike.coe : HeytingHom α β → α → β) id := @HeytingHom.id comp := @HeytingHom.comp - hom_ext α β [HeytingAlgebra α] [HeytingAlgebra β] := FunLike.coe_injective + hom_ext α β [HeytingAlgebra α] [HeytingAlgebra β] := DFunLike.coe_injective #align HeytAlg.bundled_hom HeytAlg.bundledHom deriving instance LargeCategory for HeytAlg diff --git a/Mathlib/Order/Category/Lat.lean b/Mathlib/Order/Category/Lat.lean index 2ba6724e23dde..7c0c841927428 100644 --- a/Mathlib/Order/Category/Lat.lean +++ b/Mathlib/Order/Category/Lat.lean @@ -58,7 +58,7 @@ instance : BundledHom @LatticeHom where toFun _ _ f := f.toFun id := @LatticeHom.id comp := @LatticeHom.comp - hom_ext _ _ _ _ h := FunLike.coe_injective h + hom_ext _ _ _ _ h := DFunLike.coe_injective h instance : LargeCategory.{u} Lat := BundledHom.category LatticeHom diff --git a/Mathlib/Order/Category/NonemptyFinLinOrd.lean b/Mathlib/Order/Category/NonemptyFinLinOrd.lean index 56cfc23252b87..f2d0fe2e019ff 100644 --- a/Mathlib/Order/Category/NonemptyFinLinOrd.lean +++ b/Mathlib/Order/Category/NonemptyFinLinOrd.lean @@ -201,7 +201,7 @@ theorem epi_iff_surjective {A B : NonemptyFinLinOrd.{u}} (f : A ⟶ B) : exact h₂ (le_of_lt h₁) · exfalso exact hm a (eq_of_le_of_not_lt h₂ h₁) - simp [FunLike.coe] at h + simp [DFunLike.coe] at h · intro h exact ConcreteCategory.epi_of_surjective f h set_option linter.uppercaseLean3 false in diff --git a/Mathlib/Order/Category/Semilat.lean b/Mathlib/Order/Category/Semilat.lean index 60c7c7d31e871..93be7b0610e1c 100644 --- a/Mathlib/Order/Category/Semilat.lean +++ b/Mathlib/Order/Category/Semilat.lean @@ -69,14 +69,14 @@ instance : LargeCategory.{u} SemilatSupCat where -- Porting note: added -- see https://github.com/leanprover-community/mathlib4/issues/5017 -instance instFunLike (X Y : SemilatSupCat) : FunLike (X ⟶ Y) X (fun _ => Y) := - show FunLike (SupBotHom X Y) X (fun _ => Y) from inferInstance +instance instFunLike (X Y : SemilatSupCat) : FunLike (X ⟶ Y) X Y := + show FunLike (SupBotHom X Y) X Y from inferInstance instance : ConcreteCategory SemilatSupCat where forget := { obj := SemilatSupCat.X - map := FunLike.coe } - forget_faithful := ⟨(FunLike.coe_injective ·)⟩ + map := DFunLike.coe } + forget_faithful := ⟨(DFunLike.coe_injective ·)⟩ instance hasForgetToPartOrd : HasForget₂ SemilatSupCat PartOrd where forget₂ := @@ -123,14 +123,14 @@ instance : LargeCategory.{u} SemilatInfCat where assoc _ _ _ := InfTopHom.comp_assoc _ _ _ -- Porting note: added -instance instFunLike (X Y : SemilatInfCat) : FunLike (X ⟶ Y) X (fun _ => Y) := - show FunLike (InfTopHom X Y) X (fun _ => Y) from inferInstance +instance instFunLike (X Y : SemilatInfCat) : FunLike (X ⟶ Y) X Y := + show FunLike (InfTopHom X Y) X Y from inferInstance instance : ConcreteCategory SemilatInfCat where forget := { obj := SemilatInfCat.X - map := FunLike.coe } - forget_faithful := ⟨(FunLike.coe_injective ·)⟩ + map := DFunLike.coe } + forget_faithful := ⟨(DFunLike.coe_injective ·)⟩ instance hasForgetToPartOrd : HasForget₂ SemilatInfCat PartOrd where forget₂ := diff --git a/Mathlib/Order/Closure.lean b/Mathlib/Order/Closure.lean index 0b4ee02693ff7..45891221534aa 100644 --- a/Mathlib/Order/Closure.lean +++ b/Mathlib/Order/Closure.lean @@ -73,7 +73,7 @@ namespace ClosureOperator instance [Preorder α] : OrderHomClass (ClosureOperator α) α α where coe c := c.1 - coe_injective' := by rintro ⟨⟩ ⟨⟩ h; obtain rfl := FunLike.ext' h; congr with x; simp [*] + coe_injective' := by rintro ⟨⟩ ⟨⟩ h; obtain rfl := DFunLike.ext' h; congr with x; simp [*] map_rel f _ _ h := f.mono h initialize_simps_projections ClosureOperator (toFun → apply, IsClosed → isClosed) @@ -101,7 +101,7 @@ variable {α} [PartialOrder α] (c : ClosureOperator α) @[ext] theorem ext : ∀ c₁ c₂ : ClosureOperator α, (c₁ : α → α) = (c₂ : α → α) → c₁ = c₂ := - FunLike.coe_injective + DFunLike.coe_injective #align closure_operator.ext ClosureOperator.ext /-- Constructor for a closure operator using the weaker idempotency axiom: `f (f x) ≤ f x`. -/ @@ -134,7 +134,7 @@ def ofPred (f : α → α) (p : α → Prop) (hf : ∀ x, x ≤ f x) (hfp : ∀ (hmin : ∀ ⦃x y⦄, x ≤ y → p y → f x ≤ y) : ClosureOperator α where __ := mk₂ f hf fun _ y hxy => hmin hxy (hfp y) IsClosed := p - isClosed_iff := ⟨λ hx ↦ (hmin le_rfl hx).antisymm $ hf _, λ hx ↦ hx ▸ hfp _⟩ + isClosed_iff := ⟨λ hx ↦ (hmin le_rfl hx).antisymm <| hf _, λ hx ↦ hx ▸ hfp _⟩ #align closure_operator.mk₃ ClosureOperator.ofPred #align closure_operator.mk₃_apply ClosureOperator.ofPred_apply #align closure_operator.mem_mk₃_closed ClosureOperator.ofPred_isClosed @@ -158,7 +158,7 @@ theorem idempotent (x : α) : c (c x) = c x := c.idempotent' x #align closure_operator.idempotent ClosureOperator.idempotent -@[simp] lemma isClosed_closure (x : α) : c.IsClosed (c x) := c.isClosed_iff.2 $ c.idempotent x +@[simp] lemma isClosed_closure (x : α) : c.IsClosed (c x) := c.isClosed_iff.2 <| c.idempotent x #align closure_operator.closure_is_closed ClosureOperator.isClosed_closure /-- The type of elements closed under a closure operator. -/ @@ -174,7 +174,7 @@ theorem IsClosed.closure_eq : c.IsClosed x → c x = x := c.isClosed_iff.1 #align closure_operator.closure_eq_self_of_mem_closed ClosureOperator.IsClosed.closure_eq theorem isClosed_iff_closure_le : c.IsClosed x ↔ c x ≤ x := - ⟨fun h ↦ h.closure_eq.le, fun h ↦ c.isClosed_iff.2 $ h.antisymm $ c.le_closure x⟩ + ⟨fun h ↦ h.closure_eq.le, fun h ↦ c.isClosed_iff.2 <| h.antisymm <| c.le_closure x⟩ #align closure_operator.mem_closed_iff_closure_le ClosureOperator.isClosed_iff_closure_le /-- The set of closed elements for `c` is exactly its range. -/ @@ -257,7 +257,7 @@ variable [CompleteLattice α] (c : ClosureOperator α) {p : α → Prop} def ofCompletePred (p : α → Prop) (hsinf : ∀ s, (∀ a ∈ s, p a) → p (sInf s)) : ClosureOperator α := ofPred (fun a ↦ ⨅ b : {b // a ≤ b ∧ p b}, b) p (fun a ↦ by simp [forall_swap]) - (fun a ↦ hsinf _ $ forall_range_iff.2 fun b ↦ b.2.2) + (fun a ↦ hsinf _ <| forall_range_iff.2 fun b ↦ b.2.2) (fun a b hab hb ↦ iInf_le_of_le ⟨b, hab, hb⟩ le_rfl) @[simp] diff --git a/Mathlib/Order/CompactlyGenerated.lean b/Mathlib/Order/CompactlyGenerated.lean index 8f353e1d84ec0..d2d55ef290b90 100644 --- a/Mathlib/Order/CompactlyGenerated.lean +++ b/Mathlib/Order/CompactlyGenerated.lean @@ -189,7 +189,7 @@ theorem isCompactElement_finsetSup {α β : Type*} [CompleteLattice α] {f : β classical rw [isCompactElement_iff_le_of_directed_sSup_le] intro d hemp hdir hsup - rw [← Function.comp.left_id f] + rw [← Function.id_comp f] rw [← Finset.sup_image] apply Finset.sup_le_of_le_directed d hemp hdir rintro x hx diff --git a/Mathlib/Order/CompleteLattice.lean b/Mathlib/Order/CompleteLattice.lean index 76dd3366232d2..2b5a82d2cd4c5 100644 --- a/Mathlib/Order/CompleteLattice.lean +++ b/Mathlib/Order/CompleteLattice.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl -/ import Mathlib.Data.Bool.Set import Mathlib.Data.Nat.Set +import Mathlib.Data.Set.Prod import Mathlib.Data.ULift import Mathlib.Order.Bounds.Basic import Mathlib.Order.Hom.Basic @@ -305,12 +306,7 @@ theorem iInf_le_iff {s : ι → α} : iInf s ≤ a ↔ ∀ b, (∀ i, b ≤ s i) #align infi_le_iff iInf_le_iff theorem sInf_le_sInf_of_forall_exists_le (h : ∀ x ∈ s, ∃ y ∈ t, y ≤ x) : sInf t ≤ sInf s := - le_of_forall_le - (by - simp only [le_sInf_iff] - introv h₀ h₁ - rcases h _ h₁ with ⟨y, hy, hy'⟩ - solve_by_elim [le_trans _ hy']) + le_sInf fun x hx ↦ let ⟨_y, hyt, hyx⟩ := h x hx; sInf_le_of_le hyt hyx #align Inf_le_Inf_of_forall_exists_le sInf_le_sInf_of_forall_exists_le -- We will generalize this to conditionally complete lattices in `csInf_singleton`. @@ -1992,12 +1988,12 @@ end Prod lemma sInf_prod [InfSet α] [InfSet β] {s : Set α} {t : Set β} (hs : s.Nonempty) (ht : t.Nonempty) : sInf (s ×ˢ t) = (sInf s, sInf t) := -congr_arg₂ Prod.mk (congr_arg sInf $ fst_image_prod _ ht) (congr_arg sInf $ snd_image_prod hs _) +congr_arg₂ Prod.mk (congr_arg sInf <| fst_image_prod _ ht) (congr_arg sInf <| snd_image_prod hs _) #align Inf_prod sInf_prod lemma sSup_prod [SupSet α] [SupSet β] {s : Set α} {t : Set β} (hs : s.Nonempty) (ht : t.Nonempty) : sSup (s ×ˢ t) = (sSup s, sSup t) := -congr_arg₂ Prod.mk (congr_arg sSup $ fst_image_prod _ ht) (congr_arg sSup $ snd_image_prod hs _) +congr_arg₂ Prod.mk (congr_arg sSup <| fst_image_prod _ ht) (congr_arg sSup <| snd_image_prod hs _) #align Sup_prod sSup_prod section CompleteLattice diff --git a/Mathlib/Order/CompletePartialOrder.lean b/Mathlib/Order/CompletePartialOrder.lean index 9f6378e9d4a76..6a58947bbae0f 100644 --- a/Mathlib/Order/CompletePartialOrder.lean +++ b/Mathlib/Order/CompletePartialOrder.lean @@ -53,10 +53,10 @@ protected lemma DirectedOn.sSup_le (hd : DirectedOn (. ≤ .) d) (ha : ∀ b ∈ hd.isLUB_sSup.2 ha protected lemma Directed.le_iSup (hf : Directed (. ≤ .) f) (i : ι) : f i ≤ ⨆ j, f j := -hf.directedOn_range.le_sSup $ Set.mem_range_self _ +hf.directedOn_range.le_sSup <| Set.mem_range_self _ protected lemma Directed.iSup_le (hf : Directed (. ≤ .) f) (ha : ∀ i, f i ≤ a) : ⨆ i, f i ≤ a := -hf.directedOn_range.sSup_le $ Set.forall_range_iff.2 ha +hf.directedOn_range.sSup_le <| Set.forall_range_iff.2 ha --TODO: We could mimic more `sSup`/`iSup` lemmas diff --git a/Mathlib/Order/CompleteSublattice.lean b/Mathlib/Order/CompleteSublattice.lean new file mode 100644 index 0000000000000..e14dfdf98fdf7 --- /dev/null +++ b/Mathlib/Order/CompleteSublattice.lean @@ -0,0 +1,125 @@ +/- +Copyright (c) 2023 Oliver Nash. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Oliver Nash +-/ +import Mathlib.Order.Sublattice +import Mathlib.Order.Hom.CompleteLattice + +/-! +# Complete Sublattices + +This file defines complete sublattices. These are subsets of complete lattices which are closed +under arbitrary suprema and infima. As a standard example one could take the complete sublattice of +invariant submodules of some module with respect to a linear map. + +## Main definitions: + * `CompleteSublattice`: the definition of a complete sublattice + * `CompleteSublattice.mk'`: an alternate constructor for a complete sublattice, demanding fewer + hypotheses + * `CompleteSublattice.instCompleteLattice`: a complete sublattice is a complete lattice + * `CompleteSublattice.map`: complete sublattices push forward under complete lattice morphisms. + * `CompleteSublattice.comap`: complete sublattices pull back under complete lattice morphisms. + +-/ + +open Function Set + +variable (α β : Type*) [CompleteLattice α] [CompleteLattice β] (f : CompleteLatticeHom α β) + +/-- A complete sublattice is a subset of a complete lattice that is closed under arbitrary suprema +and infima. -/ +structure CompleteSublattice extends Sublattice α where + sSupClosed' : ∀ ⦃s : Set α⦄, s ⊆ carrier → sSup s ∈ carrier + sInfClosed' : ∀ ⦃s : Set α⦄, s ⊆ carrier → sInf s ∈ carrier + +variable {α β} + +namespace CompleteSublattice + +/-- To check that a subset is a complete sublattice, one does not need to check that it is closed +under binary `Sup` since this follows from the stronger `sSup` condition. Likewise for infima. -/ +@[simps] def mk' (carrier : Set α) + (sSupClosed' : ∀ ⦃s : Set α⦄, s ⊆ carrier → sSup s ∈ carrier) + (sInfClosed' : ∀ ⦃s : Set α⦄, s ⊆ carrier → sInf s ∈ carrier) : + CompleteSublattice α where + carrier := carrier + sSupClosed' := sSupClosed' + sInfClosed' := sInfClosed' + supClosed' := fun x hx y hy ↦ by + suffices x ⊔ y = sSup {x, y} by exact this ▸ sSupClosed' (fun z hz ↦ by aesop) + simp [sSup_singleton] + infClosed' := fun x hx y hy ↦ by + suffices x ⊓ y = sInf {x, y} by exact this ▸ sInfClosed' (fun z hz ↦ by aesop) + simp [sInf_singleton] + +variable {L : CompleteSublattice α} + +instance instSetLike : SetLike (CompleteSublattice α) α where + coe L := L.carrier + coe_injective' L M h := by cases L; cases M; congr; exact SetLike.coe_injective' h + +instance instBot : Bot L where + bot := ⟨⊥, by simpa using L.sSupClosed' <| empty_subset _⟩ + +instance instTop : Top L where + top := ⟨⊤, by simpa using L.sInfClosed' <| empty_subset _⟩ + +instance instSupSet : SupSet L where + sSup s := ⟨sSup s, L.sSupClosed' image_val_subset⟩ + +instance instInfSet : InfSet L where + sInf s := ⟨sInf s, L.sInfClosed' image_val_subset⟩ + +theorem sSupClosed {s : Set α} (h : s ⊆ L) : sSup s ∈ L := L.sSupClosed' h + +theorem sInfClosed {s : Set α} (h : s ⊆ L) : sInf s ∈ L := L.sInfClosed' h + +@[simp] theorem coe_bot : (↑(⊥ : L) : α) = ⊥ := rfl + +@[simp] theorem coe_top : (↑(⊤ : L) : α) = ⊤ := rfl + +@[simp] theorem coe_sSup (S : Set L) : (↑(sSup S) : α) = sSup {(s : α) | s ∈ S} := rfl + +theorem coe_sSup' (S : Set L) : (↑(sSup S) : α) = ⨆ N ∈ S, (N : α) := by + rw [coe_sSup, ← Set.image, sSup_image] + +@[simp] theorem coe_sInf (S : Set L) : (↑(sInf S) : α) = sInf {(s : α) | s ∈ S} := rfl + +theorem coe_sInf' (S : Set L) : (↑(sInf S) : α) = ⨅ N ∈ S, (N : α) := by + rw [coe_sInf, ← Set.image, sInf_image] + +instance instCompleteLattice : CompleteLattice L := + Subtype.coe_injective.completeLattice _ + Sublattice.coe_sup Sublattice.coe_inf coe_sSup' coe_sInf' coe_top coe_bot + +/-- The push forward of a complete sublattice under a complete lattice hom is a complete +sublattice. -/ +@[simps] def map (L : CompleteSublattice α) : CompleteSublattice β where + carrier := f '' L + supClosed' := L.supClosed.image f + infClosed' := L.infClosed.image f + sSupClosed' := fun s hs ↦ by + obtain ⟨t, ht, rfl⟩ := subset_image_iff.mp hs + rw [← map_sSup] + exact mem_image_of_mem f (sSupClosed ht) + sInfClosed' := fun s hs ↦ by + obtain ⟨t, ht, rfl⟩ := subset_image_iff.mp hs + rw [← map_sInf] + exact mem_image_of_mem f (sInfClosed ht) + +@[simp] theorem mem_map {b : β} : b ∈ L.map f ↔ ∃ a ∈ L, f a = b := Iff.rfl + +/-- The pull back of a complete sublattice under a complete lattice hom is a complete sublattice. -/ +@[simps] def comap (L : CompleteSublattice β) : CompleteSublattice α where + carrier := f ⁻¹' L + supClosed' := L.supClosed.preimage f + infClosed' := L.infClosed.preimage f + sSupClosed' s hs := by + simpa only [mem_preimage, map_sSup, SetLike.mem_coe] using sSupClosed <| mapsTo'.mp hs + sInfClosed' s hs := by + simpa only [mem_preimage, map_sInf, SetLike.mem_coe] using sInfClosed <| mapsTo'.mp hs + +@[simp] theorem mem_comap {L : CompleteSublattice β} {a : α} : a ∈ L.comap f ↔ f a ∈ L := Iff.rfl + +end CompleteSublattice diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean index 179a4fbe5ceb3..c9201289b995f 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Order.Bounds.Basic import Mathlib.Order.WellFounded +import Mathlib.Data.Set.Image import Mathlib.Data.Set.Intervals.Basic import Mathlib.Data.Set.Lattice @@ -62,7 +63,7 @@ noncomputable instance WithBot.instInfSet {α : Type*} [Preorder α] [InfSet α] theorem WithTop.sSup_eq [Preorder α] [SupSet α] {s : Set (WithTop α)} (hs : ⊤ ∉ s) (hs' : BddAbove ((↑) ⁻¹' s : Set α)) : sSup s = ↑(sSup ((↑) ⁻¹' s) : α) := - (if_neg hs).trans $ if_pos hs' + (if_neg hs).trans <| if_pos hs' #align with_top.Sup_eq WithTop.sSup_eq theorem WithTop.sInf_eq [InfSet α] {s : Set (WithTop α)} (hs : ¬s ⊆ {⊤}) : @@ -72,7 +73,7 @@ theorem WithTop.sInf_eq [InfSet α] {s : Set (WithTop α)} (hs : ¬s ⊆ {⊤}) theorem WithBot.sInf_eq [Preorder α] [InfSet α] {s : Set (WithBot α)} (hs : ⊥ ∉ s) (hs' : BddBelow ((↑) ⁻¹' s : Set α)) : sInf s = ↑(sInf ((↑) ⁻¹' s) : α) := - (if_neg hs).trans $ if_pos hs' + (if_neg hs).trans <| if_pos hs' #align with_bot.Inf_eq WithBot.sInf_eq theorem WithBot.sSup_eq [SupSet α] {s : Set (WithBot α)} (hs : ¬s ⊆ {⊥}) : @@ -975,7 +976,7 @@ lemma Set.Ici_ciSup [Nonempty ι] {f : ι → α} (hf : BddAbove (range f)) : end ConditionallyCompleteLattice -instance Pi.conditionallyCompleteLattice {ι : Type*} {α : ∀ _i : ι, Type*} +instance Pi.conditionallyCompleteLattice {ι : Type*} {α : ι → Type*} [∀ i, ConditionallyCompleteLattice (α i)] : ConditionallyCompleteLattice (∀ i, α i) := { Pi.lattice, Pi.supSet, Pi.infSet with le_csSup := fun s f ⟨g, hg⟩ hf i => diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Finset.lean b/Mathlib/Order/ConditionallyCompleteLattice/Finset.lean index fca70fc653840..bd8268ec9ce12 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Finset.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Finset.lean @@ -16,24 +16,7 @@ import Mathlib.Data.Set.Finite open Set -variable {α β γ : Type*} - -section ConditionallyCompleteLattice - -variable [ConditionallyCompleteLattice α] {s t : Set α} {a b : α} - -theorem Finset.Nonempty.sup'_eq_cSup_image {s : Finset β} (hs : s.Nonempty) (f : β → α) : - s.sup' hs f = sSup (f '' s) := - eq_of_forall_ge_iff fun a => by - simp [csSup_le_iff (s.finite_toSet.image f).bddAbove (hs.to_set.image f)] -#align finset.nonempty.sup'_eq_cSup_image Finset.Nonempty.sup'_eq_cSup_image - -theorem Finset.Nonempty.sup'_id_eq_cSup {s : Finset α} (hs : s.Nonempty) : - s.sup' hs id = sSup s := by - rw [hs.sup'_eq_cSup_image, Set.image_id] -#align finset.nonempty.sup'_id_eq_cSup Finset.Nonempty.sup'_id_eq_cSup - -end ConditionallyCompleteLattice +variable {ι α β γ : Type*} section ConditionallyCompleteLinearOrder @@ -76,34 +59,33 @@ theorem Set.Finite.lt_cInf_iff (hs : s.Finite) (h : s.Nonempty) : a < sInf s ↔ end ConditionallyCompleteLinearOrder /-! -### Relation between `Sup` / `Inf` and `Finset.sup'` / `Finset.inf'` +### Relation between `sSup` / `sInf` and `Finset.sup'` / `Finset.inf'` Like the `Sup` of a `ConditionallyCompleteLattice`, `Finset.sup'` also requires the set to be non-empty. As a result, we can translate between the two. -/ - namespace Finset -variable {ι : Type*} [ConditionallyCompleteLattice α] - -theorem sup'_eq_csSup_image (s : Finset ι) (H) (f : ι → α) : s.sup' H f = sSup (f '' s) := by - apply le_antisymm - · refine' Finset.sup'_le _ _ fun a ha => _ - refine' le_csSup ⟨s.sup' H f, _⟩ ⟨a, ha, rfl⟩ - rintro i ⟨j, hj, rfl⟩ - exact Finset.le_sup' _ hj - · apply csSup_le ((coe_nonempty.mpr H).image _) - rintro _ ⟨a, ha, rfl⟩ - exact Finset.le_sup' _ ha + +section ConditionallyCompleteLattice +variable [ConditionallyCompleteLattice α] + +theorem sup'_eq_csSup_image (s : Finset ι) (H : s.Nonempty) (f : ι → α) : + s.sup' H f = sSup (f '' s) := + eq_of_forall_ge_iff fun a => by + simp [csSup_le_iff (s.finite_toSet.image f).bddAbove (H.to_set.image f)] #align finset.sup'_eq_cSup_image Finset.sup'_eq_csSup_image +#align finset.nonempty.sup'_eq_cSup_image Finset.sup'_eq_csSup_image -theorem inf'_eq_csInf_image (s : Finset ι) (hs) (f : ι → α) : s.inf' hs f = sInf (f '' s) := - sup'_eq_csSup_image (α := αᵒᵈ) _ hs _ +theorem inf'_eq_csInf_image (s : Finset ι) (H : s.Nonempty) (f : ι → α) : + s.inf' H f = sInf (f '' s) := + sup'_eq_csSup_image (α := αᵒᵈ) _ H _ #align finset.inf'_eq_cInf_image Finset.inf'_eq_csInf_image theorem sup'_id_eq_csSup (s : Finset α) (hs) : s.sup' hs id = sSup s := by rw [sup'_eq_csSup_image s hs, Set.image_id] #align finset.sup'_id_eq_cSup Finset.sup'_id_eq_csSup +#align finset.nonempty.sup'_id_eq_cSup Finset.sup'_id_eq_csSup theorem inf'_id_eq_csInf (s : Finset α) (hs) : s.inf' hs id = sInf s := sup'_id_eq_csSup (α := αᵒᵈ) _ hs @@ -117,4 +99,16 @@ lemma sup'_univ_eq_ciSup (f : ι → α) : univ.sup' univ_nonempty f = ⨆ i, f lemma inf'_univ_eq_ciInf (f : ι → α) : univ.inf' univ_nonempty f = ⨅ i, f i := by simp [inf'_eq_csInf_image, iInf] +end ConditionallyCompleteLattice + +section ConditionallyCompleteLinearOrderBot +variable [ConditionallyCompleteLinearOrderBot α] + +lemma sup_univ_eq_ciSup [Fintype ι] (f : ι → α) : univ.sup f = ⨆ i, f i := + le_antisymm + (Finset.sup_le fun _ _ => le_ciSup (finite_range _).bddAbove _) + (ciSup_le' fun _ => Finset.le_sup (mem_univ _)) + +end ConditionallyCompleteLinearOrderBot + end Finset diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Group.lean b/Mathlib/Order/ConditionallyCompleteLattice/Group.lean index dfb6f8cac1634..f040965d8e8be 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Group.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Group.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Order.ConditionallyCompleteLattice.Basic -import Mathlib.Algebra.Order.Group.TypeTags +import Mathlib.Algebra.Order.Group.Defs +import Mathlib.Algebra.Order.Monoid.OrderDual #align_import order.conditionally_complete_lattice.group from "leanprover-community/mathlib"@"46a64b5b4268c594af770c44d9e502afc6a515cb" diff --git a/Mathlib/Order/CountableDenseLinearOrder.lean b/Mathlib/Order/CountableDenseLinearOrder.lean index e18c46aa76d0b..28a03204df4c6 100644 --- a/Mathlib/Order/CountableDenseLinearOrder.lean +++ b/Mathlib/Order/CountableDenseLinearOrder.lean @@ -170,7 +170,7 @@ def definedAtRight [DenselyOrdered α] [NoMinOrder α] [NoMaxOrder α] [Nonempty · change (a, b) ∈ f'.val.image _ rwa [← Finset.mem_coe, Finset.coe_image, Equiv.image_eq_preimage] · change _ ⊆ f'.val.image _ - rwa [← Finset.coe_subset, Finset.coe_image, ← Equiv.subset_image, ← Finset.coe_image, + rwa [← Finset.coe_subset, Finset.coe_image, ← Equiv.symm_image_subset, ← Finset.coe_image, Finset.coe_subset] #align order.partial_iso.defined_at_right Order.PartialIso.definedAtRight diff --git a/Mathlib/Order/Cover.lean b/Mathlib/Order/Cover.lean index a08c80dc06f25..df86a3c970d41 100644 --- a/Mathlib/Order/Cover.lean +++ b/Mathlib/Order/Cover.lean @@ -33,124 +33,124 @@ section Preorder variable [Preorder α] [Preorder β] {a b c : α} -/-- `Wcovby a b` means that `a = b` or `b` covers `a`. +/-- `WCovBy a b` means that `a = b` or `b` covers `a`. This means that `a ≤ b` and there is no element in between. -/ -def Wcovby (a b : α) : Prop := +def WCovBy (a b : α) : Prop := a ≤ b ∧ ∀ ⦃c⦄, a < c → ¬c < b -#align wcovby Wcovby +#align wcovby WCovBy -/-- Notation for `Wcovby a b`. -/ -infixl:50 " ⩿ " => Wcovby +/-- Notation for `WCovBy a b`. -/ +infixl:50 " ⩿ " => WCovBy -theorem Wcovby.le (h : a ⩿ b) : a ≤ b := +theorem WCovBy.le (h : a ⩿ b) : a ≤ b := h.1 -#align wcovby.le Wcovby.le +#align wcovby.le WCovBy.le -theorem Wcovby.refl (a : α) : a ⩿ a := +theorem WCovBy.refl (a : α) : a ⩿ a := ⟨le_rfl, fun _ hc => hc.not_lt⟩ -#align wcovby.refl Wcovby.refl +#align wcovby.refl WCovBy.refl -@[simp] lemma Wcovby.rfl : a ⩿ a := Wcovby.refl a -#align wcovby.rfl Wcovby.rfl +@[simp] lemma WCovBy.rfl : a ⩿ a := WCovBy.refl a +#align wcovby.rfl WCovBy.rfl -protected theorem Eq.wcovby (h : a = b) : a ⩿ b := - h ▸ Wcovby.rfl -#align eq.wcovby Eq.wcovby +protected theorem Eq.wcovBy (h : a = b) : a ⩿ b := + h ▸ WCovBy.rfl +#align eq.wcovby Eq.wcovBy -theorem wcovby_of_le_of_le (h1 : a ≤ b) (h2 : b ≤ a) : a ⩿ b := +theorem wcovBy_of_le_of_le (h1 : a ≤ b) (h2 : b ≤ a) : a ⩿ b := ⟨h1, fun _ hac hcb => (hac.trans hcb).not_le h2⟩ -#align wcovby_of_le_of_le wcovby_of_le_of_le +#align wcovby_of_le_of_le wcovBy_of_le_of_le -alias LE.le.wcovby_of_le := wcovby_of_le_of_le +alias LE.le.wcovBy_of_le := wcovBy_of_le_of_le -theorem AntisymmRel.wcovby (h : AntisymmRel (· ≤ ·) a b) : a ⩿ b := - wcovby_of_le_of_le h.1 h.2 -#align antisymm_rel.wcovby AntisymmRel.wcovby +theorem AntisymmRel.wcovBy (h : AntisymmRel (· ≤ ·) a b) : a ⩿ b := + wcovBy_of_le_of_le h.1 h.2 +#align antisymm_rel.wcovby AntisymmRel.wcovBy -theorem Wcovby.wcovby_iff_le (hab : a ⩿ b) : b ⩿ a ↔ b ≤ a := - ⟨fun h => h.le, fun h => h.wcovby_of_le hab.le⟩ -#align wcovby.wcovby_iff_le Wcovby.wcovby_iff_le +theorem WCovBy.wcovBy_iff_le (hab : a ⩿ b) : b ⩿ a ↔ b ≤ a := + ⟨fun h => h.le, fun h => h.wcovBy_of_le hab.le⟩ +#align wcovby.wcovby_iff_le WCovBy.wcovBy_iff_le -theorem wcovby_of_eq_or_eq (hab : a ≤ b) (h : ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b) : a ⩿ b := +theorem wcovBy_of_eq_or_eq (hab : a ≤ b) (h : ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b) : a ⩿ b := ⟨hab, fun c ha hb => (h c ha.le hb.le).elim ha.ne' hb.ne⟩ -#align wcovby_of_eq_or_eq wcovby_of_eq_or_eq +#align wcovby_of_eq_or_eq wcovBy_of_eq_or_eq -theorem AntisymmRel.trans_wcovby (hab : AntisymmRel (· ≤ ·) a b) (hbc : b ⩿ c) : a ⩿ c := +theorem AntisymmRel.trans_wcovBy (hab : AntisymmRel (· ≤ ·) a b) (hbc : b ⩿ c) : a ⩿ c := ⟨hab.1.trans hbc.le, fun _ had hdc => hbc.2 (hab.2.trans_lt had) hdc⟩ -#align antisymm_rel.trans_wcovby AntisymmRel.trans_wcovby +#align antisymm_rel.trans_wcovby AntisymmRel.trans_wcovBy -theorem wcovby_congr_left (hab : AntisymmRel (· ≤ ·) a b) : a ⩿ c ↔ b ⩿ c := - ⟨hab.symm.trans_wcovby, hab.trans_wcovby⟩ -#align wcovby_congr_left wcovby_congr_left +theorem wcovBy_congr_left (hab : AntisymmRel (· ≤ ·) a b) : a ⩿ c ↔ b ⩿ c := + ⟨hab.symm.trans_wcovBy, hab.trans_wcovBy⟩ +#align wcovby_congr_left wcovBy_congr_left -theorem Wcovby.trans_antisymm_rel (hab : a ⩿ b) (hbc : AntisymmRel (· ≤ ·) b c) : a ⩿ c := +theorem WCovBy.trans_antisymm_rel (hab : a ⩿ b) (hbc : AntisymmRel (· ≤ ·) b c) : a ⩿ c := ⟨hab.le.trans hbc.1, fun _ had hdc => hab.2 had <| hdc.trans_le hbc.2⟩ -#align wcovby.trans_antisymm_rel Wcovby.trans_antisymm_rel +#align wcovby.trans_antisymm_rel WCovBy.trans_antisymm_rel -theorem wcovby_congr_right (hab : AntisymmRel (· ≤ ·) a b) : c ⩿ a ↔ c ⩿ b := +theorem wcovBy_congr_right (hab : AntisymmRel (· ≤ ·) a b) : c ⩿ a ↔ c ⩿ b := ⟨fun h => h.trans_antisymm_rel hab, fun h => h.trans_antisymm_rel hab.symm⟩ -#align wcovby_congr_right wcovby_congr_right +#align wcovby_congr_right wcovBy_congr_right /-- If `a ≤ b`, then `b` does not cover `a` iff there's an element in between. -/ -theorem not_wcovby_iff (h : a ≤ b) : ¬a ⩿ b ↔ ∃ c, a < c ∧ c < b := by - simp_rw [Wcovby, h, true_and_iff, not_forall, exists_prop, not_not] -#align not_wcovby_iff not_wcovby_iff +theorem not_wcovBy_iff (h : a ≤ b) : ¬a ⩿ b ↔ ∃ c, a < c ∧ c < b := by + simp_rw [WCovBy, h, true_and_iff, not_forall, exists_prop, not_not] +#align not_wcovby_iff not_wcovBy_iff -instance Wcovby.isRefl : IsRefl α (· ⩿ ·) := - ⟨Wcovby.refl⟩ -#align wcovby.is_refl Wcovby.isRefl +instance WCovBy.isRefl : IsRefl α (· ⩿ ·) := + ⟨WCovBy.refl⟩ +#align wcovby.is_refl WCovBy.isRefl -theorem Wcovby.Ioo_eq (h : a ⩿ b) : Ioo a b = ∅ := +theorem WCovBy.Ioo_eq (h : a ⩿ b) : Ioo a b = ∅ := eq_empty_iff_forall_not_mem.2 fun _ hx => h.2 hx.1 hx.2 -#align wcovby.Ioo_eq Wcovby.Ioo_eq +#align wcovby.Ioo_eq WCovBy.Ioo_eq -theorem wcovby_iff_Ioo_eq : a ⩿ b ↔ a ≤ b ∧ Ioo a b = ∅ := +theorem wcovBy_iff_Ioo_eq : a ⩿ b ↔ a ≤ b ∧ Ioo a b = ∅ := and_congr_right' <| by simp [eq_empty_iff_forall_not_mem] -#align wcovby_iff_Ioo_eq wcovby_iff_Ioo_eq +#align wcovby_iff_Ioo_eq wcovBy_iff_Ioo_eq -lemma Wcovby.of_le_of_le (hac : a ⩿ c) (hab : a ≤ b) (hbc : b ≤ c) : b ⩿ c := +lemma WCovBy.of_le_of_le (hac : a ⩿ c) (hab : a ≤ b) (hbc : b ≤ c) : b ⩿ c := ⟨hbc, fun _x hbx hxc ↦ hac.2 (hab.trans_lt hbx) hxc⟩ -lemma Wcovby.of_le_of_le' (hac : a ⩿ c) (hab : a ≤ b) (hbc : b ≤ c) : a ⩿ b := +lemma WCovBy.of_le_of_le' (hac : a ⩿ c) (hab : a ≤ b) (hbc : b ≤ c) : a ⩿ b := ⟨hab, fun _x hax hxb ↦ hac.2 hax <| hxb.trans_le hbc⟩ -theorem Wcovby.of_image (f : α ↪o β) (h : f a ⩿ f b) : a ⩿ b := +theorem WCovBy.of_image (f : α ↪o β) (h : f a ⩿ f b) : a ⩿ b := ⟨f.le_iff_le.mp h.le, fun _ hac hcb => h.2 (f.lt_iff_lt.mpr hac) (f.lt_iff_lt.mpr hcb)⟩ -#align wcovby.of_image Wcovby.of_image +#align wcovby.of_image WCovBy.of_image -theorem Wcovby.image (f : α ↪o β) (hab : a ⩿ b) (h : (range f).OrdConnected) : f a ⩿ f b := by +theorem WCovBy.image (f : α ↪o β) (hab : a ⩿ b) (h : (range f).OrdConnected) : f a ⩿ f b := by refine' ⟨f.monotone hab.le, fun c ha hb => _⟩ obtain ⟨c, rfl⟩ := h.out (mem_range_self _) (mem_range_self _) ⟨ha.le, hb.le⟩ rw [f.lt_iff_lt] at ha hb exact hab.2 ha hb -#align wcovby.image Wcovby.image +#align wcovby.image WCovBy.image -theorem Set.OrdConnected.apply_wcovby_apply_iff (f : α ↪o β) (h : (range f).OrdConnected) : +theorem Set.OrdConnected.apply_wcovBy_apply_iff (f : α ↪o β) (h : (range f).OrdConnected) : f a ⩿ f b ↔ a ⩿ b := ⟨fun h2 => h2.of_image f, fun hab => hab.image f h⟩ -#align set.ord_connected.apply_wcovby_apply_iff Set.OrdConnected.apply_wcovby_apply_iff +#align set.ord_connected.apply_wcovby_apply_iff Set.OrdConnected.apply_wcovBy_apply_iff @[simp] -theorem apply_wcovby_apply_iff {E : Type*} [OrderIsoClass E α β] (e : E) : e a ⩿ e b ↔ a ⩿ b := - (ordConnected_range (e : α ≃o β)).apply_wcovby_apply_iff ((e : α ≃o β) : α ↪o β) -#align apply_wcovby_apply_iff apply_wcovby_apply_iff +theorem apply_wcovBy_apply_iff {E : Type*} [OrderIsoClass E α β] (e : E) : e a ⩿ e b ↔ a ⩿ b := + (ordConnected_range (e : α ≃o β)).apply_wcovBy_apply_iff ((e : α ≃o β) : α ↪o β) +#align apply_wcovby_apply_iff apply_wcovBy_apply_iff @[simp] -theorem toDual_wcovby_toDual_iff : toDual b ⩿ toDual a ↔ a ⩿ b := +theorem toDual_wcovBy_toDual_iff : toDual b ⩿ toDual a ↔ a ⩿ b := and_congr_right' <| forall_congr' fun _ => forall_swap -#align to_dual_wcovby_to_dual_iff toDual_wcovby_toDual_iff +#align to_dual_wcovby_to_dual_iff toDual_wcovBy_toDual_iff @[simp] -theorem ofDual_wcovby_ofDual_iff {a b : αᵒᵈ} : ofDual a ⩿ ofDual b ↔ b ⩿ a := +theorem ofDual_wcovBy_ofDual_iff {a b : αᵒᵈ} : ofDual a ⩿ ofDual b ↔ b ⩿ a := and_congr_right' <| forall_congr' fun _ => forall_swap -#align of_dual_wcovby_of_dual_iff ofDual_wcovby_ofDual_iff +#align of_dual_wcovby_of_dual_iff ofDual_wcovBy_ofDual_iff -alias ⟨_, Wcovby.toDual⟩ := toDual_wcovby_toDual_iff -#align wcovby.to_dual Wcovby.toDual +alias ⟨_, WCovBy.toDual⟩ := toDual_wcovBy_toDual_iff +#align wcovby.to_dual WCovBy.toDual -alias ⟨_, Wcovby.ofDual⟩ := ofDual_wcovby_ofDual_iff -#align wcovby.of_dual Wcovby.ofDual +alias ⟨_, WCovBy.ofDual⟩ := ofDual_wcovBy_ofDual_iff +#align wcovby.of_dual WCovBy.ofDual end Preorder @@ -158,34 +158,34 @@ section PartialOrder variable [PartialOrder α] {a b c : α} -theorem Wcovby.eq_or_eq (h : a ⩿ b) (h2 : a ≤ c) (h3 : c ≤ b) : c = a ∨ c = b := by +theorem WCovBy.eq_or_eq (h : a ⩿ b) (h2 : a ≤ c) (h3 : c ≤ b) : c = a ∨ c = b := by rcases h2.eq_or_lt with (h2 | h2); · exact Or.inl h2.symm rcases h3.eq_or_lt with (h3 | h3); · exact Or.inr h3 exact (h.2 h2 h3).elim -#align wcovby.eq_or_eq Wcovby.eq_or_eq +#align wcovby.eq_or_eq WCovBy.eq_or_eq -/-- An `iff` version of `Wcovby.eq_or_eq` and `wcovby_of_eq_or_eq`. -/ -theorem wcovby_iff_le_and_eq_or_eq : a ⩿ b ↔ a ≤ b ∧ ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b := - ⟨fun h => ⟨h.le, fun _ => h.eq_or_eq⟩, And.rec wcovby_of_eq_or_eq⟩ -#align wcovby_iff_le_and_eq_or_eq wcovby_iff_le_and_eq_or_eq +/-- An `iff` version of `WCovBy.eq_or_eq` and `wcovBy_of_eq_or_eq`. -/ +theorem wcovBy_iff_le_and_eq_or_eq : a ⩿ b ↔ a ≤ b ∧ ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b := + ⟨fun h => ⟨h.le, fun _ => h.eq_or_eq⟩, And.rec wcovBy_of_eq_or_eq⟩ +#align wcovby_iff_le_and_eq_or_eq wcovBy_iff_le_and_eq_or_eq -theorem Wcovby.le_and_le_iff (h : a ⩿ b) : a ≤ c ∧ c ≤ b ↔ c = a ∨ c = b := by +theorem WCovBy.le_and_le_iff (h : a ⩿ b) : a ≤ c ∧ c ≤ b ↔ c = a ∨ c = b := by refine' ⟨fun h2 => h.eq_or_eq h2.1 h2.2, _⟩; rintro (rfl | rfl); exacts [⟨le_rfl, h.le⟩, ⟨h.le, le_rfl⟩] -#align wcovby.le_and_le_iff Wcovby.le_and_le_iff +#align wcovby.le_and_le_iff WCovBy.le_and_le_iff -theorem Wcovby.Icc_eq (h : a ⩿ b) : Icc a b = {a, b} := by +theorem WCovBy.Icc_eq (h : a ⩿ b) : Icc a b = {a, b} := by ext c exact h.le_and_le_iff -#align wcovby.Icc_eq Wcovby.Icc_eq +#align wcovby.Icc_eq WCovBy.Icc_eq -theorem Wcovby.Ico_subset (h : a ⩿ b) : Ico a b ⊆ {a} := by +theorem WCovBy.Ico_subset (h : a ⩿ b) : Ico a b ⊆ {a} := by rw [← Icc_diff_right, h.Icc_eq, diff_singleton_subset_iff, pair_comm] -#align wcovby.Ico_subset Wcovby.Ico_subset +#align wcovby.Ico_subset WCovBy.Ico_subset -theorem Wcovby.Ioc_subset (h : a ⩿ b) : Ioc a b ⊆ {b} := by +theorem WCovBy.Ioc_subset (h : a ⩿ b) : Ioc a b ⊆ {b} := by rw [← Icc_diff_left, h.Icc_eq, diff_singleton_subset_iff] -#align wcovby.Ioc_subset Wcovby.Ioc_subset +#align wcovby.Ioc_subset WCovBy.Ioc_subset end PartialOrder @@ -193,10 +193,10 @@ section SemilatticeSup variable [SemilatticeSup α] {a b c : α} -theorem Wcovby.sup_eq (hac : a ⩿ c) (hbc : b ⩿ c) (hab : a ≠ b) : a ⊔ b = c := +theorem WCovBy.sup_eq (hac : a ⩿ c) (hbc : b ⩿ c) (hab : a ≠ b) : a ⊔ b = c := (sup_le hac.le hbc.le).eq_of_not_lt fun h => hab.lt_sup_or_lt_sup.elim (fun h' => hac.2 h' h) fun h' => hbc.2 h' h -#align wcovby.sup_eq Wcovby.sup_eq +#align wcovby.sup_eq WCovBy.sup_eq end SemilatticeSup @@ -204,9 +204,9 @@ section SemilatticeInf variable [SemilatticeInf α] {a b c : α} -theorem Wcovby.inf_eq (hca : c ⩿ a) (hcb : c ⩿ b) (hab : a ≠ b) : a ⊓ b = c := +theorem WCovBy.inf_eq (hca : c ⩿ a) (hcb : c ⩿ b) (hab : a ≠ b) : a ⊓ b = c := (le_inf hca.le hcb.le).eq_of_not_gt fun h => hab.inf_lt_or_inf_lt.elim (hca.2 h) (hcb.2 h) -#align wcovby.inf_eq Wcovby.inf_eq +#align wcovby.inf_eq WCovBy.inf_eq end SemilatticeInf @@ -216,54 +216,54 @@ section LT variable [LT α] {a b : α} -/-- `Covby a b` means that `b` covers `a`: `a < b` and there is no element in between. -/ -def Covby (a b : α) : Prop := +/-- `CovBy a b` means that `b` covers `a`: `a < b` and there is no element in between. -/ +def CovBy (a b : α) : Prop := a < b ∧ ∀ ⦃c⦄, a < c → ¬c < b -#align covby Covby +#align covby CovBy -/-- Notation for `Covby a b`. -/ -infixl:50 " ⋖ " => Covby +/-- Notation for `CovBy a b`. -/ +infixl:50 " ⋖ " => CovBy -theorem Covby.lt (h : a ⋖ b) : a < b := +theorem CovBy.lt (h : a ⋖ b) : a < b := h.1 -#align covby.lt Covby.lt +#align covby.lt CovBy.lt /-- If `a < b`, then `b` does not cover `a` iff there's an element in between. -/ -theorem not_covby_iff (h : a < b) : ¬a ⋖ b ↔ ∃ c, a < c ∧ c < b := by - simp_rw [Covby, h, true_and_iff, not_forall, exists_prop, not_not] -#align not_covby_iff not_covby_iff +theorem not_covBy_iff (h : a < b) : ¬a ⋖ b ↔ ∃ c, a < c ∧ c < b := by + simp_rw [CovBy, h, true_and_iff, not_forall, exists_prop, not_not] +#align not_covby_iff not_covBy_iff -alias ⟨exists_lt_lt_of_not_covby, _⟩ := not_covby_iff -#align exists_lt_lt_of_not_covby exists_lt_lt_of_not_covby +alias ⟨exists_lt_lt_of_not_covBy, _⟩ := not_covBy_iff +#align exists_lt_lt_of_not_covby exists_lt_lt_of_not_covBy -alias LT.lt.exists_lt_lt := exists_lt_lt_of_not_covby +alias LT.lt.exists_lt_lt := exists_lt_lt_of_not_covBy /-- In a dense order, nothing covers anything. -/ -theorem not_covby [DenselyOrdered α] : ¬a ⋖ b := fun h => +theorem not_covBy [DenselyOrdered α] : ¬a ⋖ b := fun h => let ⟨_, hc⟩ := exists_between h.1 h.2 hc.1 hc.2 -#align not_covby not_covby +#align not_covby not_covBy -theorem densely_ordered_iff_forall_not_covby : DenselyOrdered α ↔ ∀ a b : α, ¬a ⋖ b := - ⟨fun h _ _ => @not_covby _ _ _ _ h, fun h => - ⟨fun _ _ hab => exists_lt_lt_of_not_covby hab <| h _ _⟩⟩ -#align densely_ordered_iff_forall_not_covby densely_ordered_iff_forall_not_covby +theorem densely_ordered_iff_forall_not_covBy : DenselyOrdered α ↔ ∀ a b : α, ¬a ⋖ b := + ⟨fun h _ _ => @not_covBy _ _ _ _ h, fun h => + ⟨fun _ _ hab => exists_lt_lt_of_not_covBy hab <| h _ _⟩⟩ +#align densely_ordered_iff_forall_not_covby densely_ordered_iff_forall_not_covBy @[simp] -theorem toDual_covby_toDual_iff : toDual b ⋖ toDual a ↔ a ⋖ b := +theorem toDual_covBy_toDual_iff : toDual b ⋖ toDual a ↔ a ⋖ b := and_congr_right' <| forall_congr' fun _ => forall_swap -#align to_dual_covby_to_dual_iff toDual_covby_toDual_iff +#align to_dual_covby_to_dual_iff toDual_covBy_toDual_iff @[simp] -theorem ofDual_covby_ofDual_iff {a b : αᵒᵈ} : ofDual a ⋖ ofDual b ↔ b ⋖ a := +theorem ofDual_covBy_ofDual_iff {a b : αᵒᵈ} : ofDual a ⋖ ofDual b ↔ b ⋖ a := and_congr_right' <| forall_congr' fun _ => forall_swap -#align of_dual_covby_of_dual_iff ofDual_covby_ofDual_iff +#align of_dual_covby_of_dual_iff ofDual_covBy_ofDual_iff -alias ⟨_, Covby.toDual⟩ := toDual_covby_toDual_iff -#align covby.to_dual Covby.toDual +alias ⟨_, CovBy.toDual⟩ := toDual_covBy_toDual_iff +#align covby.to_dual CovBy.toDual -alias ⟨_, Covby.ofDual⟩ := ofDual_covby_ofDual_iff -#align covby.of_dual Covby.ofDual +alias ⟨_, CovBy.ofDual⟩ := ofDual_covBy_ofDual_iff +#align covby.of_dual CovBy.ofDual end LT @@ -271,106 +271,106 @@ section Preorder variable [Preorder α] [Preorder β] {a b c : α} -theorem Covby.le (h : a ⋖ b) : a ≤ b := +theorem CovBy.le (h : a ⋖ b) : a ≤ b := h.1.le -#align covby.le Covby.le +#align covby.le CovBy.le -protected theorem Covby.ne (h : a ⋖ b) : a ≠ b := +protected theorem CovBy.ne (h : a ⋖ b) : a ≠ b := h.lt.ne -#align covby.ne Covby.ne +#align covby.ne CovBy.ne -theorem Covby.ne' (h : a ⋖ b) : b ≠ a := +theorem CovBy.ne' (h : a ⋖ b) : b ≠ a := h.lt.ne' -#align covby.ne' Covby.ne' +#align covby.ne' CovBy.ne' -protected theorem Covby.wcovby (h : a ⋖ b) : a ⩿ b := +protected theorem CovBy.wcovBy (h : a ⋖ b) : a ⩿ b := ⟨h.le, h.2⟩ -#align covby.wcovby Covby.wcovby +#align covby.wcovby CovBy.wcovBy -theorem Wcovby.covby_of_not_le (h : a ⩿ b) (h2 : ¬b ≤ a) : a ⋖ b := +theorem WCovBy.covBy_of_not_le (h : a ⩿ b) (h2 : ¬b ≤ a) : a ⋖ b := ⟨h.le.lt_of_not_le h2, h.2⟩ -#align wcovby.covby_of_not_le Wcovby.covby_of_not_le +#align wcovby.covby_of_not_le WCovBy.covBy_of_not_le -theorem Wcovby.covby_of_lt (h : a ⩿ b) (h2 : a < b) : a ⋖ b := +theorem WCovBy.covBy_of_lt (h : a ⩿ b) (h2 : a < b) : a ⋖ b := ⟨h2, h.2⟩ -#align wcovby.covby_of_lt Wcovby.covby_of_lt +#align wcovby.covby_of_lt WCovBy.covBy_of_lt -lemma Covby.of_le_of_lt (hac : a ⋖ c) (hab : a ≤ b) (hbc : b < c) : b ⋖ c := +lemma CovBy.of_le_of_lt (hac : a ⋖ c) (hab : a ≤ b) (hbc : b < c) : b ⋖ c := ⟨hbc, fun _x hbx hxc ↦ hac.2 (hab.trans_lt hbx) hxc⟩ -lemma Covby.of_lt_of_le (hac : a ⋖ c) (hab : a < b) (hbc : b ≤ c) : a ⋖ b := +lemma CovBy.of_lt_of_le (hac : a ⋖ c) (hab : a < b) (hbc : b ≤ c) : a ⋖ b := ⟨hab, fun _x hax hxb ↦ hac.2 hax <| hxb.trans_le hbc⟩ -theorem not_covby_of_lt_of_lt (h₁ : a < b) (h₂ : b < c) : ¬a ⋖ c := - (not_covby_iff (h₁.trans h₂)).2 ⟨b, h₁, h₂⟩ -#align not_covby_of_lt_of_lt not_covby_of_lt_of_lt +theorem not_covBy_of_lt_of_lt (h₁ : a < b) (h₂ : b < c) : ¬a ⋖ c := + (not_covBy_iff (h₁.trans h₂)).2 ⟨b, h₁, h₂⟩ +#align not_covby_of_lt_of_lt not_covBy_of_lt_of_lt -theorem covby_iff_wcovby_and_lt : a ⋖ b ↔ a ⩿ b ∧ a < b := - ⟨fun h => ⟨h.wcovby, h.lt⟩, fun h => h.1.covby_of_lt h.2⟩ -#align covby_iff_wcovby_and_lt covby_iff_wcovby_and_lt +theorem covBy_iff_wcovBy_and_lt : a ⋖ b ↔ a ⩿ b ∧ a < b := + ⟨fun h => ⟨h.wcovBy, h.lt⟩, fun h => h.1.covBy_of_lt h.2⟩ +#align covby_iff_wcovby_and_lt covBy_iff_wcovBy_and_lt -theorem covby_iff_wcovby_and_not_le : a ⋖ b ↔ a ⩿ b ∧ ¬b ≤ a := - ⟨fun h => ⟨h.wcovby, h.lt.not_le⟩, fun h => h.1.covby_of_not_le h.2⟩ -#align covby_iff_wcovby_and_not_le covby_iff_wcovby_and_not_le +theorem covBy_iff_wcovBy_and_not_le : a ⋖ b ↔ a ⩿ b ∧ ¬b ≤ a := + ⟨fun h => ⟨h.wcovBy, h.lt.not_le⟩, fun h => h.1.covBy_of_not_le h.2⟩ +#align covby_iff_wcovby_and_not_le covBy_iff_wcovBy_and_not_le -theorem wcovby_iff_covby_or_le_and_le : a ⩿ b ↔ a ⋖ b ∨ a ≤ b ∧ b ≤ a := - ⟨fun h => or_iff_not_imp_right.mpr fun h' => h.covby_of_not_le fun hba => h' ⟨h.le, hba⟩, - fun h' => h'.elim (fun h => h.wcovby) fun h => h.1.wcovby_of_le h.2⟩ -#align wcovby_iff_covby_or_le_and_le wcovby_iff_covby_or_le_and_le +theorem wcovBy_iff_covBy_or_le_and_le : a ⩿ b ↔ a ⋖ b ∨ a ≤ b ∧ b ≤ a := + ⟨fun h => or_iff_not_imp_right.mpr fun h' => h.covBy_of_not_le fun hba => h' ⟨h.le, hba⟩, + fun h' => h'.elim (fun h => h.wcovBy) fun h => h.1.wcovBy_of_le h.2⟩ +#align wcovby_iff_covby_or_le_and_le wcovBy_iff_covBy_or_le_and_le -theorem AntisymmRel.trans_covby (hab : AntisymmRel (· ≤ ·) a b) (hbc : b ⋖ c) : a ⋖ c := +theorem AntisymmRel.trans_covBy (hab : AntisymmRel (· ≤ ·) a b) (hbc : b ⋖ c) : a ⋖ c := ⟨hab.1.trans_lt hbc.lt, fun _ had hdc => hbc.2 (hab.2.trans_lt had) hdc⟩ -#align antisymm_rel.trans_covby AntisymmRel.trans_covby +#align antisymm_rel.trans_covby AntisymmRel.trans_covBy -theorem covby_congr_left (hab : AntisymmRel (· ≤ ·) a b) : a ⋖ c ↔ b ⋖ c := - ⟨hab.symm.trans_covby, hab.trans_covby⟩ -#align covby_congr_left covby_congr_left +theorem covBy_congr_left (hab : AntisymmRel (· ≤ ·) a b) : a ⋖ c ↔ b ⋖ c := + ⟨hab.symm.trans_covBy, hab.trans_covBy⟩ +#align covby_congr_left covBy_congr_left -theorem Covby.trans_antisymmRel (hab : a ⋖ b) (hbc : AntisymmRel (· ≤ ·) b c) : a ⋖ c := +theorem CovBy.trans_antisymmRel (hab : a ⋖ b) (hbc : AntisymmRel (· ≤ ·) b c) : a ⋖ c := ⟨hab.lt.trans_le hbc.1, fun _ had hdb => hab.2 had <| hdb.trans_le hbc.2⟩ -#align covby.trans_antisymm_rel Covby.trans_antisymmRel +#align covby.trans_antisymm_rel CovBy.trans_antisymmRel -theorem covby_congr_right (hab : AntisymmRel (· ≤ ·) a b) : c ⋖ a ↔ c ⋖ b := +theorem covBy_congr_right (hab : AntisymmRel (· ≤ ·) a b) : c ⋖ a ↔ c ⋖ b := ⟨fun h => h.trans_antisymmRel hab, fun h => h.trans_antisymmRel hab.symm⟩ -#align covby_congr_right covby_congr_right +#align covby_congr_right covBy_congr_right instance : IsNonstrictStrictOrder α (· ⩿ ·) (· ⋖ ·) := ⟨fun _ _ => - covby_iff_wcovby_and_not_le.trans <| and_congr_right fun h => h.wcovby_iff_le.not.symm⟩ + covBy_iff_wcovBy_and_not_le.trans <| and_congr_right fun h => h.wcovBy_iff_le.not.symm⟩ -instance Covby.isIrrefl : IsIrrefl α (· ⋖ ·) := +instance CovBy.isIrrefl : IsIrrefl α (· ⋖ ·) := ⟨fun _ ha => ha.ne rfl⟩ -#align covby.is_irrefl Covby.isIrrefl +#align covby.is_irrefl CovBy.isIrrefl -theorem Covby.Ioo_eq (h : a ⋖ b) : Ioo a b = ∅ := - h.wcovby.Ioo_eq -#align covby.Ioo_eq Covby.Ioo_eq +theorem CovBy.Ioo_eq (h : a ⋖ b) : Ioo a b = ∅ := + h.wcovBy.Ioo_eq +#align covby.Ioo_eq CovBy.Ioo_eq -theorem covby_iff_Ioo_eq : a ⋖ b ↔ a < b ∧ Ioo a b = ∅ := +theorem covBy_iff_Ioo_eq : a ⋖ b ↔ a < b ∧ Ioo a b = ∅ := and_congr_right' <| by simp [eq_empty_iff_forall_not_mem] -#align covby_iff_Ioo_eq covby_iff_Ioo_eq +#align covby_iff_Ioo_eq covBy_iff_Ioo_eq -theorem Covby.of_image (f : α ↪o β) (h : f a ⋖ f b) : a ⋖ b := +theorem CovBy.of_image (f : α ↪o β) (h : f a ⋖ f b) : a ⋖ b := ⟨f.lt_iff_lt.mp h.lt, fun _ hac hcb => h.2 (f.lt_iff_lt.mpr hac) (f.lt_iff_lt.mpr hcb)⟩ -#align covby.of_image Covby.of_image +#align covby.of_image CovBy.of_image -theorem Covby.image (f : α ↪o β) (hab : a ⋖ b) (h : (range f).OrdConnected) : f a ⋖ f b := - (hab.wcovby.image f h).covby_of_lt <| f.strictMono hab.lt -#align covby.image Covby.image +theorem CovBy.image (f : α ↪o β) (hab : a ⋖ b) (h : (range f).OrdConnected) : f a ⋖ f b := + (hab.wcovBy.image f h).covBy_of_lt <| f.strictMono hab.lt +#align covby.image CovBy.image -theorem Set.OrdConnected.apply_covby_apply_iff (f : α ↪o β) (h : (range f).OrdConnected) : +theorem Set.OrdConnected.apply_covBy_apply_iff (f : α ↪o β) (h : (range f).OrdConnected) : f a ⋖ f b ↔ a ⋖ b := - ⟨Covby.of_image f, fun hab => hab.image f h⟩ -#align set.ord_connected.apply_covby_apply_iff Set.OrdConnected.apply_covby_apply_iff + ⟨CovBy.of_image f, fun hab => hab.image f h⟩ +#align set.ord_connected.apply_covby_apply_iff Set.OrdConnected.apply_covBy_apply_iff @[simp] -theorem apply_covby_apply_iff {E : Type*} [OrderIsoClass E α β] (e : E) : e a ⋖ e b ↔ a ⋖ b := - (ordConnected_range (e : α ≃o β)).apply_covby_apply_iff ((e : α ≃o β) : α ↪o β) -#align apply_covby_apply_iff apply_covby_apply_iff +theorem apply_covBy_apply_iff {E : Type*} [OrderIsoClass E α β] (e : E) : e a ⋖ e b ↔ a ⋖ b := + (ordConnected_range (e : α ≃o β)).apply_covBy_apply_iff ((e : α ≃o β) : α ↪o β) +#align apply_covby_apply_iff apply_covBy_apply_iff -theorem covby_of_eq_or_eq (hab : a < b) (h : ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b) : a ⋖ b := +theorem covBy_of_eq_or_eq (hab : a < b) (h : ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b) : a ⋖ b := ⟨hab, fun c ha hb => (h c ha.le hb.le).elim ha.ne' hb.ne⟩ -#align covby_of_eq_or_eq covby_of_eq_or_eq +#align covby_of_eq_or_eq covBy_of_eq_or_eq end Preorder @@ -378,48 +378,48 @@ section PartialOrder variable [PartialOrder α] {a b c : α} -theorem Wcovby.covby_of_ne (h : a ⩿ b) (h2 : a ≠ b) : a ⋖ b := +theorem WCovBy.covBy_of_ne (h : a ⩿ b) (h2 : a ≠ b) : a ⋖ b := ⟨h.le.lt_of_ne h2, h.2⟩ -#align wcovby.covby_of_ne Wcovby.covby_of_ne +#align wcovby.covby_of_ne WCovBy.covBy_of_ne -theorem covby_iff_wcovby_and_ne : a ⋖ b ↔ a ⩿ b ∧ a ≠ b := - ⟨fun h => ⟨h.wcovby, h.ne⟩, fun h => h.1.covby_of_ne h.2⟩ -#align covby_iff_wcovby_and_ne covby_iff_wcovby_and_ne +theorem covBy_iff_wcovBy_and_ne : a ⋖ b ↔ a ⩿ b ∧ a ≠ b := + ⟨fun h => ⟨h.wcovBy, h.ne⟩, fun h => h.1.covBy_of_ne h.2⟩ +#align covby_iff_wcovby_and_ne covBy_iff_wcovBy_and_ne -theorem wcovby_iff_covby_or_eq : a ⩿ b ↔ a ⋖ b ∨ a = b := by - rw [le_antisymm_iff, wcovby_iff_covby_or_le_and_le] -#align wcovby_iff_covby_or_eq wcovby_iff_covby_or_eq +theorem wcovBy_iff_covBy_or_eq : a ⩿ b ↔ a ⋖ b ∨ a = b := by + rw [le_antisymm_iff, wcovBy_iff_covBy_or_le_and_le] +#align wcovby_iff_covby_or_eq wcovBy_iff_covBy_or_eq -theorem wcovby_iff_eq_or_covby : a ⩿ b ↔ a = b ∨ a ⋖ b := - wcovby_iff_covby_or_eq.trans or_comm -#align wcovby_iff_eq_or_covby wcovby_iff_eq_or_covby +theorem wcovBy_iff_eq_or_covBy : a ⩿ b ↔ a = b ∨ a ⋖ b := + wcovBy_iff_covBy_or_eq.trans or_comm +#align wcovby_iff_eq_or_covby wcovBy_iff_eq_or_covBy -alias ⟨Wcovby.covby_or_eq, _⟩ := wcovby_iff_covby_or_eq -#align wcovby.covby_or_eq Wcovby.covby_or_eq +alias ⟨WCovBy.covBy_or_eq, _⟩ := wcovBy_iff_covBy_or_eq +#align wcovby.covby_or_eq WCovBy.covBy_or_eq -alias ⟨Wcovby.eq_or_covby, _⟩ := wcovby_iff_eq_or_covby -#align wcovby.eq_or_covby Wcovby.eq_or_covby +alias ⟨WCovBy.eq_or_covBy, _⟩ := wcovBy_iff_eq_or_covBy +#align wcovby.eq_or_covby WCovBy.eq_or_covBy -theorem Covby.eq_or_eq (h : a ⋖ b) (h2 : a ≤ c) (h3 : c ≤ b) : c = a ∨ c = b := - h.wcovby.eq_or_eq h2 h3 -#align covby.eq_or_eq Covby.eq_or_eq +theorem CovBy.eq_or_eq (h : a ⋖ b) (h2 : a ≤ c) (h3 : c ≤ b) : c = a ∨ c = b := + h.wcovBy.eq_or_eq h2 h3 +#align covby.eq_or_eq CovBy.eq_or_eq -/-- An `iff` version of `Covby.eq_or_eq` and `covby_of_eq_or_eq`. -/ -theorem covby_iff_lt_and_eq_or_eq : a ⋖ b ↔ a < b ∧ ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b := - ⟨fun h => ⟨h.lt, fun _ => h.eq_or_eq⟩, And.rec covby_of_eq_or_eq⟩ -#align covby_iff_lt_and_eq_or_eq covby_iff_lt_and_eq_or_eq +/-- An `iff` version of `CovBy.eq_or_eq` and `covBy_of_eq_or_eq`. -/ +theorem covBy_iff_lt_and_eq_or_eq : a ⋖ b ↔ a < b ∧ ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b := + ⟨fun h => ⟨h.lt, fun _ => h.eq_or_eq⟩, And.rec covBy_of_eq_or_eq⟩ +#align covby_iff_lt_and_eq_or_eq covBy_iff_lt_and_eq_or_eq -theorem Covby.Ico_eq (h : a ⋖ b) : Ico a b = {a} := by +theorem CovBy.Ico_eq (h : a ⋖ b) : Ico a b = {a} := by rw [← Ioo_union_left h.lt, h.Ioo_eq, empty_union] -#align covby.Ico_eq Covby.Ico_eq +#align covby.Ico_eq CovBy.Ico_eq -theorem Covby.Ioc_eq (h : a ⋖ b) : Ioc a b = {b} := by +theorem CovBy.Ioc_eq (h : a ⋖ b) : Ioc a b = {b} := by rw [← Ioo_union_right h.lt, h.Ioo_eq, empty_union] -#align covby.Ioc_eq Covby.Ioc_eq +#align covby.Ioc_eq CovBy.Ioc_eq -theorem Covby.Icc_eq (h : a ⋖ b) : Icc a b = {a, b} := - h.wcovby.Icc_eq -#align covby.Icc_eq Covby.Icc_eq +theorem CovBy.Icc_eq (h : a ⋖ b) : Icc a b = {a, b} := + h.wcovBy.Icc_eq +#align covby.Icc_eq CovBy.Icc_eq end PartialOrder @@ -427,43 +427,43 @@ section LinearOrder variable [LinearOrder α] {a b c : α} -theorem Covby.Ioi_eq (h : a ⋖ b) : Ioi a = Ici b := by +theorem CovBy.Ioi_eq (h : a ⋖ b) : Ioi a = Ici b := by rw [← Ioo_union_Ici_eq_Ioi h.lt, h.Ioo_eq, empty_union] -#align covby.Ioi_eq Covby.Ioi_eq +#align covby.Ioi_eq CovBy.Ioi_eq -theorem Covby.Iio_eq (h : a ⋖ b) : Iio b = Iic a := by +theorem CovBy.Iio_eq (h : a ⋖ b) : Iio b = Iic a := by rw [← Iic_union_Ioo_eq_Iio h.lt, h.Ioo_eq, union_empty] -#align covby.Iio_eq Covby.Iio_eq +#align covby.Iio_eq CovBy.Iio_eq -theorem Wcovby.le_of_lt (hab : a ⩿ b) (hcb : c < b) : c ≤ a := +theorem WCovBy.le_of_lt (hab : a ⩿ b) (hcb : c < b) : c ≤ a := not_lt.1 fun hac => hab.2 hac hcb -#align wcovby.le_of_lt Wcovby.le_of_lt +#align wcovby.le_of_lt WCovBy.le_of_lt -theorem Wcovby.ge_of_gt (hab : a ⩿ b) (hac : a < c) : b ≤ c := +theorem WCovBy.ge_of_gt (hab : a ⩿ b) (hac : a < c) : b ≤ c := not_lt.1 <| hab.2 hac -#align wcovby.ge_of_gt Wcovby.ge_of_gt +#align wcovby.ge_of_gt WCovBy.ge_of_gt -theorem Covby.le_of_lt (hab : a ⋖ b) : c < b → c ≤ a := - hab.wcovby.le_of_lt -#align covby.le_of_lt Covby.le_of_lt +theorem CovBy.le_of_lt (hab : a ⋖ b) : c < b → c ≤ a := + hab.wcovBy.le_of_lt +#align covby.le_of_lt CovBy.le_of_lt -theorem Covby.ge_of_gt (hab : a ⋖ b) : a < c → b ≤ c := - hab.wcovby.ge_of_gt -#align covby.ge_of_gt Covby.ge_of_gt +theorem CovBy.ge_of_gt (hab : a ⋖ b) : a < c → b ≤ c := + hab.wcovBy.ge_of_gt +#align covby.ge_of_gt CovBy.ge_of_gt -theorem Covby.unique_left (ha : a ⋖ c) (hb : b ⋖ c) : a = b := +theorem CovBy.unique_left (ha : a ⋖ c) (hb : b ⋖ c) : a = b := (hb.le_of_lt ha.lt).antisymm <| ha.le_of_lt hb.lt -#align covby.unique_left Covby.unique_left +#align covby.unique_left CovBy.unique_left -theorem Covby.unique_right (hb : a ⋖ b) (hc : a ⋖ c) : b = c := +theorem CovBy.unique_right (hb : a ⋖ b) (hc : a ⋖ c) : b = c := (hb.ge_of_gt hc.lt).antisymm <| hc.ge_of_gt hb.lt -#align covby.unique_right Covby.unique_right +#align covby.unique_right CovBy.unique_right /-- If `a`, `b`, `c` are consecutive and `a < x < c` then `x = b`. -/ -theorem Covby.eq_of_between {x : α} (hab : a ⋖ b) (hbc : b ⋖ c) (hax : a < x) (hxc : x < c) : +theorem CovBy.eq_of_between {x : α} (hab : a ⋖ b) (hbc : b ⋖ c) (hax : a < x) (hxc : x < c) : x = b := le_antisymm (le_of_not_lt fun h => hbc.2 h hxc) (le_of_not_lt <| hab.2 hax) -#align covby.eq_of_between Covby.eq_of_between +#align covby.eq_of_between CovBy.eq_of_between /-- If `a < b` then there exist `a' > a` and `b' < b` such that `Set.Iio a'` is strictly to the left of `Set.Ioi b'`. -/ @@ -479,42 +479,42 @@ end LinearOrder namespace Set variable {s t : Set α} {a : α} -@[simp] lemma wcovby_insert (x : α) (s : Set α) : s ⩿ insert x s := by - refine' wcovby_of_eq_or_eq (subset_insert x s) fun t hst h2t => _ +@[simp] lemma wcovBy_insert (x : α) (s : Set α) : s ⩿ insert x s := by + refine' wcovBy_of_eq_or_eq (subset_insert x s) fun t hst h2t => _ by_cases h : x ∈ t · exact Or.inr (subset_antisymm h2t <| insert_subset_iff.mpr ⟨h, hst⟩) · refine' Or.inl (subset_antisymm _ hst) rwa [← diff_singleton_eq_self h, diff_singleton_subset_iff] -#align set.wcovby_insert Set.wcovby_insert +#align set.wcovby_insert Set.wcovBy_insert -@[simp] lemma sdiff_singleton_wcovby (s : Set α) (a : α) : s \ {a} ⩿ s := by +@[simp] lemma sdiff_singleton_wcovBy (s : Set α) (a : α) : s \ {a} ⩿ s := by by_cases ha : a ∈ s - · convert wcovby_insert a _ + · convert wcovBy_insert a _ ext simp [ha] · simp [ha] -@[simp] lemma covby_insert (ha : a ∉ s) : s ⋖ insert a s := - (wcovby_insert _ _).covby_of_lt $ ssubset_insert ha -#align set.covby_insert Set.covby_insert +@[simp] lemma covBy_insert (ha : a ∉ s) : s ⋖ insert a s := + (wcovBy_insert _ _).covBy_of_lt <| ssubset_insert ha +#align set.covby_insert Set.covBy_insert -@[simp] lemma sdiff_singleton_covby (ha : a ∈ s) : s \ {a} ⋖ s := - ⟨sdiff_lt (singleton_subset_iff.2 ha) $ singleton_ne_empty _, (sdiff_singleton_wcovby _ _).2⟩ +@[simp] lemma sdiff_singleton_covBy (ha : a ∈ s) : s \ {a} ⋖ s := + ⟨sdiff_lt (singleton_subset_iff.2 ha) <| singleton_ne_empty _, (sdiff_singleton_wcovBy _ _).2⟩ -lemma _root_.Covby.exists_set_insert (h : s ⋖ t) : ∃ a ∉ s, insert a s = t := +lemma _root_.CovBy.exists_set_insert (h : s ⋖ t) : ∃ a ∉ s, insert a s = t := let ⟨a, ha, hst⟩ := ssubset_iff_insert.1 h.lt - ⟨a, ha, (hst.eq_of_not_ssuperset $ h.2 $ ssubset_insert ha).symm⟩ + ⟨a, ha, (hst.eq_of_not_ssuperset <| h.2 <| ssubset_insert ha).symm⟩ -lemma _root_.Covby.exists_set_sdiff_singleton (h : s ⋖ t) : ∃ a ∈ t, t \ {a} = s := +lemma _root_.CovBy.exists_set_sdiff_singleton (h : s ⋖ t) : ∃ a ∈ t, t \ {a} = s := let ⟨a, ha, hst⟩ := ssubset_iff_sdiff_singleton.1 h.lt - ⟨a, ha, (hst.eq_of_not_ssubset fun h' ↦ h.2 h' $ - sdiff_lt (singleton_subset_iff.2 ha) $ singleton_ne_empty _).symm⟩ + ⟨a, ha, (hst.eq_of_not_ssubset fun h' ↦ h.2 h' <| + sdiff_lt (singleton_subset_iff.2 ha) <| singleton_ne_empty _).symm⟩ -lemma covby_iff_exists_insert : s ⋖ t ↔ ∃ a ∉ s, insert a s = t := - ⟨Covby.exists_set_insert, by rintro ⟨a, ha, rfl⟩; exact covby_insert ha⟩ +lemma covBy_iff_exists_insert : s ⋖ t ↔ ∃ a ∉ s, insert a s = t := + ⟨CovBy.exists_set_insert, by rintro ⟨a, ha, rfl⟩; exact covBy_insert ha⟩ -lemma covby_iff_exists_sdiff_singleton : s ⋖ t ↔ ∃ a ∈ t, t \ {a} = s := - ⟨Covby.exists_set_sdiff_singleton, by rintro ⟨a, ha, rfl⟩; exact sdiff_singleton_covby ha⟩ +lemma covBy_iff_exists_sdiff_singleton : s ⋖ t ↔ ∃ a ∈ t, t \ {a} = s := + ⟨CovBy.exists_set_sdiff_singleton, by rintro ⟨a, ha, rfl⟩; exact sdiff_singleton_covBy ha⟩ end Set @@ -522,16 +522,16 @@ section Relation open Relation -lemma wcovby_eq_reflGen_covby [PartialOrder α] : ((· : α) ⩿ ·) = ReflGen (· ⋖ ·) := by - ext x y; simp_rw [wcovby_iff_eq_or_covby, @eq_comm _ x, reflGen_iff] +lemma wcovBy_eq_reflGen_covBy [PartialOrder α] : ((· : α) ⩿ ·) = ReflGen (· ⋖ ·) := by + ext x y; simp_rw [wcovBy_iff_eq_or_covBy, @eq_comm _ x, reflGen_iff] -lemma transGen_wcovby_eq_reflTransGen_covby [PartialOrder α] : +lemma transGen_wcovBy_eq_reflTransGen_covBy [PartialOrder α] : TransGen ((· : α) ⩿ ·) = ReflTransGen (· ⋖ ·) := by - rw [wcovby_eq_reflGen_covby, transGen_reflGen] + rw [wcovBy_eq_reflGen_covBy, transGen_reflGen] -lemma reflTransGen_wcovby_eq_reflTransGen_covby [PartialOrder α] : +lemma reflTransGen_wcovBy_eq_reflTransGen_covBy [PartialOrder α] : ReflTransGen ((· : α) ⩿ ·) = ReflTransGen (· ⋖ ·) := by - rw [wcovby_eq_reflGen_covby, reflTransGen_reflGen] + rw [wcovBy_eq_reflGen_covBy, reflTransGen_reflGen] end Relation @@ -540,80 +540,80 @@ namespace Prod variable [PartialOrder α] [PartialOrder β] {a a₁ a₂ : α} {b b₁ b₂ : β} {x y : α × β} @[simp] -theorem swap_wcovby_swap : x.swap ⩿ y.swap ↔ x ⩿ y := - apply_wcovby_apply_iff (OrderIso.prodComm : α × β ≃o β × α) -#align prod.swap_wcovby_swap Prod.swap_wcovby_swap +theorem swap_wcovBy_swap : x.swap ⩿ y.swap ↔ x ⩿ y := + apply_wcovBy_apply_iff (OrderIso.prodComm : α × β ≃o β × α) +#align prod.swap_wcovby_swap Prod.swap_wcovBy_swap @[simp] -theorem swap_covby_swap : x.swap ⋖ y.swap ↔ x ⋖ y := - apply_covby_apply_iff (OrderIso.prodComm : α × β ≃o β × α) -#align prod.swap_covby_swap Prod.swap_covby_swap +theorem swap_covBy_swap : x.swap ⋖ y.swap ↔ x ⋖ y := + apply_covBy_apply_iff (OrderIso.prodComm : α × β ≃o β × α) +#align prod.swap_covby_swap Prod.swap_covBy_swap -theorem fst_eq_or_snd_eq_of_wcovby : x ⩿ y → x.1 = y.1 ∨ x.2 = y.2 := by +theorem fst_eq_or_snd_eq_of_wcovBy : x ⩿ y → x.1 = y.1 ∨ x.2 = y.2 := by refine' fun h => of_not_not fun hab => _ push_neg at hab exact h.2 (mk_lt_mk.2 <| Or.inl ⟨hab.1.lt_of_le h.1.1, le_rfl⟩) (mk_lt_mk.2 <| Or.inr ⟨le_rfl, hab.2.lt_of_le h.1.2⟩) -#align prod.fst_eq_or_snd_eq_of_wcovby Prod.fst_eq_or_snd_eq_of_wcovby +#align prod.fst_eq_or_snd_eq_of_wcovby Prod.fst_eq_or_snd_eq_of_wcovBy -theorem _root_.Wcovby.fst (h : x ⩿ y) : x.1 ⩿ y.1 := +theorem _root_.WCovBy.fst (h : x ⩿ y) : x.1 ⩿ y.1 := ⟨h.1.1, fun _ h₁ h₂ => h.2 (mk_lt_mk_iff_left.2 h₁) ⟨⟨h₂.le, h.1.2⟩, fun hc => h₂.not_le hc.1⟩⟩ -#align wcovby.fst Wcovby.fst +#align wcovby.fst WCovBy.fst -theorem _root_.Wcovby.snd (h : x ⩿ y) : x.2 ⩿ y.2 := +theorem _root_.WCovBy.snd (h : x ⩿ y) : x.2 ⩿ y.2 := ⟨h.1.2, fun _ h₁ h₂ => h.2 (mk_lt_mk_iff_right.2 h₁) ⟨⟨h.1.1, h₂.le⟩, fun hc => h₂.not_le hc.2⟩⟩ -#align wcovby.snd Wcovby.snd +#align wcovby.snd WCovBy.snd -theorem mk_wcovby_mk_iff_left : (a₁, b) ⩿ (a₂, b) ↔ a₁ ⩿ a₂ := by - refine' ⟨Wcovby.fst, (And.imp mk_le_mk_iff_left.2) fun h c h₁ h₂ => _⟩ +theorem mk_wcovBy_mk_iff_left : (a₁, b) ⩿ (a₂, b) ↔ a₁ ⩿ a₂ := by + refine' ⟨WCovBy.fst, (And.imp mk_le_mk_iff_left.2) fun h c h₁ h₂ => _⟩ have : c.2 = b := h₂.le.2.antisymm h₁.le.2 rw [← @Prod.mk.eta _ _ c, this, mk_lt_mk_iff_left] at h₁ h₂ exact h h₁ h₂ -#align prod.mk_wcovby_mk_iff_left Prod.mk_wcovby_mk_iff_left +#align prod.mk_wcovby_mk_iff_left Prod.mk_wcovBy_mk_iff_left -theorem mk_wcovby_mk_iff_right : (a, b₁) ⩿ (a, b₂) ↔ b₁ ⩿ b₂ := - swap_wcovby_swap.trans mk_wcovby_mk_iff_left -#align prod.mk_wcovby_mk_iff_right Prod.mk_wcovby_mk_iff_right +theorem mk_wcovBy_mk_iff_right : (a, b₁) ⩿ (a, b₂) ↔ b₁ ⩿ b₂ := + swap_wcovBy_swap.trans mk_wcovBy_mk_iff_left +#align prod.mk_wcovby_mk_iff_right Prod.mk_wcovBy_mk_iff_right -theorem mk_covby_mk_iff_left : (a₁, b) ⋖ (a₂, b) ↔ a₁ ⋖ a₂ := by - simp_rw [covby_iff_wcovby_and_lt, mk_wcovby_mk_iff_left, mk_lt_mk_iff_left] -#align prod.mk_covby_mk_iff_left Prod.mk_covby_mk_iff_left +theorem mk_covBy_mk_iff_left : (a₁, b) ⋖ (a₂, b) ↔ a₁ ⋖ a₂ := by + simp_rw [covBy_iff_wcovBy_and_lt, mk_wcovBy_mk_iff_left, mk_lt_mk_iff_left] +#align prod.mk_covby_mk_iff_left Prod.mk_covBy_mk_iff_left -theorem mk_covby_mk_iff_right : (a, b₁) ⋖ (a, b₂) ↔ b₁ ⋖ b₂ := by - simp_rw [covby_iff_wcovby_and_lt, mk_wcovby_mk_iff_right, mk_lt_mk_iff_right] -#align prod.mk_covby_mk_iff_right Prod.mk_covby_mk_iff_right +theorem mk_covBy_mk_iff_right : (a, b₁) ⋖ (a, b₂) ↔ b₁ ⋖ b₂ := by + simp_rw [covBy_iff_wcovBy_and_lt, mk_wcovBy_mk_iff_right, mk_lt_mk_iff_right] +#align prod.mk_covby_mk_iff_right Prod.mk_covBy_mk_iff_right -theorem mk_wcovby_mk_iff : (a₁, b₁) ⩿ (a₂, b₂) ↔ a₁ ⩿ a₂ ∧ b₁ = b₂ ∨ b₁ ⩿ b₂ ∧ a₁ = a₂ := by +theorem mk_wcovBy_mk_iff : (a₁, b₁) ⩿ (a₂, b₂) ↔ a₁ ⩿ a₂ ∧ b₁ = b₂ ∨ b₁ ⩿ b₂ ∧ a₁ = a₂ := by refine' ⟨fun h => _, _⟩ - · obtain rfl | rfl : a₁ = a₂ ∨ b₁ = b₂ := fst_eq_or_snd_eq_of_wcovby h - · exact Or.inr ⟨mk_wcovby_mk_iff_right.1 h, rfl⟩ - · exact Or.inl ⟨mk_wcovby_mk_iff_left.1 h, rfl⟩ + · obtain rfl | rfl : a₁ = a₂ ∨ b₁ = b₂ := fst_eq_or_snd_eq_of_wcovBy h + · exact Or.inr ⟨mk_wcovBy_mk_iff_right.1 h, rfl⟩ + · exact Or.inl ⟨mk_wcovBy_mk_iff_left.1 h, rfl⟩ · rintro (⟨h, rfl⟩ | ⟨h, rfl⟩) - · exact mk_wcovby_mk_iff_left.2 h - · exact mk_wcovby_mk_iff_right.2 h -#align prod.mk_wcovby_mk_iff Prod.mk_wcovby_mk_iff + · exact mk_wcovBy_mk_iff_left.2 h + · exact mk_wcovBy_mk_iff_right.2 h +#align prod.mk_wcovby_mk_iff Prod.mk_wcovBy_mk_iff -theorem mk_covby_mk_iff : (a₁, b₁) ⋖ (a₂, b₂) ↔ a₁ ⋖ a₂ ∧ b₁ = b₂ ∨ b₁ ⋖ b₂ ∧ a₁ = a₂ := by +theorem mk_covBy_mk_iff : (a₁, b₁) ⋖ (a₂, b₂) ↔ a₁ ⋖ a₂ ∧ b₁ = b₂ ∨ b₁ ⋖ b₂ ∧ a₁ = a₂ := by refine' ⟨fun h => _, _⟩ - · obtain rfl | rfl : a₁ = a₂ ∨ b₁ = b₂ := fst_eq_or_snd_eq_of_wcovby h.wcovby - · exact Or.inr ⟨mk_covby_mk_iff_right.1 h, rfl⟩ - · exact Or.inl ⟨mk_covby_mk_iff_left.1 h, rfl⟩ + · obtain rfl | rfl : a₁ = a₂ ∨ b₁ = b₂ := fst_eq_or_snd_eq_of_wcovBy h.wcovBy + · exact Or.inr ⟨mk_covBy_mk_iff_right.1 h, rfl⟩ + · exact Or.inl ⟨mk_covBy_mk_iff_left.1 h, rfl⟩ · rintro (⟨h, rfl⟩ | ⟨h, rfl⟩) - · exact mk_covby_mk_iff_left.2 h - · exact mk_covby_mk_iff_right.2 h -#align prod.mk_covby_mk_iff Prod.mk_covby_mk_iff + · exact mk_covBy_mk_iff_left.2 h + · exact mk_covBy_mk_iff_right.2 h +#align prod.mk_covby_mk_iff Prod.mk_covBy_mk_iff -theorem wcovby_iff : x ⩿ y ↔ x.1 ⩿ y.1 ∧ x.2 = y.2 ∨ x.2 ⩿ y.2 ∧ x.1 = y.1 := by +theorem wcovBy_iff : x ⩿ y ↔ x.1 ⩿ y.1 ∧ x.2 = y.2 ∨ x.2 ⩿ y.2 ∧ x.1 = y.1 := by cases x cases y - exact mk_wcovby_mk_iff -#align prod.wcovby_iff Prod.wcovby_iff + exact mk_wcovBy_mk_iff +#align prod.wcovby_iff Prod.wcovBy_iff -theorem covby_iff : x ⋖ y ↔ x.1 ⋖ y.1 ∧ x.2 = y.2 ∨ x.2 ⋖ y.2 ∧ x.1 = y.1 := by +theorem covBy_iff : x ⋖ y ↔ x.1 ⋖ y.1 ∧ x.2 = y.2 ∨ x.2 ⋖ y.2 ∧ x.1 = y.1 := by cases x cases y - exact mk_covby_mk_iff -#align prod.covby_iff Prod.covby_iff + exact mk_covBy_mk_iff +#align prod.covby_iff Prod.covBy_iff end Prod diff --git a/Mathlib/Order/Disjoint.lean b/Mathlib/Order/Disjoint.lean index f835326cd6e3a..c87f5eac11b0c 100644 --- a/Mathlib/Order/Disjoint.lean +++ b/Mathlib/Order/Disjoint.lean @@ -3,6 +3,7 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ +import Aesop import Mathlib.Order.BoundedOrder #align_import order.disjoint from "leanprover-community/mathlib"@"22c4d2ff43714b6ff724b2745ccfdc0f236a4a76" diff --git a/Mathlib/Order/Estimator.lean b/Mathlib/Order/Estimator.lean index 364c8baeb69cb..d72d355352dde 100644 --- a/Mathlib/Order/Estimator.lean +++ b/Mathlib/Order/Estimator.lean @@ -3,11 +3,11 @@ Copyright (c) 2023 Kim Liesinger. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Liesinger -/ +import Mathlib.Data.Set.Defs +import Mathlib.Order.Heyting.Basic import Mathlib.Order.RelClasses -import Mathlib.Data.Set.Image import Mathlib.Order.Hom.Basic import Mathlib.Lean.Thunk -import Mathlib.Data.Prod.Lex /-! # Improvable lower bounds. @@ -107,7 +107,7 @@ def Estimator.improveUntilAux | none, _ => .error <| if r then none else e | some e', _ => improveUntilAux a p e' true -termination_by Estimator.improveUntilAux p I e r => (⟨_, mem_range_self e⟩ : range (bound a)) +termination_by (⟨_, mem_range_self e⟩ : range (bound a)) /-- Improve an estimate until it satisfies a predicate, @@ -140,7 +140,7 @@ theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool) exact Bool.bool_eq_false h | some e', _ => exact Estimator.improveUntilAux_spec a p e' true -termination_by Estimator.improveUntilAux_spec p I e r => (⟨_, mem_range_self e⟩ : range (bound a)) +termination_by (⟨_, mem_range_self e⟩ : range (bound a)) /-- If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`. diff --git a/Mathlib/Order/Filter/AtTopBot.lean b/Mathlib/Order/Filter/AtTopBot.lean index ed455c726dda7..679a420c74225 100644 --- a/Mathlib/Order/Filter/AtTopBot.lean +++ b/Mathlib/Order/Filter/AtTopBot.lean @@ -10,6 +10,7 @@ import Mathlib.Data.Set.Intervals.OrderIso import Mathlib.Order.Filter.Bases import Mathlib.Order.ConditionallyCompleteLattice.Basic import Mathlib.Algebra.Order.Group.MinMax +import Mathlib.Algebra.Order.Group.Instances #align_import order.filter.at_top_bot from "leanprover-community/mathlib"@"1f0096e6caa61e9c849ec2adbd227e960e9dff58" @@ -991,7 +992,7 @@ theorem tendsto_abs_atTop_atTop : Tendsto (abs : α → α) atTop atTop := /-- $\lim_{x\to-\infty}|x|=+\infty$ -/ theorem tendsto_abs_atBot_atTop : Tendsto (abs : α → α) atBot atTop := - tendsto_atTop_mono neg_le_abs_self tendsto_neg_atBot_atTop + tendsto_atTop_mono neg_le_abs tendsto_neg_atBot_atTop #align filter.tendsto_abs_at_bot_at_top Filter.tendsto_abs_atBot_atTop @[simp] @@ -1917,7 +1918,7 @@ if a filter `k` is countably generated then `Tendsto f k l` iff for every sequen converging to `k`, `f ∘ u` tends to `l`. -/ theorem tendsto_iff_seq_tendsto {f : α → β} {k : Filter α} {l : Filter β} [k.IsCountablyGenerated] : Tendsto f k l ↔ ∀ x : ℕ → α, Tendsto x atTop k → Tendsto (f ∘ x) atTop l := by - refine' ⟨fun h x hx => h.comp hx, fun H s hs => _⟩ + refine ⟨fun h x hx => h.comp hx, fun H s hs => ?_⟩ contrapose! H have : NeBot (k ⊓ 𝓟 (f ⁻¹' sᶜ)) := by simpa [neBot_iff, inf_principal_eq_bot] rcases (k ⊓ 𝓟 (f ⁻¹' sᶜ)).exists_seq_tendsto with ⟨x, hx⟩ @@ -1932,57 +1933,28 @@ theorem tendsto_of_seq_tendsto {f : α → β} {k : Filter α} {l : Filter β} [ tendsto_iff_seq_tendsto.2 #align filter.tendsto_of_seq_tendsto Filter.tendsto_of_seq_tendsto --- porting note: move to `Basic` -theorem tendsto_iff_forall_eventually_mem {x : ι → α} {f : Filter α} {l : Filter ι} : - Tendsto x l f ↔ ∀ s ∈ f, ∀ᶠ n in l, x n ∈ s := - Iff.rfl -#align filter.tendsto_iff_forall_eventually_mem Filter.tendsto_iff_forall_eventually_mem - --- porting note: move to `Basic` -theorem not_tendsto_iff_exists_frequently_nmem {x : ι → α} {f : Filter α} {l : Filter ι} : - ¬Tendsto x l f ↔ ∃ s ∈ f, ∃ᶠ n in l, x n ∉ s := by - simp only [tendsto_iff_forall_eventually_mem, not_forall, exists_prop, Filter.Frequently, not_not] -#align filter.not_tendsto_iff_exists_frequently_nmem Filter.not_tendsto_iff_exists_frequently_nmem +theorem eventually_iff_seq_eventually {ι : Type*} {l : Filter ι} {p : ι → Prop} + [l.IsCountablyGenerated] : + (∀ᶠ n in l, p n) ↔ ∀ x : ℕ → ι, Tendsto x atTop l → ∀ᶠ n : ℕ in atTop, p (x n) := by + simpa using tendsto_iff_seq_tendsto (f := id) (l := 𝓟 {x | p x}) +#align filter.eventually_iff_seq_eventually Filter.eventually_iff_seq_eventually theorem frequently_iff_seq_frequently {ι : Type*} {l : Filter ι} {p : ι → Prop} - [hl : l.IsCountablyGenerated] : + [l.IsCountablyGenerated] : (∃ᶠ n in l, p n) ↔ ∃ x : ℕ → ι, Tendsto x atTop l ∧ ∃ᶠ n : ℕ in atTop, p (x n) := by - refine' ⟨fun h_freq => _, fun h_exists_freq => _⟩ - · have : NeBot (l ⊓ 𝓟 { x : ι | p x }) := by simpa [neBot_iff, inf_principal_eq_bot] - obtain ⟨x, hx⟩ := exists_seq_tendsto (l ⊓ 𝓟 { x : ι | p x }) - rw [tendsto_inf] at hx - cases' hx with hx_l hx_p - refine' ⟨x, hx_l, _⟩ - rw [tendsto_principal] at hx_p - exact hx_p.frequently - · obtain ⟨x, hx_tendsto, hx_freq⟩ := h_exists_freq - simp_rw [Filter.Frequently, Filter.Eventually] at hx_freq ⊢ - have : { n : ℕ | ¬p (x n) } = { n | x n ∈ { y | ¬p y } } := rfl - rw [this, ← mem_map'] at hx_freq - exact mt (@hx_tendsto _) hx_freq + simp only [Filter.Frequently, eventually_iff_seq_eventually (l := l)] + push_neg; rfl #align filter.frequently_iff_seq_frequently Filter.frequently_iff_seq_frequently -theorem eventually_iff_seq_eventually {ι : Type*} {l : Filter ι} {p : ι → Prop} - [hl : l.IsCountablyGenerated] : - (∀ᶠ n in l, p n) ↔ ∀ x : ℕ → ι, Tendsto x atTop l → ∀ᶠ n : ℕ in atTop, p (x n) := by - have : (∀ᶠ n in l, p n) ↔ ¬∃ᶠ n in l, ¬p n := by - rw [not_frequently] - simp_rw [not_not] - rw [this, frequently_iff_seq_frequently] - push_neg - simp_rw [not_frequently, not_not] -#align filter.eventually_iff_seq_eventually Filter.eventually_iff_seq_eventually - theorem subseq_forall_of_frequently {ι : Type*} {x : ℕ → ι} {p : ι → Prop} {l : Filter ι} (h_tendsto : Tendsto x atTop l) (h : ∃ᶠ n in atTop, p (x n)) : ∃ ns : ℕ → ℕ, Tendsto (fun n => x (ns n)) atTop l ∧ ∀ n, p (x (ns n)) := by - rw [tendsto_iff_seq_tendsto] at h_tendsto choose ns hge hns using frequently_atTop.1 h - exact ⟨ns, h_tendsto ns (tendsto_atTop_mono hge tendsto_id), hns⟩ + exact ⟨ns, h_tendsto.comp (tendsto_atTop_mono hge tendsto_id), hns⟩ #align filter.subseq_forall_of_frequently Filter.subseq_forall_of_frequently theorem exists_seq_forall_of_frequently {ι : Type*} {l : Filter ι} {p : ι → Prop} - [hl : l.IsCountablyGenerated] (h : ∃ᶠ n in l, p n) : + [l.IsCountablyGenerated] (h : ∃ᶠ n in l, p n) : ∃ ns : ℕ → ι, Tendsto ns atTop l ∧ ∀ n, p (ns n) := by rw [frequently_iff_seq_frequently] at h obtain ⟨x, hx_tendsto, hx_freq⟩ := h @@ -1990,41 +1962,35 @@ theorem exists_seq_forall_of_frequently {ι : Type*} {l : Filter ι} {p : ι → exact ⟨x ∘ n_to_n, h_tendsto, h_freq⟩ #align filter.exists_seq_forall_of_frequently Filter.exists_seq_forall_of_frequently +lemma frequently_iff_seq_forall {ι : Type*} {l : Filter ι} {p : ι → Prop} + [l.IsCountablyGenerated] : + (∃ᶠ n in l, p n) ↔ ∃ ns : ℕ → ι, Tendsto ns atTop l ∧ ∀ n, p (ns n) := + ⟨exists_seq_forall_of_frequently, fun ⟨_ns, hnsl, hpns⟩ ↦ + hnsl.frequently <| frequently_of_forall hpns⟩ + /-- A sequence converges if every subsequence has a convergent subsequence. -/ theorem tendsto_of_subseq_tendsto {α ι : Type*} {x : ι → α} {f : Filter α} {l : Filter ι} [l.IsCountablyGenerated] - (hxy : - ∀ ns : ℕ → ι, Tendsto ns atTop l → ∃ ms : ℕ → ℕ, Tendsto (fun n => x (ns <| ms n)) atTop f) : + (hxy : ∀ ns : ℕ → ι, Tendsto ns atTop l → + ∃ ms : ℕ → ℕ, Tendsto (fun n => x (ns <| ms n)) atTop f) : Tendsto x l f := by - by_contra h + contrapose! hxy obtain ⟨s, hs, hfreq⟩ : ∃ s ∈ f, ∃ᶠ n in l, x n ∉ s := by - rwa [not_tendsto_iff_exists_frequently_nmem] at h + rwa [not_tendsto_iff_exists_frequently_nmem] at hxy obtain ⟨y, hy_tendsto, hy_freq⟩ := exists_seq_forall_of_frequently hfreq - specialize hxy y hy_tendsto - obtain ⟨ms, hms_tendsto⟩ := hxy - specialize hms_tendsto hs - rw [mem_map] at hms_tendsto - have hms_freq : ∀ n : ℕ, x (y (ms n)) ∉ s := fun n => hy_freq (ms n) - have h_empty : (fun n : ℕ => x (y (ms n))) ⁻¹' s = ∅ := by - ext1 n - simp only [Set.mem_preimage, Set.mem_empty_iff_false, iff_false_iff] - exact hms_freq n - rw [h_empty] at hms_tendsto - exact empty_not_mem atTop hms_tendsto + refine ⟨y, hy_tendsto, fun ms hms_tendsto ↦ ?_⟩ + rcases (hms_tendsto.eventually_mem hs).exists with ⟨n, hn⟩ + exact absurd hn <| hy_freq _ #align filter.tendsto_of_subseq_tendsto Filter.tendsto_of_subseq_tendsto theorem subseq_tendsto_of_neBot {f : Filter α} [IsCountablyGenerated f] {u : ℕ → α} (hx : NeBot (f ⊓ map u atTop)) : ∃ θ : ℕ → ℕ, StrictMono θ ∧ Tendsto (u ∘ θ) atTop f := by - obtain ⟨B, h⟩ := f.exists_antitone_basis - have : ∀ N, ∃ n ≥ N, u n ∈ B N := fun N => - Filter.inf_map_atTop_neBot_iff.mp hx _ (h.1.mem_of_mem trivial) N - choose φ hφ using this - cases' forall_and.mp hφ with φ_ge φ_in - have lim_uφ : Tendsto (u ∘ φ) atTop f := h.tendsto φ_in - have lim_φ : Tendsto φ atTop atTop := tendsto_atTop_mono φ_ge tendsto_id - obtain ⟨ψ, hψ, hψφ⟩ : ∃ ψ : ℕ → ℕ, StrictMono ψ ∧ StrictMono (φ ∘ ψ) - exact strictMono_subseq_of_tendsto_atTop lim_φ - exact ⟨φ ∘ ψ, hψφ, lim_uφ.comp hψ.tendsto_atTop⟩ + rw [← Filter.push_pull', map_neBot_iff] at hx + rcases exists_seq_tendsto (comap u f ⊓ atTop) with ⟨φ, hφ⟩ + rw [tendsto_inf, tendsto_comap_iff] at hφ + obtain ⟨ψ, hψ, hψφ⟩ : ∃ ψ : ℕ → ℕ, StrictMono ψ ∧ StrictMono (φ ∘ ψ) := + strictMono_subseq_of_tendsto_atTop hφ.2 + exact ⟨φ ∘ ψ, hψφ, hφ.1.comp hψ.tendsto_atTop⟩ #align filter.subseq_tendsto_of_ne_bot Filter.subseq_tendsto_of_neBot end Filter diff --git a/Mathlib/Order/Filter/Bases.lean b/Mathlib/Order/Filter/Bases.lean index 1d665eeb3c7d3..da61298eac6f2 100644 --- a/Mathlib/Order/Filter/Bases.lean +++ b/Mathlib/Order/Filter/Bases.lean @@ -829,7 +829,7 @@ protected theorem HasBasis.biInter_mem {f : Set α → Set β} (h : HasBasis l p #align filter.has_basis.bInter_mem Filter.HasBasis.biInter_mem protected theorem HasBasis.ker (h : HasBasis l p s) : l.ker = ⋂ (i) (_ : p i), s i := - l.ker_def.trans $ h.biInter_mem monotone_id + l.ker_def.trans <| h.biInter_mem monotone_id #align filter.has_basis.sInter_sets Filter.HasBasis.ker variable {ι'' : Type*} [Preorder ι''] (l) (s'' : ι'' → Set α) diff --git a/Mathlib/Order/Filter/Basic.lean b/Mathlib/Order/Filter/Basic.lean index 41393120a5061..4a4fc2d1058cd 100644 --- a/Mathlib/Order/Filter/Basic.lean +++ b/Mathlib/Order/Filter/Basic.lean @@ -392,8 +392,8 @@ theorem mem_generate_iff {s : Set <| Set α} {U : Set α} : #align filter.mem_generate_iff Filter.mem_generate_iff @[simp] lemma generate_singleton (s : Set α) : generate {s} = 𝓟 s := - le_antisymm (λ _t ht ↦ mem_of_superset (mem_generate_of_mem $ mem_singleton _) ht) <| - le_generate_iff.2 $ singleton_subset_iff.2 Subset.rfl + le_antisymm (λ _t ht ↦ mem_of_superset (mem_generate_of_mem <| mem_singleton _) ht) <| + le_generate_iff.2 <| singleton_subset_iff.2 Subset.rfl /-- `mk_of_closure s hs` constructs a filter on `α` whose elements set is exactly `s : Set (Set α)`, provided one gives the assumption `hs : (generate s).sets = s`. -/ @@ -1252,6 +1252,10 @@ theorem eventually_principal {a : Set α} {p : α → Prop} : (∀ᶠ x in 𝓟 Iff.rfl #align filter.eventually_principal Filter.eventually_principal +theorem Eventually.forall_mem {α : Type*} {f : Filter α} {s : Set α} {P : α → Prop} + (hP : ∀ᶠ x in f, P x) (hf : 𝓟 s ≤ f) : ∀ x ∈ s, P x := + Filter.eventually_principal.mp (hP.filter_mono hf) + theorem eventually_inf {f g : Filter α} {p : α → Prop} : (∀ᶠ x in f ⊓ g, p x) ↔ ∃ s ∈ f, ∃ t ∈ g, ∀ x ∈ s ∩ t, p x := mem_inf_iff_superset @@ -1548,6 +1552,12 @@ theorem EventuallyEq.mul [Mul β] {f f' g g' : α → β} {l : Filter α} (h : f #align filter.eventually_eq.mul Filter.EventuallyEq.mul #align filter.eventually_eq.add Filter.EventuallyEq.add +@[to_additive const_smul] +theorem EventuallyEq.pow_const {γ} [Pow β γ] {f g : α → β} {l : Filter α} (h : f =ᶠ[l] g) (c : γ): + (fun x => f x ^ c) =ᶠ[l] fun x => g x ^ c := + h.fun_comp (· ^ c) +#align filter.eventually_eq.const_smul Filter.EventuallyEq.const_smul + @[to_additive] theorem EventuallyEq.inv [Inv β] {f g : α → β} {l : Filter α} (h : f =ᶠ[l] g) : (fun x => (f x)⁻¹) =ᶠ[l] fun x => (g x)⁻¹ := @@ -1562,11 +1572,7 @@ theorem EventuallyEq.div [Div β] {f f' g g' : α → β} {l : Filter α} (h : f #align filter.eventually_eq.div Filter.EventuallyEq.div #align filter.eventually_eq.sub Filter.EventuallyEq.sub -@[to_additive] -theorem EventuallyEq.const_smul {𝕜} [SMul 𝕜 β] {l : Filter α} {f g : α → β} (h : f =ᶠ[l] g) - (c : 𝕜) : (fun x => c • f x) =ᶠ[l] fun x => c • g x := - h.fun_comp fun x => c • x -#align filter.eventually_eq.const_smul Filter.EventuallyEq.const_smul +attribute [to_additive] EventuallyEq.const_smul #align filter.eventually_eq.const_vadd Filter.EventuallyEq.const_vadd @[to_additive] @@ -2428,6 +2434,9 @@ theorem map_comap_of_surjective {f : α → β} (hf : Surjective f) (l : Filter map_comap_of_mem <| by simp only [hf.range_eq, univ_mem] #align filter.map_comap_of_surjective Filter.map_comap_of_surjective +theorem comap_injective {f : α → β} (hf : Surjective f) : Injective (comap f) := + LeftInverse.injective <| map_comap_of_surjective hf + theorem _root_.Function.Surjective.filter_map_top {f : α → β} (hf : Surjective f) : map f ⊤ = ⊤ := (congr_arg _ comap_top).symm.trans <| map_comap_of_surjective hf ⊤ #align function.surjective.filter_map_top Function.Surjective.filter_map_top @@ -2987,7 +2996,7 @@ lemma ker_def (f : Filter α) : f.ker = ⋂ s ∈ f, s := sInter_eq_biInter /-- `Filter.principal` forms a Galois coinsertion with `Filter.ker`. -/ def gi_principal_ker : GaloisCoinsertion (𝓟 : Set α → Filter α) ker := -GaloisConnection.toGaloisCoinsertion (λ s f ↦ by simp [principal_le_iff]) $ by +GaloisConnection.toGaloisCoinsertion (λ s f ↦ by simp [principal_le_iff]) <| by simp only [le_iff_subset, subset_def, mem_ker, mem_principal]; aesop lemma ker_mono : Monotone (ker : Filter α → Set α) := gi_principal_ker.gc.monotone_u @@ -2995,7 +3004,7 @@ lemma ker_surjective : Surjective (ker : Filter α → Set α) := gi_principal_k @[simp] lemma ker_bot : ker (⊥ : Filter α) = ∅ := sInter_eq_empty_iff.2 λ _ ↦ ⟨∅, trivial, id⟩ @[simp] lemma ker_top : ker (⊤ : Filter α) = univ := gi_principal_ker.gc.u_top -@[simp] lemma ker_eq_univ : ker f = univ ↔ f = ⊤ := gi_principal_ker.gc.u_eq_top.trans $ by simp +@[simp] lemma ker_eq_univ : ker f = univ ↔ f = ⊤ := gi_principal_ker.gc.u_eq_top.trans <| by simp @[simp] lemma ker_inf (f g : Filter α) : ker (f ⊓ g) = ker f ∩ ker g := gi_principal_ker.gc.u_inf @[simp] lemma ker_iInf (f : ι → Filter α) : ker (⨅ i, f i) = ⨅ i, ker (f i) := gi_principal_ker.gc.u_iInf @@ -3031,11 +3040,25 @@ theorem tendsto_iff_eventually {f : α → β} {l₁ : Filter α} {l₂ : Filter Iff.rfl #align filter.tendsto_iff_eventually Filter.tendsto_iff_eventually +theorem tendsto_iff_forall_eventually_mem {f : α → β} {l₁ : Filter α} {l₂ : Filter β} : + Tendsto f l₁ l₂ ↔ ∀ s ∈ l₂, ∀ᶠ x in l₁, f x ∈ s := + Iff.rfl +#align filter.tendsto_iff_forall_eventually_mem Filter.tendsto_iff_forall_eventually_mem + +lemma Tendsto.eventually_mem {f : α → β} {l₁ : Filter α} {l₂ : Filter β} {s : Set β} + (hf : Tendsto f l₁ l₂) (h : s ∈ l₂) : ∀ᶠ x in l₁, f x ∈ s := + hf h + theorem Tendsto.eventually {f : α → β} {l₁ : Filter α} {l₂ : Filter β} {p : β → Prop} (hf : Tendsto f l₁ l₂) (h : ∀ᶠ y in l₂, p y) : ∀ᶠ x in l₁, p (f x) := hf h #align filter.tendsto.eventually Filter.Tendsto.eventually +theorem not_tendsto_iff_exists_frequently_nmem {f : α → β} {l₁ : Filter α} {l₂ : Filter β} : + ¬Tendsto f l₁ l₂ ↔ ∃ s ∈ l₂, ∃ᶠ x in l₁, f x ∉ s := by + simp only [tendsto_iff_forall_eventually_mem, not_forall, exists_prop, not_eventually] +#align filter.not_tendsto_iff_exists_frequently_nmem Filter.not_tendsto_iff_exists_frequently_nmem + theorem Tendsto.frequently {f : α → β} {l₁ : Filter α} {l₂ : Filter β} {p : β → Prop} (hf : Tendsto f l₁ l₂) (h : ∃ᶠ x in l₁, p (f x)) : ∃ᶠ y in l₂, p y := mt hf.eventually h diff --git a/Mathlib/Order/Filter/Extr.lean b/Mathlib/Order/Filter/Extr.lean index e43876eaa3b60..9b411c33fff60 100644 --- a/Mathlib/Order/Filter/Extr.lean +++ b/Mathlib/Order/Filter/Extr.lean @@ -92,12 +92,12 @@ variable (f : α → β) (s : Set α) (l : Filter α) (a : α) /-! ### Definitions -/ -/-- `IsMinFilter f l a` means that `f a ≤ f x` in some `l`-neighborhood of `a` -/ +/-- `IsMinFilter f l a` means that `f a ≤ f x` for all `x` in some `l`-neighborhood of `a` -/ def IsMinFilter : Prop := ∀ᶠ x in l, f a ≤ f x #align is_min_filter IsMinFilter -/-- `is_maxFilter f l a` means that `f x ≤ f a` in some `l`-neighborhood of `a` -/ +/-- `is_maxFilter f l a` means that `f x ≤ f a` for all `x` in some `l`-neighborhood of `a` -/ def IsMaxFilter : Prop := ∀ᶠ x in l, f x ≤ f a #align is_max_filter IsMaxFilter @@ -107,12 +107,12 @@ def IsExtrFilter : Prop := IsMinFilter f l a ∨ IsMaxFilter f l a #align is_extr_filter IsExtrFilter -/-- `IsMinOn f s a` means that `f a ≤ f x` for all `x ∈ a`. Note that we do not assume `a ∈ s`. -/ +/-- `IsMinOn f s a` means that `f a ≤ f x` for all `x ∈ s`. Note that we do not assume `a ∈ s`. -/ def IsMinOn := IsMinFilter f (𝓟 s) a #align is_min_on IsMinOn -/-- `IsMaxOn f s a` means that `f x ≤ f a` for all `x ∈ a`. Note that we do not assume `a ∈ s`. -/ +/-- `IsMaxOn f s a` means that `f x ≤ f a` for all `x ∈ s`. Note that we do not assume `a ∈ s`. -/ def IsMaxOn := IsMaxFilter f (𝓟 s) a #align is_max_on IsMaxOn diff --git a/Mathlib/Order/Filter/Prod.lean b/Mathlib/Order/Filter/Prod.lean index e7deb41fa8b80..1b46df659d3ea 100644 --- a/Mathlib/Order/Filter/Prod.lean +++ b/Mathlib/Order/Filter/Prod.lean @@ -181,6 +181,10 @@ theorem Eventually.curry {la : Filter α} {lb : Filter β} {p : α × β → Pro exact ha.mono fun a ha => hb.mono fun b hb => h ha hb #align filter.eventually.curry Filter.Eventually.curry +protected lemma Frequently.uncurry {la : Filter α} {lb : Filter β} {p : α → β → Prop} + (h : ∃ᶠ x in la, ∃ᶠ y in lb, p x y) : ∃ᶠ xy in la ×ˢ lb, p xy.1 xy.2 := + mt (fun h ↦ by simpa only [not_frequently] using h.curry) h + /-- A fact that is eventually true about all pairs `l ×ˢ l` is eventually true about all diagonal pairs `(i, i)` -/ theorem Eventually.diag_of_prod {p : α × α → Prop} (h : ∀ᶠ i in f ×ˢ f, p i) : diff --git a/Mathlib/Order/GaloisConnection.lean b/Mathlib/Order/GaloisConnection.lean index defed5491802b..173ffbbe78fc3 100644 --- a/Mathlib/Order/GaloisConnection.lean +++ b/Mathlib/Order/GaloisConnection.lean @@ -202,30 +202,22 @@ section PartialOrder variable [Preorder α] [PartialOrder β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) -theorem l_u_l_eq_l (a : α) : l (u (l a)) = l a := - (gc.l_u_le _).antisymm (gc.monotone_l (gc.le_u_l _)) +theorem l_u_l_eq_l (a : α) : l (u (l a)) = l a := gc.dual.u_l_u_eq_u _ #align galois_connection.l_u_l_eq_l GaloisConnection.l_u_l_eq_l -theorem l_u_l_eq_l' : l ∘ u ∘ l = l := - funext gc.l_u_l_eq_l +theorem l_u_l_eq_l' : l ∘ u ∘ l = l := funext gc.l_u_l_eq_l #align galois_connection.l_u_l_eq_l' GaloisConnection.l_u_l_eq_l' theorem l_unique {l' : α → β} {u' : β → α} (gc' : GaloisConnection l' u') (hu : ∀ b, u b = u' b) {a : α} : l a = l' a := - le_antisymm (gc.l_le <| (hu (l' a)).symm ▸ gc'.le_u_l _) (gc'.l_le <| hu (l a) ▸ gc.le_u_l _) + gc.dual.u_unique gc'.dual hu #align galois_connection.l_unique GaloisConnection.l_unique /-- If there exists an `a` such that `b = l a`, then `a = u b` is one such element. -/ -theorem exists_eq_l (b : β) : (∃ a : α, b = l a) ↔ b = l (u b) := - ⟨fun ⟨_, hS⟩ => hS.symm ▸ (gc.l_u_l_eq_l _).symm, fun HI => ⟨_, HI⟩⟩ +theorem exists_eq_l (b : β) : (∃ a : α, b = l a) ↔ b = l (u b) := gc.dual.exists_eq_u _ #align galois_connection.exists_eq_l GaloisConnection.exists_eq_l -theorem l_eq {x : α} {z : β} : l x = z ↔ ∀ y, z ≤ y ↔ x ≤ u y := by - constructor - · rintro rfl y - exact gc x y - · intro H - exact ((gc _ _).mpr <| (H z).mp le_rfl).antisymm ((H <| l x).mpr (gc.le_u_l x)) +theorem l_eq {x : α} {z : β} : l x = z ↔ ∀ y, z ≤ y ↔ x ≤ u y := gc.dual.u_eq #align galois_connection.l_eq GaloisConnection.l_eq end PartialOrder @@ -272,8 +264,7 @@ section SemilatticeInf variable [SemilatticeInf α] [SemilatticeInf β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) -theorem u_inf : u (b₁ ⊓ b₂) = u b₁ ⊓ u b₂ := - gc.dual.l_sup +theorem u_inf : u (b₁ ⊓ b₂) = u b₁ ⊓ u b₂ := gc.dual.l_sup #align galois_connection.u_inf GaloisConnection.u_inf end SemilatticeInf @@ -329,7 +320,7 @@ protected theorem id [pα : Preorder α] : @GaloisConnection α α pα pα id id protected theorem compose [Preorder α] [Preorder β] [Preorder γ] {l1 : α → β} {u1 : β → α} {l2 : β → γ} {u2 : γ → β} (gc1 : GaloisConnection l1 u1) (gc2 : GaloisConnection l2 u2) : - GaloisConnection (l2 ∘ l1) (u1 ∘ u2) := by intro a b; dsimp; rw [gc2, gc1] + GaloisConnection (l2 ∘ l1) (u1 ∘ u2) := fun _ _ ↦ (gc2 _ _).trans (gc1 _ _) #align galois_connection.compose GaloisConnection.compose protected theorem dfun {ι : Type u} {α : ι → Type v} {β : ι → Type w} [∀ i, Preorder (α i)] @@ -341,8 +332,7 @@ protected theorem dfun {ι : Type u} {α : ι → Type v} {β : ι → Type w} [ protected theorem compl [BooleanAlgebra α] [BooleanAlgebra β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) : - GaloisConnection (compl ∘ u ∘ compl) (compl ∘ l ∘ compl) := by - intro a b + GaloisConnection (compl ∘ u ∘ compl) (compl ∘ l ∘ compl) := fun a b ↦ by dsimp rw [le_compl_iff_le_compl, gc, compl_le_iff_compl_le] diff --git a/Mathlib/Order/GameAdd.lean b/Mathlib/Order/GameAdd.lean index 428022e59af62..15ccf11f4d3ff 100644 --- a/Mathlib/Order/GameAdd.lean +++ b/Mathlib/Order/GameAdd.lean @@ -91,7 +91,7 @@ theorem gameAdd_le_lex : GameAdd rα rβ ≤ Prod.Lex rα rβ := fun _ _ h => theorem rprod_le_transGen_gameAdd : RProd rα rβ ≤ Relation.TransGen (GameAdd rα rβ) | _, _, h => h.rec (by intro _ _ _ _ hα hβ - exact Relation.TransGen.tail (Relation.TransGen.single $ GameAdd.fst hα) (GameAdd.snd hβ)) + exact Relation.TransGen.tail (Relation.TransGen.single <| GameAdd.fst hα) (GameAdd.snd hβ)) #align prod.rprod_le_trans_gen_game_add Prod.rprod_le_transGen_gameAdd end Prod @@ -230,7 +230,7 @@ def GameAdd.fix {C : α → α → Sort*} (hr : WellFounded rα) C a b := by -- Porting note: this was refactored for #3414 (reenableeta), and could perhaps be cleaned up. have := hr.sym2_gameAdd - dsimp only [GameAdd, lift₂, FunLike.coe, EquivLike.coe] at this + dsimp only [GameAdd, lift₂, DFunLike.coe, EquivLike.coe] at this exact @WellFounded.fix (α × α) (fun x => C x.1 x.2) _ this.of_quotient_lift₂ (fun ⟨x₁, x₂⟩ IH' => IH x₁ x₂ fun a' b' => IH' ⟨a', b'⟩) (a, b) #align sym2.game_add.fix Sym2.GameAdd.fix diff --git a/Mathlib/Order/Grade.lean b/Mathlib/Order/Grade.lean index 01c1a6246dc9b..1453acf708954 100644 --- a/Mathlib/Order/Grade.lean +++ b/Mathlib/Order/Grade.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Yaël Dillies, Violeta Hernández Palacios. All rights reserv Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Violeta Hernández Palacios, Grayson Burton, Vladimir Ivanov -/ -import Mathlib.Data.Finset.Basic import Mathlib.Data.Int.SuccPred #align_import order.grade from "leanprover-community/mathlib"@"9003f28797c0664a49e4179487267c494477d853" @@ -56,19 +55,19 @@ Instead, we define graded orders by their grade function, without talking about * [Richard Stanley, *Enumerative Combinatorics*][stanley2012] -/ -open Finset Nat OrderDual +open Nat OrderDual variable {𝕆 ℙ α β : Type*} /-- An `𝕆`-graded order is an order `α` equipped with a strictly monotone function -`grade 𝕆 : α → 𝕆` which preserves order covering (`Covby`). -/ +`grade 𝕆 : α → 𝕆` which preserves order covering (`CovBy`). -/ class GradeOrder (𝕆 α : Type*) [Preorder 𝕆] [Preorder α] where /-- The grading function. -/ grade : α → 𝕆 /-- `grade` is strictly monotonic. -/ grade_strictMono : StrictMono grade - /-- `grade` preserves `Covby`. -/ - covby_grade ⦃a b : α⦄ : a ⋖ b → grade a ⋖ grade b + /-- `grade` preserves `CovBy`. -/ + covBy_grade ⦃a b : α⦄ : a ⋖ b → grade a ⋖ grade b #align grade_order GradeOrder /-- An `𝕆`-graded order where minimal elements have minimal grades. -/ @@ -105,9 +104,9 @@ def grade : α → 𝕆 := GradeOrder.grade #align grade grade -protected theorem Covby.grade (h : a ⋖ b) : grade 𝕆 a ⋖ grade 𝕆 b := - GradeOrder.covby_grade h -#align covby.grade Covby.grade +protected theorem CovBy.grade (h : a ⋖ b) : grade 𝕆 a ⋖ grade 𝕆 b := + GradeOrder.covBy_grade h +#align covby.grade CovBy.grade variable {𝕆} @@ -115,10 +114,10 @@ theorem grade_strictMono : StrictMono (grade 𝕆 : α → 𝕆) := GradeOrder.grade_strictMono #align grade_strict_mono grade_strictMono -theorem covby_iff_lt_covby_grade : a ⋖ b ↔ a < b ∧ grade 𝕆 a ⋖ grade 𝕆 b := +theorem covBy_iff_lt_covBy_grade : a ⋖ b ↔ a < b ∧ grade 𝕆 a ⋖ grade 𝕆 b := ⟨fun h => ⟨h.1, h.grade _⟩, And.imp_right fun h _ ha hb => h.2 (grade_strictMono ha) <| grade_strictMono hb⟩ -#align covby_iff_lt_covby_grade covby_iff_lt_covby_grade +#align covby_iff_lt_covby_grade covBy_iff_lt_covBy_grade end GradeOrder @@ -191,9 +190,9 @@ theorem grade_ne_grade_iff : grade 𝕆 a ≠ grade 𝕆 b ↔ a ≠ b := grade_injective.ne_iff #align grade_ne_grade_iff grade_ne_grade_iff -theorem grade_covby_grade_iff : grade 𝕆 a ⋖ grade 𝕆 b ↔ a ⋖ b := - (covby_iff_lt_covby_grade.trans <| and_iff_right_of_imp fun h => grade_lt_grade_iff.1 h.1).symm -#align grade_covby_grade_iff grade_covby_grade_iff +theorem grade_covBy_grade_iff : grade 𝕆 a ⋖ grade 𝕆 b ↔ a ⋖ b := + (covBy_iff_lt_covBy_grade.trans <| and_iff_right_of_imp fun h => grade_lt_grade_iff.1 h.1).symm +#align grade_covby_grade_iff grade_covBy_grade_iff end LinearOrder @@ -226,7 +225,7 @@ instance Preorder.toGradeBoundedOrder : GradeBoundedOrder α α where isMin_grade _ := id isMax_grade _ := id grade_strictMono := strictMono_id - covby_grade _ _ := id + covBy_grade _ _ := id #align preorder.to_grade_bounded_order Preorder.toGradeBoundedOrder @[simp] @@ -239,7 +238,7 @@ theorem grade_self (a : α) : grade α a = a := instance OrderDual.gradeOrder [GradeOrder 𝕆 α] : GradeOrder 𝕆ᵒᵈ αᵒᵈ where grade := toDual ∘ grade 𝕆 ∘ ofDual grade_strictMono := grade_strictMono.dual - covby_grade _ _ h := (h.ofDual.grade _).toDual + covBy_grade _ _ h := (h.ofDual.grade _).toDual instance OrderDual.gradeMinOrder [GradeMaxOrder 𝕆 α] : GradeMinOrder 𝕆ᵒᵈ αᵒᵈ := { OrderDual.gradeOrder with isMin_grade := fun _ => IsMax.grade (α := α) 𝕆 } @@ -266,72 +265,72 @@ theorem grade_ofDual [GradeOrder 𝕆 α] (a : αᵒᵈ) : grade 𝕆 (ofDual a) /-- Lifts a graded order along a strictly monotone function. -/ @[reducible] def GradeOrder.liftLeft [GradeOrder 𝕆 α] (f : 𝕆 → ℙ) (hf : StrictMono f) - (hcovby : ∀ a b, a ⋖ b → f a ⋖ f b) : GradeOrder ℙ α + (hcovBy : ∀ a b, a ⋖ b → f a ⋖ f b) : GradeOrder ℙ α where grade := f ∘ (@grade 𝕆 _ _ _ _) -- porting note - what the hell?! used to be `grade 𝕆` grade_strictMono := hf.comp grade_strictMono - covby_grade _ _ h := hcovby _ _ <| h.grade _ + covBy_grade _ _ h := hcovBy _ _ <| h.grade _ #align grade_order.lift_left GradeOrder.liftLeft -- See note [reducible non-instances] /-- Lifts a graded order along a strictly monotone function. -/ @[reducible] def GradeMinOrder.liftLeft [GradeMinOrder 𝕆 α] (f : 𝕆 → ℙ) (hf : StrictMono f) - (hcovby : ∀ a b, a ⋖ b → f a ⋖ f b) (hmin : ∀ a, IsMin a → IsMin (f a)) : GradeMinOrder ℙ α := - { GradeOrder.liftLeft f hf hcovby with isMin_grade := fun _ ha => hmin _ <| ha.grade _ } + (hcovBy : ∀ a b, a ⋖ b → f a ⋖ f b) (hmin : ∀ a, IsMin a → IsMin (f a)) : GradeMinOrder ℙ α := + { GradeOrder.liftLeft f hf hcovBy with isMin_grade := fun _ ha => hmin _ <| ha.grade _ } #align grade_min_order.lift_left GradeMinOrder.liftLeft -- See note [reducible non-instances] /-- Lifts a graded order along a strictly monotone function. -/ @[reducible] def GradeMaxOrder.liftLeft [GradeMaxOrder 𝕆 α] (f : 𝕆 → ℙ) (hf : StrictMono f) - (hcovby : ∀ a b, a ⋖ b → f a ⋖ f b) (hmax : ∀ a, IsMax a → IsMax (f a)) : GradeMaxOrder ℙ α := - { GradeOrder.liftLeft f hf hcovby with isMax_grade := fun _ ha => hmax _ <| ha.grade _ } + (hcovBy : ∀ a b, a ⋖ b → f a ⋖ f b) (hmax : ∀ a, IsMax a → IsMax (f a)) : GradeMaxOrder ℙ α := + { GradeOrder.liftLeft f hf hcovBy with isMax_grade := fun _ ha => hmax _ <| ha.grade _ } #align grade_max_order.lift_left GradeMaxOrder.liftLeft -- See note [reducible non-instances] /-- Lifts a graded order along a strictly monotone function. -/ @[reducible] def GradeBoundedOrder.liftLeft [GradeBoundedOrder 𝕆 α] (f : 𝕆 → ℙ) (hf : StrictMono f) - (hcovby : ∀ a b, a ⋖ b → f a ⋖ f b) (hmin : ∀ a, IsMin a → IsMin (f a)) + (hcovBy : ∀ a b, a ⋖ b → f a ⋖ f b) (hmin : ∀ a, IsMin a → IsMin (f a)) (hmax : ∀ a, IsMax a → IsMax (f a)) : GradeBoundedOrder ℙ α := - { GradeMinOrder.liftLeft f hf hcovby hmin, GradeMaxOrder.liftLeft f hf hcovby hmax with } + { GradeMinOrder.liftLeft f hf hcovBy hmin, GradeMaxOrder.liftLeft f hf hcovBy hmax with } #align grade_bounded_order.lift_left GradeBoundedOrder.liftLeft -- See note [reducible non-instances] /-- Lifts a graded order along a strictly monotone function. -/ @[reducible] def GradeOrder.liftRight [GradeOrder 𝕆 β] (f : α → β) (hf : StrictMono f) - (hcovby : ∀ a b, a ⋖ b → f a ⋖ f b) : GradeOrder 𝕆 α + (hcovBy : ∀ a b, a ⋖ b → f a ⋖ f b) : GradeOrder 𝕆 α where grade := (@grade 𝕆 _ _ _ _) ∘ f -- porting note: again, weird grade_strictMono := grade_strictMono.comp hf - covby_grade _ _ h := (hcovby _ _ h).grade _ + covBy_grade _ _ h := (hcovBy _ _ h).grade _ #align grade_order.lift_right GradeOrder.liftRight -- See note [reducible non-instances] /-- Lifts a graded order along a strictly monotone function. -/ @[reducible] def GradeMinOrder.liftRight [GradeMinOrder 𝕆 β] (f : α → β) (hf : StrictMono f) - (hcovby : ∀ a b, a ⋖ b → f a ⋖ f b) (hmin : ∀ a, IsMin a → IsMin (f a)) : GradeMinOrder 𝕆 α := - { GradeOrder.liftRight f hf hcovby with isMin_grade := fun _ ha => (hmin _ ha).grade _ } + (hcovBy : ∀ a b, a ⋖ b → f a ⋖ f b) (hmin : ∀ a, IsMin a → IsMin (f a)) : GradeMinOrder 𝕆 α := + { GradeOrder.liftRight f hf hcovBy with isMin_grade := fun _ ha => (hmin _ ha).grade _ } #align grade_min_order.lift_right GradeMinOrder.liftRight -- See note [reducible non-instances] /-- Lifts a graded order along a strictly monotone function. -/ @[reducible] def GradeMaxOrder.liftRight [GradeMaxOrder 𝕆 β] (f : α → β) (hf : StrictMono f) - (hcovby : ∀ a b, a ⋖ b → f a ⋖ f b) (hmax : ∀ a, IsMax a → IsMax (f a)) : GradeMaxOrder 𝕆 α := - { GradeOrder.liftRight f hf hcovby with isMax_grade := fun _ ha => (hmax _ ha).grade _ } + (hcovBy : ∀ a b, a ⋖ b → f a ⋖ f b) (hmax : ∀ a, IsMax a → IsMax (f a)) : GradeMaxOrder 𝕆 α := + { GradeOrder.liftRight f hf hcovBy with isMax_grade := fun _ ha => (hmax _ ha).grade _ } #align grade_max_order.lift_right GradeMaxOrder.liftRight -- See note [reducible non-instances] /-- Lifts a graded order along a strictly monotone function. -/ @[reducible] def GradeBoundedOrder.liftRight [GradeBoundedOrder 𝕆 β] (f : α → β) (hf : StrictMono f) - (hcovby : ∀ a b, a ⋖ b → f a ⋖ f b) (hmin : ∀ a, IsMin a → IsMin (f a)) + (hcovBy : ∀ a b, a ⋖ b → f a ⋖ f b) (hmin : ∀ a, IsMin a → IsMin (f a)) (hmax : ∀ a, IsMax a → IsMax (f a)) : GradeBoundedOrder 𝕆 α := - { GradeMinOrder.liftRight f hf hcovby hmin, GradeMaxOrder.liftRight f hf hcovby hmax with } + { GradeMinOrder.liftRight f hf hcovBy hmin, GradeMaxOrder.liftRight f hf hcovBy hmax with } #align grade_bounded_order.lift_right GradeBoundedOrder.liftRight /-! #### `Fin n`-graded to `ℕ`-graded to `ℤ`-graded -/ @@ -342,7 +341,7 @@ def GradeBoundedOrder.liftRight [GradeBoundedOrder 𝕆 β] (f : α → β) (hf inferrable. -/ @[reducible] def GradeOrder.finToNat (n : ℕ) [GradeOrder (Fin n) α] : GradeOrder ℕ α := - (GradeOrder.liftLeft (_ : Fin n → ℕ) Fin.val_strictMono) fun _ _ => Covby.coe_fin + (GradeOrder.liftLeft (_ : Fin n → ℕ) Fin.val_strictMono) fun _ _ => CovBy.coe_fin #align grade_order.fin_to_nat GradeOrder.finToNat -- See note [reducible non-instances] @@ -350,7 +349,7 @@ def GradeOrder.finToNat (n : ℕ) [GradeOrder (Fin n) α] : GradeOrder ℕ α := inferrable. -/ @[reducible] def GradeMinOrder.finToNat (n : ℕ) [GradeMinOrder (Fin n) α] : GradeMinOrder ℕ α := - (GradeMinOrder.liftLeft (_ : Fin n → ℕ) Fin.val_strictMono fun _ _ => Covby.coe_fin) fun a h => by + (GradeMinOrder.liftLeft (_ : Fin n → ℕ) Fin.val_strictMono fun _ _ => CovBy.coe_fin) fun a h => by cases n · exact a.elim0 rw [h.eq_bot, Fin.bot_eq_zero] @@ -358,5 +357,5 @@ def GradeMinOrder.finToNat (n : ℕ) [GradeMinOrder (Fin n) α] : GradeMinOrder #align grade_min_order.fin_to_nat GradeMinOrder.finToNat instance GradeOrder.natToInt [GradeOrder ℕ α] : GradeOrder ℤ α := - (GradeOrder.liftLeft _ Int.coe_nat_strictMono) fun _ _ => Covby.cast_int + (GradeOrder.liftLeft _ Int.coe_nat_strictMono) fun _ _ => CovBy.cast_int #align grade_order.nat_to_int GradeOrder.natToInt diff --git a/Mathlib/Order/Heyting/Basic.lean b/Mathlib/Order/Heyting/Basic.lean index 4c520ce888cc6..aeed34d4dc541 100644 --- a/Mathlib/Order/Heyting/Basic.lean +++ b/Mathlib/Order/Heyting/Basic.lean @@ -33,13 +33,6 @@ Heyting algebras are the order theoretic equivalent of cartesian-closed categori * `CoheytingAlgebra`: Co-Heyting algebra. * `BiheytingAlgebra`: bi-Heyting algebra. -## Notation - -* `⇨`: Heyting implication -* `\`: Difference -* `¬`: Heyting negation -* `ᶜ`: (Pseudo-)complement - ## References * [Francis Borceux, *Handbook of Categorical Algebra III*][borceux-vol3] @@ -57,37 +50,6 @@ variable {ι α β : Type*} /-! ### Notation -/ - -/-- Syntax typeclass for Heyting implication `⇨`. -/ -@[notation_class] -class HImp (α : Type*) where - /-- Heyting implication `⇨` -/ - himp : α → α → α -#align has_himp HImp - -/-- Syntax typeclass for Heyting negation `¬`. - -The difference between `HasCompl` and `HNot` is that the former belongs to Heyting algebras, -while the latter belongs to co-Heyting algebras. They are both pseudo-complements, but `compl` -underestimates while `HNot` overestimates. In boolean algebras, they are equal. -See `hnot_eq_compl`. --/ -@[notation_class] -class HNot (α : Type*) where - /-- Heyting negation `¬` -/ - hnot : α → α -#align has_hnot HNot - -export HImp (himp) -export SDiff (sdiff) -export HNot (hnot) - -/-- Heyting implication -/ -infixr:60 " ⇨ " => himp - -/-- Heyting negation -/ -prefix:72 "¬" => hnot - section variable (α β) diff --git a/Mathlib/Order/Heyting/Hom.lean b/Mathlib/Order/Heyting/Hom.lean index 14f0726e2af91..1a1e6cd75ca3a 100644 --- a/Mathlib/Order/Heyting/Hom.lean +++ b/Mathlib/Order/Heyting/Hom.lean @@ -13,7 +13,7 @@ import Mathlib.Order.Hom.Lattice A Heyting homomorphism between two Heyting algebras is a bounded lattice homomorphism that preserves Heyting implication. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -184,6 +184,8 @@ def BoundedLatticeHomClass.toBiheytingHomClass [BooleanAlgebra α] [BooleanAlgeb section HeytingAlgebra +open scoped symmDiff + variable [HeytingAlgebra α] [HeytingAlgebra β] [HeytingHomClass F α β] (f : F) @[simp] @@ -199,6 +201,8 @@ end HeytingAlgebra section CoheytingAlgebra +open scoped symmDiff + variable [CoheytingAlgebra α] [CoheytingAlgebra β] [CoheytingHomClass F α β] (f : F) @[simp] @@ -251,10 +255,10 @@ instance instHeytingHomClass : HeytingHomClass (HeytingHom α β) α β where -- Porting note: CoeFun undesired here in lean 4 --- /-- Helper instance for when there's too many metavariables to apply `FunLike.CoeFun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.CoeFun` -- directly. -/ -- instance : CoeFun (HeytingHom α β) fun _ => α → β := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun -- @[simp] -- Porting note: not in simp-nf, simp can simplify lhs. Added aux simp lemma theorem toFun_eq_coe {f : HeytingHom α β} : f.toFun = ⇑f := @@ -267,7 +271,7 @@ theorem toFun_eq_coe_aux {f : HeytingHom α β} : (↑f.toLatticeHom) = ⇑f := @[ext] theorem ext {f g : HeytingHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align heyting_hom.ext HeytingHom.ext /-- Copy of a `HeytingHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -286,7 +290,7 @@ theorem coe_copy (f : HeytingHom α β) (f' : α → β) (h : f' = f) : ⇑(f.co #align heyting_hom.coe_copy HeytingHom.coe_copy theorem copy_eq (f : HeytingHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align heyting_hom.copy_eq HeytingHom.copy_eq variable (α) @@ -314,7 +318,7 @@ instance : Inhabited (HeytingHom α α) := ⟨HeytingHom.id _⟩ instance : PartialOrder (HeytingHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective /-- Composition of `HeytingHom`s as a `HeytingHom`. -/ def comp (f : HeytingHom β γ) (g : HeytingHom α β) : HeytingHom α γ := @@ -354,7 +358,7 @@ theorem id_comp (f : HeytingHom α β) : (HeytingHom.id β).comp f = f := @[simp] theorem cancel_right (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ #align heyting_hom.cancel_right HeytingHom.cancel_right @[simp] @@ -377,10 +381,10 @@ instance : CoheytingHomClass (CoheytingHom α β) α β where map_sdiff := CoheytingHom.map_sdiff' -- Porting note: CoeFun undesired here in lean 4 --- /-- Helper instance for when there's too many metavariables to apply `FunLike.CoeFun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.CoeFun` -- directly. -/ -- instance : CoeFun (CoheytingHom α β) fun _ => α → β := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun -- @[simp] -- Porting note: not in simp-nf, simp can simplify lhs. Added aux simp lemma @@ -394,7 +398,7 @@ theorem toFun_eq_coe_aux {f : CoheytingHom α β} : (↑f.toLatticeHom) = ⇑f : @[ext] theorem ext {f g : CoheytingHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align coheyting_hom.ext CoheytingHom.ext /-- Copy of a `CoheytingHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -413,7 +417,7 @@ theorem coe_copy (f : CoheytingHom α β) (f' : α → β) (h : f' = f) : ⇑(f. #align coheyting_hom.coe_copy CoheytingHom.coe_copy theorem copy_eq (f : CoheytingHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align coheyting_hom.copy_eq CoheytingHom.copy_eq variable (α) @@ -441,7 +445,7 @@ instance : Inhabited (CoheytingHom α α) := ⟨CoheytingHom.id _⟩ instance : PartialOrder (CoheytingHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective /-- Composition of `CoheytingHom`s as a `CoheytingHom`. -/ def comp (f : CoheytingHom β γ) (g : CoheytingHom α β) : CoheytingHom α γ := @@ -481,7 +485,7 @@ theorem id_comp (f : CoheytingHom α β) : (CoheytingHom.id β).comp f = f := @[simp] theorem cancel_right (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ #align coheyting_hom.cancel_right CoheytingHom.cancel_right @[simp] @@ -504,10 +508,10 @@ instance : BiheytingHomClass (BiheytingHom α β) α β where map_sdiff f := f.map_sdiff' -- Porting note: CoeFun undesired here in lean 4 --- /-- Helper instance for when there's too many metavariables to apply `FunLike.CoeFun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.CoeFun` -- directly. -/ -- instance : CoeFun (BiheytingHom α β) fun _ => α → β := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun -- @[simp] -- Porting note: not in simp-nf, simp can simplify lhs. Added aux simp lemma theorem toFun_eq_coe {f : BiheytingHom α β} : f.toFun = (f : α → β) := @@ -520,7 +524,7 @@ theorem toFun_eq_coe_aux {f : BiheytingHom α β} : (↑f.toLatticeHom) = ⇑f : @[ext] theorem ext {f g : BiheytingHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align biheyting_hom.ext BiheytingHom.ext /-- Copy of a `BiheytingHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -539,7 +543,7 @@ theorem coe_copy (f : BiheytingHom α β) (f' : α → β) (h : f' = f) : ⇑(f. #align biheyting_hom.coe_copy BiheytingHom.coe_copy theorem copy_eq (f : BiheytingHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align biheyting_hom.copy_eq BiheytingHom.copy_eq variable (α) @@ -565,7 +569,7 @@ instance : Inhabited (BiheytingHom α α) := ⟨BiheytingHom.id _⟩ instance : PartialOrder (BiheytingHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective /-- Composition of `BiheytingHom`s as a `BiheytingHom`. -/ def comp (f : BiheytingHom β γ) (g : BiheytingHom α β) : BiheytingHom α γ := @@ -605,7 +609,7 @@ theorem id_comp (f : BiheytingHom α β) : (BiheytingHom.id β).comp f = f := @[simp] theorem cancel_right (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ #align biheyting_hom.cancel_right BiheytingHom.cancel_right @[simp] diff --git a/Mathlib/Order/Hom/Basic.lean b/Mathlib/Order/Hom/Basic.lean index 06eee5893eafb..2a7ec9378503d 100644 --- a/Mathlib/Order/Hom/Basic.lean +++ b/Mathlib/Order/Hom/Basic.lean @@ -220,10 +220,10 @@ instance : OrderHomClass (α →o β) α β where coe_injective' f g h := by cases f; cases g; congr map_rel f _ _ h := f.monotone' h -/-- Helper instance for when there's too many metavariables to apply the coercion via `FunLike` +/-- Helper instance for when there's too many metavariables to apply the coercion via `DFunLike` directly. -/ instance : CoeFun (α →o β) fun _ => α → β := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ @[simp] theorem coe_mk (f : α → β) (hf : Monotone f) : ⇑(mk f hf) = f := rfl #align order_hom.coe_fun_mk OrderHom.coe_mk @@ -240,7 +240,7 @@ protected theorem mono (f : α →o β) : Monotone f := projection directly instead. -/ def Simps.coe (f : α →o β) : α → β := f -/- Porting note: TODO: all other FunLike classes use `apply` instead of `coe` +/- Porting note: TODO: all other DFunLike classes use `apply` instead of `coe` for the projection names. Maybe we should change this. -/ initialize_simps_projections OrderHom (toFun → coe) @@ -250,7 +250,7 @@ initialize_simps_projections OrderHom (toFun → coe) -- See library note [partially-applied ext lemmas] @[ext] theorem ext (f g : α →o β) (h : (f : α → β) = g) : f = g := - FunLike.coe_injective h + DFunLike.coe_injective h #align order_hom.ext OrderHom.ext @[simp] theorem coe_eq (f : α →o β) : OrderHomClass.toOrderHom f = f := rfl @@ -276,7 +276,7 @@ theorem coe_copy (f : α →o β) (f' : α → β) (h : f' = f) : (f.copy f' h) #align order_hom.coe_copy OrderHom.coe_copy theorem copy_eq (f : α →o β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align order_hom.copy_eq OrderHom.copy_eq /-- The identity function as bundled monotone function. -/ @@ -802,7 +802,7 @@ theorem toFun_eq_coe {f : α ≃o β} : f.toFun = f := -- See note [partially-applied ext lemmas] @[ext] theorem ext {f g : α ≃o β} (h : (f : α → β) = g) : f = g := - FunLike.coe_injective h + DFunLike.coe_injective h #align order_iso.ext OrderIso.ext /-- Reinterpret an order isomorphism as an order embedding. -/ @@ -1093,8 +1093,8 @@ def ofHomInv {F G : Type*} [OrderHomClass F α β] [OrderHomClass G β α] (f : α ≃o β where toFun := f invFun := g - left_inv := FunLike.congr_fun h₂ - right_inv := FunLike.congr_fun h₁ + left_inv := DFunLike.congr_fun h₂ + right_inv := DFunLike.congr_fun h₁ map_rel_iff' := @fun a b => ⟨fun h => by replace h := map_rel g h diff --git a/Mathlib/Order/Hom/Bounded.lean b/Mathlib/Order/Hom/Bounded.lean index 3808f37d13f49..7be2f70307fb4 100644 --- a/Mathlib/Order/Hom/Bounded.lean +++ b/Mathlib/Order/Hom/Bounded.lean @@ -13,7 +13,7 @@ import Mathlib.Order.BoundedOrder This file defines (bounded) order homomorphisms. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -36,7 +36,7 @@ variable {F α β γ δ : Type*} /-- The type of `⊤`-preserving functions from `α` to `β`. -/ structure TopHom (α β : Type*) [Top α] [Top β] where - /-- The underlying function. The preferred spelling is `FunLike.coe`. -/ + /-- The underlying function. The preferred spelling is `DFunLike.coe`. -/ toFun : α → β /-- The function preserves the top element. The preferred spelling is `map_top`. -/ map_top' : toFun ⊤ = ⊤ @@ -44,7 +44,7 @@ structure TopHom (α β : Type*) [Top α] [Top β] where /-- The type of `⊥`-preserving functions from `α` to `β`. -/ structure BotHom (α β : Type*) [Bot α] [Bot β] where - /-- The underlying function. The preferred spelling is `FunLike.coe`. -/ + /-- The underlying function. The preferred spelling is `DFunLike.coe`. -/ toFun : α → β /-- The function preserves the bottom element. The preferred spelling is `map_bot`. -/ map_bot' : toFun ⊥ = ⊥ @@ -65,7 +65,7 @@ section You should extend this class when you extend `TopHom`. -/ class TopHomClass (F : Type*) (α β : outParam <| Type*) [Top α] [Top β] extends - FunLike F α fun _ => β where + DFunLike F α fun _ => β where /-- A `TopHomClass` morphism preserves the top element. -/ map_top (f : F) : f ⊤ = ⊤ #align top_hom_class TopHomClass @@ -74,7 +74,7 @@ class TopHomClass (F : Type*) (α β : outParam <| Type*) [Top α] [Top β] exte You should extend this class when you extend `BotHom`. -/ class BotHomClass (F : Type*) (α β : outParam <| Type*) [Bot α] [Bot β] extends - FunLike F α fun _ => β where + DFunLike F α fun _ => β where /-- A `BotHomClass` morphism preserves the bottom element. -/ map_bot (f : F) : f ⊥ = ⊥ #align bot_hom_class BotHomClass @@ -120,7 +120,7 @@ instance (priority := 100) OrderIsoClass.toTopHomClass [LE α] [OrderTop α] -- See note [lower instance priority] instance (priority := 100) OrderIsoClass.toBotHomClass [LE α] [OrderBot α] [PartialOrder β] [OrderBot β] [OrderIsoClass F α β] : BotHomClass F α β := - { --⟨λ f, le_bot_iff.1 $ (le_map_inv_iff f).1 bot_le⟩ + { --⟨λ f, le_bot_iff.1 <| (le_map_inv_iff f).1 bot_le⟩ show OrderHomClass F α β from inferInstance with map_bot := fun f => le_bot_iff.1 <| (le_map_inv_iff f).1 bot_le } #align order_iso_class.to_bot_hom_class OrderIsoClass.toBotHomClass @@ -205,7 +205,7 @@ initialize_simps_projections TopHom (toFun → apply) @[ext] theorem ext {f g : TopHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align top_hom.ext TopHom.ext /-- Copy of a `TopHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -222,7 +222,7 @@ theorem coe_copy (f : TopHom α β) (f' : α → β) (h : f' = f) : ⇑(f.copy f #align top_hom.coe_copy TopHom.coe_copy theorem copy_eq (f : TopHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align top_hom.copy_eq TopHom.copy_eq instance : Inhabited (TopHom α β) := @@ -283,7 +283,7 @@ theorem id_comp (f : TopHom α β) : (TopHom.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : TopHom β γ} {f : TopHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => TopHom.ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (fun g => comp g f)⟩ + ⟨fun h => TopHom.ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun g => comp g f)⟩ #align top_hom.cancel_right TopHom.cancel_right @[simp] @@ -296,10 +296,10 @@ theorem cancel_left {g : TopHom β γ} {f₁ f₂ : TopHom α β} (hg : Injectiv end Top instance [Preorder β] [Top β] : Preorder (TopHom α β) := - Preorder.lift (FunLike.coe : TopHom α β → α → β) + Preorder.lift (DFunLike.coe : TopHom α β → α → β) instance [PartialOrder β] [Top β] : PartialOrder (TopHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective section OrderTop @@ -329,7 +329,7 @@ instance : Inf (TopHom α β) := ⟨fun f g => ⟨f ⊓ g, by rw [Pi.inf_apply, map_top, map_top, inf_top_eq]⟩⟩ instance : SemilatticeInf (TopHom α β) := - (FunLike.coe_injective.semilatticeInf _) fun _ _ => rfl + (DFunLike.coe_injective.semilatticeInf _) fun _ _ => rfl @[simp] theorem coe_inf : ⇑(f ⊓ g) = ⇑f ⊓ ⇑g := @@ -351,7 +351,7 @@ instance : Sup (TopHom α β) := ⟨fun f g => ⟨f ⊔ g, by rw [Pi.sup_apply, map_top, map_top, sup_top_eq]⟩⟩ instance : SemilatticeSup (TopHom α β) := - (FunLike.coe_injective.semilatticeSup _) fun _ _ => rfl + (DFunLike.coe_injective.semilatticeSup _) fun _ _ => rfl @[simp] theorem coe_sup : ⇑(f ⊔ g) = ⇑f ⊔ ⇑g := @@ -366,10 +366,10 @@ theorem sup_apply (a : α) : (f ⊔ g) a = f a ⊔ g a := end SemilatticeSup instance [Lattice β] [OrderTop β] : Lattice (TopHom α β) := - FunLike.coe_injective.lattice _ (fun _ _ => rfl) fun _ _ => rfl + DFunLike.coe_injective.lattice _ (fun _ _ => rfl) fun _ _ => rfl instance [DistribLattice β] [OrderTop β] : DistribLattice (TopHom α β) := - FunLike.coe_injective.distribLattice _ (fun _ _ => rfl) fun _ _ => rfl + DFunLike.coe_injective.distribLattice _ (fun _ _ => rfl) fun _ _ => rfl end TopHom @@ -397,7 +397,7 @@ initialize_simps_projections BotHom (toFun → apply) @[ext] theorem ext {f g : BotHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align bot_hom.ext BotHom.ext /-- Copy of a `BotHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -414,7 +414,7 @@ theorem coe_copy (f : BotHom α β) (f' : α → β) (h : f' = f) : ⇑(f.copy f #align bot_hom.coe_copy BotHom.coe_copy theorem copy_eq (f : BotHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align bot_hom.copy_eq BotHom.copy_eq instance : Inhabited (BotHom α β) := @@ -475,7 +475,7 @@ theorem id_comp (f : BotHom α β) : (BotHom.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : BotHom β γ} {f : BotHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => BotHom.ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (comp · f)⟩ + ⟨fun h => BotHom.ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (comp · f)⟩ #align bot_hom.cancel_right BotHom.cancel_right @[simp] @@ -488,10 +488,10 @@ theorem cancel_left {g : BotHom β γ} {f₁ f₂ : BotHom α β} (hg : Injectiv end Bot instance [Preorder β] [Bot β] : Preorder (BotHom α β) := - Preorder.lift (FunLike.coe : BotHom α β → α → β) + Preorder.lift (DFunLike.coe : BotHom α β → α → β) instance [PartialOrder β] [Bot β] : PartialOrder (BotHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective section OrderBot @@ -521,7 +521,7 @@ instance : Inf (BotHom α β) := ⟨fun f g => ⟨f ⊓ g, by rw [Pi.inf_apply, map_bot, map_bot, inf_bot_eq]⟩⟩ instance : SemilatticeInf (BotHom α β) := - (FunLike.coe_injective.semilatticeInf _) fun _ _ => rfl + (DFunLike.coe_injective.semilatticeInf _) fun _ _ => rfl @[simp] theorem coe_inf : ⇑(f ⊓ g) = ⇑f ⊓ ⇑g := @@ -543,7 +543,7 @@ instance : Sup (BotHom α β) := ⟨fun f g => ⟨f ⊔ g, by rw [Pi.sup_apply, map_bot, map_bot, sup_bot_eq]⟩⟩ instance : SemilatticeSup (BotHom α β) := - (FunLike.coe_injective.semilatticeSup _) fun _ _ => rfl + (DFunLike.coe_injective.semilatticeSup _) fun _ _ => rfl @[simp] theorem coe_sup : ⇑(f ⊔ g) = ⇑f ⊔ ⇑g := @@ -558,10 +558,10 @@ theorem sup_apply (a : α) : (f ⊔ g) a = f a ⊔ g a := end SemilatticeSup instance [Lattice β] [OrderBot β] : Lattice (BotHom α β) := - FunLike.coe_injective.lattice _ (fun _ _ => rfl) fun _ _ => rfl + DFunLike.coe_injective.lattice _ (fun _ _ => rfl) fun _ _ => rfl instance [DistribLattice β] [OrderBot β] : DistribLattice (BotHom α β) := - FunLike.coe_injective.distribLattice _ (fun _ _ => rfl) fun _ _ => rfl + DFunLike.coe_injective.distribLattice _ (fun _ _ => rfl) fun _ _ => rfl end BotHom @@ -598,7 +598,7 @@ instance : BoundedOrderHomClass (BoundedOrderHom α β) α @[ext] theorem ext {f g : BoundedOrderHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align bounded_order_hom.ext BoundedOrderHom.ext /-- Copy of a `BoundedOrderHom` with a new `toFun` equal to the old one. Useful to fix @@ -613,7 +613,7 @@ theorem coe_copy (f : BoundedOrderHom α β) (f' : α → β) (h : f' = f) : ⇑ #align bounded_order_hom.coe_copy BoundedOrderHom.coe_copy theorem copy_eq (f : BoundedOrderHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align bounded_order_hom.copy_eq BoundedOrderHom.copy_eq variable (α) @@ -691,7 +691,7 @@ theorem id_comp (f : BoundedOrderHom α β) : (BoundedOrderHom.id β).comp f = f @[simp] theorem cancel_right {g₁ g₂ : BoundedOrderHom β γ} {f : BoundedOrderHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => BoundedOrderHom.ext <| hf.forall.2 <| FunLike.ext_iff.1 h, + ⟨fun h => BoundedOrderHom.ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun g => comp g f)⟩ #align bounded_order_hom.cancel_right BoundedOrderHom.cancel_right diff --git a/Mathlib/Order/Hom/CompleteLattice.lean b/Mathlib/Order/Hom/CompleteLattice.lean index 612327af887a9..2f3c21f4ae9ba 100644 --- a/Mathlib/Order/Hom/CompleteLattice.lean +++ b/Mathlib/Order/Hom/CompleteLattice.lean @@ -13,7 +13,7 @@ import Mathlib.Order.Hom.Lattice This file defines frame homomorphisms and complete lattice homomorphisms. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -84,7 +84,7 @@ section You should extend this class when you extend `sSupHom`. -/ class sSupHomClass (F : Type*) (α β : outParam <| Type*) [SupSet α] [SupSet β] extends - FunLike F α fun _ => β where + DFunLike F α fun _ => β where /-- The proposition that members of `sSupHomClass`s commute with arbitrary suprema/joins. -/ map_sSup (f : F) (s : Set α) : f (sSup s) = sSup (f '' s) #align Sup_hom_class sSupHomClass @@ -93,7 +93,7 @@ class sSupHomClass (F : Type*) (α β : outParam <| Type*) [SupSet α] [SupSet You should extend this class when you extend `sInfHom`. -/ class sInfHomClass (F : Type*) (α β : outParam <| Type*) [InfSet α] [InfSet β] extends - FunLike F α fun _ => β where + DFunLike F α fun _ => β where /-- The proposition that members of `sInfHomClass`s commute with arbitrary infima/meets. -/ map_sInf (f : F) (s : Set α) : f (sInf s) = sInf (f '' s) #align Inf_hom_class sInfHomClass @@ -218,6 +218,13 @@ instance (priority := 100) OrderIsoClass.toCompleteLatticeHomClass [CompleteLatt { OrderIsoClass.tosSupHomClass, OrderIsoClass.tosInfHomClass with } #align order_iso_class.to_complete_lattice_hom_class OrderIsoClass.toCompleteLatticeHomClass +/-- Reinterpret an order isomorphism as a morphism of complete lattices. -/ +@[simps] def OrderIso.toCompleteLatticeHom [CompleteLattice α] [CompleteLattice β] + (f : OrderIso α β) : CompleteLatticeHom α β where + toFun := f + map_sInf' := sInfHomClass.map_sInf f + map_sSup' := sSupHomClass.map_sSup f + instance [SupSet α] [SupSet β] [sSupHomClass F α β] : CoeTC F (sSupHom α β) := ⟨fun f => ⟨f, map_sSup f⟩⟩ @@ -249,10 +256,10 @@ instance : sSupHomClass (sSupHom α β) α β map_sSup := sSupHom.map_sSup' -- Porting note: We do not want CoeFun for this in lean 4 --- /-- Helper instance for when there's too many metavariables to apply `funLike.has_coe_toFun` +-- /-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` -- directly. -/ -- instance : CoeFun (sSupHom α β) fun _ => α → β := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun @[simp] lemma toFun_eq_coe (f : sSupHom α β) : f.toFun = f := rfl #align Sup_hom.to_fun_eq_coe sSupHom.toFun_eq_coe @@ -261,7 +268,7 @@ instance : sSupHomClass (sSupHom α β) α β @[ext] theorem ext {f g : sSupHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align Sup_hom.ext sSupHom.ext /-- Copy of a `sSupHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -278,7 +285,7 @@ theorem coe_copy (f : sSupHom α β) (f' : α → β) (h : f' = f) : ⇑(f.copy #align Sup_hom.coe_copy sSupHom.coe_copy theorem copy_eq (f : sSupHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align Sup_hom.copy_eq sSupHom.copy_eq variable (α) @@ -339,7 +346,7 @@ theorem id_comp (f : sSupHom α β) : (sSupHom.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : sSupHom β γ} {f : sSupHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ #align Sup_hom.cancel_right sSupHom.cancel_right @[simp] @@ -353,7 +360,7 @@ end SupSet variable { _ : CompleteLattice β} instance : PartialOrder (sSupHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective instance : Bot (sSupHom α β) := ⟨⟨fun _ => ⊥, fun s => by @@ -398,7 +405,7 @@ instance : sInfHomClass (sInfHom α β) α β -- /-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_toFun` -- directly. -/ -- instance : CoeFun (sInfHom α β) fun _ => α → β := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun @[simp] lemma toFun_eq_coe (f : sInfHom α β) : f.toFun = f := rfl #align Inf_hom.to_fun_eq_coe sInfHom.toFun_eq_coe @@ -407,7 +414,7 @@ instance : sInfHomClass (sInfHom α β) α β @[ext] theorem ext {f g : sInfHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align Inf_hom.ext sInfHom.ext /-- Copy of a `sInfHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -424,7 +431,7 @@ theorem coe_copy (f : sInfHom α β) (f' : α → β) (h : f' = f) : ⇑(f.copy #align Inf_hom.coe_copy sInfHom.coe_copy theorem copy_eq (f : sInfHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align Inf_hom.copy_eq sInfHom.copy_eq variable (α) @@ -485,7 +492,7 @@ theorem id_comp (f : sInfHom α β) : (sInfHom.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : sInfHom β γ} {f : sInfHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ #align Inf_hom.cancel_right sInfHom.cancel_right @[simp] @@ -499,7 +506,7 @@ end InfSet variable [CompleteLattice β] instance : PartialOrder (sInfHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective instance : Top (sInfHom α β) := ⟨⟨fun _ => ⊤, fun s => by @@ -545,7 +552,7 @@ instance : FrameHomClass (FrameHom α β) α β -- /-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_toFun` -- directly. -/ -- instance : CoeFun (FrameHom α β) fun _ => α → β := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun /-- Reinterpret a `FrameHom` as a `LatticeHom`. -/ def toLatticeHom (f : FrameHom α β) : LatticeHom α β := @@ -561,7 +568,7 @@ lemma toFun_eq_coe (f : FrameHom α β) : f.toFun = f := rfl @[ext] theorem ext {f g : FrameHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align frame_hom.ext FrameHom.ext /-- Copy of a `FrameHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -576,7 +583,7 @@ theorem coe_copy (f : FrameHom α β) (f' : α → β) (h : f' = f) : ⇑(f.copy #align frame_hom.coe_copy FrameHom.coe_copy theorem copy_eq (f : FrameHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align frame_hom.copy_eq FrameHom.copy_eq variable (α) @@ -636,7 +643,7 @@ theorem id_comp (f : FrameHom α β) : (FrameHom.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : FrameHom β γ} {f : FrameHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ #align frame_hom.cancel_right FrameHom.cancel_right @[simp] @@ -646,7 +653,7 @@ theorem cancel_left {g : FrameHom β γ} {f₁ f₂ : FrameHom α β} (hg : Inje #align frame_hom.cancel_left FrameHom.cancel_left instance : PartialOrder (FrameHom α β) := - PartialOrder.lift _ FunLike.coe_injective + PartialOrder.lift _ DFunLike.coe_injective end FrameHom @@ -678,7 +685,7 @@ def toBoundedLatticeHom (f : CompleteLatticeHom α β) : BoundedLatticeHom α β -- /-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_toFun` -- directly. -/ -- instance : CoeFun (CompleteLatticeHom α β) fun _ => α → β := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun lemma toFun_eq_coe (f : CompleteLatticeHom α β) : f.toFun = f := rfl #align complete_lattice_hom.to_fun_eq_coe CompleteLatticeHom.toFun_eq_coe @@ -691,7 +698,7 @@ rfl @[ext] theorem ext {f g : CompleteLatticeHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align complete_lattice_hom.ext CompleteLatticeHom.ext /-- Copy of a `CompleteLatticeHom` with a new `toFun` equal to the old one. Useful to fix @@ -707,7 +714,7 @@ theorem coe_copy (f : CompleteLatticeHom α β) (f' : α → β) (h : f' = f) : #align complete_lattice_hom.coe_copy CompleteLatticeHom.coe_copy theorem copy_eq (f : CompleteLatticeHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align complete_lattice_hom.copy_eq CompleteLatticeHom.copy_eq variable (α) @@ -766,7 +773,7 @@ theorem id_comp (f : CompleteLatticeHom α β) : (CompleteLatticeHom.id β).comp @[simp] theorem cancel_right {g₁ g₂ : CompleteLatticeHom β γ} {f : CompleteLatticeHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (fun a ↦ comp a f)⟩ #align complete_lattice_hom.cancel_right CompleteLatticeHom.cancel_right @[simp] diff --git a/Mathlib/Order/Hom/Lattice.lean b/Mathlib/Order/Hom/Lattice.lean index 8bb035d4410b7..0c12a0af9b282 100644 --- a/Mathlib/Order/Hom/Lattice.lean +++ b/Mathlib/Order/Hom/Lattice.lean @@ -13,7 +13,7 @@ import Mathlib.Order.SymmDiff This file defines (bounded) lattice homomorphisms. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -100,7 +100,7 @@ section You should extend this class when you extend `SupHom`. -/ class SupHomClass (F : Type*) (α β : outParam <| Type*) [Sup α] [Sup β] extends - FunLike F α fun _ => β where + DFunLike F α fun _ => β where /-- A `SupHomClass` morphism preserves suprema. -/ map_sup (f : F) (a b : α) : f (a ⊔ b) = f a ⊔ f b #align sup_hom_class SupHomClass @@ -109,7 +109,7 @@ class SupHomClass (F : Type*) (α β : outParam <| Type*) [Sup α] [Sup β] exte You should extend this class when you extend `InfHom`. -/ class InfHomClass (F : Type*) (α β : outParam <| Type*) [Inf α] [Inf β] extends - FunLike F α fun _ => β where + DFunLike F α fun _ => β where /-- An `InfHomClass` morphism preserves infima. -/ map_inf (f : F) (a b : α) : f (a ⊓ b) = f a ⊓ f b #align inf_hom_class InfHomClass @@ -291,6 +291,7 @@ theorem map_sdiff' (a b : α) : f (a \ b) = f a \ f b := by rw [sdiff_eq, sdiff_eq, map_inf, map_compl'] #align map_sdiff' map_sdiff' +open scoped symmDiff in /-- Special case of `map_symmDiff` for boolean algebras. -/ theorem map_symmDiff' (a b : α) : f (a ∆ b) = f a ∆ f b := by rw [symmDiff, symmDiff, map_sup, map_sdiff', map_sdiff'] @@ -339,11 +340,11 @@ instance : SupHomClass (SupHom α β) α β where coe_injective' f g h := by cases f; cases g; congr map_sup := SupHom.map_sup' -/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ --- porting note: replaced `CoeFun` with `FunLike` so that we use `FunLike.coe` instead of `toFun` -instance : FunLike (SupHom α β) α fun _ => β := - SupHomClass.toFunLike +-- porting note: replaced `CoeFun` with `FunLike` so that we use `DFunLike.coe` instead of `toFun` +instance : FunLike (SupHom α β) α β := + SupHomClass.toDFunLike @[simp] lemma toFun_eq_coe (f : SupHom α β) : f.toFun = f := rfl #align sup_hom.to_fun_eq_coe SupHom.toFun_eq_coe @@ -352,7 +353,7 @@ instance : FunLike (SupHom α β) α fun _ => β := @[ext] theorem ext {f g : SupHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align sup_hom.ext SupHom.ext /-- Copy of a `SupHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -368,7 +369,7 @@ theorem coe_copy (f : SupHom α β) (f' : α → β) (h : f' = f) : ⇑(f.copy f #align sup_hom.coe_copy SupHom.coe_copy theorem copy_eq (f : SupHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align sup_hom.copy_eq SupHom.copy_eq variable (α) @@ -424,7 +425,7 @@ theorem comp_assoc (f : SupHom γ δ) (g : SupHom β γ) (h : SupHom α β) : @[simp] theorem cancel_right {g₁ g₂ : SupHom β γ} {f : SupHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => SupHom.ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ + ⟨fun h => SupHom.ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ #align sup_hom.cancel_right SupHom.cancel_right @[simp] @@ -462,7 +463,7 @@ instance : Sup (SupHom α β) := exact sup_sup_sup_comm _ _ _ _⟩⟩ instance : SemilatticeSup (SupHom α β) := - (FunLike.coe_injective.semilatticeSup _) fun _ _ => rfl + (DFunLike.coe_injective.semilatticeSup _) fun _ _ => rfl instance [Bot β] : Bot (SupHom α β) := ⟨SupHom.const α ⊥⟩ @@ -480,7 +481,7 @@ instance [BoundedOrder β] : BoundedOrder (SupHom α β) := BoundedOrder.lift ((↑) : _ → α → β) (fun _ _ => id) rfl rfl @[simp] -theorem coe_sup (f g : SupHom α β) : FunLike.coe (f ⊔ g) = f ⊔ g := +theorem coe_sup (f g : SupHom α β) : DFunLike.coe (f ⊔ g) = f ⊔ g := rfl #align sup_hom.coe_sup SupHom.coe_sup @@ -527,10 +528,10 @@ instance : InfHomClass (InfHom α β) α β where coe_injective' f g h := by cases f; cases g; congr map_inf := InfHom.map_inf' -/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ -instance : FunLike (InfHom α β) α fun _ => β := - InfHomClass.toFunLike +instance : FunLike (InfHom α β) α β := + InfHomClass.toDFunLike @[simp] lemma toFun_eq_coe (f : InfHom α β) : f.toFun = (f : α → β) := rfl #align inf_hom.to_fun_eq_coe InfHom.toFun_eq_coe @@ -539,7 +540,7 @@ instance : FunLike (InfHom α β) α fun _ => β := @[ext] theorem ext {f g : InfHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align inf_hom.ext InfHom.ext /-- Copy of an `InfHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -556,7 +557,7 @@ theorem coe_copy (f : InfHom α β) (f' : α → β) (h : f' = f) : ⇑(f.copy f #align inf_hom.coe_copy InfHom.coe_copy theorem copy_eq (f : InfHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align inf_hom.copy_eq InfHom.copy_eq variable (α) @@ -612,7 +613,7 @@ theorem comp_assoc (f : InfHom γ δ) (g : InfHom β γ) (h : InfHom α β) : @[simp] theorem cancel_right {g₁ g₂ : InfHom β γ} {f : InfHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => InfHom.ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ + ⟨fun h => InfHom.ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ #align inf_hom.cancel_right InfHom.cancel_right @[simp] @@ -650,7 +651,7 @@ instance : Inf (InfHom α β) := exact inf_inf_inf_comm _ _ _ _⟩⟩ instance : SemilatticeInf (InfHom α β) := - (FunLike.coe_injective.semilatticeInf _) fun _ _ => rfl + (DFunLike.coe_injective.semilatticeInf _) fun _ _ => rfl instance [Bot β] : Bot (InfHom α β) := ⟨InfHom.const α ⊥⟩ @@ -668,7 +669,7 @@ instance [BoundedOrder β] : BoundedOrder (InfHom α β) := BoundedOrder.lift ((↑) : _ → α → β) (fun _ _ => id) rfl rfl @[simp] -theorem coe_inf (f g : InfHom α β) : FunLike.coe (f ⊓ g) = f ⊓ g := +theorem coe_inf (f g : InfHom α β) : DFunLike.coe (f ⊓ g) = f ⊓ g := rfl #align inf_hom.coe_inf InfHom.coe_inf @@ -724,9 +725,9 @@ instance : SupBotHomClass (SupBotHom α β) α β map_sup f := f.map_sup' map_bot f := f.map_bot' --- porting note: replaced `CoeFun` instance with `FunLike` instance -instance : FunLike (SupBotHom α β) α fun _ => β := - SupHomClass.toFunLike +-- porting note: replaced `CoeFun` instance with `DFunLike` instance +instance : FunLike (SupBotHom α β) α β := + SupHomClass.toDFunLike lemma toFun_eq_coe (f : SupBotHom α β) : f.toFun = f := rfl #align sup_bot_hom.to_fun_eq_coe SupBotHom.toFun_eq_coe @@ -737,7 +738,7 @@ lemma toFun_eq_coe (f : SupBotHom α β) : f.toFun = f := rfl @[ext] theorem ext {f g : SupBotHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align sup_bot_hom.ext SupBotHom.ext /-- Copy of a `SupBotHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -752,7 +753,7 @@ theorem coe_copy (f : SupBotHom α β) (f' : α → β) (h : f' = f) : ⇑(f.cop #align sup_bot_hom.coe_copy SupBotHom.coe_copy theorem copy_eq (f : SupBotHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align sup_bot_hom.copy_eq SupBotHom.copy_eq variable (α) @@ -808,7 +809,7 @@ theorem comp_assoc (f : SupBotHom γ δ) (g : SupBotHom β γ) (h : SupBotHom α @[simp] theorem cancel_right {g₁ g₂ : SupBotHom β γ} {f : SupBotHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ #align sup_bot_hom.cancel_right SupBotHom.cancel_right @[simp] @@ -825,14 +826,14 @@ instance : Sup (SupBotHom α β) := ⟨fun f g => { f.toBotHom ⊔ g.toBotHom with toSupHom := f.toSupHom ⊔ g.toSupHom }⟩ instance : SemilatticeSup (SupBotHom α β) := - (FunLike.coe_injective.semilatticeSup _) fun _ _ => rfl + (DFunLike.coe_injective.semilatticeSup _) fun _ _ => rfl instance : OrderBot (SupBotHom α β) where bot := ⟨⊥, rfl⟩ bot_le _ _ := bot_le @[simp] -theorem coe_sup (f g : SupBotHom α β) : FunLike.coe (f ⊔ g) = f ⊔ g := +theorem coe_sup (f g : SupBotHom α β) : DFunLike.coe (f ⊔ g) = f ⊔ g := rfl #align sup_bot_hom.coe_sup SupBotHom.coe_sup @@ -879,10 +880,10 @@ instance : InfTopHomClass (InfTopHom α β) α β map_inf f := f.map_inf' map_top f := f.map_top' -/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ -instance : FunLike (InfTopHom α β) α fun _ => β := - InfHomClass.toFunLike +instance : FunLike (InfTopHom α β) α β := + InfHomClass.toDFunLike theorem toFun_eq_coe (f : InfTopHom α β) : f.toFun = f := rfl #align inf_top_hom.to_fun_eq_coe InfTopHom.toFun_eq_coe @@ -893,7 +894,7 @@ theorem toFun_eq_coe (f : InfTopHom α β) : f.toFun = f := rfl @[ext] theorem ext {f g : InfTopHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align inf_top_hom.ext InfTopHom.ext /-- Copy of an `InfTopHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -908,7 +909,7 @@ theorem coe_copy (f : InfTopHom α β) (f' : α → β) (h : f' = f) : ⇑(f.cop #align inf_top_hom.coe_copy InfTopHom.coe_copy theorem copy_eq (f : InfTopHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align inf_top_hom.copy_eq InfTopHom.copy_eq variable (α) @@ -964,7 +965,7 @@ theorem comp_assoc (f : InfTopHom γ δ) (g : InfTopHom β γ) (h : InfTopHom α @[simp] theorem cancel_right {g₁ g₂ : InfTopHom β γ} {f : InfTopHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ #align inf_top_hom.cancel_right InfTopHom.cancel_right @[simp] @@ -981,14 +982,14 @@ instance : Inf (InfTopHom α β) := ⟨fun f g => { f.toTopHom ⊓ g.toTopHom with toInfHom := f.toInfHom ⊓ g.toInfHom }⟩ instance : SemilatticeInf (InfTopHom α β) := - (FunLike.coe_injective.semilatticeInf _) fun _ _ => rfl + (DFunLike.coe_injective.semilatticeInf _) fun _ _ => rfl instance : OrderTop (InfTopHom α β) where top := ⟨⊤, rfl⟩ le_top _ _ := le_top @[simp] -theorem coe_inf (f g : InfTopHom α β) : FunLike.coe (f ⊓ g) = f ⊓ g := +theorem coe_inf (f g : InfTopHom α β) : DFunLike.coe (f ⊓ g) = f ⊓ g := rfl #align inf_top_hom.coe_inf InfTopHom.coe_inf @@ -1028,10 +1029,10 @@ instance : LatticeHomClass (LatticeHom α β) α β map_sup f := f.map_sup' map_inf f := f.map_inf' -/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ -instance : FunLike (LatticeHom α β) α fun _ => β := - SupHomClass.toFunLike +instance : FunLike (LatticeHom α β) α β := + SupHomClass.toDFunLike lemma toFun_eq_coe (f : LatticeHom α β) : f.toFun = f := rfl #align lattice_hom.to_fun_eq_coe LatticeHom.toFun_eq_coe @@ -1042,7 +1043,7 @@ lemma toFun_eq_coe (f : LatticeHom α β) : f.toFun = f := rfl @[ext] theorem ext {f g : LatticeHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align lattice_hom.ext LatticeHom.ext /-- Copy of a `LatticeHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -1057,7 +1058,7 @@ theorem coe_copy (f : LatticeHom α β) (f' : α → β) (h : f' = f) : ⇑(f.co #align lattice_hom.coe_copy LatticeHom.coe_copy theorem copy_eq (f : LatticeHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align lattice_hom.copy_eq LatticeHom.copy_eq variable (α) @@ -1140,7 +1141,7 @@ theorem id_comp (f : LatticeHom α β) : (LatticeHom.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : LatticeHom β γ} {f : LatticeHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => LatticeHom.ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ + ⟨fun h => LatticeHom.ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ #align lattice_hom.cancel_right LatticeHom.cancel_right @[simp] @@ -1229,7 +1230,7 @@ instance instBoundedLatticeHomClass : BoundedLatticeHomClass (BoundedLatticeHom @[ext] theorem ext {f g : BoundedLatticeHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align bounded_lattice_hom.ext BoundedLatticeHom.ext /-- Copy of a `BoundedLatticeHom` with a new `toFun` equal to the old one. Useful to fix @@ -1244,7 +1245,7 @@ theorem coe_copy (f : BoundedLatticeHom α β) (f' : α → β) (h : f' = f) : #align bounded_lattice_hom.coe_copy BoundedLatticeHom.coe_copy theorem copy_eq (f : BoundedLatticeHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align bounded_lattice_hom.copy_eq BoundedLatticeHom.copy_eq variable (α) @@ -1335,7 +1336,7 @@ theorem comp_assoc (f : BoundedLatticeHom γ δ) (g : BoundedLatticeHom β γ) @[simp] theorem cancel_right {g₁ g₂ : BoundedLatticeHom β γ} {f : BoundedLatticeHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => BoundedLatticeHom.ext <| hf.forall.2 <| FunLike.ext_iff.1 h, + ⟨fun h => BoundedLatticeHom.ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ #align bounded_lattice_hom.cancel_right BoundedLatticeHom.cancel_right @@ -1597,14 +1598,14 @@ protected def withTop (f : SupHom α β) : SupHom (WithTop α) (WithTop β) wher #align sup_hom.with_top SupHom.withTop @[simp] -theorem withTop_id : (SupHom.id α).withTop = SupHom.id _ := FunLike.coe_injective Option.map_id +theorem withTop_id : (SupHom.id α).withTop = SupHom.id _ := DFunLike.coe_injective Option.map_id #align sup_hom.with_top_id SupHom.withTop_id @[simp] theorem withTop_comp (f : SupHom β γ) (g : SupHom α β) : (f.comp g).withTop = f.withTop.comp g.withTop := --- porting note: Proof was `FunLike.coe_injective (Option.map_comp_map _ _).symm` - FunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ +-- porting note: Proof was `DFunLike.coe_injective (Option.map_comp_map _ _).symm` + DFunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ #align sup_hom.with_top_comp SupHom.withTop_comp /-- Adjoins a `⊥` to the domain and codomain of a `SupHom`. -/ @@ -1621,14 +1622,14 @@ protected def withBot (f : SupHom α β) : SupBotHom (WithBot α) (WithBot β) w #align sup_hom.with_bot SupHom.withBot @[simp] -theorem withBot_id : (SupHom.id α).withBot = SupBotHom.id _ := FunLike.coe_injective Option.map_id +theorem withBot_id : (SupHom.id α).withBot = SupBotHom.id _ := DFunLike.coe_injective Option.map_id #align sup_hom.with_bot_id SupHom.withBot_id @[simp] theorem withBot_comp (f : SupHom β γ) (g : SupHom α β) : (f.comp g).withBot = f.withBot.comp g.withBot := --- porting note: Proof was `FunLike.coe_injective (Option.map_comp_map _ _).symm` - FunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ +-- porting note: Proof was `DFunLike.coe_injective (Option.map_comp_map _ _).symm` + DFunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ #align sup_hom.with_bot_comp SupHom.withBot_comp /-- Adjoins a `⊤` to the codomain of a `SupHom`. -/ @@ -1676,14 +1677,14 @@ protected def withTop (f : InfHom α β) : InfTopHom (WithTop α) (WithTop β) w #align inf_hom.with_top InfHom.withTop @[simp] -theorem withTop_id : (InfHom.id α).withTop = InfTopHom.id _ := FunLike.coe_injective Option.map_id +theorem withTop_id : (InfHom.id α).withTop = InfTopHom.id _ := DFunLike.coe_injective Option.map_id #align inf_hom.with_top_id InfHom.withTop_id @[simp] theorem withTop_comp (f : InfHom β γ) (g : InfHom α β) : (f.comp g).withTop = f.withTop.comp g.withTop := --- porting note: Proof was `FunLike.coe_injective (Option.map_comp_map _ _).symm` - FunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ +-- porting note: Proof was `DFunLike.coe_injective (Option.map_comp_map _ _).symm` + DFunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ #align inf_hom.with_top_comp InfHom.withTop_comp /-- Adjoins a `⊥` to the domain and codomain of an `InfHom`. -/ @@ -1699,14 +1700,14 @@ protected def withBot (f : InfHom α β) : InfHom (WithBot α) (WithBot β) wher #align inf_hom.with_bot InfHom.withBot @[simp] -theorem withBot_id : (InfHom.id α).withBot = InfHom.id _ := FunLike.coe_injective Option.map_id +theorem withBot_id : (InfHom.id α).withBot = InfHom.id _ := DFunLike.coe_injective Option.map_id #align inf_hom.with_bot_id InfHom.withBot_id @[simp] theorem withBot_comp (f : InfHom β γ) (g : InfHom α β) : (f.comp g).withBot = f.withBot.comp g.withBot := --- porting note: Proof was `FunLike.coe_injective (Option.map_comp_map _ _).symm` - FunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ +-- porting note: Proof was `DFunLike.coe_injective (Option.map_comp_map _ _).symm` + DFunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ #align inf_hom.with_bot_comp InfHom.withBot_comp /-- Adjoins a `⊤` to the codomain of an `InfHom`. -/ @@ -1754,14 +1755,14 @@ lemma withTop_apply (f : LatticeHom α β) (a : WithTop α) : f.withTop a = a.ma @[simp] theorem withTop_id : (LatticeHom.id α).withTop = LatticeHom.id _ := - FunLike.coe_injective Option.map_id + DFunLike.coe_injective Option.map_id #align lattice_hom.with_top_id LatticeHom.withTop_id @[simp] theorem withTop_comp (f : LatticeHom β γ) (g : LatticeHom α β) : (f.comp g).withTop = f.withTop.comp g.withTop := --- porting note: Proof was `FunLike.coe_injective (Option.map_comp_map _ _).symm` - FunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ +-- porting note: Proof was `DFunLike.coe_injective (Option.map_comp_map _ _).symm` + DFunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ #align lattice_hom.with_top_comp LatticeHom.withTop_comp /-- Adjoins a `⊥` to the domain and codomain of a `LatticeHom`. -/ @@ -1778,14 +1779,14 @@ lemma withBot_apply (f : LatticeHom α β) (a : WithBot α) : f.withBot a = a.ma @[simp] theorem withBot_id : (LatticeHom.id α).withBot = LatticeHom.id _ := - FunLike.coe_injective Option.map_id + DFunLike.coe_injective Option.map_id #align lattice_hom.with_bot_id LatticeHom.withBot_id @[simp] theorem withBot_comp (f : LatticeHom β γ) (g : LatticeHom α β) : (f.comp g).withBot = f.withBot.comp g.withBot := --- porting note: Proof was `FunLike.coe_injective (Option.map_comp_map _ _).symm` - FunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ +-- porting note: Proof was `DFunLike.coe_injective (Option.map_comp_map _ _).symm` + DFunLike.coe_injective <| Eq.symm <| Option.map_comp_map _ _ #align lattice_hom.with_bot_comp LatticeHom.withBot_comp /-- Adjoins a `⊤` and `⊥` to the domain and codomain of a `LatticeHom`. -/ @@ -1804,7 +1805,7 @@ lemma withTopWithBot_apply (f : LatticeHom α β) (a : WithTop <| WithBot α) : @[simp] theorem withTopWithBot_id : (LatticeHom.id α).withTopWithBot = BoundedLatticeHom.id _ := - FunLike.coe_injective $ by + DFunLike.coe_injective <| by refine' (congr_arg Option.map _).trans Option.map_id rw [withBot_id] rfl @@ -1831,7 +1832,7 @@ def withBot' [OrderBot β] (f : LatticeHom α β) : LatticeHom (WithBot α) β : /-- Adjoins a `⊤` and `⊥` to the codomain of a `LatticeHom`. -/ @[simps] def withTopWithBot' [BoundedOrder β] (f : LatticeHom α β) : - BoundedLatticeHom (WithTop $ WithBot α) β where + BoundedLatticeHom (WithTop <| WithBot α) β where toLatticeHom := f.withBot'.withTop' map_top' := rfl map_bot' := rfl diff --git a/Mathlib/Order/InitialSeg.lean b/Mathlib/Order/InitialSeg.lean index 1062281ebc660..cddbbeb149793 100644 --- a/Mathlib/Order/InitialSeg.lean +++ b/Mathlib/Order/InitialSeg.lean @@ -75,7 +75,7 @@ instance : EmbeddingLike (r ≼i s) α β := injective' := fun f => f.inj' } @[ext] lemma ext {f g : r ≼i s} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align initial_seg.ext InitialSeg.ext @[simp] diff --git a/Mathlib/Order/Irreducible.lean b/Mathlib/Order/Irreducible.lean index 56e53bcc4e5c7..41b8be8a89469 100644 --- a/Mathlib/Order/Irreducible.lean +++ b/Mathlib/Order/Irreducible.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Data.Finset.Lattice -import Mathlib.Data.Fintype.Card #align_import order.irreducible from "leanprover-community/mathlib"@"bf2428c9486c407ca38b5b3fb10b87dad0bc99fa" diff --git a/Mathlib/Order/Iterate.lean b/Mathlib/Order/Iterate.lean index 3aa4f48939f1f..634d240497896 100644 --- a/Mathlib/Order/Iterate.lean +++ b/Mathlib/Order/Iterate.lean @@ -46,7 +46,7 @@ theorem seq_le_seq (hf : Monotone f) (n : ℕ) (h₀ : x 0 ≤ y 0) (hx : ∀ k (hy : ∀ k < n, f (y k) ≤ y (k + 1)) : x n ≤ y n := by induction' n with n ihn · exact h₀ - · refine' (hx _ n.lt_succ_self).trans ((hf $ ihn _ _).trans (hy _ n.lt_succ_self)) + · refine' (hx _ n.lt_succ_self).trans ((hf <| ihn _ _).trans (hy _ n.lt_succ_self)) exact fun k hk => hx _ (hk.trans n.lt_succ_self) exact fun k hk => hy _ (hk.trans n.lt_succ_self) #align monotone.seq_le_seq Monotone.seq_le_seq @@ -55,7 +55,7 @@ theorem seq_pos_lt_seq_of_lt_of_le (hf : Monotone f) {n : ℕ} (hn : 0 < n) (h (hx : ∀ k < n, x (k + 1) < f (x k)) (hy : ∀ k < n, f (y k) ≤ y (k + 1)) : x n < y n := by induction' n with n ihn · exact hn.false.elim - suffices x n ≤ y n from (hx n n.lt_succ_self).trans_le ((hf this).trans $ hy n n.lt_succ_self) + suffices x n ≤ y n from (hx n n.lt_succ_self).trans_le ((hf this).trans <| hy n n.lt_succ_self) cases n with | zero => exact h₀ | succ n => diff --git a/Mathlib/Order/Lattice.lean b/Mathlib/Order/Lattice.lean index 2445a1d667d50..89dc78ea9ae86 100644 --- a/Mathlib/Order/Lattice.lean +++ b/Mathlib/Order/Lattice.lean @@ -163,12 +163,12 @@ theorem sup_le_iff : a ⊔ b ≤ c ↔ a ≤ c ∧ b ≤ c := @[simp] theorem sup_eq_left : a ⊔ b = a ↔ b ≤ a := - le_antisymm_iff.trans $ by simp [le_rfl] + le_antisymm_iff.trans <| by simp [le_rfl] #align sup_eq_left sup_eq_left @[simp] theorem sup_eq_right : a ⊔ b = b ↔ a ≤ b := - le_antisymm_iff.trans $ by simp [le_rfl] + le_antisymm_iff.trans <| by simp [le_rfl] #align sup_eq_right sup_eq_right @[simp] @@ -192,12 +192,12 @@ attribute [simp] sup_of_le_left sup_of_le_right @[simp] theorem left_lt_sup : a < a ⊔ b ↔ ¬b ≤ a := - le_sup_left.lt_iff_ne.trans $ not_congr left_eq_sup + le_sup_left.lt_iff_ne.trans <| not_congr left_eq_sup #align left_lt_sup left_lt_sup @[simp] theorem right_lt_sup : b < a ⊔ b ↔ ¬a ≤ b := - le_sup_right.lt_iff_ne.trans $ not_congr right_eq_sup + le_sup_right.lt_iff_ne.trans <| not_congr right_eq_sup #align right_lt_sup right_lt_sup theorem left_or_right_lt_sup (h : a ≠ b) : a < a ⊔ b ∨ b < a ⊔ b := @@ -280,11 +280,11 @@ theorem sup_sup_distrib_right (a b c : α) : a ⊔ b ⊔ c = a ⊔ c ⊔ (b ⊔ #align sup_sup_distrib_right sup_sup_distrib_right theorem sup_congr_left (hb : b ≤ a ⊔ c) (hc : c ≤ a ⊔ b) : a ⊔ b = a ⊔ c := - (sup_le le_sup_left hb).antisymm $ sup_le le_sup_left hc + (sup_le le_sup_left hb).antisymm <| sup_le le_sup_left hc #align sup_congr_left sup_congr_left theorem sup_congr_right (ha : a ≤ b ⊔ c) (hb : b ≤ a ⊔ c) : a ⊔ c = b ⊔ c := - (sup_le ha le_sup_right).antisymm $ sup_le hb le_sup_right + (sup_le ha le_sup_right).antisymm <| sup_le hb le_sup_right #align sup_congr_right sup_congr_right theorem sup_eq_sup_iff_left : a ⊔ b = a ⊔ c ↔ b ≤ a ⊔ c ∧ c ≤ a ⊔ b := @@ -420,12 +420,12 @@ theorem le_inf_iff : a ≤ b ⊓ c ↔ a ≤ b ∧ a ≤ c := @[simp] theorem inf_eq_left : a ⊓ b = a ↔ a ≤ b := - le_antisymm_iff.trans $ by simp [le_rfl] + le_antisymm_iff.trans <| by simp [le_rfl] #align inf_eq_left inf_eq_left @[simp] theorem inf_eq_right : a ⊓ b = b ↔ b ≤ a := - le_antisymm_iff.trans $ by simp [le_rfl] + le_antisymm_iff.trans <| by simp [le_rfl] #align inf_eq_right inf_eq_right @[simp] @@ -894,7 +894,7 @@ theorem sup_eq_maxDefault [SemilatticeSup α] [DecidableRel ((· ≤ ·) : α ext x y unfold maxDefault split_ifs with h' - exacts [sup_of_le_right h', sup_of_le_left $ (total_of (· ≤ ·) x y).resolve_left h'] + exacts [sup_of_le_right h', sup_of_le_left <| (total_of (· ≤ ·) x y).resolve_left h'] #align sup_eq_max_default sup_eq_maxDefault theorem inf_eq_minDefault [SemilatticeInf α] [DecidableRel ((· ≤ ·) : α → α → Prop)] @@ -903,7 +903,7 @@ theorem inf_eq_minDefault [SemilatticeInf α] [DecidableRel ((· ≤ ·) : α ext x y unfold minDefault split_ifs with h' - exacts [inf_of_le_left h', inf_of_le_right $ (total_of (· ≤ ·) x y).resolve_left h'] + exacts [inf_of_le_left h', inf_of_le_right <| (total_of (· ≤ ·) x y).resolve_left h'] #align inf_eq_min_default inf_eq_minDefault /-- A lattice with total order is a linear order. @@ -930,8 +930,8 @@ instance (priority := 100) {α : Type u} [LinearOrder α] : __ := inferInstanceAs (Lattice α) le_sup_inf _ b c := match le_total b c with - | Or.inl h => inf_le_of_left_le $ sup_le_sup_left (le_inf (le_refl b) h) _ - | Or.inr h => inf_le_of_right_le $ sup_le_sup_left (le_inf h (le_refl c)) _ + | Or.inl h => inf_le_of_left_le <| sup_le_sup_left (le_inf (le_refl b) h) _ + | Or.inr h => inf_le_of_right_le <| sup_le_sup_left (le_inf h (le_refl c)) _ instance : DistribLattice ℕ := inferInstance @@ -1098,7 +1098,7 @@ theorem map_inf_le [SemilatticeInf α] [SemilatticeInf β] {f : α → β} (h : theorem of_map_inf [SemilatticeInf α] [SemilatticeInf β] {f : α → β} (h : ∀ x y, f (x ⊓ y) = f x ⊓ f y) : Monotone f := - fun x y hxy => inf_eq_left.1 $ by rw [← h, inf_eq_left.2 hxy] + fun x y hxy => inf_eq_left.1 <| by rw [← h, inf_eq_left.2 hxy] #align monotone.of_map_inf Monotone.of_map_inf theorem of_map_sup [SemilatticeSup α] [SemilatticeSup β] {f : α → β} diff --git a/Mathlib/Order/LiminfLimsup.lean b/Mathlib/Order/LiminfLimsup.lean index 2c0eb89cd0d9b..74b135ea9525f 100644 --- a/Mathlib/Order/LiminfLimsup.lean +++ b/Mathlib/Order/LiminfLimsup.lean @@ -1025,10 +1025,10 @@ theorem bliminf_or_le_inf_aux_left : (bliminf u f fun x => p x ∨ q x) ≤ blim theorem bliminf_or_le_inf_aux_right : (bliminf u f fun x => p x ∨ q x) ≤ bliminf u f q := bliminf_or_le_inf.trans inf_le_right -/- Porting note: Replaced `e` with `FunLike.coe e` to override the strange +/- Porting note: Replaced `e` with `DFunLike.coe e` to override the strange coercion to `↑(RelIso.toRelEmbedding e).toEmbedding`.-/ theorem OrderIso.apply_blimsup [CompleteLattice γ] (e : α ≃o γ) : - FunLike.coe e (blimsup u f p) = blimsup ((FunLike.coe e) ∘ u) f p := by + DFunLike.coe e (blimsup u f p) = blimsup ((DFunLike.coe e) ∘ u) f p := by simp only [blimsup_eq, map_sInf, Function.comp_apply] congr ext c diff --git a/Mathlib/Order/ModularLattice.lean b/Mathlib/Order/ModularLattice.lean index e6f4a6236245f..046c26bf2461e 100644 --- a/Mathlib/Order/ModularLattice.lean +++ b/Mathlib/Order/ModularLattice.lean @@ -61,28 +61,28 @@ variable {α : Type*} cover `a ⊓ b`. -/ class IsWeakUpperModularLattice (α : Type*) [Lattice α] : Prop where /-- `a ⊔ b` covers `a` and `b` if `a` and `b` both cover `a ⊓ b`. -/ - covby_sup_of_inf_covby_covby {a b : α} : a ⊓ b ⋖ a → a ⊓ b ⋖ b → a ⋖ a ⊔ b + covBy_sup_of_inf_covBy_covBy {a b : α} : a ⊓ b ⋖ a → a ⊓ b ⋖ b → a ⋖ a ⊔ b #align is_weak_upper_modular_lattice IsWeakUpperModularLattice /-- A weakly lower modular lattice is a lattice where `a` and `b` cover `a ⊓ b` if `a ⊔ b` covers both `a` and `b`. -/ class IsWeakLowerModularLattice (α : Type*) [Lattice α] : Prop where /-- `a` and `b` cover `a ⊓ b` if `a ⊔ b` covers both `a` and `b` -/ - inf_covby_of_covby_covby_sup {a b : α} : a ⋖ a ⊔ b → b ⋖ a ⊔ b → a ⊓ b ⋖ a + inf_covBy_of_covBy_covBy_sup {a b : α} : a ⋖ a ⊔ b → b ⋖ a ⊔ b → a ⊓ b ⋖ a #align is_weak_lower_modular_lattice IsWeakLowerModularLattice /-- An upper modular lattice, aka semimodular lattice, is a lattice where `a ⊔ b` covers `a` and `b` if either `a` or `b` covers `a ⊓ b`. -/ class IsUpperModularLattice (α : Type*) [Lattice α] : Prop where /-- `a ⊔ b` covers `a` and `b` if either `a` or `b` covers `a ⊓ b` -/ - covby_sup_of_inf_covby {a b : α} : a ⊓ b ⋖ a → b ⋖ a ⊔ b + covBy_sup_of_inf_covBy {a b : α} : a ⊓ b ⋖ a → b ⋖ a ⊔ b #align is_upper_modular_lattice IsUpperModularLattice /-- A lower modular lattice is a lattice where `a` and `b` both cover `a ⊓ b` if `a ⊔ b` covers either `a` or `b`. -/ class IsLowerModularLattice (α : Type*) [Lattice α] : Prop where /-- `a` and `b` both cover `a ⊓ b` if `a ⊔ b` covers either `a` or `b` -/ - inf_covby_of_covby_sup {a b : α} : a ⋖ a ⊔ b → a ⊓ b ⋖ b + inf_covBy_of_covBy_sup {a b : α} : a ⋖ a ⊔ b → a ⊓ b ⋖ b #align is_lower_modular_lattice IsLowerModularLattice /-- A modular lattice is one with a limited associativity between `⊓` and `⊔`. -/ @@ -95,20 +95,20 @@ section WeakUpperModular variable [Lattice α] [IsWeakUpperModularLattice α] {a b : α} -theorem covby_sup_of_inf_covby_of_inf_covby_left : a ⊓ b ⋖ a → a ⊓ b ⋖ b → a ⋖ a ⊔ b := - IsWeakUpperModularLattice.covby_sup_of_inf_covby_covby -#align covby_sup_of_inf_covby_of_inf_covby_left covby_sup_of_inf_covby_of_inf_covby_left +theorem covBy_sup_of_inf_covBy_of_inf_covBy_left : a ⊓ b ⋖ a → a ⊓ b ⋖ b → a ⋖ a ⊔ b := + IsWeakUpperModularLattice.covBy_sup_of_inf_covBy_covBy +#align covby_sup_of_inf_covby_of_inf_covby_left covBy_sup_of_inf_covBy_of_inf_covBy_left -theorem covby_sup_of_inf_covby_of_inf_covby_right : a ⊓ b ⋖ a → a ⊓ b ⋖ b → b ⋖ a ⊔ b := by +theorem covBy_sup_of_inf_covBy_of_inf_covBy_right : a ⊓ b ⋖ a → a ⊓ b ⋖ b → b ⋖ a ⊔ b := by rw [inf_comm, sup_comm] - exact fun ha hb => covby_sup_of_inf_covby_of_inf_covby_left hb ha -#align covby_sup_of_inf_covby_of_inf_covby_right covby_sup_of_inf_covby_of_inf_covby_right + exact fun ha hb => covBy_sup_of_inf_covBy_of_inf_covBy_left hb ha +#align covby_sup_of_inf_covby_of_inf_covby_right covBy_sup_of_inf_covBy_of_inf_covBy_right -alias Covby.sup_of_inf_of_inf_left := covby_sup_of_inf_covby_of_inf_covby_left -#align covby.sup_of_inf_of_inf_left Covby.sup_of_inf_of_inf_left +alias CovBy.sup_of_inf_of_inf_left := covBy_sup_of_inf_covBy_of_inf_covBy_left +#align covby.sup_of_inf_of_inf_left CovBy.sup_of_inf_of_inf_left -alias Covby.sup_of_inf_of_inf_right := covby_sup_of_inf_covby_of_inf_covby_right -#align covby.sup_of_inf_of_inf_right Covby.sup_of_inf_of_inf_right +alias CovBy.sup_of_inf_of_inf_right := covBy_sup_of_inf_covBy_of_inf_covBy_right +#align covby.sup_of_inf_of_inf_right CovBy.sup_of_inf_of_inf_right instance : IsWeakLowerModularLattice (OrderDual α) := ⟨fun ha hb => (ha.ofDual.sup_of_inf_of_inf_left hb.ofDual).toDual⟩ @@ -119,20 +119,20 @@ section WeakLowerModular variable [Lattice α] [IsWeakLowerModularLattice α] {a b : α} -theorem inf_covby_of_covby_sup_of_covby_sup_left : a ⋖ a ⊔ b → b ⋖ a ⊔ b → a ⊓ b ⋖ a := - IsWeakLowerModularLattice.inf_covby_of_covby_covby_sup -#align inf_covby_of_covby_sup_of_covby_sup_left inf_covby_of_covby_sup_of_covby_sup_left +theorem inf_covBy_of_covBy_sup_of_covBy_sup_left : a ⋖ a ⊔ b → b ⋖ a ⊔ b → a ⊓ b ⋖ a := + IsWeakLowerModularLattice.inf_covBy_of_covBy_covBy_sup +#align inf_covby_of_covby_sup_of_covby_sup_left inf_covBy_of_covBy_sup_of_covBy_sup_left -theorem inf_covby_of_covby_sup_of_covby_sup_right : a ⋖ a ⊔ b → b ⋖ a ⊔ b → a ⊓ b ⋖ b := by +theorem inf_covBy_of_covBy_sup_of_covBy_sup_right : a ⋖ a ⊔ b → b ⋖ a ⊔ b → a ⊓ b ⋖ b := by rw [sup_comm, inf_comm] - exact fun ha hb => inf_covby_of_covby_sup_of_covby_sup_left hb ha -#align inf_covby_of_covby_sup_of_covby_sup_right inf_covby_of_covby_sup_of_covby_sup_right + exact fun ha hb => inf_covBy_of_covBy_sup_of_covBy_sup_left hb ha +#align inf_covby_of_covby_sup_of_covby_sup_right inf_covBy_of_covBy_sup_of_covBy_sup_right -alias Covby.inf_of_sup_of_sup_left := inf_covby_of_covby_sup_of_covby_sup_left -#align covby.inf_of_sup_of_sup_left Covby.inf_of_sup_of_sup_left +alias CovBy.inf_of_sup_of_sup_left := inf_covBy_of_covBy_sup_of_covBy_sup_left +#align covby.inf_of_sup_of_sup_left CovBy.inf_of_sup_of_sup_left -alias Covby.inf_of_sup_of_sup_right := inf_covby_of_covby_sup_of_covby_sup_right -#align covby.inf_of_sup_of_sup_right Covby.inf_of_sup_of_sup_right +alias CovBy.inf_of_sup_of_sup_right := inf_covBy_of_covBy_sup_of_covBy_sup_right +#align covby.inf_of_sup_of_sup_right CovBy.inf_of_sup_of_sup_right instance : IsWeakUpperModularLattice (OrderDual α) := ⟨fun ha hb => (ha.ofDual.inf_of_sup_of_sup_left hb.ofDual).toDual⟩ @@ -143,25 +143,25 @@ section UpperModular variable [Lattice α] [IsUpperModularLattice α] {a b : α} -theorem covby_sup_of_inf_covby_left : a ⊓ b ⋖ a → b ⋖ a ⊔ b := - IsUpperModularLattice.covby_sup_of_inf_covby -#align covby_sup_of_inf_covby_left covby_sup_of_inf_covby_left +theorem covBy_sup_of_inf_covBy_left : a ⊓ b ⋖ a → b ⋖ a ⊔ b := + IsUpperModularLattice.covBy_sup_of_inf_covBy +#align covby_sup_of_inf_covby_left covBy_sup_of_inf_covBy_left -theorem covby_sup_of_inf_covby_right : a ⊓ b ⋖ b → a ⋖ a ⊔ b := by +theorem covBy_sup_of_inf_covBy_right : a ⊓ b ⋖ b → a ⋖ a ⊔ b := by rw [sup_comm, inf_comm] - exact covby_sup_of_inf_covby_left -#align covby_sup_of_inf_covby_right covby_sup_of_inf_covby_right + exact covBy_sup_of_inf_covBy_left +#align covby_sup_of_inf_covby_right covBy_sup_of_inf_covBy_right -alias Covby.sup_of_inf_left := covby_sup_of_inf_covby_left -#align covby.sup_of_inf_left Covby.sup_of_inf_left +alias CovBy.sup_of_inf_left := covBy_sup_of_inf_covBy_left +#align covby.sup_of_inf_left CovBy.sup_of_inf_left -alias Covby.sup_of_inf_right := covby_sup_of_inf_covby_right -#align covby.sup_of_inf_right Covby.sup_of_inf_right +alias CovBy.sup_of_inf_right := covBy_sup_of_inf_covBy_right +#align covby.sup_of_inf_right CovBy.sup_of_inf_right -- See note [lower instance priority] instance (priority := 100) IsUpperModularLattice.to_isWeakUpperModularLattice : IsWeakUpperModularLattice α := - ⟨fun _ => Covby.sup_of_inf_right⟩ + ⟨fun _ => CovBy.sup_of_inf_right⟩ #align is_upper_modular_lattice.to_is_weak_upper_modular_lattice IsUpperModularLattice.to_isWeakUpperModularLattice instance : IsLowerModularLattice (OrderDual α) := @@ -173,25 +173,25 @@ section LowerModular variable [Lattice α] [IsLowerModularLattice α] {a b : α} -theorem inf_covby_of_covby_sup_left : a ⋖ a ⊔ b → a ⊓ b ⋖ b := - IsLowerModularLattice.inf_covby_of_covby_sup -#align inf_covby_of_covby_sup_left inf_covby_of_covby_sup_left +theorem inf_covBy_of_covBy_sup_left : a ⋖ a ⊔ b → a ⊓ b ⋖ b := + IsLowerModularLattice.inf_covBy_of_covBy_sup +#align inf_covby_of_covby_sup_left inf_covBy_of_covBy_sup_left -theorem inf_covby_of_covby_sup_right : b ⋖ a ⊔ b → a ⊓ b ⋖ a := by +theorem inf_covBy_of_covBy_sup_right : b ⋖ a ⊔ b → a ⊓ b ⋖ a := by rw [inf_comm, sup_comm] - exact inf_covby_of_covby_sup_left -#align inf_covby_of_covby_sup_right inf_covby_of_covby_sup_right + exact inf_covBy_of_covBy_sup_left +#align inf_covby_of_covby_sup_right inf_covBy_of_covBy_sup_right -alias Covby.inf_of_sup_left := inf_covby_of_covby_sup_left -#align covby.inf_of_sup_left Covby.inf_of_sup_left +alias CovBy.inf_of_sup_left := inf_covBy_of_covBy_sup_left +#align covby.inf_of_sup_left CovBy.inf_of_sup_left -alias Covby.inf_of_sup_right := inf_covby_of_covby_sup_right -#align covby.inf_of_sup_right Covby.inf_of_sup_right +alias CovBy.inf_of_sup_right := inf_covBy_of_covBy_sup_right +#align covby.inf_of_sup_right CovBy.inf_of_sup_right -- See note [lower instance priority] instance (priority := 100) IsLowerModularLattice.to_isWeakLowerModularLattice : IsWeakLowerModularLattice α := - ⟨fun _ => Covby.inf_of_sup_right⟩ + ⟨fun _ => CovBy.inf_of_sup_right⟩ #align is_lower_modular_lattice.to_is_weak_lower_modular_lattice IsLowerModularLattice.to_isWeakLowerModularLattice instance : IsUpperModularLattice (OrderDual α) := @@ -346,7 +346,7 @@ def infIooOrderIsoIooSup (a b : α) : Ioo (a ⊓ b) a ≃o Ioo b (a ⊔ b) where -- See note [lower instance priority] instance (priority := 100) IsModularLattice.to_isLowerModularLattice : IsLowerModularLattice α := ⟨fun {a b} => by - simp_rw [covby_iff_Ioo_eq, @sup_comm _ _ a, @inf_comm _ _ a, ← isEmpty_coe_sort, right_lt_sup, + simp_rw [covBy_iff_Ioo_eq, @sup_comm _ _ a, @inf_comm _ _ a, ← isEmpty_coe_sort, right_lt_sup, inf_lt_left, (infIooOrderIsoIooSup b a).symm.toEquiv.isEmpty_congr] exact id⟩ #align is_modular_lattice.to_is_lower_modular_lattice IsModularLattice.to_isLowerModularLattice @@ -354,7 +354,7 @@ instance (priority := 100) IsModularLattice.to_isLowerModularLattice : IsLowerMo -- See note [lower instance priority] instance (priority := 100) IsModularLattice.to_isUpperModularLattice : IsUpperModularLattice α := ⟨fun {a b} => by - simp_rw [covby_iff_Ioo_eq, ← isEmpty_coe_sort, right_lt_sup, inf_lt_left, + simp_rw [covBy_iff_Ioo_eq, ← isEmpty_coe_sort, right_lt_sup, inf_lt_left, (infIooOrderIsoIooSup a b).toEquiv.isEmpty_congr] exact id⟩ #align is_modular_lattice.to_is_upper_modular_lattice IsModularLattice.to_isUpperModularLattice diff --git a/Mathlib/Order/Monotone/Basic.lean b/Mathlib/Order/Monotone/Basic.lean index a81d17e1925ac..566f68b05f58c 100644 --- a/Mathlib/Order/Monotone/Basic.lean +++ b/Mathlib/Order/Monotone/Basic.lean @@ -939,14 +939,14 @@ lemma not_monotone_not_antitone_iff_exists_le_le : { exact ⟨c, a, b, hcd.trans hda, hab, Or.inl ⟨hfcd.trans_le hfda, hfba⟩⟩ } } obtain hac | hca := le_total a c { obtain hfdb | hfbd := le_or_lt (f d) (f b) - { exact ⟨a, c, d, hac, hcd, Or.inr ⟨hfcd.trans $ hfdb.trans_lt hfba, hfcd⟩⟩ } + { exact ⟨a, c, d, hac, hcd, Or.inr ⟨hfcd.trans <| hfdb.trans_lt hfba, hfcd⟩⟩ } obtain hfca | hfac := lt_or_le (f c) (f a) { exact ⟨a, c, d, hac, hcd, Or.inr ⟨hfca, hfcd⟩⟩ } obtain hbd | hdb := le_total b d { exact ⟨a, b, d, hab, hbd, Or.inr ⟨hfba, hfbd⟩⟩ } { exact ⟨a, d, b, had, hdb, Or.inl ⟨hfac.trans_lt hfcd, hfbd⟩⟩ } } { obtain hfdb | hfbd := le_or_lt (f d) (f b) - { exact ⟨c, a, b, hca, hab, Or.inl ⟨hfcd.trans $ hfdb.trans_lt hfba, hfba⟩⟩ } + { exact ⟨c, a, b, hca, hab, Or.inl ⟨hfcd.trans <| hfdb.trans_lt hfba, hfba⟩⟩ } obtain hfca | hfac := lt_or_le (f c) (f a) { exact ⟨c, a, b, hca, hab, Or.inl ⟨hfca, hfba⟩⟩ } obtain hbd | hdb := le_total b d @@ -960,8 +960,8 @@ lemma not_monotone_not_antitone_iff_exists_lt_lt : ¬ Monotone f ∧ ¬ Antitone f ↔ ∃ a b c, a < b ∧ b < c ∧ (f a < f b ∧ f c < f b ∨ f b < f a ∧ f b < f c) := by simp_rw [not_monotone_not_antitone_iff_exists_le_le, ← and_assoc] - refine' exists₃_congr (fun a b c ↦ and_congr_left $ - fun h ↦ (Ne.le_iff_lt _).and $ Ne.le_iff_lt _) <;> + refine' exists₃_congr (fun a b c ↦ and_congr_left <| + fun h ↦ (Ne.le_iff_lt _).and <| Ne.le_iff_lt _) <;> (rintro rfl; simp at h) #align not_monotone_not_antitone_iff_exists_lt_lt not_monotone_not_antitone_iff_exists_lt_lt diff --git a/Mathlib/Order/Monotone/Monovary.lean b/Mathlib/Order/Monotone/Monovary.lean index 98f39c3b368b2..1e5fda94f3b51 100644 --- a/Mathlib/Order/Monotone/Monovary.lean +++ b/Mathlib/Order/Monotone/Monovary.lean @@ -3,7 +3,8 @@ Copyright (c) 2021 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Data.Set.Image +import Mathlib.Data.Set.Defs +import Mathlib.Order.Lattice #align_import order.monotone.monovary from "leanprover-community/mathlib"@"6cb77a8eaff0ddd100e87b1591c6d3ad319514ff" diff --git a/Mathlib/Order/Notation.lean b/Mathlib/Order/Notation.lean new file mode 100644 index 0000000000000..858474b435184 --- /dev/null +++ b/Mathlib/Order/Notation.lean @@ -0,0 +1,124 @@ +/- +Copyright (c) 2017 Johannes Hölzl. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johannes Hölzl, Yury Kudryashov, Yaël Dillies +-/ +import Mathlib.Tactic.Basic +import Mathlib.Tactic.Simps.NotationClass +import Mathlib.Mathport.Rename + +/-! +# Notation classes for lattice operations + +In this file we introduce typeclasses and definitions for lattice operations. + +## Main definitions + +* `Sup`: type class for the `⊔` notation +* `Inf`: type class for the `⊓` notation +* `HasCompl`: type class for the `ᶜ` notation +* `Top`: type class for the `⊤` notation +* `Bot`: type class for the `⊥` notation + +## Notations + +* `x ⊔ y`: lattice join operation; +* `x ⊓ y`: lattice meet operation; +* `xᶜ`: complement in a lattice; + +-/ + +/-- Set / lattice complement -/ +@[notation_class] +class HasCompl (α : Type*) where + /-- Set / lattice complement -/ + compl : α → α +#align has_compl HasCompl + +export HasCompl (compl) + +@[inherit_doc] +postfix:1024 "ᶜ" => compl + +/-! ### `Sup` and `Inf` -/ + +/-- Typeclass for the `⊔` (`\lub`) notation -/ +@[notation_class, ext] +class Sup (α : Type*) where + /-- Least upper bound (`\lub` notation) -/ + sup : α → α → α +#align has_sup Sup + +/-- Typeclass for the `⊓` (`\glb`) notation -/ +@[notation_class, ext] +class Inf (α : Type*) where + /-- Greatest lower bound (`\glb` notation) -/ + inf : α → α → α +#align has_inf Inf + +@[inherit_doc] +infixl:68 " ⊔ " => Sup.sup + +@[inherit_doc] +infixl:69 " ⊓ " => Inf.inf + +/-- Syntax typeclass for Heyting implication `⇨`. -/ +@[notation_class] +class HImp (α : Type*) where + /-- Heyting implication `⇨` -/ + himp : α → α → α +#align has_himp HImp + +/-- Syntax typeclass for Heyting negation `¬`. + +The difference between `HasCompl` and `HNot` is that the former belongs to Heyting algebras, +while the latter belongs to co-Heyting algebras. They are both pseudo-complements, but `compl` +underestimates while `HNot` overestimates. In boolean algebras, they are equal. +See `hnot_eq_compl`. +-/ +@[notation_class] +class HNot (α : Type*) where + /-- Heyting negation `¬` -/ + hnot : α → α +#align has_hnot HNot + +export HImp (himp) +export SDiff (sdiff) +export HNot (hnot) + +/-- Heyting implication -/ +infixr:60 " ⇨ " => himp + +/-- Heyting negation -/ +prefix:72 "¬" => hnot + + +/-- Typeclass for the `⊤` (`\top`) notation -/ +@[notation_class, ext] +class Top (α : Type*) where + /-- The top (`⊤`, `\top`) element -/ + top : α +#align has_top Top + +/-- Typeclass for the `⊥` (`\bot`) notation -/ +@[notation_class, ext] +class Bot (α : Type*) where + /-- The bot (`⊥`, `\bot`) element -/ + bot : α +#align has_bot Bot + +/-- The top (`⊤`, `\top`) element -/ +notation "⊤" => Top.top + +/-- The bot (`⊥`, `\bot`) element -/ +notation "⊥" => Bot.bot + +instance (priority := 100) top_nonempty (α : Type*) [Top α] : Nonempty α := + ⟨⊤⟩ +#align has_top_nonempty top_nonempty + +instance (priority := 100) bot_nonempty (α : Type*) [Bot α] : Nonempty α := + ⟨⊥⟩ +#align has_bot_nonempty bot_nonempty + +attribute [match_pattern] Bot.bot Top.top diff --git a/Mathlib/Order/OmegaCompletePartialOrder.lean b/Mathlib/Order/OmegaCompletePartialOrder.lean index bfadb8a4c1e07..dd4161b566a1d 100644 --- a/Mathlib/Order/OmegaCompletePartialOrder.lean +++ b/Mathlib/Order/OmegaCompletePartialOrder.lean @@ -96,7 +96,7 @@ variable {α : Type u} {β : Type v} {γ : Type*} variable [Preorder α] [Preorder β] [Preorder γ] instance : OrderHomClass (Chain α) ℕ α := inferInstanceAs <| OrderHomClass (ℕ →o α) ℕ α -instance : CoeFun (Chain α) fun _ => ℕ → α := ⟨FunLike.coe⟩ +instance : CoeFun (Chain α) fun _ => ℕ → α := ⟨DFunLike.coe⟩ instance [Inhabited α] : Inhabited (Chain α) := ⟨⟨default, fun _ _ _ => le_rfl⟩⟩ @@ -568,8 +568,9 @@ theorem inf_continuous (f g : α →o β) (hf : Continuous f) (hg : Continuous g refine' fun c => eq_of_forall_ge_iff fun z => _ simp only [inf_le_iff, hf c, hg c, ωSup_le_iff, ← forall_or_left, ← forall_or_right, Chain.map_coe, OrderHom.coe_inf, ge_iff_le, Pi.inf_apply, Function.comp] - exact ⟨λ h _ => h _ _, λ h i j => (h (max j i)).imp (le_trans $ f.mono $ c.mono $ le_max_left _ _) - (le_trans $ g.mono $ c.mono $ le_max_right _ _)⟩ + exact ⟨fun h _ ↦ h _ _, fun h i j ↦ + (h (max j i)).imp (le_trans <| f.mono <| c.mono <| le_max_left _ _) + (le_trans <| g.mono <| c.mono <| le_max_right _ _)⟩ #align complete_lattice.inf_continuous CompleteLattice.inf_continuous theorem inf_continuous' {f g : α → β} (hf : Continuous' f) (hg : Continuous' g) : @@ -623,7 +624,7 @@ attribute [nolint docBlame] ContinuousHom.toOrderHom instance : OrderHomClass (α →𝒄 β) α β where coe f := f.toFun - coe_injective' := by rintro ⟨⟩ ⟨⟩ h; congr; exact FunLike.ext' h + coe_injective' := by rintro ⟨⟩ ⟨⟩ h; congr; exact DFunLike.ext' h map_rel f _ _ h := f.mono h -- Porting note: removed to avoid conflict with the generic instance @@ -642,7 +643,7 @@ theorem toOrderHom_eq_coe (f : α →𝒄 β) : f.1 = f := rfl @[simp] theorem coe_mk (f : α →o β) (hf : Continuous f) : ⇑(mk f hf) = f := rfl @[simp] theorem coe_toOrderHom (f : α →𝒄 β) : ⇑f.1 = f := rfl -/-- See Note [custom simps projection]. We specify this explicitly because we don't have a FunLike +/-- See Note [custom simps projection]. We specify this explicitly because we don't have a DFunLike instance. -/ def Simps.apply (h : α →𝒄 β) : α → β := @@ -651,7 +652,7 @@ def Simps.apply (h : α →𝒄 β) : α → β := initialize_simps_projections ContinuousHom (toFun → apply) theorem congr_fun {f g : α →𝒄 β} (h : f = g) (x : α) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align omega_complete_partial_order.continuous_hom.congr_fun OmegaCompletePartialOrder.ContinuousHom.congr_fun theorem congr_arg (f : α →𝒄 β) {x y : α} (h : x = y) : f x = f y := @@ -751,11 +752,11 @@ def comp (f : β →𝒄 γ) (g : α →𝒄 β) : α →𝒄 γ := ⟨.comp f.1 #align omega_complete_partial_order.continuous_hom.comp_apply OmegaCompletePartialOrder.ContinuousHom.comp_apply @[ext] -protected theorem ext (f g : α →𝒄 β) (h : ∀ x, f x = g x) : f = g := FunLike.ext f g h +protected theorem ext (f g : α →𝒄 β) (h : ∀ x, f x = g x) : f = g := DFunLike.ext f g h #align omega_complete_partial_order.continuous_hom.ext OmegaCompletePartialOrder.ContinuousHom.ext protected theorem coe_inj (f g : α →𝒄 β) (h : (f : α → β) = g) : f = g := - FunLike.ext' h + DFunLike.ext' h #align omega_complete_partial_order.continuous_hom.coe_inj OmegaCompletePartialOrder.ContinuousHom.coe_inj @[simp] diff --git a/Mathlib/Order/PFilter.lean b/Mathlib/Order/PFilter.lean index 3fe55da2debf4..f0e4cf3612a27 100644 --- a/Mathlib/Order/PFilter.lean +++ b/Mathlib/Order/PFilter.lean @@ -12,19 +12,15 @@ import Mathlib.Order.Ideal ## Main definitions -Throughout this file, `P` is at least a preorder, but some sections -require more structure, such as a bottom element, a top element, or -a join-semilattice structure. +Throughout this file, `P` is at least a preorder, but some sections require more structure, +such as a bottom element, a top element, or a join-semilattice structure. -- `Order.PFilter P`: The type of nonempty, downward directed, upward closed - subsets of `P`. This is dual to `Order.Ideal`, so it - simply wraps `Order.Ideal Pᵒᵈ`. +- `Order.PFilter P`: The type of nonempty, downward directed, upward closed subsets of `P`. + This is dual to `Order.Ideal`, so it simply wraps `Order.Ideal Pᵒᵈ`. - `Order.IsPFilter P`: a predicate for when a `Set P` is a filter. - -Note the relation between `Order/Filter` and `Order/PFilter`: for any -type `α`, `Filter α` represents the same mathematical object as -`PFilter (Set α)`. +Note the relation between `Order/Filter` and `Order/PFilter`: for any type `α`, +`Filter α` represents the same mathematical object as `PFilter (Set α)`. ## References @@ -40,16 +36,16 @@ open OrderDual namespace Order -variable {P : Type*} - /-- A filter on a preorder `P` is a subset of `P` that is - nonempty - downward directed - upward closed. -/ -structure PFilter (P) [Preorder P] where +structure PFilter (P : Type*) [Preorder P] where dual : Ideal Pᵒᵈ #align order.pfilter Order.PFilter +variable {P : Type*} + /-- A predicate for when a subset of `P` is a filter. -/ def IsPFilter [Preorder P] (F : Set P) : Prop := IsIdeal (OrderDual.ofDual ⁻¹' F) diff --git a/Mathlib/Order/PartialSups.lean b/Mathlib/Order/PartialSups.lean index 028cc1cfa2793..abc662a3c86ce 100644 --- a/Mathlib/Order/PartialSups.lean +++ b/Mathlib/Order/PartialSups.lean @@ -5,7 +5,8 @@ Authors: Scott Morrison -/ import Mathlib.Data.Finset.Lattice import Mathlib.Order.Hom.Basic -import Mathlib.Order.ConditionallyCompleteLattice.Finset +import Mathlib.Data.Set.Finite +import Mathlib.Order.ConditionallyCompleteLattice.Basic #align_import order.partial_sups from "leanprover-community/mathlib"@"d6fad0e5bf2d6f48da9175d25c3dc5706b3834ce" diff --git a/Mathlib/Order/Partition/Finpartition.lean b/Mathlib/Order/Partition/Finpartition.lean index 25c7531fdfad7..c3b7e3e8193c1 100644 --- a/Mathlib/Order/Partition/Finpartition.lean +++ b/Mathlib/Order/Partition/Finpartition.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Bhavik Mehta -/ import Mathlib.Algebra.BigOperators.Basic -import Mathlib.Order.Atoms.Finite import Mathlib.Order.SupIndep +import Mathlib.Order.Atoms +import Mathlib.Data.Fintype.Powerset #align_import order.partition.finpartition from "leanprover-community/mathlib"@"d6fad0e5bf2d6f48da9175d25c3dc5706b3834ce" @@ -289,7 +290,7 @@ instance : Inf (Finpartition a) := simp [t] at h exact Disjoint.mono inf_le_left inf_le_left (P.disjoint hx₁ hx₂ xdiff)) (by - rw [sup_image, comp.left_id, sup_product_left] + rw [sup_image, id_comp, sup_product_left] trans P.parts.sup id ⊓ Q.parts.sup id · simp_rw [Finset.sup_inf_distrib_right, Finset.sup_inf_distrib_left] rfl @@ -435,7 +436,7 @@ def avoid (b : α) : Finpartition (a \ b) := ofErase (P.parts.image (· \ b)) (P.disjoint.image_finset_of_le fun a ↦ sdiff_le).supIndep - (by rw [sup_image, comp.left_id, Finset.sup_sdiff_right, ← id_def, P.supParts]) + (by rw [sup_image, id_comp, Finset.sup_sdiff_right, ← id_def, P.supParts]) #align finpartition.avoid Finpartition.avoid @[simp] @@ -488,7 +489,7 @@ instance (s : Finset α) : Bot (Finpartition s) := (by rw [Finset.coe_map] exact Finset.pairwiseDisjoint_range_singleton.subset (Set.image_subset_range _ _)) - supParts := by rw [sup_map, comp.left_id, Embedding.coeFn_mk, Finset.sup_singleton'] + supParts := by rw [sup_map, id_comp, Embedding.coeFn_mk, Finset.sup_singleton'] not_bot_mem := by simp }⟩ @[simp] diff --git a/Mathlib/Order/PropInstances.lean b/Mathlib/Order/PropInstances.lean index 9657f3abb0f16..3d84cf3688430 100644 --- a/Mathlib/Order/PropInstances.lean +++ b/Mathlib/Order/PropInstances.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Order.Disjoint -import Mathlib.Order.WithBot #align_import order.prop_instances from "leanprover-community/mathlib"@"6623e6af705e97002a9054c1c05a980180276fc1" diff --git a/Mathlib/Order/RelClasses.lean b/Mathlib/Order/RelClasses.lean index d6cc4a85990a6..7e4f9fc84243b 100644 --- a/Mathlib/Order/RelClasses.lean +++ b/Mathlib/Order/RelClasses.lean @@ -289,7 +289,7 @@ instance WellFoundedRelation.isWellFounded [h : WellFoundedRelation α] : theorem WellFoundedRelation.asymmetric {α : Sort*} [WellFoundedRelation α] {a b : α} : WellFoundedRelation.rel a b → ¬ WellFoundedRelation.rel b a := fun hab hba => WellFoundedRelation.asymmetric hba hab -termination_by _ => a +termination_by a lemma WellFounded.prod_lex {ra : α → α → Prop} {rb : β → β → Prop} (ha : WellFounded ra) (hb : WellFounded rb) : WellFounded (Prod.Lex ra rb) := diff --git a/Mathlib/Order/RelIso/Basic.lean b/Mathlib/Order/RelIso/Basic.lean index ed1445b4c1519..423e33e840414 100644 --- a/Mathlib/Order/RelIso/Basic.lean +++ b/Mathlib/Order/RelIso/Basic.lean @@ -65,7 +65,7 @@ The relations `r` and `s` are `outParam`s since figuring them out from a goal is matching problem that Lean usually can't do unaided. -/ class RelHomClass (F : Type*) {α β : outParam <| Type*} (r : outParam <| α → α → Prop) - (s : outParam <| β → β → Prop) extends FunLike F α fun _ => β where + (s : outParam <| β → β → Prop) extends DFunLike F α fun _ => β where /-- A `RelHomClass` sends related elements to related elements -/ map_rel : ∀ (f : F) {a b}, r a b → s (f a) (f b) #align rel_hom_class RelHomClass @@ -94,7 +94,7 @@ protected theorem acc [RelHomClass F r s] (f : F) (a : α) : Acc s (f a) → Acc exact ⟨_, fun a' h => IH (f a') (map_rel f h) _ rfl⟩ #align rel_hom_class.acc RelHomClass.acc -protected theorem wellFounded [RelHomClass F r s] (f : F) : ∀ _ : WellFounded s, WellFounded r +protected theorem wellFounded [RelHomClass F r s] (f : F) : WellFounded s → WellFounded r | ⟨H⟩ => ⟨fun _ => RelHomClass.acc f _ (H _)⟩ #align rel_hom_class.well_founded RelHomClass.wellFounded @@ -123,16 +123,16 @@ theorem coe_fn_toFun (f : r →r s) : f.toFun = (f : α → β) := /-- The map `coe_fn : (r →r s) → (α → β)` is injective. -/ theorem coe_fn_injective : Injective fun (f : r →r s) => (f : α → β) := - FunLike.coe_injective + DFunLike.coe_injective #align rel_hom.coe_fn_injective RelHom.coe_fn_injective @[ext] theorem ext ⦃f g : r →r s⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align rel_hom.ext RelHom.ext theorem ext_iff {f g : r →r s} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align rel_hom.ext_iff RelHom.ext_iff /-- Identity map is a relation homomorphism. -/ @@ -271,16 +271,16 @@ theorem coe_mk : ⇑(⟨f, h⟩ : r ↪r s) = f := /-- The map `coe_fn : (r ↪r s) → (α → β)` is injective. -/ theorem coe_fn_injective : Injective fun f : r ↪r s => (f : α → β) := - FunLike.coe_injective + DFunLike.coe_injective #align rel_embedding.coe_fn_injective RelEmbedding.coe_fn_injective @[ext] theorem ext ⦃f g : r ↪r s⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align rel_embedding.ext RelEmbedding.ext theorem ext_iff {f g : r ↪r s} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align rel_embedding.ext_iff RelEmbedding.ext_iff /-- Identity map is a relation embedding. -/ @@ -630,7 +630,7 @@ theorem toEquiv_injective : Injective (toEquiv : r ≃r s → α ≃ β) instance : CoeOut (r ≃r s) (r ↪r s) := ⟨toRelEmbedding⟩ --- Porting note: moved to after `RelHomClass` instance and redefined as `FunLike.coe` +-- Porting note: moved to after `RelHomClass` instance and redefined as `DFunLike.coe` -- instance : CoeFun (r ≃r s) fun _ => α → β := -- ⟨fun f => f⟩ @@ -645,12 +645,12 @@ instance : EquivLike (r ≃r s) α β where inv f := f.toEquiv.symm left_inv f := f.left_inv right_inv f := f.right_inv - coe_injective' _ _ hf _ := FunLike.ext' hf + coe_injective' _ _ hf _ := DFunLike.ext' hf --Porting note: helper instance -- see Note [function coercion] instance : CoeFun (r ≃r s) fun _ => α → β := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ @[simp] theorem coe_toRelEmbedding (f : r ≃r s) : (f.toRelEmbedding : α → β) = f := @@ -678,16 +678,16 @@ theorem coe_fn_toEquiv (f : r ≃r s) : (f.toEquiv : α → β) = f := /-- The map `coe_fn : (r ≃r s) → (α → β)` is injective. Lean fails to parse `function.injective (λ e : r ≃r s, (e : α → β))`, so we use a trick to say the same. -/ theorem coe_fn_injective : Injective fun f : r ≃r s => (f : α → β) := - FunLike.coe_injective + DFunLike.coe_injective #align rel_iso.coe_fn_injective RelIso.coe_fn_injective @[ext] theorem ext ⦃f g : r ≃r s⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align rel_iso.ext RelIso.ext theorem ext_iff {f g : r ≃r s} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align rel_iso.ext_iff RelIso.ext_iff /-- Inverse map of a relation isomorphism is a relation isomorphism. -/ @@ -696,7 +696,7 @@ protected def symm (f : r ≃r s) : s ≃r r := #align rel_iso.symm RelIso.symm /-- See Note [custom simps projection]. We need to specify this projection explicitly in this case, - because `RelIso` defines custom coercions other than the ones given by `FunLike`. -/ + because `RelIso` defines custom coercions other than the ones given by `DFunLike`. -/ def Simps.apply (h : r ≃r s) : α → β := h #align rel_iso.simps.apply RelIso.Simps.apply diff --git a/Mathlib/Order/RelSeries.lean b/Mathlib/Order/RelSeries.lean index 5a404fae3be89..39496f70ec74a 100644 --- a/Mathlib/Order/RelSeries.lean +++ b/Mathlib/Order/RelSeries.lean @@ -3,8 +3,8 @@ Copyright (c) 2023 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jujian Zhang, Fangming Li -/ -import Mathlib.Logic.Equiv.Fin -import Mathlib.Data.List.Indexes +import Mathlib.Data.List.Chain +import Mathlib.Data.List.OfFn import Mathlib.Data.Rel import Mathlib.Tactic.Linarith import Mathlib.Tactic.Abel @@ -232,7 +232,7 @@ is another `r`-series @[simps] def insertNth (p : RelSeries r) (i : Fin p.length) (a : α) (prev_connect : r (p (Fin.castSucc i)) a) (connect_next : r a (p i.succ)) : RelSeries r where - toFun := (Fin.castSucc i.succ).insertNth a p + toFun := (Fin.castSucc i.succ).insertNth a p step m := by set x := _; set y := _; change r x y obtain hm | hm | hm := lt_trichotomy m.1 i.1 diff --git a/Mathlib/Order/Sublattice.lean b/Mathlib/Order/Sublattice.lean index 0e7e522889ee5..3e6daec6aa190 100644 --- a/Mathlib/Order/Sublattice.lean +++ b/Mathlib/Order/Sublattice.lean @@ -107,7 +107,7 @@ def subtype (L : Sublattice α) : LatticeHom L α where @[simp, norm_cast] lemma coe_subtype (L : Sublattice α) : L.subtype = ((↑) : L → α) := rfl lemma subtype_apply (L : Sublattice α) (a : L) : L.subtype a = a := rfl -lemma subtype_injective (L : Sublattice α) : Injective $ subtype L := Subtype.coe_injective +lemma subtype_injective (L : Sublattice α) : Injective <| subtype L := Subtype.coe_injective /-- The inclusion homomorphism from a sublattice `L` to a bigger sublattice `M`. -/ def inclusion (h : L ≤ M) : LatticeHom L M where @@ -118,7 +118,7 @@ def inclusion (h : L ≤ M) : LatticeHom L M where @[simp] lemma coe_inclusion (h : L ≤ M) : inclusion h = Set.inclusion h := rfl lemma inclusion_apply (h : L ≤ M) (a : L) : inclusion h a = Set.inclusion h a := rfl -lemma inclusion_injective (h : L ≤ M) : Injective $ inclusion h := Set.inclusion_injective h +lemma inclusion_injective (h : L ≤ M) : Injective <| inclusion h := Set.inclusion_injective h @[simp] lemma inclusion_rfl (L : Sublattice α) : inclusion le_rfl = LatticeHom.id L := rfl @[simp] lemma subtype_comp_inclusion (h : L ≤ M) : M.subtype.comp (inclusion h) = L.subtype := rfl @@ -144,9 +144,9 @@ instance instInf : Inf (Sublattice α) where /-- The inf of sublattices is their intersection. -/ instance instInfSet : InfSet (Sublattice α) where sInf S := { carrier := ⨅ L ∈ S, L - supClosed' := supClosed_sInter $ forall_range_iff.2 fun L ↦ supClosed_sInter $ + supClosed' := supClosed_sInter <| forall_range_iff.2 fun L ↦ supClosed_sInter <| forall_range_iff.2 fun _ ↦ L.supClosed - infClosed' := infClosed_sInter $ forall_range_iff.2 fun L ↦ infClosed_sInter $ + infClosed' := infClosed_sInter <| forall_range_iff.2 fun L ↦ infClosed_sInter <| forall_range_iff.2 fun _ ↦ L.infClosed } instance instInhabited : Inhabited (Sublattice α) := ⟨⊥⟩ @@ -190,7 +190,7 @@ instance instCompleteLattice : CompleteLattice (Sublattice α) where fun _s ↦ IsGLB.of_image SetLike.coe_subset_coe isGLB_biInf lemma subsingleton_iff : Subsingleton (Sublattice α) ↔ IsEmpty α := - ⟨fun _ ↦ univ_eq_empty_iff.1 $ coe_inj.2 $ Subsingleton.elim ⊤ ⊥, + ⟨fun _ ↦ univ_eq_empty_iff.1 <| coe_inj.2 <| Subsingleton.elim ⊤ ⊥, fun _ ↦ SetLike.coe_injective.subsingleton⟩ instance [IsEmpty α] : Unique (Sublattice α) where @@ -228,10 +228,10 @@ lemma apply_coe_mem_map (f : LatticeHom α β) (a : L) : f a ∈ L.map f := mem_ lemma map_mono : Monotone (map f) := fun _ _ ↦ image_subset _ -@[simp] lemma map_id : L.map (LatticeHom.id α) = L := SetLike.coe_injective $ image_id _ +@[simp] lemma map_id : L.map (LatticeHom.id α) = L := SetLike.coe_injective <| image_id _ @[simp] lemma map_map (g : LatticeHom β γ) (f : LatticeHom α β) : - (L.map f).map g = L.map (g.comp f) := SetLike.coe_injective $ image_image _ _ _ + (L.map f).map g = L.map (g.comp f) := SetLike.coe_injective <| image_image _ _ _ lemma mem_map_equiv {f : α ≃o β} {a : β} : a ∈ L.map f ↔ f.symm a ∈ L := Set.mem_image_equiv @@ -239,7 +239,7 @@ lemma apply_mem_map_iff (hf : Injective f) : f a ∈ L.map f ↔ a ∈ L := hf.m lemma map_equiv_eq_comap_symm (f : α ≃o β) (L : Sublattice α) : L.map f = L.comap (f.symm : LatticeHom β α) := - SetLike.coe_injective $ f.toEquiv.image_eq_preimage L + SetLike.coe_injective <| f.toEquiv.image_eq_preimage L lemma comap_equiv_eq_map_symm (f : β ≃o α) (L : Sublattice α) : L.comap f = L.map (f.symm : LatticeHom α β) := (map_equiv_eq_comap_symm f.symm L).symm @@ -286,6 +286,6 @@ lemma map_inf (L M : Sublattice α) (f : LatticeHom α β) (hf : Injective f) : simp [Set.image_inter hf] lemma map_top (f : LatticeHom α β) (h : Surjective f) : Sublattice.map f ⊤ = ⊤ := - SetLike.coe_injective $ by simp [h.range_eq] + SetLike.coe_injective <| by simp [h.range_eq] end Sublattice diff --git a/Mathlib/Order/SuccPred/Basic.lean b/Mathlib/Order/SuccPred/Basic.lean index a51154c03d6ec..d0a546046e186 100644 --- a/Mathlib/Order/SuccPred/Basic.lean +++ b/Mathlib/Order/SuccPred/Basic.lean @@ -50,7 +50,7 @@ Is `GaloisConnection pred succ` always true? If not, we should introduce class SuccPredOrder (α : Type*) [Preorder α] extends SuccOrder α, PredOrder α := (pred_succ_gc : GaloisConnection (pred : α → α) succ) ``` -`Covby` should help here. +`CovBy` should help here. -/ @@ -239,13 +239,13 @@ theorem lt_succ_iff_not_isMax : a < succ a ↔ ¬IsMax a := alias ⟨_, lt_succ_of_not_isMax⟩ := lt_succ_iff_not_isMax #align order.lt_succ_of_not_is_max Order.lt_succ_of_not_isMax -theorem wcovby_succ (a : α) : a ⩿ succ a := +theorem wcovBy_succ (a : α) : a ⩿ succ a := ⟨le_succ a, fun _ hb => (succ_le_of_lt hb).not_lt⟩ -#align order.wcovby_succ Order.wcovby_succ +#align order.wcovby_succ Order.wcovBy_succ -theorem covby_succ_of_not_isMax (h : ¬IsMax a) : a ⋖ succ a := - (wcovby_succ a).covby_of_lt <| lt_succ_of_not_isMax h -#align order.covby_succ_of_not_is_max Order.covby_succ_of_not_isMax +theorem covBy_succ_of_not_isMax (h : ¬IsMax a) : a ⋖ succ a := + (wcovBy_succ a).covBy_of_lt <| lt_succ_of_not_isMax h +#align order.covby_succ_of_not_is_max Order.covBy_succ_of_not_isMax theorem lt_succ_iff_of_not_isMax (ha : ¬IsMax a) : b < succ a ↔ b ≤ a := ⟨le_of_lt_succ, fun h => h.trans_lt <| lt_succ_of_not_isMax ha⟩ @@ -256,7 +256,7 @@ theorem succ_le_iff_of_not_isMax (ha : ¬IsMax a) : succ a ≤ b ↔ a < b := #align order.succ_le_iff_of_not_is_max Order.succ_le_iff_of_not_isMax lemma succ_lt_succ_of_not_isMax (h : a < b) (hb : ¬ IsMax b) : succ a < succ b := - (lt_succ_iff_of_not_isMax hb).2 $ succ_le_of_lt h + (lt_succ_iff_of_not_isMax hb).2 <| succ_le_of_lt h theorem succ_lt_succ_iff_of_not_isMax (ha : ¬IsMax a) (hb : ¬IsMax b) : succ a < succ b ↔ a < b := by @@ -360,9 +360,9 @@ alias ⟨lt_of_succ_lt_succ, succ_lt_succ⟩ := succ_lt_succ_iff theorem succ_strictMono : StrictMono (succ : α → α) := fun _ _ => succ_lt_succ #align order.succ_strict_mono Order.succ_strictMono -theorem covby_succ (a : α) : a ⋖ succ a := - covby_succ_of_not_isMax <| not_isMax a -#align order.covby_succ Order.covby_succ +theorem covBy_succ (a : α) : a ⋖ succ a := + covBy_succ_of_not_isMax <| not_isMax a +#align order.covby_succ Order.covBy_succ @[simp] theorem Iio_succ (a : α) : Iio (succ a) = Iic a := @@ -427,15 +427,15 @@ theorem le_le_succ_iff : a ≤ b ∧ b ≤ succ a ↔ b = a ∨ b = succ a := by · exact ⟨le_succ a, le_rfl⟩ #align order.le_le_succ_iff Order.le_le_succ_iff -theorem _root_.Covby.succ_eq (h : a ⋖ b) : succ a = b := +theorem _root_.CovBy.succ_eq (h : a ⋖ b) : succ a = b := (succ_le_of_lt h.lt).eq_of_not_lt fun h' => h.2 (lt_succ_of_not_isMax h.lt.not_isMax) h' -#align covby.succ_eq Covby.succ_eq +#align covby.succ_eq CovBy.succ_eq -theorem _root_.Wcovby.le_succ (h : a ⩿ b) : b ≤ succ a := by - obtain h | rfl := h.covby_or_eq - · exact (Covby.succ_eq h).ge +theorem _root_.WCovBy.le_succ (h : a ⩿ b) : b ≤ succ a := by + obtain h | rfl := h.covBy_or_eq + · exact (CovBy.succ_eq h).ge · exact le_succ _ -#align wcovby.le_succ Wcovby.le_succ +#align wcovby.le_succ WCovBy.le_succ theorem le_succ_iff_eq_or_le : a ≤ succ b ↔ a = succ b ∨ a ≤ b := by by_cases hb : IsMax b @@ -496,11 +496,11 @@ theorem lt_succ_iff_eq_or_lt : a < succ b ↔ a = b ∨ a < b := lt_succ_iff.trans le_iff_eq_or_lt #align order.lt_succ_iff_eq_or_lt Order.lt_succ_iff_eq_or_lt -theorem succ_eq_iff_covby : succ a = b ↔ a ⋖ b := +theorem succ_eq_iff_covBy : succ a = b ↔ a ⋖ b := ⟨by rintro rfl - exact covby_succ _, Covby.succ_eq⟩ -#align order.succ_eq_iff_covby Order.succ_eq_iff_covby + exact covBy_succ _, CovBy.succ_eq⟩ +#align order.succ_eq_iff_covby Order.succ_eq_iff_covBy theorem Iio_succ_eq_insert (a : α) : Iio (succ a) = insert a (Iio a) := Iio_succ_eq_insert_of_not_isMax <| not_isMax a @@ -570,7 +570,7 @@ instance [PartialOrder α] : Subsingleton (SuccOrder α) := ext a by_cases ha : IsMax a · exact (@IsMax.succ_eq _ _ h₀ _ ha).trans ha.succ_eq.symm - · exact @Covby.succ_eq _ _ h₀ _ _ (covby_succ_of_not_isMax ha)⟩ + · exact @CovBy.succ_eq _ _ h₀ _ _ (covBy_succ_of_not_isMax ha)⟩ section CompleteLattice @@ -627,13 +627,13 @@ theorem pred_lt_iff_not_isMin : pred a < a ↔ ¬IsMin a := alias ⟨_, pred_lt_of_not_isMin⟩ := pred_lt_iff_not_isMin #align order.pred_lt_of_not_is_min Order.pred_lt_of_not_isMin -theorem pred_wcovby (a : α) : pred a ⩿ a := +theorem pred_wcovBy (a : α) : pred a ⩿ a := ⟨pred_le a, fun _ hb => (le_of_pred_lt hb).not_lt⟩ -#align order.pred_wcovby Order.pred_wcovby +#align order.pred_wcovby Order.pred_wcovBy -theorem pred_covby_of_not_isMin (h : ¬IsMin a) : pred a ⋖ a := - (pred_wcovby a).covby_of_lt <| pred_lt_of_not_isMin h -#align order.pred_covby_of_not_is_min Order.pred_covby_of_not_isMin +theorem pred_covBy_of_not_isMin (h : ¬IsMin a) : pred a ⋖ a := + (pred_wcovBy a).covBy_of_lt <| pred_lt_of_not_isMin h +#align order.pred_covby_of_not_is_min Order.pred_covBy_of_not_isMin theorem pred_lt_iff_of_not_isMin (ha : ¬IsMin a) : pred a < b ↔ a ≤ b := ⟨le_of_pred_lt, (pred_lt_of_not_isMin ha).trans_le⟩ @@ -644,7 +644,7 @@ theorem le_pred_iff_of_not_isMin (ha : ¬IsMin a) : b ≤ pred a ↔ b < a := #align order.le_pred_iff_of_not_is_min Order.le_pred_iff_of_not_isMin lemma pred_lt_pred_of_not_isMin (h : a < b) (ha : ¬ IsMin a) : pred a < pred b := - (pred_lt_iff_of_not_isMin ha).2 $ le_pred_of_lt h + (pred_lt_iff_of_not_isMin ha).2 <| le_pred_of_lt h @[simp, mono] theorem pred_le_pred {a b : α} (h : a ≤ b) : pred a ≤ pred b := @@ -727,9 +727,9 @@ alias ⟨lt_of_pred_lt_pred, pred_lt_pred⟩ := pred_lt_pred_iff theorem pred_strictMono : StrictMono (pred : α → α) := fun _ _ => pred_lt_pred #align order.pred_strict_mono Order.pred_strictMono -theorem pred_covby (a : α) : pred a ⋖ a := - pred_covby_of_not_isMin <| not_isMin a -#align order.pred_covby Order.pred_covby +theorem pred_covBy (a : α) : pred a ⋖ a := + pred_covBy_of_not_isMin <| not_isMin a +#align order.pred_covby Order.pred_covBy @[simp] theorem Ioi_pred (a : α) : Ioi (pred a) = Ici a := @@ -786,15 +786,15 @@ theorem pred_le_le_iff {a b : α} : pred a ≤ b ∧ b ≤ a ↔ b = a ∨ b = p · exact ⟨le_rfl, pred_le a⟩ #align order.pred_le_le_iff Order.pred_le_le_iff -theorem _root_.Covby.pred_eq {a b : α} (h : a ⋖ b) : pred b = a := +theorem _root_.CovBy.pred_eq {a b : α} (h : a ⋖ b) : pred b = a := (le_pred_of_lt h.lt).eq_of_not_gt fun h' => h.2 h' <| pred_lt_of_not_isMin h.lt.not_isMin -#align covby.pred_eq Covby.pred_eq +#align covby.pred_eq CovBy.pred_eq -theorem _root_.Wcovby.pred_le (h : a ⩿ b) : pred b ≤ a := by - obtain h | rfl := h.covby_or_eq - · exact (Covby.pred_eq h).le +theorem _root_.WCovBy.pred_le (h : a ⩿ b) : pred b ≤ a := by + obtain h | rfl := h.covBy_or_eq + · exact (CovBy.pred_eq h).le · exact pred_le _ -#align wcovby.pred_le Wcovby.pred_le +#align wcovby.pred_le WCovBy.pred_le theorem pred_le_iff_eq_or_le : pred a ≤ b ↔ b = pred a ∨ a ≤ b := by by_cases ha : IsMin a @@ -846,11 +846,11 @@ theorem pred_lt_iff_eq_or_lt : pred a < b ↔ a = b ∨ a < b := pred_lt_iff.trans le_iff_eq_or_lt #align order.pred_lt_iff_eq_or_lt Order.pred_lt_iff_eq_or_lt -theorem pred_eq_iff_covby : pred b = a ↔ a ⋖ b := +theorem pred_eq_iff_covBy : pred b = a ↔ a ⋖ b := ⟨by rintro rfl - exact pred_covby _, Covby.pred_eq⟩ -#align order.pred_eq_iff_covby Order.pred_eq_iff_covby + exact pred_covBy _, CovBy.pred_eq⟩ +#align order.pred_eq_iff_covby Order.pred_eq_iff_covBy theorem Ioi_pred_eq_insert (a : α) : Ioi (pred a) = insert a (Ioi a) := ext fun _ => pred_lt_iff_eq_or_lt.trans <| or_congr_left eq_comm @@ -921,7 +921,7 @@ instance [PartialOrder α] : Subsingleton (PredOrder α) := ext a by_cases ha : IsMin a · exact (@IsMin.pred_eq _ _ h₀ _ ha).trans ha.pred_eq.symm - · exact @Covby.pred_eq _ _ h₀ _ _ (pred_covby_of_not_isMin ha)⟩ + · exact @CovBy.pred_eq _ _ h₀ _ _ (pred_covBy_of_not_isMin ha)⟩ section CompleteLattice @@ -945,22 +945,22 @@ variable [PartialOrder α] [SuccOrder α] [PredOrder α] {a b : α} @[simp] theorem succ_pred_of_not_isMin (h : ¬IsMin a) : succ (pred a) = a := - Covby.succ_eq (pred_covby_of_not_isMin h) + CovBy.succ_eq (pred_covBy_of_not_isMin h) #align order.succ_pred_of_not_is_min Order.succ_pred_of_not_isMin @[simp] theorem pred_succ_of_not_isMax (h : ¬IsMax a) : pred (succ a) = a := - Covby.pred_eq (covby_succ_of_not_isMax h) + CovBy.pred_eq (covBy_succ_of_not_isMax h) #align order.pred_succ_of_not_is_max Order.pred_succ_of_not_isMax --Porting note: removing @[simp],`simp` can prove it theorem succ_pred [NoMinOrder α] (a : α) : succ (pred a) = a := - Covby.succ_eq (pred_covby _) + CovBy.succ_eq (pred_covBy _) #align order.succ_pred Order.succ_pred --Porting note: removing @[simp],`simp` can prove it theorem pred_succ [NoMaxOrder α] (a : α) : pred (succ a) = a := - Covby.pred_eq (covby_succ _) + CovBy.pred_eq (covBy_succ _) #align order.pred_succ Order.pred_succ theorem pred_succ_iterate_of_not_isMax (i : α) (n : ℕ) (hin : ¬IsMax (succ^[n - 1] i)) : @@ -1477,7 +1477,7 @@ variable [Preorder α] [Nonempty α] [Preorder β] {f : α → β} lemma StrictMono.not_bddAbove_range [NoMaxOrder α] [SuccOrder β] [IsSuccArchimedean β] (hf : StrictMono f) : ¬ BddAbove (Set.range f) := by rintro ⟨m, hm⟩ - have hm' : ∀ a, f a ≤ m := λ a ↦ hm $ Set.mem_range_self _ + have hm' : ∀ a, f a ≤ m := λ a ↦ hm <| Set.mem_range_self _ obtain ⟨a₀⟩ := ‹Nonempty α› suffices ∀ b, f a₀ ≤ b → ∃ a, b < f a by obtain ⟨a, ha⟩ : ∃ a, m < f a := this m (hm' a₀) diff --git a/Mathlib/Order/SuccPred/Limit.lean b/Mathlib/Order/SuccPred/Limit.lean index ad5197a673326..8b0a4a3f3598c 100644 --- a/Mathlib/Order/SuccPred/Limit.lean +++ b/Mathlib/Order/SuccPred/Limit.lean @@ -43,12 +43,12 @@ def IsSuccLimit (a : α) : Prop := ∀ b, ¬b ⋖ a #align order.is_succ_limit Order.IsSuccLimit -theorem not_isSuccLimit_iff_exists_covby (a : α) : ¬IsSuccLimit a ↔ ∃ b, b ⋖ a := by +theorem not_isSuccLimit_iff_exists_covBy (a : α) : ¬IsSuccLimit a ↔ ∃ b, b ⋖ a := by simp [IsSuccLimit] -#align order.not_is_succ_limit_iff_exists_covby Order.not_isSuccLimit_iff_exists_covby +#align order.not_is_succ_limit_iff_exists_covby Order.not_isSuccLimit_iff_exists_covBy @[simp] -theorem isSuccLimit_of_dense [DenselyOrdered α] (a : α) : IsSuccLimit a := fun _ => not_covby +theorem isSuccLimit_of_dense [DenselyOrdered α] (a : α) : IsSuccLimit a := fun _ => not_covBy #align order.is_succ_limit_of_dense Order.isSuccLimit_of_dense end LT @@ -69,7 +69,7 @@ variable [SuccOrder α] protected theorem IsSuccLimit.isMax (h : IsSuccLimit (succ a)) : IsMax a := by by_contra H - exact h a (covby_succ_of_not_isMax H) + exact h a (covBy_succ_of_not_isMax H) #align order.is_succ_limit.is_max Order.IsSuccLimit.isMax theorem not_isSuccLimit_succ_of_not_isMax (ha : ¬IsMax a) : ¬IsSuccLimit (succ a) := by @@ -120,14 +120,14 @@ section PartialOrder variable [PartialOrder α] [SuccOrder α] {a b : α} {C : α → Sort*} theorem isSuccLimit_of_succ_ne (h : ∀ b, succ b ≠ a) : IsSuccLimit a := fun b hba => - h b (Covby.succ_eq hba) + h b (CovBy.succ_eq hba) #align order.is_succ_limit_of_succ_ne Order.isSuccLimit_of_succ_ne theorem not_isSuccLimit_iff : ¬IsSuccLimit a ↔ ∃ b, ¬IsMax b ∧ succ b = a := by - rw [not_isSuccLimit_iff_exists_covby] - refine' exists_congr fun b => ⟨fun hba => ⟨hba.lt.not_isMax, (Covby.succ_eq hba)⟩, _⟩ + rw [not_isSuccLimit_iff_exists_covBy] + refine' exists_congr fun b => ⟨fun hba => ⟨hba.lt.not_isMax, (CovBy.succ_eq hba)⟩, _⟩ rintro ⟨h, rfl⟩ - exact covby_succ_of_not_isMax h + exact covBy_succ_of_not_isMax h #align order.not_is_succ_limit_iff Order.not_isSuccLimit_iff /-- See `not_isSuccLimit_iff` for a version that states that `a` is a successor of a value other @@ -138,7 +138,7 @@ theorem mem_range_succ_of_not_isSuccLimit (h : ¬IsSuccLimit a) : a ∈ range (@ #align order.mem_range_succ_of_not_is_succ_limit Order.mem_range_succ_of_not_isSuccLimit theorem isSuccLimit_of_succ_lt (H : ∀ a < b, succ a < b) : IsSuccLimit b := fun a hab => - (H a hab.lt).ne (Covby.succ_eq hab) + (H a hab.lt).ne (CovBy.succ_eq hab) #align order.is_succ_limit_of_succ_lt Order.isSuccLimit_of_succ_lt theorem IsSuccLimit.succ_lt (hb : IsSuccLimit b) (ha : a < b) : succ a < b := by @@ -245,11 +245,11 @@ def IsPredLimit (a : α) : Prop := ∀ b, ¬a ⋖ b #align order.is_pred_limit Order.IsPredLimit -theorem not_isPredLimit_iff_exists_covby (a : α) : ¬IsPredLimit a ↔ ∃ b, a ⋖ b := by +theorem not_isPredLimit_iff_exists_covBy (a : α) : ¬IsPredLimit a ↔ ∃ b, a ⋖ b := by simp [IsPredLimit] -#align order.not_is_pred_limit_iff_exists_covby Order.not_isPredLimit_iff_exists_covby +#align order.not_is_pred_limit_iff_exists_covby Order.not_isPredLimit_iff_exists_covBy -theorem isPredLimit_of_dense [DenselyOrdered α] (a : α) : IsPredLimit a := fun _ => not_covby +theorem isPredLimit_of_dense [DenselyOrdered α] (a : α) : IsPredLimit a := fun _ => not_covBy #align order.is_pred_limit_of_dense Order.isPredLimit_of_dense @[simp] @@ -286,7 +286,7 @@ variable [PredOrder α] protected theorem IsPredLimit.isMin (h : IsPredLimit (pred a)) : IsMin a := by by_contra H - exact h a (pred_covby_of_not_isMin H) + exact h a (pred_covBy_of_not_isMin H) #align order.is_pred_limit.is_min Order.IsPredLimit.isMin theorem not_isPredLimit_pred_of_not_isMin (ha : ¬IsMin a) : ¬IsPredLimit (pred a) := by @@ -334,7 +334,7 @@ section PartialOrder variable [PartialOrder α] [PredOrder α] {a b : α} {C : α → Sort*} theorem isPredLimit_of_pred_ne (h : ∀ b, pred b ≠ a) : IsPredLimit a := fun b hba => - h b (Covby.pred_eq hba) + h b (CovBy.pred_eq hba) #align order.is_pred_limit_of_pred_ne Order.isPredLimit_of_pred_ne theorem not_isPredLimit_iff : ¬IsPredLimit a ↔ ∃ b, ¬IsMin b ∧ pred b = a := by @@ -350,7 +350,7 @@ theorem mem_range_pred_of_not_isPredLimit (h : ¬IsPredLimit a) : a ∈ range (@ #align order.mem_range_pred_of_not_is_pred_limit Order.mem_range_pred_of_not_isPredLimit theorem isPredLimit_of_pred_lt (H : ∀ a > b, pred a < b) : IsPredLimit b := fun a hab => - (H a hab.lt).ne (Covby.pred_eq hab) + (H a hab.lt).ne (CovBy.pred_eq hab) #align order.is_pred_limit_of_pred_lt Order.isPredLimit_of_pred_lt theorem IsPredLimit.lt_pred (h : IsPredLimit a) : a < b → a < pred b := diff --git a/Mathlib/Order/SupClosed.lean b/Mathlib/Order/SupClosed.lean index 99968407468a6..f31630e0e43f8 100644 --- a/Mathlib/Order/SupClosed.lean +++ b/Mathlib/Order/SupClosed.lean @@ -52,7 +52,7 @@ lemma supClosed_sInter (hS : ∀ s ∈ S, SupClosed s) : SupClosed (⋂₀ S) := λ _a ha _b hb _s hs ↦ hS _ hs (ha _ hs) (hb _ hs) lemma supClosed_iInter (hf : ∀ i, SupClosed (f i)) : SupClosed (⋂ i, f i) := -supClosed_sInter $ forall_range_iff.2 hf +supClosed_sInter <| forall_range_iff.2 hf lemma SupClosed.directedOn (hs : SupClosed s) : DirectedOn (· ≤ ·) s := λ _a ha _b hb ↦ ⟨_, hs ha hb, le_sup_left, le_sup_right⟩ @@ -65,7 +65,7 @@ lemma SupClosed.preimage [SupHomClass F β α] (hs : SupClosed s) (f : F) : SupC lemma SupClosed.image [SupHomClass F α β] (hs : SupClosed s) (f : F) : SupClosed (f '' s) := by rintro _ ⟨a, ha, rfl⟩ _ ⟨b, hb, rfl⟩ rw [← map_sup] - exact Set.mem_image_of_mem _ $ hs ha hb + exact Set.mem_image_of_mem _ <| hs ha hb lemma supClosed_range [SupHomClass F α β] (f : F) : SupClosed (Set.range f) := by simpa using supClosed_univ.image f @@ -116,7 +116,7 @@ lemma infClosed_sInter (hS : ∀ s ∈ S, InfClosed s) : InfClosed (⋂₀ S) := λ _a ha _b hb _s hs ↦ hS _ hs (ha _ hs) (hb _ hs) lemma infClosed_iInter (hf : ∀ i, InfClosed (f i)) : InfClosed (⋂ i, f i) := -infClosed_sInter $ forall_range_iff.2 hf +infClosed_sInter <| forall_range_iff.2 hf lemma InfClosed.codirectedOn (hs : InfClosed s) : DirectedOn (· ≥ ·) s := λ _a ha _b hb ↦ ⟨_, hs ha hb, inf_le_left, inf_le_right⟩ @@ -129,7 +129,7 @@ lemma InfClosed.preimage [InfHomClass F β α] (hs : InfClosed s) (f : F) : InfC lemma InfClosed.image [InfHomClass F α β] (hs : InfClosed s) (f : F) : InfClosed (f '' s) := by rintro _ ⟨a, ha, rfl⟩ _ ⟨b, hb, rfl⟩ rw [← map_inf] - exact Set.mem_image_of_mem _ $ hs ha hb + exact Set.mem_image_of_mem _ <| hs ha hb lemma infClosed_range [InfHomClass F α β] (f : F) : InfClosed (Set.range f) := by simpa using infClosed_univ.image f @@ -260,10 +260,10 @@ def supClosure : ClosureOperator (Set α) := .ofPred (by classical rintro s _ ⟨t, ht, hts, rfl⟩ _ ⟨u, hu, hus, rfl⟩ - refine' ⟨_, ht.mono $ subset_union_left _ _, _, sup'_union ht hu _⟩ + refine' ⟨_, ht.mono <| subset_union_left _ _, _, sup'_union ht hu _⟩ rw [coe_union] exact Set.union_subset hts hus) - (by rintro s₁ s₂ hs h₂ _ ⟨t, ht, hts, rfl⟩; exact h₂.finsetSup'_mem ht λ i hi ↦ hs $ hts hi) + (by rintro s₁ s₂ hs h₂ _ ⟨t, ht, hts, rfl⟩; exact h₂.finsetSup'_mem ht λ i hi ↦ hs <| hts hi) @[simp] lemma subset_supClosure {s : Set α} : s ⊆ supClosure s := supClosure.le_closure _ @@ -283,9 +283,9 @@ supClosure.idempotent _ @[simp] lemma supClosure_univ : supClosure (Set.univ : Set α) = Set.univ := by simp @[simp] lemma upperBounds_supClosure (s : Set α) : upperBounds (supClosure s) = upperBounds s := -(upperBounds_mono_set subset_supClosure).antisymm $ by +(upperBounds_mono_set subset_supClosure).antisymm <| by rintro a ha _ ⟨t, ht, hts, rfl⟩ - exact sup'_le _ _ λ b hb ↦ ha $ hts hb + exact sup'_le _ _ λ b hb ↦ ha <| hts hb @[simp] lemma isLUB_supClosure : IsLUB (supClosure s) a ↔ IsLUB s a := by simp [IsLUB] @@ -294,7 +294,7 @@ lemma sup_mem_supClosure (ha : a ∈ s) (hb : b ∈ s) : a ⊔ b ∈ supClosure lemma finsetSup'_mem_supClosure {ι : Type*} {t : Finset ι} (ht : t.Nonempty) {f : ι → α} (hf : ∀ i ∈ t, f i ∈ s) : t.sup' ht f ∈ supClosure s := - supClosed_supClosure.finsetSup'_mem _ fun _i hi ↦ subset_supClosure $ hf _ hi + supClosed_supClosure.finsetSup'_mem _ fun _i hi ↦ subset_supClosure <| hf _ hi lemma supClosure_min : s ⊆ t → SupClosed t → supClosure s ⊆ t := supClosure.closure_min @@ -323,10 +323,10 @@ def infClosure : ClosureOperator (Set α) := ClosureOperator.ofPred (by classical rintro s _ ⟨t, ht, hts, rfl⟩ _ ⟨u, hu, hus, rfl⟩ - refine' ⟨_, ht.mono $ subset_union_left _ _, _, inf'_union ht hu _⟩ + refine' ⟨_, ht.mono <| subset_union_left _ _, _, inf'_union ht hu _⟩ rw [coe_union] exact Set.union_subset hts hus) - (by rintro s₁ s₂ hs h₂ _ ⟨t, ht, hts, rfl⟩; exact h₂.finsetInf'_mem ht λ i hi ↦ hs $ hts hi) + (by rintro s₁ s₂ hs h₂ _ ⟨t, ht, hts, rfl⟩; exact h₂.finsetInf'_mem ht λ i hi ↦ hs <| hts hi) @[simp] lemma subset_infClosure {s : Set α} : s ⊆ infClosure s := infClosure.le_closure _ @@ -346,9 +346,9 @@ infClosure.idempotent _ @[simp] lemma infClosure_univ : infClosure (Set.univ : Set α) = Set.univ := by simp @[simp] lemma lowerBounds_infClosure (s : Set α) : lowerBounds (infClosure s) = lowerBounds s := -(lowerBounds_mono_set subset_infClosure).antisymm $ by +(lowerBounds_mono_set subset_infClosure).antisymm <| by rintro a ha _ ⟨t, ht, hts, rfl⟩ - exact le_inf' _ _ λ b hb ↦ ha $ hts hb + exact le_inf' _ _ λ b hb ↦ ha <| hts hb @[simp] lemma isGLB_infClosure : IsGLB (infClosure s) a ↔ IsGLB s a := by simp [IsGLB] open Finset @@ -358,7 +358,7 @@ lemma inf_mem_infClosure (ha : a ∈ s) (hb : b ∈ s) : a ⊓ b ∈ infClosure lemma finsetInf'_mem_infClosure {ι : Type*} {t : Finset ι} (ht : t.Nonempty) {f : ι → α} (hf : ∀ i ∈ t, f i ∈ s) : t.inf' ht f ∈ infClosure s := - infClosed_infClosure.finsetInf'_mem _ fun _i hi ↦ subset_infClosure $ hf _ hi + infClosed_infClosure.finsetInf'_mem _ fun _i hi ↦ subset_infClosure <| hf _ hi lemma infClosure_min : s ⊆ t → InfClosed t → infClosure s ⊆ t := infClosure.closure_min @@ -426,12 +426,12 @@ protected lemma InfClosed.supClosure (hs : InfClosed s) : InfClosed (supClosure @[simp] lemma supClosure_infClosure (s : Set α) : supClosure (infClosure s) = latticeClosure s := le_antisymm (supClosure_min (infClosure_min subset_latticeClosure isSublattice_latticeClosure.2) - isSublattice_latticeClosure.1) $ latticeClosure_min (subset_infClosure.trans subset_supClosure) + isSublattice_latticeClosure.1) <| latticeClosure_min (subset_infClosure.trans subset_supClosure) ⟨supClosed_supClosure, infClosed_infClosure.supClosure⟩ @[simp] lemma infClosure_supClosure (s : Set α) : infClosure (supClosure s) = latticeClosure s := le_antisymm (infClosure_min (supClosure_min subset_latticeClosure isSublattice_latticeClosure.1) - isSublattice_latticeClosure.2) $ latticeClosure_min (subset_supClosure.trans subset_infClosure) + isSublattice_latticeClosure.2) <| latticeClosure_min (subset_supClosure.trans subset_infClosure) ⟨supClosed_supClosure.infClosure, infClosed_infClosure⟩ lemma Set.Finite.latticeClosure (hs : s.Finite) : (latticeClosure s).Finite := by @@ -444,13 +444,13 @@ end DistribLattice def SemilatticeSup.toCompleteSemilatticeSup [SemilatticeSup α] (sSup : Set α → α) (h : ∀ s, SupClosed s → IsLUB s (sSup s)) : CompleteSemilatticeSup α where sSup := fun s => sSup (supClosure s) - le_sSup s a ha := (h _ supClosed_supClosure).1 $ subset_supClosure ha - sSup_le s a ha := (isLUB_le_iff $ h _ supClosed_supClosure).2 $ by rwa [upperBounds_supClosure] + le_sSup s a ha := (h _ supClosed_supClosure).1 <| subset_supClosure ha + sSup_le s a ha := (isLUB_le_iff <| h _ supClosed_supClosure).2 <| by rwa [upperBounds_supClosure] /-- A meet-semilattice where every inf-closed set has a greatest lower bound is automatically complete. -/ def SemilatticeInf.toCompleteSemilatticeInf [SemilatticeInf α] (sInf : Set α → α) (h : ∀ s, InfClosed s → IsGLB s (sInf s)) : CompleteSemilatticeInf α where sInf := fun s => sInf (infClosure s) - sInf_le s a ha := (h _ infClosed_infClosure).1 $ subset_infClosure ha - le_sInf s a ha := (le_isGLB_iff $ h _ infClosed_infClosure).2 $ by rwa [lowerBounds_infClosure] + sInf_le s a ha := (h _ infClosed_infClosure).1 <| subset_infClosure ha + le_sInf s a ha := (le_isGLB_iff <| h _ infClosed_infClosure).2 <| by rwa [lowerBounds_infClosure] diff --git a/Mathlib/Order/SymmDiff.lean b/Mathlib/Order/SymmDiff.lean index f3a4df6ad6697..28a16946cf572 100644 --- a/Mathlib/Order/SymmDiff.lean +++ b/Mathlib/Order/SymmDiff.lean @@ -67,13 +67,13 @@ def bihimp [Inf α] [HImp α] (a b : α) : α := (b ⇨ a) ⊓ (a ⇨ b) #align bihimp bihimp -/- This notation might conflict with the Laplacian once we have it. Feel free to put it in locale - `order` or `symmDiff` if that happens. -/ /-- Notation for symmDiff -/ -infixl:100 " ∆ " => symmDiff +scoped[symmDiff] infixl:100 " ∆ " => symmDiff /-- Notation for bihimp -/ -infixl:100 " ⇔ " => bihimp +scoped[symmDiff] infixl:100 " ⇔ " => bihimp + +open scoped symmDiff theorem symmDiff_def [Sup α] [SDiff α] (a b : α) : a ∆ b = a \ b ⊔ b \ a := rfl diff --git a/Mathlib/Order/UpperLower/Basic.lean b/Mathlib/Order/UpperLower/Basic.lean index 1e0a088eb305e..68aceac89e998 100644 --- a/Mathlib/Order/UpperLower/Basic.lean +++ b/Mathlib/Order/UpperLower/Basic.lean @@ -208,23 +208,23 @@ lemma IsLowerSet.isUpperSet_preimage_coe (hs : IsLowerSet s) : lemma IsUpperSet.sdiff (hs : IsUpperSet s) (ht : ∀ b ∈ s, ∀ c ∈ t, b ≤ c → b ∈ t) : IsUpperSet (s \ t) := - fun _b _c hbc hb ↦ ⟨hs hbc hb.1, fun hc ↦ hb.2 $ ht _ hb.1 _ hc hbc⟩ + fun _b _c hbc hb ↦ ⟨hs hbc hb.1, fun hc ↦ hb.2 <| ht _ hb.1 _ hc hbc⟩ lemma IsLowerSet.sdiff (hs : IsLowerSet s) (ht : ∀ b ∈ s, ∀ c ∈ t, c ≤ b → b ∈ t) : IsLowerSet (s \ t) := - fun _b _c hcb hb ↦ ⟨hs hcb hb.1, fun hc ↦ hb.2 $ ht _ hb.1 _ hc hcb⟩ + fun _b _c hcb hb ↦ ⟨hs hcb hb.1, fun hc ↦ hb.2 <| ht _ hb.1 _ hc hcb⟩ lemma IsUpperSet.sdiff_of_isLowerSet (hs : IsUpperSet s) (ht : IsLowerSet t) : IsUpperSet (s \ t) := - hs.sdiff $ by aesop + hs.sdiff <| by aesop lemma IsLowerSet.sdiff_of_isUpperSet (hs : IsLowerSet s) (ht : IsUpperSet t) : IsLowerSet (s \ t) := - hs.sdiff $ by aesop + hs.sdiff <| by aesop lemma IsUpperSet.erase (hs : IsUpperSet s) (has : ∀ b ∈ s, b ≤ a → b = a) : IsUpperSet (s \ {a}) := - hs.sdiff $ by simpa using has + hs.sdiff <| by simpa using has lemma IsLowerSet.erase (hs : IsLowerSet s) (has : ∀ b ∈ s, a ≤ b → b = a) : IsLowerSet (s \ {a}) := - hs.sdiff $ by simpa using has + hs.sdiff <| by simpa using has end LE @@ -1045,7 +1045,7 @@ def map (f : α ≃o β) : UpperSet α ≃o UpperSet β where @[simp] theorem symm_map (f : α ≃o β) : (map f).symm = map f.symm := - FunLike.ext _ _ fun s => ext <| by convert Set.preimage_equiv_eq_image_symm s f.toEquiv + DFunLike.ext _ _ fun s => ext <| by convert Set.preimage_equiv_eq_image_symm s f.toEquiv #align upper_set.symm_map UpperSet.symm_map @[simp] @@ -1090,7 +1090,7 @@ def map (f : α ≃o β) : LowerSet α ≃o LowerSet β where @[simp] theorem symm_map (f : α ≃o β) : (map f).symm = map f.symm := - FunLike.ext _ _ fun s => ext <| by convert Set.preimage_equiv_eq_image_symm s f.toEquiv + DFunLike.ext _ _ fun s => ext <| by convert Set.preimage_equiv_eq_image_symm s f.toEquiv #align lower_set.symm_map LowerSet.symm_map @[simp] @@ -1215,7 +1215,7 @@ section PartialOrder variable [PartialOrder α] {a b : α} nonrec lemma Ici_injective : Injective (Ici : α → UpperSet α) := fun _a _b hab ↦ - Ici_injective $ congr_arg ((↑) : _ → Set α) hab + Ici_injective <| congr_arg ((↑) : _ → Set α) hab @[simp] lemma Ici_inj : Ici a = Ici b ↔ a = b := Ici_injective.eq_iff @@ -1324,7 +1324,7 @@ section PartialOrder variable [PartialOrder α] {a b : α} nonrec lemma Iic_injective : Injective (Iic : α → LowerSet α) := fun _a _b hab ↦ - Iic_injective $ congr_arg ((↑) : _ → Set α) hab + Iic_injective <| congr_arg ((↑) : _ → Set α) hab @[simp] lemma Iic_inj : Iic a = Iic b ↔ a = b := Iic_injective.eq_iff @@ -1466,11 +1466,11 @@ theorem LowerSet.iSup_Iic (s : Set α) : ⨆ a ∈ s, LowerSet.Iic a = lowerClos #align lower_set.supr_Iic LowerSet.iSup_Iic @[simp] lemma lowerClosure_le {t : LowerSet α} : lowerClosure s ≤ t ↔ s ⊆ t := - ⟨fun h ↦ subset_lowerClosure.trans $ LowerSet.coe_subset_coe.2 h, + ⟨fun h ↦ subset_lowerClosure.trans <| LowerSet.coe_subset_coe.2 h, fun h ↦ lowerClosure_min h t.lower⟩ @[simp] lemma le_upperClosure {s : UpperSet α} : s ≤ upperClosure t ↔ t ⊆ s := - ⟨fun h ↦ subset_upperClosure.trans $ UpperSet.coe_subset_coe.2 h, + ⟨fun h ↦ subset_upperClosure.trans <| UpperSet.coe_subset_coe.2 h, fun h ↦ upperClosure_min h s.upper⟩ theorem gc_upperClosure_coe : @@ -1624,7 +1624,7 @@ protected alias ⟨BddBelow.of_upperClosure, BddBelow.upperClosure⟩ := bddBelo Disjoint ↑(upperClosure s) t ↔ Disjoint s t := by refine ⟨Disjoint.mono_left subset_upperClosure, ?_⟩ simp only [disjoint_left, SetLike.mem_coe, mem_upperClosure, forall_exists_index, and_imp] - exact fun h a b hb hba ha ↦ h hb $ ht hba ha + exact fun h a b hb hba ha ↦ h hb <| ht hba ha @[simp] lemma IsLowerSet.disjoint_upperClosure_right (hs : IsLowerSet s) : Disjoint s (upperClosure t) ↔ Disjoint s t := by @@ -1683,12 +1683,12 @@ lemma erase_le : s.erase a ≤ s := diff_subset _ _ lemma sdiff_sup_lowerClosure (hts : t ⊆ s) (hst : ∀ b ∈ s, ∀ c ∈ t, c ≤ b → b ∈ t) : s.sdiff t ⊔ lowerClosure t = s := by - refine' le_antisymm (sup_le sdiff_le_left $ lowerClosure_le.2 hts) fun a ha ↦ _ + refine' le_antisymm (sup_le sdiff_le_left <| lowerClosure_le.2 hts) fun a ha ↦ _ obtain hat | hat := em (a ∈ t) · exact subset_union_right _ _ (subset_lowerClosure hat) · refine subset_union_left _ _ ⟨ha, ?_⟩ rintro ⟨b, hb, hba⟩ - exact hat $ hst _ ha _ hb hba + exact hat <| hst _ ha _ hb hba lemma lowerClosure_sup_sdiff (hts : t ⊆ s) (hst : ∀ b ∈ s, ∀ c ∈ t, c ≤ b → b ∈ t) : lowerClosure t ⊔ s.sdiff t = s := by rw [sup_comm, sdiff_sup_lowerClosure hts hst] @@ -1744,12 +1744,12 @@ lemma le_erase : s ≤ s.erase a := diff_subset _ _ lemma sdiff_inf_upperClosure (hts : t ⊆ s) (hst : ∀ b ∈ s, ∀ c ∈ t, b ≤ c → b ∈ t) : s.sdiff t ⊓ upperClosure t = s := by - refine' ge_antisymm (le_inf le_sdiff_left $ le_upperClosure.2 hts) fun a ha ↦ _ + refine' ge_antisymm (le_inf le_sdiff_left <| le_upperClosure.2 hts) fun a ha ↦ _ obtain hat | hat := em (a ∈ t) · exact subset_union_right _ _ (subset_upperClosure hat) · refine subset_union_left _ _ ⟨ha, ?_⟩ rintro ⟨b, hb, hab⟩ - exact hat $ hst _ ha _ hb hab + exact hat <| hst _ ha _ hb hab lemma upperClosure_inf_sdiff (hts : t ⊆ s) (hst : ∀ b ∈ s, ∀ c ∈ t, b ≤ c → b ∈ t) : upperClosure t ⊓ s.sdiff t = s := by rw [inf_comm, sdiff_inf_upperClosure hts hst] diff --git a/Mathlib/Order/WellFounded.lean b/Mathlib/Order/WellFounded.lean index f92e43ee2cf9a..09faeba8c2a25 100644 --- a/Mathlib/Order/WellFounded.lean +++ b/Mathlib/Order/WellFounded.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Data.Set.Image +import Mathlib.Data.Set.Basic #align_import order.well_founded from "leanprover-community/mathlib"@"2c84c2c5496117349007d97104e7bbb471381592" diff --git a/Mathlib/Order/WellFoundedSet.lean b/Mathlib/Order/WellFoundedSet.lean index f386c03253504..6a52cba1294a8 100644 --- a/Mathlib/Order/WellFoundedSet.lean +++ b/Mathlib/Order/WellFoundedSet.lean @@ -20,10 +20,10 @@ A well-founded subset of an ordered type is one on which the relation `<` is wel ## Main Definitions * `Set.WellFoundedOn s r` indicates that the relation `r` is well-founded when restricted to the set `s`. - * `Set.IsWf s` indicates that `<` is well-founded when restricted to `s`. + * `Set.IsWF s` indicates that `<` is well-founded when restricted to `s`. * `Set.PartiallyWellOrderedOn s r` indicates that the relation `r` is partially well-ordered (also known as well quasi-ordered) when restricted to the set `s`. - * `Set.IsPwo s` indicates that any infinite sequence of elements in `s` contains an infinite + * `Set.IsPWO s` indicates that any infinite sequence of elements in `s` contains an infinite monotone subsequence. Note that this is equivalent to containing only two comparable elements. ## Main Results @@ -33,9 +33,9 @@ A well-founded subset of an ordered type is one on which the relation `<` is wel Higman, but this proof more closely follows Nash-Williams. * `Set.wellFoundedOn_iff` relates `well_founded_on` to the well-foundedness of a relation on the original type, to avoid dealing with subtypes. - * `Set.IsWf.mono` shows that a subset of a well-founded subset is well-founded. - * `Set.IsWf.union` shows that the union of two well-founded subsets is well-founded. - * `Finset.isWf` shows that all `Finset`s are well-founded. + * `Set.IsWF.mono` shows that a subset of a well-founded subset is well-founded. + * `Set.IsWF.union` shows that the union of two well-founded subsets is well-founded. + * `Finset.isWF` shows that all `Finset`s are well-founded. ## TODO @@ -211,22 +211,22 @@ section LT variable [LT α] {s t : Set α} -/-- `s.IsWf` indicates that `<` is well-founded when restricted to `s`. -/ -def IsWf (s : Set α) : Prop := +/-- `s.IsWF` indicates that `<` is well-founded when restricted to `s`. -/ +def IsWF (s : Set α) : Prop := WellFoundedOn s (· < ·) -#align set.is_wf Set.IsWf +#align set.is_wf Set.IsWF @[simp] -theorem isWf_empty : IsWf (∅ : Set α) := +theorem isWF_empty : IsWF (∅ : Set α) := wellFounded_of_isEmpty _ -#align set.is_wf_empty Set.isWf_empty +#align set.is_wf_empty Set.isWF_empty -theorem isWf_univ_iff : IsWf (univ : Set α) ↔ WellFounded ((· < ·) : α → α → Prop) := by - simp [IsWf, wellFoundedOn_iff] -#align set.is_wf_univ_iff Set.isWf_univ_iff +theorem isWF_univ_iff : IsWF (univ : Set α) ↔ WellFounded ((· < ·) : α → α → Prop) := by + simp [IsWF, wellFoundedOn_iff] +#align set.is_wf_univ_iff Set.isWF_univ_iff -theorem IsWf.mono (h : IsWf t) (st : s ⊆ t) : IsWf s := h.subset st -#align set.is_wf.mono Set.IsWf.mono +theorem IsWF.mono (h : IsWF t) (st : s ⊆ t) : IsWF s := h.subset st +#align set.is_wf.mono Set.IsWF.mono end LT @@ -234,11 +234,11 @@ section Preorder variable [Preorder α] {s t : Set α} {a : α} -protected nonrec theorem IsWf.union (hs : IsWf s) (ht : IsWf t) : IsWf (s ∪ t) := hs.union ht -#align set.is_wf.union Set.IsWf.union +protected nonrec theorem IsWF.union (hs : IsWF s) (ht : IsWF t) : IsWF (s ∪ t) := hs.union ht +#align set.is_wf.union Set.IsWF.union -@[simp] theorem isWf_union : IsWf (s ∪ t) ↔ IsWf s ∧ IsWf t := wellFoundedOn_union -#align set.is_wf_union Set.isWf_union +@[simp] theorem isWF_union : IsWF (s ∪ t) ↔ IsWF s ∧ IsWF t := wellFoundedOn_union +#align set.is_wf_union Set.isWF_union end Preorder @@ -246,11 +246,11 @@ section Preorder variable [Preorder α] {s t : Set α} {a : α} -theorem isWf_iff_no_descending_seq : - IsWf s ↔ ∀ f : ℕ → α, StrictAnti f → ¬∀ n, f (OrderDual.toDual n) ∈ s := +theorem isWF_iff_no_descending_seq : + IsWF s ↔ ∀ f : ℕ → α, StrictAnti f → ¬∀ n, f (OrderDual.toDual n) ∈ s := wellFoundedOn_iff_no_descending_seq.trans ⟨fun H f hf => H ⟨⟨f, hf.injective⟩, hf.lt_iff_lt⟩, fun H f => H f fun _ _ => f.map_rel_iff.2⟩ -#align set.is_wf_iff_no_descending_seq Set.isWf_iff_no_descending_seq +#align set.is_wf_iff_no_descending_seq Set.isWF_iff_no_descending_seq end Preorder @@ -421,98 +421,98 @@ theorem PartiallyWellOrderedOn.wellFoundedOn [IsPreorder α r] (h : s.PartiallyW end PartiallyWellOrderedOn -section IsPwo +section IsPWO variable [Preorder α] [Preorder β] {s t : Set α} /-- A subset of a preorder is partially well-ordered when any infinite sequence contains a monotone subsequence of length 2 (or equivalently, an infinite monotone subsequence). -/ -def IsPwo (s : Set α) : Prop := +def IsPWO (s : Set α) : Prop := PartiallyWellOrderedOn s (· ≤ ·) -#align set.is_pwo Set.IsPwo +#align set.is_pwo Set.IsPWO -nonrec theorem IsPwo.mono (ht : t.IsPwo) : s ⊆ t → s.IsPwo := ht.mono -#align set.is_pwo.mono Set.IsPwo.mono +nonrec theorem IsPWO.mono (ht : t.IsPWO) : s ⊆ t → s.IsPWO := ht.mono +#align set.is_pwo.mono Set.IsPWO.mono -nonrec theorem IsPwo.exists_monotone_subseq (h : s.IsPwo) (f : ℕ → α) (hf : ∀ n, f n ∈ s) : +nonrec theorem IsPWO.exists_monotone_subseq (h : s.IsPWO) (f : ℕ → α) (hf : ∀ n, f n ∈ s) : ∃ g : ℕ ↪o ℕ, Monotone (f ∘ g) := h.exists_monotone_subseq f hf -#align set.is_pwo.exists_monotone_subseq Set.IsPwo.exists_monotone_subseq +#align set.is_pwo.exists_monotone_subseq Set.IsPWO.exists_monotone_subseq -theorem isPwo_iff_exists_monotone_subseq : - s.IsPwo ↔ ∀ f : ℕ → α, (∀ n, f n ∈ s) → ∃ g : ℕ ↪o ℕ, Monotone (f ∘ g) := +theorem isPWO_iff_exists_monotone_subseq : + s.IsPWO ↔ ∀ f : ℕ → α, (∀ n, f n ∈ s) → ∃ g : ℕ ↪o ℕ, Monotone (f ∘ g) := partiallyWellOrderedOn_iff_exists_monotone_subseq -#align set.is_pwo_iff_exists_monotone_subseq Set.isPwo_iff_exists_monotone_subseq +#align set.is_pwo_iff_exists_monotone_subseq Set.isPWO_iff_exists_monotone_subseq -protected theorem IsPwo.isWf (h : s.IsPwo) : s.IsWf := by +protected theorem IsPWO.isWF (h : s.IsPWO) : s.IsWF := by simpa only [← lt_iff_le_not_le] using h.wellFoundedOn -#align set.is_pwo.is_wf Set.IsPwo.isWf +#align set.is_pwo.is_wf Set.IsPWO.isWF -nonrec theorem IsPwo.prod {t : Set β} (hs : s.IsPwo) (ht : t.IsPwo) : IsPwo (s ×ˢ t) := +nonrec theorem IsPWO.prod {t : Set β} (hs : s.IsPWO) (ht : t.IsPWO) : IsPWO (s ×ˢ t) := hs.prod ht -#align set.is_pwo.prod Set.IsPwo.prod +#align set.is_pwo.prod Set.IsPWO.prod -theorem IsPwo.image_of_monotoneOn (hs : s.IsPwo) {f : α → β} (hf : MonotoneOn f s) : - IsPwo (f '' s) := +theorem IsPWO.image_of_monotoneOn (hs : s.IsPWO) {f : α → β} (hf : MonotoneOn f s) : + IsPWO (f '' s) := hs.image_of_monotone_on hf -#align set.is_pwo.image_of_monotone_on Set.IsPwo.image_of_monotoneOn +#align set.is_pwo.image_of_monotone_on Set.IsPWO.image_of_monotoneOn -theorem IsPwo.image_of_monotone (hs : s.IsPwo) {f : α → β} (hf : Monotone f) : IsPwo (f '' s) := +theorem IsPWO.image_of_monotone (hs : s.IsPWO) {f : α → β} (hf : Monotone f) : IsPWO (f '' s) := hs.image_of_monotone_on (hf.monotoneOn _) -#align set.is_pwo.image_of_monotone Set.IsPwo.image_of_monotone +#align set.is_pwo.image_of_monotone Set.IsPWO.image_of_monotone -protected nonrec theorem IsPwo.union (hs : IsPwo s) (ht : IsPwo t) : IsPwo (s ∪ t) := +protected nonrec theorem IsPWO.union (hs : IsPWO s) (ht : IsPWO t) : IsPWO (s ∪ t) := hs.union ht -#align set.is_pwo.union Set.IsPwo.union +#align set.is_pwo.union Set.IsPWO.union @[simp] -theorem isPwo_union : IsPwo (s ∪ t) ↔ IsPwo s ∧ IsPwo t := +theorem isPWO_union : IsPWO (s ∪ t) ↔ IsPWO s ∧ IsPWO t := partiallyWellOrderedOn_union -#align set.is_pwo_union Set.isPwo_union +#align set.is_pwo_union Set.isPWO_union -protected theorem Finite.isPwo (hs : s.Finite) : IsPwo s := hs.partiallyWellOrderedOn -#align set.finite.is_pwo Set.Finite.isPwo +protected theorem Finite.isPWO (hs : s.Finite) : IsPWO s := hs.partiallyWellOrderedOn +#align set.finite.is_pwo Set.Finite.isPWO -@[simp] theorem isPwo_of_finite [Finite α] : s.IsPwo := s.toFinite.isPwo -#align set.is_pwo_of_finite Set.isPwo_of_finite +@[simp] theorem isPWO_of_finite [Finite α] : s.IsPWO := s.toFinite.isPWO +#align set.is_pwo_of_finite Set.isPWO_of_finite -@[simp] theorem isPwo_singleton (a : α) : IsPwo ({a} : Set α) := (finite_singleton a).isPwo -#align set.is_pwo_singleton Set.isPwo_singleton +@[simp] theorem isPWO_singleton (a : α) : IsPWO ({a} : Set α) := (finite_singleton a).isPWO +#align set.is_pwo_singleton Set.isPWO_singleton -@[simp] theorem isPwo_empty : IsPwo (∅ : Set α) := finite_empty.isPwo -#align set.is_pwo_empty Set.isPwo_empty +@[simp] theorem isPWO_empty : IsPWO (∅ : Set α) := finite_empty.isPWO +#align set.is_pwo_empty Set.isPWO_empty -protected theorem Subsingleton.isPwo (hs : s.Subsingleton) : IsPwo s := hs.finite.isPwo -#align set.subsingleton.is_pwo Set.Subsingleton.isPwo +protected theorem Subsingleton.isPWO (hs : s.Subsingleton) : IsPWO s := hs.finite.isPWO +#align set.subsingleton.is_pwo Set.Subsingleton.isPWO @[simp] -theorem isPwo_insert {a} : IsPwo (insert a s) ↔ IsPwo s := by - simp only [← singleton_union, isPwo_union, isPwo_singleton, true_and_iff] -#align set.is_pwo_insert Set.isPwo_insert +theorem isPWO_insert {a} : IsPWO (insert a s) ↔ IsPWO s := by + simp only [← singleton_union, isPWO_union, isPWO_singleton, true_and_iff] +#align set.is_pwo_insert Set.isPWO_insert -protected theorem IsPwo.insert (h : IsPwo s) (a : α) : IsPwo (insert a s) := - isPwo_insert.2 h -#align set.is_pwo.insert Set.IsPwo.insert +protected theorem IsPWO.insert (h : IsPWO s) (a : α) : IsPWO (insert a s) := + isPWO_insert.2 h +#align set.is_pwo.insert Set.IsPWO.insert -protected theorem Finite.isWf (hs : s.Finite) : IsWf s := hs.isPwo.isWf -#align set.finite.is_wf Set.Finite.isWf +protected theorem Finite.isWF (hs : s.Finite) : IsWF s := hs.isPWO.isWF +#align set.finite.is_wf Set.Finite.isWF -@[simp] theorem isWf_singleton {a : α} : IsWf ({a} : Set α) := (finite_singleton a).isWf -#align set.is_wf_singleton Set.isWf_singleton +@[simp] theorem isWF_singleton {a : α} : IsWF ({a} : Set α) := (finite_singleton a).isWF +#align set.is_wf_singleton Set.isWF_singleton -protected theorem Subsingleton.isWf (hs : s.Subsingleton) : IsWf s := hs.isPwo.isWf -#align set.subsingleton.is_wf Set.Subsingleton.isWf +protected theorem Subsingleton.isWF (hs : s.Subsingleton) : IsWF s := hs.isPWO.isWF +#align set.subsingleton.is_wf Set.Subsingleton.isWF @[simp] -theorem isWf_insert {a} : IsWf (insert a s) ↔ IsWf s := by - simp only [← singleton_union, isWf_union, isWf_singleton, true_and_iff] -#align set.is_wf_insert Set.isWf_insert +theorem isWF_insert {a} : IsWF (insert a s) ↔ IsWF s := by + simp only [← singleton_union, isWF_union, isWF_singleton, true_and_iff] +#align set.is_wf_insert Set.isWF_insert -protected theorem IsWf.insert (h : IsWf s) (a : α) : IsWf (insert a s) := - isWf_insert.2 h -#align set.is_wf.insert Set.IsWf.insert +protected theorem IsWF.insert (h : IsWF s) (a : α) : IsWF (insert a s) := + isWF_insert.2 h +#align set.is_wf.insert Set.IsWF.insert -end IsPwo +end IsPWO section WellFoundedOn @@ -520,7 +520,7 @@ variable {r : α → α → Prop} [IsStrictOrder α r] {s : Set α} {a : α} protected theorem Finite.wellFoundedOn (hs : s.Finite) : s.WellFoundedOn r := letI := partialOrderOfSO r - hs.isWf + hs.isWF #align set.finite.well_founded_on Set.Finite.wellFoundedOn @[simp] @@ -548,18 +548,18 @@ section LinearOrder variable [LinearOrder α] {s : Set α} -protected theorem IsWf.isPwo (hs : s.IsWf) : s.IsPwo := by +protected theorem IsWF.isPWO (hs : s.IsWF) : s.IsPWO := by intro f hf lift f to ℕ → s using hf rcases hs.has_min (range f) (range_nonempty _) with ⟨_, ⟨m, rfl⟩, hm⟩ simp only [forall_range_iff, not_lt] at hm exact ⟨m, m + 1, lt_add_one m, hm _⟩ -#align set.is_wf.is_pwo Set.IsWf.isPwo +#align set.is_wf.is_pwo Set.IsWF.isPWO -/-- In a linear order, the predicates `Set.IsWf` and `Set.IsPwo` are equivalent. -/ -theorem isWf_iff_isPwo : s.IsWf ↔ s.IsPwo := - ⟨IsWf.isPwo, IsPwo.isWf⟩ -#align set.is_wf_iff_is_pwo Set.isWf_iff_isPwo +/-- In a linear order, the predicates `Set.IsWF` and `Set.IsPWO` are equivalent. -/ +theorem isWF_iff_isPWO : s.IsWF ↔ s.IsPWO := + ⟨IsWF.isPWO, IsPWO.isWF⟩ +#align set.is_wf_iff_is_pwo Set.isWF_iff_isPWO end LinearOrder @@ -576,20 +576,20 @@ protected theorem partiallyWellOrderedOn [IsRefl α r] (s : Finset α) : #align finset.partially_well_ordered_on Finset.partiallyWellOrderedOn @[simp] -protected theorem isPwo [Preorder α] (s : Finset α) : Set.IsPwo (↑s : Set α) := +protected theorem isPWO [Preorder α] (s : Finset α) : Set.IsPWO (↑s : Set α) := s.partiallyWellOrderedOn -#align finset.is_pwo Finset.isPwo +#align finset.is_pwo Finset.isPWO @[simp] -protected theorem isWf [Preorder α] (s : Finset α) : Set.IsWf (↑s : Set α) := - s.finite_toSet.isWf -#align finset.is_wf Finset.isWf +protected theorem isWF [Preorder α] (s : Finset α) : Set.IsWF (↑s : Set α) := + s.finite_toSet.isWF +#align finset.is_wf Finset.isWF @[simp] protected theorem wellFoundedOn [IsStrictOrder α r] (s : Finset α) : Set.WellFoundedOn (↑s : Set α) r := letI := partialOrderOfSO r - s.isWf + s.isWF #align finset.well_founded_on Finset.wellFoundedOn theorem wellFoundedOn_sup [IsStrictOrder α r] (s : Finset ι) {f : ι → Set α} : @@ -602,15 +602,15 @@ theorem partiallyWellOrderedOn_sup (s : Finset ι) {f : ι → Set α} : Finset.cons_induction_on s (by simp) fun a s ha hs => by simp [-sup_set_eq_biUnion, hs] #align finset.partially_well_ordered_on_sup Finset.partiallyWellOrderedOn_sup -theorem isWf_sup [Preorder α] (s : Finset ι) {f : ι → Set α} : - (s.sup f).IsWf ↔ ∀ i ∈ s, (f i).IsWf := +theorem isWF_sup [Preorder α] (s : Finset ι) {f : ι → Set α} : + (s.sup f).IsWF ↔ ∀ i ∈ s, (f i).IsWF := s.wellFoundedOn_sup -#align finset.is_wf_sup Finset.isWf_sup +#align finset.is_wf_sup Finset.isWF_sup -theorem isPwo_sup [Preorder α] (s : Finset ι) {f : ι → Set α} : - (s.sup f).IsPwo ↔ ∀ i ∈ s, (f i).IsPwo := +theorem isPWO_sup [Preorder α] (s : Finset ι) {f : ι → Set α} : + (s.sup f).IsPWO ↔ ∀ i ∈ s, (f i).IsPWO := s.partiallyWellOrderedOn_sup -#align finset.is_pwo_sup Finset.isPwo_sup +#align finset.is_pwo_sup Finset.isPWO_sup @[simp] theorem wellFoundedOn_bUnion [IsStrictOrder α r] (s : Finset ι) {f : ι → Set α} : @@ -625,16 +625,16 @@ theorem partiallyWellOrderedOn_bUnion (s : Finset ι) {f : ι → Set α} : #align finset.partially_well_ordered_on_bUnion Finset.partiallyWellOrderedOn_bUnion @[simp] -theorem isWf_bUnion [Preorder α] (s : Finset ι) {f : ι → Set α} : - (⋃ i ∈ s, f i).IsWf ↔ ∀ i ∈ s, (f i).IsWf := +theorem isWF_bUnion [Preorder α] (s : Finset ι) {f : ι → Set α} : + (⋃ i ∈ s, f i).IsWF ↔ ∀ i ∈ s, (f i).IsWF := s.wellFoundedOn_bUnion -#align finset.is_wf_bUnion Finset.isWf_bUnion +#align finset.is_wf_bUnion Finset.isWF_bUnion @[simp] -theorem isPwo_bUnion [Preorder α] (s : Finset ι) {f : ι → Set α} : - (⋃ i ∈ s, f i).IsPwo ↔ ∀ i ∈ s, (f i).IsPwo := +theorem isPWO_bUnion [Preorder α] (s : Finset ι) {f : ι → Set α} : + (⋃ i ∈ s, f i).IsPWO ↔ ∀ i ∈ s, (f i).IsPWO := s.partiallyWellOrderedOn_bUnion -#align finset.is_pwo_bUnion Finset.isPwo_bUnion +#align finset.is_pwo_bUnion Finset.isPWO_bUnion end Finset @@ -644,24 +644,24 @@ section Preorder variable [Preorder α] {s : Set α} {a : α} -/-- `Set.IsWf.min` returns a minimal element of a nonempty well-founded set. -/ -noncomputable nonrec def IsWf.min (hs : IsWf s) (hn : s.Nonempty) : α := +/-- `Set.IsWF.min` returns a minimal element of a nonempty well-founded set. -/ +noncomputable nonrec def IsWF.min (hs : IsWF s) (hn : s.Nonempty) : α := hs.min univ (nonempty_iff_univ_nonempty.1 hn.to_subtype) -#align set.is_wf.min Set.IsWf.min +#align set.is_wf.min Set.IsWF.min -theorem IsWf.min_mem (hs : IsWf s) (hn : s.Nonempty) : hs.min hn ∈ s := +theorem IsWF.min_mem (hs : IsWF s) (hn : s.Nonempty) : hs.min hn ∈ s := (WellFounded.min hs univ (nonempty_iff_univ_nonempty.1 hn.to_subtype)).2 -#align set.is_wf.min_mem Set.IsWf.min_mem +#align set.is_wf.min_mem Set.IsWF.min_mem -nonrec theorem IsWf.not_lt_min (hs : IsWf s) (hn : s.Nonempty) (ha : a ∈ s) : ¬a < hs.min hn := +nonrec theorem IsWF.not_lt_min (hs : IsWF s) (hn : s.Nonempty) (ha : a ∈ s) : ¬a < hs.min hn := hs.not_lt_min univ (nonempty_iff_univ_nonempty.1 hn.to_subtype) (mem_univ (⟨a, ha⟩ : s)) -#align set.is_wf.not_lt_min Set.IsWf.not_lt_min +#align set.is_wf.not_lt_min Set.IsWF.not_lt_min @[simp] -theorem isWf_min_singleton (a) {hs : IsWf ({a} : Set α)} {hn : ({a} : Set α).Nonempty} : +theorem isWF_min_singleton (a) {hs : IsWF ({a} : Set α)} {hn : ({a} : Set α).Nonempty} : hs.min hn = a := - eq_of_mem_singleton (IsWf.min_mem hs hn) -#align set.is_wf_min_singleton Set.isWf_min_singleton + eq_of_mem_singleton (IsWF.min_mem hs hn) +#align set.is_wf_min_singleton Set.isWF_min_singleton end Preorder @@ -669,28 +669,28 @@ section LinearOrder variable [LinearOrder α] {s t : Set α} {a : α} -theorem IsWf.min_le (hs : s.IsWf) (hn : s.Nonempty) (ha : a ∈ s) : hs.min hn ≤ a := +theorem IsWF.min_le (hs : s.IsWF) (hn : s.Nonempty) (ha : a ∈ s) : hs.min hn ≤ a := le_of_not_lt (hs.not_lt_min hn ha) -#align set.is_wf.min_le Set.IsWf.min_le +#align set.is_wf.min_le Set.IsWF.min_le -theorem IsWf.le_min_iff (hs : s.IsWf) (hn : s.Nonempty) : a ≤ hs.min hn ↔ ∀ b, b ∈ s → a ≤ b := +theorem IsWF.le_min_iff (hs : s.IsWF) (hn : s.Nonempty) : a ≤ hs.min hn ↔ ∀ b, b ∈ s → a ≤ b := ⟨fun ha _b hb => le_trans ha (hs.min_le hn hb), fun h => h _ (hs.min_mem _)⟩ -#align set.is_wf.le_min_iff Set.IsWf.le_min_iff +#align set.is_wf.le_min_iff Set.IsWF.le_min_iff -theorem IsWf.min_le_min_of_subset {hs : s.IsWf} {hsn : s.Nonempty} {ht : t.IsWf} {htn : t.Nonempty} +theorem IsWF.min_le_min_of_subset {hs : s.IsWF} {hsn : s.Nonempty} {ht : t.IsWF} {htn : t.Nonempty} (hst : s ⊆ t) : ht.min htn ≤ hs.min hsn := - (IsWf.le_min_iff _ _).2 fun _b hb => ht.min_le htn (hst hb) -#align set.is_wf.min_le_min_of_subset Set.IsWf.min_le_min_of_subset + (IsWF.le_min_iff _ _).2 fun _b hb => ht.min_le htn (hst hb) +#align set.is_wf.min_le_min_of_subset Set.IsWF.min_le_min_of_subset -theorem IsWf.min_union (hs : s.IsWf) (hsn : s.Nonempty) (ht : t.IsWf) (htn : t.Nonempty) : +theorem IsWF.min_union (hs : s.IsWF) (hsn : s.Nonempty) (ht : t.IsWF) (htn : t.Nonempty) : (hs.union ht).min (union_nonempty.2 (Or.intro_left _ hsn)) = Min.min (hs.min hsn) (ht.min htn) := by - refine' le_antisymm (le_min (IsWf.min_le_min_of_subset (subset_union_left _ _)) - (IsWf.min_le_min_of_subset (subset_union_right _ _))) _ + refine' le_antisymm (le_min (IsWF.min_le_min_of_subset (subset_union_left _ _)) + (IsWF.min_le_min_of_subset (subset_union_right _ _))) _ rw [min_le_iff] exact ((mem_union _ _ _).1 ((hs.union ht).min_mem (union_nonempty.2 (.inl hsn)))).imp (hs.min_le _) (ht.min_le _) -#align set.is_wf.min_union Set.IsWf.min_union +#align set.is_wf.min_union Set.IsWF.min_union end LinearOrder @@ -812,22 +812,22 @@ theorem partiallyWellOrderedOn_sublistForall₂ (r : α → α → Prop) [IsRefl end Set.PartiallyWellOrderedOn -theorem WellFounded.isWf [LT α] (h : WellFounded ((· < ·) : α → α → Prop)) (s : Set α) : s.IsWf := - (Set.isWf_univ_iff.2 h).mono s.subset_univ -#align well_founded.is_wf WellFounded.isWf +theorem WellFounded.isWF [LT α] (h : WellFounded ((· < ·) : α → α → Prop)) (s : Set α) : s.IsWF := + (Set.isWF_univ_iff.2 h).mono s.subset_univ +#align well_founded.is_wf WellFounded.isWF /-- A version of **Dickson's lemma** any subset of functions `Π s : σ, α s` is partially well ordered, when `σ` is a `Fintype` and each `α s` is a linear well order. This includes the classical case of Dickson's lemma that `ℕ ^ n` is a well partial order. Some generalizations would be possible based on this proof, to include cases where the target is partially well ordered, and also to consider the case of `Set.PartiallyWellOrderedOn` instead of -`Set.IsPwo`. -/ -theorem Pi.isPwo {α : ι → Type*} [∀ i, LinearOrder (α i)] [∀ i, IsWellOrder (α i) (· < ·)] - [Finite ι] (s : Set (∀ i, α i)) : s.IsPwo := by +`Set.IsPWO`. -/ +theorem Pi.isPWO {α : ι → Type*} [∀ i, LinearOrder (α i)] [∀ i, IsWellOrder (α i) (· < ·)] + [Finite ι] (s : Set (∀ i, α i)) : s.IsPWO := by cases nonempty_fintype ι suffices ∀ (s : Finset ι) (f : ℕ → ∀ s, α s), ∃ g : ℕ ↪o ℕ, ∀ ⦃a b : ℕ⦄, a ≤ b → ∀ x, x ∈ s → (f ∘ g) a x ≤ (f ∘ g) b x by - refine isPwo_iff_exists_monotone_subseq.2 fun f _ => ?_ + refine isPWO_iff_exists_monotone_subseq.2 fun f _ => ?_ simpa only [Finset.mem_univ, true_imp_iff] using this Finset.univ f refine' Finset.cons_induction _ _ · intro f @@ -835,11 +835,11 @@ theorem Pi.isPwo {α : ι → Type*} [∀ i, LinearOrder (α i)] [∀ i, IsWellO simp only [IsEmpty.forall_iff, imp_true_iff, forall_const, Finset.not_mem_empty] · intro x s hx ih f obtain ⟨g, hg⟩ := - (IsWellFounded.wf.isWf univ).isPwo.exists_monotone_subseq (fun n => f n x) mem_univ + (IsWellFounded.wf.isWF univ).isPWO.exists_monotone_subseq (fun n => f n x) mem_univ obtain ⟨g', hg'⟩ := ih (f ∘ g) refine' ⟨g'.trans g, fun a b hab => (Finset.forall_mem_cons _ _).2 _⟩ exact ⟨hg (OrderHomClass.mono g' hab), hg' hab⟩ -#align pi.is_pwo Pi.isPwo +#align pi.is_pwo Pi.isPWO section ProdLex variable {rα : α → α → Prop} {rβ : β → β → Prop} {f : γ → α} {g : γ → β} {s : Set γ} diff --git a/Mathlib/Order/WithBot.lean b/Mathlib/Order/WithBot.lean index 7977e8b44fee8..bfa33337f27cd 100644 --- a/Mathlib/Order/WithBot.lean +++ b/Mathlib/Order/WithBot.lean @@ -7,6 +7,7 @@ import Mathlib.Logic.Nontrivial.Basic import Mathlib.Order.BoundedOrder import Mathlib.Data.Option.NAry import Mathlib.Tactic.Lift +import Mathlib.Data.Option.Basic #align_import order.with_bot from "leanprover-community/mathlib"@"0111834459f5d7400215223ea95ae38a1265a907" @@ -262,6 +263,13 @@ theorem unbot_le_iff {a : WithBot α} (h : a ≠ ⊥) {b : α} : match a, h with | some _, _ => simp only [unbot_coe, coe_le_coe] +theorem unbot'_le_iff {a : WithBot α} {b c : α} (h : a = ⊥ → b ≤ c) : + a.unbot' b ≤ c ↔ a ≤ c := by + induction a using recBotCoe + · simpa using h rfl + · simp +#align with_bot.unbot'_bot_le_iff WithBot.unbot'_le_iff + end LE section LT @@ -286,6 +294,7 @@ theorem none_lt_some (a : α) : @LT.lt (WithBot α) _ none (some a) := ⟨a, rfl, fun _ hb => (Option.not_mem_none _ hb).elim⟩ #align with_bot.none_lt_some WithBot.none_lt_some +@[simp] theorem bot_lt_coe (a : α) : (⊥ : WithBot α) < a := none_lt_some a #align with_bot.bot_lt_coe WithBot.bot_lt_coe @@ -300,7 +309,7 @@ theorem lt_iff_exists_coe : ∀ {a b : WithBot α}, a < b ↔ ∃ p : α, b = p | a, none => iff_of_false (not_lt_none _) <| by simp [none_eq_bot] #align with_bot.lt_iff_exists_coe WithBot.lt_iff_exists_coe -theorem lt_coe_iff : ∀ {x : WithBot α}, x < b ↔ ∀ a, x = ↑a → a < b +theorem lt_coe_iff : ∀ {x : WithBot α}, x < b ↔ ∀ a : α, x = ↑a → a < b | Option.some b => by simp [some_eq_coe, coe_eq_coe, coe_lt_coe] | none => by simp [none_eq_bot, bot_lt_coe] #align with_bot.lt_coe_iff WithBot.lt_coe_iff @@ -312,6 +321,12 @@ protected theorem bot_lt_iff_ne_bot : ∀ {x : WithBot α}, ⊥ < x ↔ x ≠ | (x : α) => by simp [bot_lt_coe] #align with_bot.bot_lt_iff_ne_bot WithBot.bot_lt_iff_ne_bot +theorem unbot'_lt_iff {a : WithBot α} {b c : α} (h : a = ⊥ → b < c) : + a.unbot' b < c ↔ a < c := by + induction a using recBotCoe + · simpa [bot_lt_coe] using h rfl + · simp + end LT instance preorder [Preorder α] : Preorder (WithBot α) where @@ -332,24 +347,24 @@ instance partialOrder [PartialOrder α] : PartialOrder (WithBot α) := cases' o₁ with a · cases' o₂ with b · rfl - rcases h₂ b rfl with ⟨_, ⟨⟩, _⟩ - · rcases h₁ a rfl with ⟨b, ⟨⟩, h₁'⟩ rcases h₂ b rfl with ⟨_, ⟨⟩, h₂'⟩ rw [le_antisymm h₁' h₂'] } #align with_bot.partial_order WithBot.partialOrder -theorem coe_strictMono [Preorder α] : StrictMono (fun (a : α) => (a : WithBot α)) := - fun _ _ => coe_lt_coe.2 +section Preorder + +variable [Preorder α] [Preorder β] + +theorem coe_strictMono : StrictMono (fun (a : α) => (a : WithBot α)) := fun _ _ => coe_lt_coe.2 #align with_bot.coe_strict_mono WithBot.coe_strictMono -theorem coe_mono [Preorder α] : Monotone (fun (a : α) => (a : WithBot α)) := - fun _ _ => coe_le_coe.2 +theorem coe_mono : Monotone (fun (a : α) => (a : WithBot α)) := fun _ _ => coe_le_coe.2 #align with_bot.coe_mono WithBot.coe_mono -theorem monotone_iff [Preorder α] [Preorder β] {f : WithBot α → β} : +theorem monotone_iff {f : WithBot α → β} : Monotone f ↔ Monotone (λ a => f a : α → β) ∧ ∀ x : α, f ⊥ ≤ f x := ⟨fun h => ⟨h.comp WithBot.coe_mono, fun _ => h bot_le⟩, fun h => WithBot.forall.2 @@ -359,28 +374,27 @@ theorem monotone_iff [Preorder α] [Preorder β] {f : WithBot α → β} : #align with_bot.monotone_iff WithBot.monotone_iff @[simp] -theorem monotone_map_iff [Preorder α] [Preorder β] {f : α → β} : - Monotone (WithBot.map f) ↔ Monotone f := +theorem monotone_map_iff {f : α → β} : Monotone (WithBot.map f) ↔ Monotone f := monotone_iff.trans <| by simp [Monotone] #align with_bot.monotone_map_iff WithBot.monotone_map_iff alias ⟨_, _root_.Monotone.withBot_map⟩ := monotone_map_iff #align monotone.with_bot_map Monotone.withBot_map -theorem strictMono_iff [Preorder α] [Preorder β] {f : WithBot α → β} : - StrictMono f ↔ StrictMono (λ a => f a : α → β) ∧ ∀ x : α, f ⊥ < f x := +theorem strictMono_iff {f : WithBot α → β} : + StrictMono f ↔ StrictMono (fun a => f a : α → β) ∧ ∀ x : α, f ⊥ < f x := ⟨fun h => ⟨h.comp WithBot.coe_strictMono, fun _ => h (bot_lt_coe _)⟩, fun h => WithBot.forall.2 ⟨WithBot.forall.2 ⟨flip absurd (lt_irrefl _), fun x _ => h.2 x⟩, fun _ => WithBot.forall.2 ⟨fun h => (not_lt_bot h).elim, fun _ hle => h.1 (coe_lt_coe.1 hle)⟩⟩⟩ #align with_bot.strict_mono_iff WithBot.strictMono_iff -theorem strictAnti_iff [Preorder α] [Preorder β] {f : WithBot α → β} : +theorem strictAnti_iff {f : WithBot α → β} : StrictAnti f ↔ StrictAnti (λ a => f a : α → β) ∧ ∀ x : α, f x < f ⊥ := strictMono_iff (β := βᵒᵈ) @[simp] -theorem strictMono_map_iff [Preorder α] [Preorder β] {f : α → β} : +theorem strictMono_map_iff {f : α → β} : StrictMono (WithBot.map f) ↔ StrictMono f := strictMono_iff.trans <| by simp [StrictMono, bot_lt_coe] #align with_bot.strict_mono_map_iff WithBot.strictMono_map_iff @@ -388,30 +402,24 @@ theorem strictMono_map_iff [Preorder α] [Preorder β] {f : α → β} : alias ⟨_, _root_.StrictMono.withBot_map⟩ := strictMono_map_iff #align strict_mono.with_bot_map StrictMono.withBot_map -theorem map_le_iff [Preorder α] [Preorder β] (f : α → β) (mono_iff : ∀ {a b}, f a ≤ f b ↔ a ≤ b) : +theorem map_le_iff (f : α → β) (mono_iff : ∀ {a b}, f a ≤ f b ↔ a ≤ b) : ∀ a b : WithBot α, a.map f ≤ b.map f ↔ a ≤ b | ⊥, _ => by simp only [map_bot, bot_le] | (a : α), ⊥ => by simp only [map_coe, map_bot, coe_ne_bot, not_coe_le_bot _] | (a : α), (b : α) => by simpa only [map_coe, coe_le_coe] using mono_iff #align with_bot.map_le_iff WithBot.map_le_iff -theorem le_coe_unbot' [Preorder α] : ∀ (a : WithBot α) (b : α), a ≤ a.unbot' b +theorem le_coe_unbot' : ∀ (a : WithBot α) (b : α), a ≤ a.unbot' b | (a : α), _ => le_rfl | ⊥, _ => bot_le #align with_bot.le_coe_unbot' WithBot.le_coe_unbot' -theorem unbot'_le_iff [LE α] {a : WithBot α} {b c : α} (h : a = ⊥ → b ≤ c) : - a.unbot' b ≤ c ↔ a ≤ c := by - cases a - · simpa using h rfl - · simp [some_eq_coe] -#align with_bot.unbot'_bot_le_iff WithBot.unbot'_le_iff +@[simp] +theorem lt_coe_bot [OrderBot α] : ∀ {x : WithBot α}, x < (⊥ : α) ↔ x = ⊥ + | (x : α) => by simp + | ⊥ => by simp -theorem unbot'_lt_iff [LT α] {a : WithBot α} {b c : α} (h : a = ⊥ → b < c) : - a.unbot' b < c ↔ a < c := by - cases a - · simpa [bot_lt_coe] using h rfl - · simp [some_eq_coe] +end Preorder instance semilatticeSup [SemilatticeSup α] : SemilatticeSup (WithBot α) := { WithBot.partialOrder, @WithBot.orderBot α _ with @@ -421,13 +429,10 @@ instance semilatticeSup [SemilatticeSup α] : SemilatticeSup (WithBot α) := sup_le := fun o₁ o₂ o₃ h₁ h₂ a ha => by cases' o₁ with b <;> cases' o₂ with c <;> cases ha · exact h₂ a rfl - · exact h₁ a rfl - · rcases h₁ b rfl with ⟨d, ⟨⟩, h₁'⟩ simp at h₂ - exact ⟨d, rfl, sup_le h₁' h₂⟩ - } + exact ⟨d, rfl, sup_le h₁' h₂⟩ } theorem coe_sup [SemilatticeSup α] (a b : α) : ((a ⊔ b : α) : WithBot α) = (a : WithBot α) ⊔ b := rfl @@ -519,6 +524,20 @@ instance instWellFoundedLT [LT α] [WellFoundedLT α] : WellFoundedLT (WithBot | (b : α), hlt => ih _ (some_lt_some.1 hlt) #align with_bot.well_founded_lt WithBot.instWellFoundedLT +instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where + wf := + have acc_some (a : α) : Acc ((· > ·) : WithBot α → WithBot α → Prop) a := + (wellFounded_gt.1 a).rec fun _ _ ih => + .intro _ fun + | (b : α), hlt => ih _ (coe_lt_coe.1 hlt) + | ⊥, hlt => absurd hlt (not_lt_none _) + .intro fun + | (a : α) => acc_some a + | ⊥ => .intro _ fun + | (b : α), _ => acc_some b + | ⊥, hlt => absurd hlt (not_lt_none _) +#align with_bot.well_founded_gt WithBot.instWellFoundedGT + instance denselyOrdered [LT α] [DenselyOrdered α] [NoMinOrder α] : DenselyOrdered (WithBot α) := ⟨fun a b => match a, b with @@ -904,6 +923,10 @@ theorem le_untop_iff {a : α} {b : WithTop α} (h : b ≠ ⊤) : a ≤ untop b h ↔ (a : WithTop α) ≤ b := @WithBot.unbot_le_iff αᵒᵈ _ _ _ _ +theorem le_untop'_iff {a : WithTop α} {b c : α} (h : a = ⊤ → c ≤ b) : + c ≤ a.untop' b ↔ c ≤ a := + WithBot.unbot'_le_iff (α := αᵒᵈ) h + end LE section LT @@ -943,6 +966,10 @@ theorem ofDual_lt_ofDual_iff {a b : WithTop αᵒᵈ} : WithTop.ofDual a < WithT Iff.rfl #align with_top.of_dual_lt_of_dual_iff WithTop.ofDual_lt_ofDual_iff +theorem lt_untop'_iff {a : WithTop α} {b c : α} (h : a = ⊤ → c < b) : + c < a.untop' b ↔ c < a := + WithBot.unbot'_lt_iff (α := αᵒᵈ) h + end LT end WithTop @@ -1093,6 +1120,7 @@ theorem some_lt_some : @LT.lt (WithTop α) _ (Option.some a) (Option.some b) ↔ coe_lt_coe #align with_top.some_lt_some WithTop.some_lt_some +@[simp] theorem coe_lt_top (a : α) : (a : WithTop α) < ⊤ := by simp [← toDual_lt_toDual_iff, WithBot.bot_lt_coe] #align with_top.coe_lt_top WithTop.coe_lt_top @@ -1113,7 +1141,8 @@ theorem lt_iff_exists_coe {a b : WithTop α} : a < b ↔ ∃ p : α, a = p ∧ exact exists_congr fun _ => and_congr_left' Iff.rfl #align with_top.lt_iff_exists_coe WithTop.lt_iff_exists_coe -theorem coe_lt_iff {x : WithTop α} : ↑a < x ↔ ∀ b, x = ↑b → a < b := by simp +theorem coe_lt_iff {x : WithTop α} : ↑a < x ↔ ∀ b : α, x = ↑b → a < b := + WithBot.lt_coe_iff (α := αᵒᵈ) #align with_top.coe_lt_iff WithTop.coe_lt_iff /-- A version of `lt_top_iff_ne_top` for `WithTop` that only requires `LT α`, not @@ -1127,28 +1156,25 @@ end LT instance preorder [Preorder α] : Preorder (WithTop α) where le := (· ≤ ·) lt := (· < ·) - lt_iff_le_not_le := by simp [← toDual_lt_toDual_iff, lt_iff_le_not_le] - le_refl _ := toDual_le_toDual_iff.mp le_rfl - le_trans _ _ _ := by - simp_rw [← toDual_le_toDual_iff] - exact Function.swap le_trans + lt_iff_le_not_le := @lt_iff_le_not_le (WithBot αᵒᵈ)ᵒᵈ _ + le_refl := @le_refl (WithBot αᵒᵈ)ᵒᵈ _ + le_trans := @le_trans (WithBot αᵒᵈ)ᵒᵈ _ -instance partialOrder [PartialOrder α] : PartialOrder (WithTop α) := - { WithTop.preorder with - le_antisymm := fun _ _ => by - simp_rw [← toDual_le_toDual_iff] - exact Function.swap le_antisymm } +instance partialOrder [PartialOrder α] : PartialOrder (WithTop α) where + le_antisymm := @le_antisymm (WithBot αᵒᵈ)ᵒᵈ _ #align with_top.partial_order WithTop.partialOrder -theorem coe_strictMono [Preorder α] : StrictMono (fun a : α => (a : WithTop α)) := - fun _ _ => some_lt_some.2 +section Preorder + +variable [Preorder α] [Preorder β] + +theorem coe_strictMono : StrictMono (fun a : α => (a : WithTop α)) := fun _ _ => some_lt_some.2 #align with_top.coe_strict_mono WithTop.coe_strictMono -theorem coe_mono [Preorder α] : Monotone (fun a : α => (a : WithTop α)) := - fun _ _ => coe_le_coe.2 +theorem coe_mono : Monotone (fun a : α => (a : WithTop α)) := fun _ _ => coe_le_coe.2 #align with_top.coe_mono WithTop.coe_mono -theorem monotone_iff [Preorder α] [Preorder β] {f : WithTop α → β} : +theorem monotone_iff {f : WithTop α → β} : Monotone f ↔ Monotone (fun (a : α) => f a) ∧ ∀ x : α, f x ≤ f ⊤ := ⟨fun h => ⟨h.comp WithTop.coe_mono, fun _ => h le_top⟩, fun h => WithTop.forall.2 @@ -1157,15 +1183,14 @@ theorem monotone_iff [Preorder α] [Preorder β] {f : WithTop α → β} : #align with_top.monotone_iff WithTop.monotone_iff @[simp] -theorem monotone_map_iff [Preorder α] [Preorder β] {f : α → β} : - Monotone (WithTop.map f) ↔ Monotone f := +theorem monotone_map_iff {f : α → β} : Monotone (WithTop.map f) ↔ Monotone f := monotone_iff.trans <| by simp [Monotone] #align with_top.monotone_map_iff WithTop.monotone_map_iff alias ⟨_, _root_.Monotone.withTop_map⟩ := monotone_map_iff #align monotone.with_top_map Monotone.withTop_map -theorem strictMono_iff [Preorder α] [Preorder β] {f : WithTop α → β} : +theorem strictMono_iff {f : WithTop α → β} : StrictMono f ↔ StrictMono (fun (a : α) => f a) ∧ ∀ x : α, f x < f ⊤ := ⟨fun h => ⟨h.comp WithTop.coe_strictMono, fun _ => h (coe_lt_top _)⟩, fun h => WithTop.forall.2 @@ -1173,57 +1198,40 @@ theorem strictMono_iff [Preorder α] [Preorder β] {f : WithTop α → β} : WithTop.forall.2 ⟨fun _ => h.2 x, fun _ hle => h.1 (coe_lt_coe.1 hle)⟩⟩⟩ #align with_top.strict_mono_iff WithTop.strictMono_iff -theorem strictAnti_iff [Preorder α] [Preorder β] {f : WithTop α → β} : +theorem strictAnti_iff {f : WithTop α → β} : StrictAnti f ↔ StrictAnti (λ a => f a : α → β) ∧ ∀ x : α, f ⊤ < f x := strictMono_iff (β := βᵒᵈ) @[simp] -theorem strictMono_map_iff [Preorder α] [Preorder β] {f : α → β} : - StrictMono (WithTop.map f) ↔ StrictMono f := +theorem strictMono_map_iff {f : α → β} : StrictMono (WithTop.map f) ↔ StrictMono f := strictMono_iff.trans <| by simp [StrictMono, coe_lt_top] #align with_top.strict_mono_map_iff WithTop.strictMono_map_iff alias ⟨_, _root_.StrictMono.withTop_map⟩ := strictMono_map_iff #align strict_mono.with_top_map StrictMono.withTop_map -theorem map_le_iff [Preorder α] [Preorder β] (f : α → β) (a b : WithTop α) +theorem map_le_iff (f : α → β) (a b : WithTop α) (mono_iff : ∀ {a b}, f a ≤ f b ↔ a ≤ b) : a.map f ≤ b.map f ↔ a ≤ b := by erw [← toDual_le_toDual_iff, toDual_map, toDual_map, WithBot.map_le_iff, toDual_le_toDual_iff] simp [mono_iff] #align with_top.map_le_iff WithTop.map_le_iff -theorem coe_untop'_le [Preorder α] : ∀ (a : WithTop α) (b : α), a.untop' b ≤ a - | (a : α), _ => le_rfl - | ⊤, _ => le_top +theorem coe_untop'_le (a : WithTop α) (b : α) : a.untop' b ≤ a := + WithBot.le_coe_unbot' (α := αᵒᵈ) a b -theorem le_untop'_iff [LE α] {a : WithTop α} {b c : α} (h : a = ⊤ → c ≤ b) : - c ≤ a.untop' b ↔ c ≤ a := by - cases a - · simpa using h rfl - · simp [some_eq_coe] +@[simp] +theorem coe_top_lt [OrderTop α] {x : WithTop α} : (⊤ : α) < x ↔ x = ⊤ := + WithBot.lt_coe_bot (α := αᵒᵈ) -theorem lt_untop'_iff [LT α] {a : WithTop α} {b c : α} (h : a = ⊤ → c < b) : - c < a.untop' b ↔ c < a := by - cases a - · simpa [none_eq_top, coe_lt_top] using h rfl - · simp [some_eq_coe] +end Preorder instance semilatticeInf [SemilatticeInf α] : SemilatticeInf (WithTop α) := { WithTop.partialOrder with inf := Option.liftOrGet (· ⊓ ·), - inf_le_left := fun o₁ o₂ a ha => by cases ha; cases o₂ <;> simp [Option.liftOrGet], - inf_le_right := fun o₁ o₂ a ha => by cases ha; cases o₁ <;> simp [Option.liftOrGet], - le_inf := fun o₁ o₂ o₃ h₁ h₂ a ha => by - cases' o₂ with b <;> cases' o₃ with c <;> cases ha - · exact h₂ a rfl - - · exact h₁ a rfl - - · rcases h₁ b rfl with ⟨d, ⟨⟩, h₁'⟩ - simp at h₂ - exact ⟨d, rfl, le_inf h₁' h₂⟩ - } + inf_le_left := @inf_le_left (WithBot αᵒᵈ)ᵒᵈ _ + inf_le_right := @inf_le_right (WithBot αᵒᵈ)ᵒᵈ _ + le_inf := @le_inf (WithBot αᵒᵈ)ᵒᵈ _ } theorem coe_inf [SemilatticeInf α] (a b : α) : ((a ⊓ b : α) : WithTop α) = (a : WithTop α) ⊓ b := rfl @@ -1232,17 +1240,9 @@ theorem coe_inf [SemilatticeInf α] (a b : α) : ((a ⊓ b : α) : WithTop α) = instance semilatticeSup [SemilatticeSup α] : SemilatticeSup (WithTop α) := { WithTop.partialOrder with sup := Option.map₂ (· ⊔ ·), - le_sup_left := fun o₁ o₂ a ha => by - rcases Option.mem_map₂_iff.1 ha with ⟨a, b, (rfl : _ = _), (rfl : _ = _), rfl⟩ - exact ⟨_, rfl, le_sup_left⟩, - le_sup_right := fun o₁ o₂ a ha => by - rcases Option.mem_map₂_iff.1 ha with ⟨a, b, (rfl : _ = _), (rfl : _ = _), rfl⟩ - exact ⟨_, rfl, le_sup_right⟩, - sup_le := fun o₁ o₂ o₃ h₁ h₂ a ha => by - cases ha - rcases h₁ a rfl with ⟨b, ⟨⟩, ab⟩ - rcases h₂ a rfl with ⟨c, ⟨⟩, ac⟩ - exact ⟨_, rfl, sup_le ab ac⟩ } + le_sup_left := @le_sup_left (WithBot αᵒᵈ)ᵒᵈ _ + le_sup_right := @le_sup_right (WithBot αᵒᵈ)ᵒᵈ _ + sup_le := @sup_le (WithBot αᵒᵈ)ᵒᵈ _ } theorem coe_sup [SemilatticeSup α] (a b : α) : ((a ⊔ b : α) : WithTop α) = (a : WithTop α) ⊔ b := rfl @@ -1253,13 +1253,7 @@ instance lattice [Lattice α] : Lattice (WithTop α) := instance distribLattice [DistribLattice α] : DistribLattice (WithTop α) := { WithTop.lattice with - le_sup_inf := fun o₁ o₂ o₃ => - match o₁, o₂, o₃ with - | ⊤, _, _ => le_rfl - | (a₁ : α), ⊤, ⊤ => le_rfl - | (a₁ : α), ⊤, (a₃ : α) => le_rfl - | (a₁ : α), (a₂ : α), ⊤ => le_rfl - | (a₁ : α), (a₂ : α), (a₃ : α) => coe_le_coe.mpr le_sup_inf } + le_sup_inf := @le_sup_inf (WithBot αᵒᵈ)ᵒᵈ _ } -- porting note: added, previously this was found via unfolding `WithTop` instance decidableEq [DecidableEq α] : DecidableEq (WithTop α) := instDecidableEqOption @@ -1294,47 +1288,16 @@ theorem coe_max [LinearOrder α] (x y : α) : (↑(max x y) : WithTop α) = max rfl #align with_top.coe_max WithTop.coe_max -instance instWellFoundedLT [LT α] [WellFoundedLT α] : WellFoundedLT (WithTop α) where - wf := - have not_top_lt : ∀ a : WithTop α, ¬ ⊤ < a := (fun.) - have acc_some (a : α) : Acc ((· < ·) : WithTop α → WithTop α → Prop) a := - (wellFounded_lt.1 a).rec fun _ _ ih => - .intro _ fun - | (b : α), hlt => ih _ (some_lt_some.1 hlt) - | ⊤, hlt => nomatch not_top_lt _ hlt - .intro fun - | (a : α) => acc_some a - | ⊤ => .intro _ fun - | (b : α), _ => acc_some b - | ⊤, hlt => nomatch not_top_lt _ hlt +instance instWellFoundedLT [LT α] [WellFoundedLT α] : WellFoundedLT (WithTop α) := + inferInstanceAs <| WellFoundedLT (WithBot αᵒᵈ)ᵒᵈ #align with_top.well_founded_lt WithTop.instWellFoundedLT open OrderDual -instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) where - wf := ⟨fun a => by - -- ideally, use RelHomClass.acc, but that is defined later - have : Acc (· < ·) (WithTop.toDual a) := wellFounded_lt.apply _ - revert this - generalize ha : WithBot.toDual a = b - intro ac - induction' ac with _ H IH generalizing a - subst ha - exact ⟨_, fun a' h => IH (WithTop.toDual a') (toDual_lt_toDual.mpr h) _ rfl⟩⟩ +instance instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithTop α) := + inferInstanceAs <| WellFoundedGT (WithBot αᵒᵈ)ᵒᵈ #align with_top.well_founded_gt WithTop.instWellFoundedGT -instance _root_.WithBot.instWellFoundedGT [LT α] [WellFoundedGT α] : WellFoundedGT (WithBot α) where - wf := ⟨fun a => by - -- ideally, use RelHomClass.acc, but that is defined later - have : Acc (· < ·) (WithBot.toDual a) := wellFounded_lt.apply _ - revert this - generalize ha : WithBot.toDual a = b - intro ac - induction' ac with _ H IH generalizing a - subst ha - exact ⟨_, fun a' h => IH (WithBot.toDual a') (toDual_lt_toDual.mpr h) _ rfl⟩⟩ -#align with_bot.well_founded_gt WithBot.instWellFoundedGT - instance trichotomous.lt [Preorder α] [IsTrichotomous α (· < ·)] : IsTrichotomous (WithTop α) (· < ·) := ⟨by diff --git a/Mathlib/Probability/Cdf.lean b/Mathlib/Probability/Cdf.lean index 7016f399cdbfc..e67943ae3cac2 100644 --- a/Mathlib/Probability/Cdf.lean +++ b/Mathlib/Probability/Cdf.lean @@ -15,11 +15,11 @@ Two probability measures are equal if and only if they have the same cdf. ## Main definitions * `ProbabilityTheory.cdf μ`: cumulative distribution function of `μ : Measure ℝ`, defined as the - conditional cdf (`ProbabilityTheory.condCdf`) of the product measure + conditional cdf (`ProbabilityTheory.condCDF`) of the product measure `(Measure.dirac Unit.unit).prod μ` evaluated at `Unit.unit`. The definition could be replaced by the more elementary `cdf μ x = (μ (Iic x)).toReal`, but using -`condCdf` gives us access to its API, from which most properties of the cdf follow directly. +`condCDF` gives us access to its API, from which most properties of the cdf follow directly. ## Main statements @@ -30,11 +30,11 @@ The definition could be replaced by the more elementary `cdf μ x = (μ (Iic x)) ## TODO -The definition could be extended to a finite measure by rescaling `condCdf`, but it would be nice +The definition could be extended to a finite measure by rescaling `condCDF`, but it would be nice to have more structure on Stieltjes functions first. Right now, if `f` is a Stieltjes function, `2 • f` makes no sense. We could define Stieltjes functions as a submodule. -The definition could be extended to `ℝⁿ`, either by extending the definition of `condCdf`, or by +The definition could be extended to `ℝⁿ`, either by extending the definition of `condCDF`, or by using another construction here. -/ @@ -49,29 +49,29 @@ for probability measures. In that case, it satisfies `cdf μ x = (μ (Iic x)).to `ProbabilityTheory.cdf_eq_toReal`). -/ noncomputable def cdf (μ : Measure ℝ) : StieltjesFunction := - condCdf ((Measure.dirac Unit.unit).prod μ) Unit.unit + condCDF ((Measure.dirac Unit.unit).prod μ) Unit.unit section ExplicitMeasureArg variable (μ : Measure ℝ) /-- The cdf is non-negative. -/ -lemma cdf_nonneg (x : ℝ) : 0 ≤ cdf μ x := condCdf_nonneg _ _ _ +lemma cdf_nonneg (x : ℝ) : 0 ≤ cdf μ x := condCDF_nonneg _ _ _ /-- The cdf is lower or equal to 1. -/ -lemma cdf_le_one (x : ℝ) : cdf μ x ≤ 1 := condCdf_le_one _ _ _ +lemma cdf_le_one (x : ℝ) : cdf μ x ≤ 1 := condCDF_le_one _ _ _ /-- The cdf is monotone. -/ -lemma monotone_cdf : Monotone (cdf μ) := (condCdf _ _).mono +lemma monotone_cdf : Monotone (cdf μ) := (condCDF _ _).mono /-- The cdf tends to 0 at -∞. -/ -lemma tendsto_cdf_atBot : Tendsto (cdf μ) atBot (𝓝 0) := tendsto_condCdf_atBot _ _ +lemma tendsto_cdf_atBot : Tendsto (cdf μ) atBot (𝓝 0) := tendsto_condCDF_atBot _ _ /-- The cdf tends to 1 at +∞. -/ -lemma tendsto_cdf_atTop : Tendsto (cdf μ) atTop (𝓝 1) := tendsto_condCdf_atTop _ _ +lemma tendsto_cdf_atTop : Tendsto (cdf μ) atTop (𝓝 1) := tendsto_condCDF_atTop _ _ lemma ofReal_cdf [IsProbabilityMeasure μ] (x : ℝ) : ENNReal.ofReal (cdf μ x) = μ (Iic x) := by have := IsProbabilityMeasure.toIsFiniteMeasure (Measure.prod (Measure.dirac ()) μ) - have h := lintegral_condCdf ((Measure.dirac Unit.unit).prod μ) x + have h := lintegral_condCDF ((Measure.dirac Unit.unit).prod μ) x simpa only [MeasureTheory.Measure.fst_prod, Measure.prod_prod, measure_univ, one_mul, lintegral_dirac] using h diff --git a/Mathlib/Probability/Distributions/Exponential.lean b/Mathlib/Probability/Distributions/Exponential.lean index 034cb4c4b1d1d..ff401925d6a9c 100644 --- a/Mathlib/Probability/Distributions/Exponential.lean +++ b/Mathlib/Probability/Distributions/Exponential.lean @@ -3,182 +3,139 @@ Copyright (c) 2023 Claus Clausen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Claus Clausen, Patrick Massot -/ - -import Mathlib.Analysis.SpecialFunctions.Gaussian import Mathlib.Probability.Notation import Mathlib.Probability.Cdf import Mathlib.Probability.Distributions.Gamma /-! # Exponential distributions over ℝ -Define the Exponential Measure over the Reals +Define the Exponential measure over the reals. ## Main definitions -* `exponentialPdfReal`: the function `r x ↦ r * (Real.exp (-(r * ↑x))` for `0 ≤ x` +* `exponentialPDFReal`: the function `r x ↦ r * exp (-(r * x)` for `0 ≤ x` or `0` else, which is the probability density function of a exponential distribution with rate `r` (when `hr : 0 < r`). -* `exponentialPdf`: `ℝ≥0∞`-valued pdf, - `exponentialPdf r = ENNReal.ofReal (exponentialPdfReal r)`. +* `exponentialPDF`: `ℝ≥0∞`-valued pdf, + `exponentialPDF r = ENNReal.ofReal (exponentialPDFReal r)`. * `expMeasure`: an exponential measure on `ℝ`, parametrized by its rate `r`. -* `exponentialCdfReal`: the Cdf given by the Definition of CDF in `ProbabilityTheory.Cdf` on +* `exponentialCDFReal`: the CDF given by the definition of CDF in `ProbabilityTheory.CDF` applied to + the exponential measure. ## Main results -* `exponentialCdfReal_eq`: Proof that the `exponentialCdfReal` given by the Definition equals the - known function given as `r x ↦ 1 - (Real.exp (-(r * ↑x))` for `0 ≤ x` or `0` else. +* `exponentialCDFReal_eq`: Proof that the `exponentialCDFReal` given by the definition equals the + known function given as `r x ↦ 1 - exp (- (r * x))` for `0 ≤ x` or `0` else. -/ -open scoped ENNReal NNReal Real +open scoped ENNReal NNReal open MeasureTheory Real Set Filter Topology -lemma lintegral_eq_lintegral_Ici_add_Iio (f : ℝ → ℝ≥0∞) (c : ℝ) : - ∫⁻ x, f x = (∫⁻ x in Ici c, f x) + ∫⁻ x in Iio c, f x := by - rw [← lintegral_add_compl f (measurableSet_Ici (a := c)), compl_Ici] - namespace ProbabilityTheory -section ExponentialPdf +section ExponentialPDF -/-- Define the PDF of the exponential distribution depending on its rate-/ +/-- The pdf of the exponential distribution depending on its rate -/ noncomputable -def exponentialPdfReal (r x : ℝ) : ℝ := - if 0 ≤ x then r * exp (-(r * x)) else 0 +def exponentialPDFReal (r x : ℝ) : ℝ := + gammaPDFReal 1 r x -/-- The PDF of the exponential Distribution on the extended real Numbers-/ +/-- The pdf of the exponential distribution, as a function valued in `ℝ≥0∞` -/ noncomputable -def exponentialPdf (r x : ℝ) : ℝ≥0∞ := - ENNReal.ofReal (exponentialPdfReal r x) +def exponentialPDF (r x : ℝ) : ℝ≥0∞ := + ENNReal.ofReal (exponentialPDFReal r x) -lemma exponentialPdf_eq (r x : ℝ) : - exponentialPdf r x = ENNReal.ofReal (if 0 ≤ x then r * exp (-(r * x)) else 0) := rfl +lemma exponentialPDF_eq (r x : ℝ) : + exponentialPDF r x = ENNReal.ofReal (if 0 ≤ x then r * exp (-(r * x)) else 0) := by + rw [exponentialPDF, exponentialPDFReal, gammaPDFReal] + simp only [rpow_one, Gamma_one, div_one, sub_self, rpow_zero, mul_one] -lemma exponentialPdf_of_neg {r x : ℝ} (hx : x < 0) : exponentialPdf r x = 0 := by - simp only [exponentialPdf_eq, if_neg (not_le.mpr hx), ENNReal.ofReal_zero] +lemma exponentialPDF_of_neg {r x : ℝ} (hx : x < 0) : exponentialPDF r x = 0 := gammaPDF_of_neg hx -lemma exponentialPdf_of_nonneg {r x : ℝ} (hx : 0 ≤ x) : - exponentialPdf r x = ENNReal.ofReal (r * rexp (-(r * x))) := by - simp only [exponentialPdf_eq, if_pos hx] +lemma exponentialPDF_of_nonneg {r x : ℝ} (hx : 0 ≤ x) : + exponentialPDF r x = ENNReal.ofReal (r * rexp (-(r * x))) := by + simp only [exponentialPDF_eq, if_pos hx] -lemma hasDerivAt_exp_neg {r x : ℝ} (hr : 0 < r) : - HasDerivAt (fun a ↦ -1/r * exp (-(r * a))) (exp (-(r * x))) x := by - convert (((hasDerivAt_id x).const_mul (-r)).exp.const_mul (-1/r)) using 1 <;> field_simp +/-- The Lebesgue integral of the exponential pdf over nonpositive reals equals 0-/ +lemma lintegral_exponentialPDF_of_nonpos {x r : ℝ} (hx : x ≤ 0) : + ∫⁻ y in Iio x, exponentialPDF r y = 0 := lintegral_gammaPDF_of_nonpos hx -lemma hasDerivAt_neg_exp_mul_exp {r x : ℝ} : - HasDerivAt (fun a ↦ -exp (-(r * a))) (r * exp (-(r * x))) x := by - convert (((hasDerivAt_id x).const_mul (-r)).exp.const_mul (-1)) using 1 - · simp only [one_mul, id_eq, neg_mul] - simp only [id_eq, neg_mul, mul_one, mul_neg, one_mul, neg_neg, mul_comm] +/-- The exponential pdf is measurable. -/ +@[measurability] +lemma measurable_exponentialPDFReal (r : ℝ) : Measurable (exponentialPDFReal r) := + measurable_gammaPDFReal 1 r -/-- the Lebesgue-Integral of the exponential PDF over nonpositive Reals equals 0-/ -lemma lintegral_exponentialPdf_of_nonpos {x r : ℝ} (hx : x ≤ 0) : - ∫⁻ y in Iio x, exponentialPdf r y = 0 := by - rw [set_lintegral_congr_fun (g := fun _ ↦ 0) measurableSet_Iio] - · rw [lintegral_zero, ← ENNReal.ofReal_zero] - · simp only [exponentialPdf_eq, ge_iff_le, ENNReal.ofReal_eq_zero] - apply ae_of_all _ fun a (_ : a < _) ↦ by rw [if_neg (by linarith)] +-- The exponential pdf is strongly measurable -/ +@[measurability] + lemma stronglyMeasurable_exponentialPDFReal (r : ℝ) : + StronglyMeasurable (exponentialPDFReal r) := stronglyMeasurable_gammaPDFReal 1 r -/-- The exponential pdf is measurable. -/ -lemma measurable_exponentialPdfReal (r : ℝ) : - Measurable (exponentialPdfReal r) := by - refine Measurable.ite ?hp ((measurable_id'.const_mul r).neg.exp.const_mul r) ?hg - · exact measurableSet_Ici - · exact measurable_const - -/-- The exponential Pdf is strongly measurable -/ -lemma stronglyMeasurable_exponentialPdfReal (r : ℝ) : - StronglyMeasurable (exponentialPdfReal r) := - (measurable_exponentialPdfReal r).stronglyMeasurable - -/-- the exponential Pdf is positive for all positive reals-/ -lemma exponentialPdfReal_pos {x r : ℝ} {hr : 0 < r} (hx : 0 < x) : - 0 < exponentialPdfReal r x := by - simp only [exponentialPdfReal, if_pos hx.le] - positivity - -/-- The exponential Pdf is nonnegative-/ -lemma exponentialPdfReal_nonneg {r : ℝ} (hr : 0 < r) (x : ℝ) : - 0 ≤ exponentialPdfReal r x := by - unfold exponentialPdfReal; split_ifs <;> positivity - -/-- A negative exponential function is integrable on Intervals in R≥0 -/ -lemma exp_neg_integrableOn_Ioc {b x : ℝ} (hb : 0 < b) : - IntegrableOn (fun x ↦ rexp (-(b * x))) (Ioc 0 x) := by - simp only [neg_mul_eq_neg_mul] - exact (exp_neg_integrableOn_Ioi _ hb).mono_set Ioc_subset_Ioi_self +/-- The exponential pdf is positive for all positive reals -/ +lemma exponentialPDFReal_pos {x r : ℝ} (hr : 0 < r) (hx : 0 < x) : + 0 < exponentialPDFReal r x := gammaPDFReal_pos zero_lt_one hr hx + +/-- The exponential pdf is nonnegative-/ +lemma exponentialPDFReal_nonneg {r : ℝ} (hr : 0 < r) (x : ℝ) : + 0 ≤ exponentialPDFReal r x := gammaPDFReal_nonneg zero_lt_one hr x open Measure -/-- The Pdf of the exponential Distribution integrates to 1-/ +/-- The pdf of the exponential distribution integrates to 1 -/ @[simp] -lemma lintegral_exponentialPdf_eq_one (r : ℝ) (hr : 0 < r) : ∫⁻ x, exponentialPdf r x = 1 := by - rw [lintegral_eq_lintegral_Ici_add_Iio (exponentialPdf r) 0, ← ENNReal.toReal_eq_one_iff] - have leftSide : ∫⁻ x in Iio 0, exponentialPdf r x = 0 := by - rw [set_lintegral_congr_fun measurableSet_Iio - (ae_of_all _ (fun x (hx : x < 0) ↦ exponentialPdf_of_neg hx)), lintegral_zero] - have rightSide : - ∫⁻ x in Ici 0, exponentialPdf r x = ∫⁻ x in Ici 0, ENNReal.ofReal (r * rexp (-(r * x))) := - set_lintegral_congr_fun isClosed_Ici.measurableSet - (ae_of_all _ (fun x (hx : 0 ≤ x) ↦ exponentialPdf_of_nonneg hx)) - simp only [leftSide, add_zero] - rw [rightSide, ENNReal.toReal_eq_one_iff, ← ENNReal.toReal_eq_one_iff] - rw [← integral_eq_lintegral_of_nonneg_ae (ae_of_all _ (fun _ ↦ by positivity))] - · have integrOn : IntegrableOn (fun x ↦ rexp (-(r * x))) (Ioi 0) := by - simp only [← neg_mul, exp_neg_integrableOn_Ioi 0 hr] - rw [integral_mul_left, integral_Ici_eq_integral_Ioi, - integral_Ioi_of_hasDerivAt_of_tendsto' (m := 0) (fun _ _ ↦ hasDerivAt_exp_neg hr) integrOn] - · field_simp - · rw [← mul_zero (-1/r)] - exact tendsto_const_nhds.mul (tendsto_exp_neg_atTop_nhds_0.comp - ((tendsto_const_mul_atTop_of_pos hr).2 tendsto_id)) - · exact ((measurable_id'.const_mul r).neg.exp.const_mul r).stronglyMeasurable.aestronglyMeasurable - -end ExponentialPdf +lemma lintegral_exponentialPDF_eq_one {r : ℝ} (hr : 0 < r) : ∫⁻ x, exponentialPDF r x = 1 := + lintegral_gammaPDF_eq_one zero_lt_one hr + +end ExponentialPDF open MeasureTheory -/-- Measure defined by the exponential Distribution -/ +/-- Measure defined by the exponential distribution -/ noncomputable -def expMeasure (r : ℝ) : Measure ℝ := - volume.withDensity (exponentialPdf r) +def expMeasure (r : ℝ) : Measure ℝ := gammaMeasure 1 r -instance instIsProbabilityMeasureExponential (r : ℝ) [Fact (0 < r)] : - IsProbabilityMeasure (expMeasure r) where - measure_univ := by simp [expMeasure, lintegral_exponentialPdf_eq_one r Fact.out] +lemma isProbabilityMeasureExponential {r : ℝ} (hr : 0 < r) : + IsProbabilityMeasure (expMeasure r) := isProbabilityMeasureGamma zero_lt_one hr -section ExponentialCdf +section ExponentialCDF -/-- CDF of the exponential Distribution -/ +/-- CDF of the exponential distribution -/ noncomputable -def exponentialCdfReal (r : ℝ) : StieltjesFunction := +def exponentialCDFReal (r : ℝ) : StieltjesFunction := cdf (expMeasure r) -lemma exponentialCdfReal_eq_integral (r x : ℝ) [Fact (0 < r)] : - exponentialCdfReal r x = ∫ x in Iic x, exponentialPdfReal r x := by - rw [exponentialCdfReal,cdf_eq_toReal] - simp only [expMeasure, measurableSet_Iic, withDensity_apply] - rw [integral_eq_lintegral_of_nonneg_ae]; exact rfl - · exact ae_of_all _ fun a ↦ by simp [Pi.zero_apply, exponentialPdfReal_nonneg Fact.out a] - · exact (Measurable.aestronglyMeasurable (measurable_exponentialPdfReal r)).restrict +lemma exponentialCDFReal_eq_integral {r : ℝ} (hr : 0 < r) (x : ℝ) : + exponentialCDFReal r x = ∫ x in Iic x, exponentialPDFReal r x := + gammaCDFReal_eq_integral zero_lt_one hr x -lemma exponentialCdfReal_eq_lintegral (r x : ℝ) [Fact (0 < r)] : - exponentialCdfReal r x = ENNReal.toReal (∫⁻ x in Iic x, exponentialPdf r x) := by - simp only [exponentialPdf, exponentialCdfReal, cdf_eq_toReal] - simp only [expMeasure, measurableSet_Iic, withDensity_apply, exponentialPdf] +lemma exponentialCDFReal_eq_lintegral {r : ℝ} (hr : 0 < r) (x : ℝ) : + exponentialCDFReal r x = ENNReal.toReal (∫⁻ x in Iic x, exponentialPDF r x) := + gammaCDFReal_eq_lintegral zero_lt_one hr x open Topology -lemma lintegral_exponentialPdf_eq_antiDeriv (r x : ℝ) (hr : 0 < r) : - ∫⁻ y in Iic x, exponentialPdf r y +lemma hasDerivAt_neg_exp_mul_exp {r x : ℝ} : + HasDerivAt (fun a ↦ -exp (-(r * a))) (r * exp (-(r * x))) x := by + convert (((hasDerivAt_id x).const_mul (-r)).exp.const_mul (-1)) using 1 + · simp only [one_mul, id_eq, neg_mul] + simp only [id_eq, neg_mul, mul_one, mul_neg, one_mul, neg_neg, mul_comm] + +/-- A negative exponential function is integrable on intervals in `R≥0` -/ +lemma exp_neg_integrableOn_Ioc {b x : ℝ} (hb : 0 < b) : + IntegrableOn (fun x ↦ rexp (-(b * x))) (Ioc 0 x) := by + simp only [neg_mul_eq_neg_mul] + exact (exp_neg_integrableOn_Ioi _ hb).mono_set Ioc_subset_Ioi_self + +lemma lintegral_exponentialPDF_eq_antiDeriv {r : ℝ} (hr : 0 < r) (x : ℝ) : + ∫⁻ y in Iic x, exponentialPDF r y = ENNReal.ofReal (if 0 ≤ x then 1 - exp (-(r * x)) else 0) := by split_ifs with h case neg => - simp only [exponentialPdf_eq] + simp only [exponentialPDF_eq] rw [set_lintegral_congr_fun measurableSet_Iic, lintegral_zero, ENNReal.ofReal_zero] exact ae_of_all _ fun a (_ : a ≤ _) ↦ by rw [if_neg (by linarith), ENNReal.ofReal_eq_zero] case pos => - rw [lintegral_Iic_eq_lintegral_Iio_add_Icc _ h, lintegral_exponentialPdf_of_nonpos (le_refl 0), + rw [lintegral_Iic_eq_lintegral_Iio_add_Icc _ h, lintegral_exponentialPDF_of_nonpos (le_refl 0), zero_add] - simp only [exponentialPdf_eq] + simp only [exponentialPDF_eq] rw [set_lintegral_congr_fun measurableSet_Icc (ae_of_all _ (by intro a ⟨(hle : _ ≤ a), _⟩; rw [if_pos hle]))] rw [← ENNReal.toReal_eq_toReal _ ENNReal.ofReal_ne_top, ← integral_eq_lintegral_of_nonneg_ae @@ -204,14 +161,14 @@ lemma lintegral_exponentialPdf_eq_antiDeriv (r x : ℝ) (hr : 0 < r) : rw [integrableOn_Icc_iff_integrableOn_Ioc] exact Integrable.const_mul (exp_neg_integrableOn_Ioc hr) _ -/-- The Definition of the CDF equals the known Formular ``1 - exp (-(r * x))``-/ -lemma exponentialCdfReal_eq {r : ℝ} [Fact (0 < r)] (x : ℝ) : - exponentialCdfReal r x = if 0 ≤ x then 1 - exp (-(r * x)) else 0 := by - simp only [exponentialCdfReal_eq_lintegral, lintegral_exponentialPdf_eq_antiDeriv _ _ Fact.out, +/-- The CDF of the exponential distribution equals ``1 - exp (-(r * x))``-/ +lemma exponentialCDFReal_eq {r : ℝ} (hr : 0 < r) (x : ℝ) : + exponentialCDFReal r x = if 0 ≤ x then 1 - exp (-(r * x)) else 0 := by + rw [exponentialCDFReal_eq_lintegral hr, lintegral_exponentialPDF_eq_antiDeriv hr x, ENNReal.toReal_ofReal_eq_iff] split_ifs with h · simp only [sub_nonneg, exp_le_one_iff, Left.neg_nonpos_iff, gt_iff_lt, ge_iff_le] - exact mul_nonneg (le_of_lt Fact.out) h - · simp + exact mul_nonneg hr.le h + · exact le_rfl -end ExponentialCdf +end ExponentialCDF diff --git a/Mathlib/Probability/Distributions/Gamma.lean b/Mathlib/Probability/Distributions/Gamma.lean index 8ab6181d25d5b..abdd54baf1194 100644 --- a/Mathlib/Probability/Distributions/Gamma.lean +++ b/Mathlib/Probability/Distributions/Gamma.lean @@ -3,25 +3,23 @@ Copyright (c) 2024 Josha Dekker. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Josha Dekker -/ - -import Mathlib.Analysis.SpecialFunctions.Gaussian import Mathlib.Probability.Notation import Mathlib.Probability.Cdf import Mathlib.Analysis.SpecialFunctions.Gamma.Basic /-! # Gamma distributions over ℝ -Define the Gamma Measure over the Reals +Define the gamma measure over the reals. ## Main definitions -* `gammaPdfReal`: the function `a r x ↦ r ^ a / (Gamma a) * x ^ (a-1) * exp (-(r * x))` - for `0 ≤ x` or `0` else, which is the probability density function of a Gamma distribution with +* `gammaPDFReal`: the function `a r x ↦ r ^ a / (Gamma a) * x ^ (a-1) * exp (-(r * x))` + for `0 ≤ x` or `0` else, which is the probability density function of a gamma distribution with shape `a` and rate `r` (when `ha : 0 < a ` and `hr : 0 < r`). -* `gammaPdf`: `ℝ≥0∞`-valued pdf, - `gammaPdf a r = ENNReal.ofReal (gammaPdfReal a r)`. -* `gammaMeasure`: a Gamma measure on `ℝ`, parametrized by its shape `a` and rate `r`. -* `gammaCdfReal`: the CDF given by the definition of CDF in `ProbabilityTheory.Cdf` applied to the - Gamma measure. +* `gammaPDF`: `ℝ≥0∞`-valued pdf, + `gammaPDF a r = ENNReal.ofReal (gammaPDFReal a r)`. +* `gammaMeasure`: a gamma measure on `ℝ`, parametrized by its shape `a` and rate `r`. +* `gammaCDFReal`: the CDF given by the definition of CDF in `ProbabilityTheory.CDF` applied to the + gamma measure. -/ open scoped ENNReal NNReal @@ -38,66 +36,73 @@ lemma lintegral_Iic_eq_lintegral_Iio_add_Icc {y z : ℝ} (f : ℝ → ℝ≥0∞ namespace ProbabilityTheory -section GammaPdf +section GammaPDF -/-- The pdf of the gamma distribution depending on its scale and rate-/ +/-- The pdf of the gamma distribution depending on its scale and rate -/ noncomputable -def gammaPdfReal (a r x : ℝ) : ℝ := +def gammaPDFReal (a r x : ℝ) : ℝ := if 0 ≤ x then r ^ a / (Gamma a) * x ^ (a-1) * exp (-(r * x)) else 0 -/-- The pdf of the Gamma distribution, as a function valued in `ℝ≥0∞` -/ +/-- The pdf of the gamma distribution, as a function valued in `ℝ≥0∞` -/ noncomputable -def gammaPdf (a r x : ℝ) : ℝ≥0∞ := - ENNReal.ofReal (gammaPdfReal a r x) +def gammaPDF (a r x : ℝ) : ℝ≥0∞ := + ENNReal.ofReal (gammaPDFReal a r x) -lemma gammaPdf_eq (a r x : ℝ) : - gammaPdf a r x = ENNReal.ofReal (if 0 ≤ x then +lemma gammaPDF_eq (a r x : ℝ) : + gammaPDF a r x = ENNReal.ofReal (if 0 ≤ x then r ^ a / (Gamma a) * x ^ (a-1) * exp (-(r * x)) else 0) := rfl -lemma gammaPdf_of_neg {a r x : ℝ} (hx : x < 0) : gammaPdf a r x = 0 := by - simp only [gammaPdf_eq, if_neg (not_le.mpr hx), ENNReal.ofReal_zero] +lemma gammaPDF_of_neg {a r x : ℝ} (hx : x < 0) : gammaPDF a r x = 0 := by + simp only [gammaPDF_eq, if_neg (not_le.mpr hx), ENNReal.ofReal_zero] -lemma gammaPdf_of_nonneg {a r x : ℝ} (hx : 0 ≤ x) : - gammaPdf a r x = ENNReal.ofReal (r ^ a / (Gamma a) * x ^ (a-1) * exp (-(r * x))) := by - simp only [gammaPdf_eq, if_pos hx] +lemma gammaPDF_of_nonneg {a r x : ℝ} (hx : 0 ≤ x) : + gammaPDF a r x = ENNReal.ofReal (r ^ a / (Gamma a) * x ^ (a-1) * exp (-(r * x))) := by + simp only [gammaPDF_eq, if_pos hx] -/-- the Lebesgue integral of the Gamma pdf over nonpositive reals equals 0 -/ -lemma lintegral_gammaPdf_of_nonpos {x a r : ℝ} (hx : x ≤ 0) : - ∫⁻ y in Iio x, gammaPdf a r y = 0 := by +/-- The Lebesgue integral of the gamma pdf over nonpositive reals equals 0 -/ +lemma lintegral_gammaPDF_of_nonpos {x a r : ℝ} (hx : x ≤ 0) : + ∫⁻ y in Iio x, gammaPDF a r y = 0 := by rw [set_lintegral_congr_fun (g := fun _ ↦ 0) measurableSet_Iio] · rw [lintegral_zero, ← ENNReal.ofReal_zero] - · simp only [gammaPdf_eq, ge_iff_le, ENNReal.ofReal_eq_zero] + · simp only [gammaPDF_eq, ge_iff_le, ENNReal.ofReal_eq_zero] apply ae_of_all _ fun a (_ : a < _) ↦ by rw [if_neg (by linarith)] /-- The gamma pdf is measurable. -/ -lemma measurable_gammaPdfReal (a r : ℝ) : Measurable (gammaPdfReal a r) := +@[measurability] +lemma measurable_gammaPDFReal (a r : ℝ) : Measurable (gammaPDFReal a r) := Measurable.ite measurableSet_Ici (((measurable_id'.pow_const _).const_mul _).mul (measurable_id'.const_mul _).neg.exp) measurable_const -/-- the Gamma pdf is positive for all positive reals -/ -lemma gammaPdfReal_pos {x a r : ℝ} (ha : 0 < a) (hr : 0 < r) (hx : 0 < x) : - 0 < gammaPdfReal a r x := by - simp only [gammaPdfReal, if_pos hx.le] +/-- The gamma pdf is strongly measurable -/ +@[measurability] + lemma stronglyMeasurable_gammaPDFReal (a r : ℝ) : + StronglyMeasurable (gammaPDFReal a r) := + (measurable_gammaPDFReal a r).stronglyMeasurable + +/-- The gamma pdf is positive for all positive reals -/ +lemma gammaPDFReal_pos {x a r : ℝ} (ha : 0 < a) (hr : 0 < r) (hx : 0 < x) : + 0 < gammaPDFReal a r x := by + simp only [gammaPDFReal, if_pos hx.le] positivity -/-- The Gamma pdf is nonnegative -/ -lemma gammaPdfReal_nonneg {a r : ℝ} (ha : 0 < a) (hr : 0 < r) (x : ℝ) : - 0 ≤ gammaPdfReal a r x := by - unfold gammaPdfReal +/-- The gamma pdf is nonnegative -/ +lemma gammaPDFReal_nonneg {a r : ℝ} (ha : 0 < a) (hr : 0 < r) (x : ℝ) : + 0 ≤ gammaPDFReal a r x := by + unfold gammaPDFReal split_ifs <;> positivity open Measure -/-- The pdf of the Gamma distribution integrates to 1 -/ +/-- The pdf of the gamma distribution integrates to 1 -/ @[simp] -lemma lintegral_gammaPdf_eq_one {a r : ℝ} (ha : 0 < a) (hr : 0 < r) : - ∫⁻ x, gammaPdf a r x = 1 := by - have leftSide : ∫⁻ x in Iio 0, gammaPdf a r x = 0 := by +lemma lintegral_gammaPDF_eq_one {a r : ℝ} (ha : 0 < a) (hr : 0 < r) : + ∫⁻ x, gammaPDF a r x = 1 := by + have leftSide : ∫⁻ x in Iio 0, gammaPDF a r x = 0 := by rw [set_lintegral_congr_fun measurableSet_Iio - (ae_of_all _ (fun x (hx : x < 0) ↦ gammaPdf_of_neg hx)), lintegral_zero] - have rightSide : ∫⁻ x in Ici 0, gammaPdf a r x = + (ae_of_all _ (fun x (hx : x < 0) ↦ gammaPDF_of_neg hx)), lintegral_zero] + have rightSide : ∫⁻ x in Ici 0, gammaPDF a r x = ∫⁻ x in Ici 0, ENNReal.ofReal (r ^ a / Gamma a * x ^ (a - 1) * exp (-(r * x))) := - set_lintegral_congr_fun measurableSet_Ici (ae_of_all _ (fun _ ↦ gammaPdf_of_nonneg)) + set_lintegral_congr_fun measurableSet_Ici (ae_of_all _ (fun _ ↦ gammaPDF_of_nonneg)) rw [← ENNReal.toReal_eq_one_iff, ← lintegral_add_compl _ measurableSet_Ici, compl_Ici, leftSide, rightSide, add_zero, ← integral_eq_lintegral_of_nonneg_ae] · simp_rw [integral_Ici_eq_integral_Ioi, mul_assoc] @@ -106,42 +111,42 @@ lemma lintegral_gammaPdf_eq_one {a r : ℝ} (ha : 0 < a) (hr : 0 < r) : div_rpow zero_le_one hr.le, one_rpow, mul_one_div, div_self (rpow_pos_of_pos hr _).ne'] · rw [EventuallyLE, ae_restrict_iff' measurableSet_Ici] exact ae_of_all _ (fun x (hx : 0 ≤ x) ↦ by positivity) - · apply (measurable_gammaPdfReal a r).aestronglyMeasurable.congr + · apply (measurable_gammaPDFReal a r).aestronglyMeasurable.congr refine (ae_restrict_iff' measurableSet_Ici).mpr <| ae_of_all _ fun x (hx : 0 ≤ x) ↦ ?_ - simp_rw [gammaPdfReal, eq_true_intro hx, ite_true] + simp_rw [gammaPDFReal, eq_true_intro hx, ite_true] -end GammaPdf +end GammaPDF open MeasureTheory -/-- Measure defined by the Gamma distribution -/ +/-- Measure defined by the gamma distribution -/ noncomputable def gammaMeasure (a r : ℝ) : Measure ℝ := - volume.withDensity (gammaPdf a r) + volume.withDensity (gammaPDF a r) lemma isProbabilityMeasureGamma {a r : ℝ} (ha : 0 < a) (hr : 0 < r) : IsProbabilityMeasure (gammaMeasure a r) where - measure_univ := by simp [gammaMeasure, lintegral_gammaPdf_eq_one ha hr] + measure_univ := by simp [gammaMeasure, lintegral_gammaPDF_eq_one ha hr] -section GammaCdf +section GammaCDF -/-- CDF of the Gamma distribution -/ +/-- CDF of the gamma distribution -/ noncomputable -def gammaCdfReal (a r : ℝ) : StieltjesFunction := +def gammaCDFReal (a r : ℝ) : StieltjesFunction := cdf (gammaMeasure a r) -lemma gammaCdfReal_eq_integral {a r : ℝ} (ha : 0 < a) (hr : 0 < r) (x : ℝ) : - gammaCdfReal a r x = ∫ x in Iic x, gammaPdfReal a r x := by +lemma gammaCDFReal_eq_integral {a r : ℝ} (ha : 0 < a) (hr : 0 < r) (x : ℝ) : + gammaCDFReal a r x = ∫ x in Iic x, gammaPDFReal a r x := by have : IsProbabilityMeasure (gammaMeasure a r) := isProbabilityMeasureGamma ha hr - rw [gammaCdfReal, cdf_eq_toReal, gammaMeasure, withDensity_apply _ measurableSet_Iic] + rw [gammaCDFReal, cdf_eq_toReal, gammaMeasure, withDensity_apply _ measurableSet_Iic] refine (integral_eq_lintegral_of_nonneg_ae ?_ ?_).symm - · exact ae_of_all _ fun b ↦ by simp only [Pi.zero_apply, gammaPdfReal_nonneg ha hr] - · exact (measurable_gammaPdfReal a r).aestronglyMeasurable.restrict + · exact ae_of_all _ fun b ↦ by simp only [Pi.zero_apply, gammaPDFReal_nonneg ha hr] + · exact (measurable_gammaPDFReal a r).aestronglyMeasurable.restrict -lemma gammaCdfReal_eq_lintegral {a r : ℝ} (ha : 0 < a) (hr : 0 < r) (x : ℝ) : - gammaCdfReal a r x = ENNReal.toReal (∫⁻ x in Iic x, gammaPdf a r x) := by +lemma gammaCDFReal_eq_lintegral {a r : ℝ} (ha : 0 < a) (hr : 0 < r) (x : ℝ) : + gammaCDFReal a r x = ENNReal.toReal (∫⁻ x in Iic x, gammaPDF a r x) := by have : IsProbabilityMeasure (gammaMeasure a r) := isProbabilityMeasureGamma ha hr - simp only [gammaPdf, gammaCdfReal, cdf_eq_toReal] - simp only [gammaMeasure, measurableSet_Iic, withDensity_apply, gammaPdf] + simp only [gammaPDF, gammaCDFReal, cdf_eq_toReal] + simp only [gammaMeasure, measurableSet_Iic, withDensity_apply, gammaPDF] -end GammaCdf +end GammaCDF diff --git a/Mathlib/Probability/Distributions/Gaussian.lean b/Mathlib/Probability/Distributions/Gaussian.lean index 76028a93f2627..2d5ab5cb683e3 100644 --- a/Mathlib/Probability/Distributions/Gaussian.lean +++ b/Mathlib/Probability/Distributions/Gaussian.lean @@ -5,6 +5,7 @@ Authors: Lorenzo Luccioli, Rémy Degenne, Alexander Bentkamp -/ import Mathlib.Analysis.SpecialFunctions.Gaussian import Mathlib.Probability.Notation +import Mathlib.MeasureTheory.Decomposition.Lebesgue /-! # Gaussian distributions over ℝ @@ -13,13 +14,13 @@ We define a Gaussian measure over the reals. ## Main definitions -* `gaussianPdfReal`: the function `μ v x ↦ (1 / (sqrt (2 * pi * v))) * exp (- (x - μ)^2 / (2 * v))`, +* `gaussianPDFReal`: the function `μ v x ↦ (1 / (sqrt (2 * pi * v))) * exp (- (x - μ)^2 / (2 * v))`, which is the probability density function of a Gaussian distribution with mean `μ` and variance `v` (when `v ≠ 0`). -* `gaussianPdf`: `ℝ≥0∞`-valued pdf, `gaussianPdf μ v x = ENNReal.ofReal (gaussianPdfReal μ v x)`. +* `gaussianPDF`: `ℝ≥0∞`-valued pdf, `gaussianPDF μ v x = ENNReal.ofReal (gaussianPDFReal μ v x)`. * `gaussianReal`: a Gaussian measure on `ℝ`, parametrized by its mean `μ` and variance `v`. If `v = 0`, this is `dirac μ`, otherwise it is defined as the measure with density - `gaussianPdf μ v` with respect to the Lebesgue measure. + `gaussianPDF μ v` with respect to the Lebesgue measure. ## Main results @@ -36,44 +37,44 @@ open MeasureTheory namespace ProbabilityTheory -section GaussianPdf +section GaussianPDF /-- Probability density function of the gaussian distribution with mean `μ` and variance `v`. -/ noncomputable -def gaussianPdfReal (μ : ℝ) (v : ℝ≥0) (x : ℝ) : ℝ := +def gaussianPDFReal (μ : ℝ) (v : ℝ≥0) (x : ℝ) : ℝ := (Real.sqrt (2 * π * v))⁻¹ * rexp (- (x - μ)^2 / (2 * v)) -lemma gaussianPdfReal_def (μ : ℝ) (v : ℝ≥0) : - gaussianPdfReal μ v = +lemma gaussianPDFReal_def (μ : ℝ) (v : ℝ≥0) : + gaussianPDFReal μ v = fun x ↦ (Real.sqrt (2 * π * v))⁻¹ * rexp (- (x - μ)^2 / (2 * v)) := rfl @[simp] -lemma gaussianPdfReal_zero_var (m : ℝ) : gaussianPdfReal m 0 = 0 := by +lemma gaussianPDFReal_zero_var (m : ℝ) : gaussianPDFReal m 0 = 0 := by ext1 x - simp [gaussianPdfReal] + simp [gaussianPDFReal] /-- The gaussian pdf is positive when the variance is not zero. -/ -lemma gaussianPdfReal_pos (μ : ℝ) (v : ℝ≥0) (x : ℝ) (hv : v ≠ 0) : 0 < gaussianPdfReal μ v x := by - rw [gaussianPdfReal] +lemma gaussianPDFReal_pos (μ : ℝ) (v : ℝ≥0) (x : ℝ) (hv : v ≠ 0) : 0 < gaussianPDFReal μ v x := by + rw [gaussianPDFReal] positivity /--The gaussian pdf is nonnegative. -/ -lemma gaussianPdfReal_nonneg (μ : ℝ) (v : ℝ≥0) (x : ℝ) : 0 ≤ gaussianPdfReal μ v x := by - rw [gaussianPdfReal] +lemma gaussianPDFReal_nonneg (μ : ℝ) (v : ℝ≥0) (x : ℝ) : 0 ≤ gaussianPDFReal μ v x := by + rw [gaussianPDFReal] positivity /-- The gaussian pdf is measurable. -/ -lemma measurable_gaussianPdfReal (μ : ℝ) (v : ℝ≥0) : Measurable (gaussianPdfReal μ v) := +lemma measurable_gaussianPDFReal (μ : ℝ) (v : ℝ≥0) : Measurable (gaussianPDFReal μ v) := (((measurable_id.add_const _).pow_const _).neg.div_const _).exp.const_mul _ /-- The gaussian pdf is strongly measurable. -/ -lemma stronglyMeasurable_gaussianPdfReal (μ : ℝ) (v : ℝ≥0) : - StronglyMeasurable (gaussianPdfReal μ v) := - (measurable_gaussianPdfReal μ v).stronglyMeasurable +lemma stronglyMeasurable_gaussianPDFReal (μ : ℝ) (v : ℝ≥0) : + StronglyMeasurable (gaussianPDFReal μ v) := + (measurable_gaussianPDFReal μ v).stronglyMeasurable -lemma integrable_gaussianPdfReal (μ : ℝ) (v : ℝ≥0) : - Integrable (gaussianPdfReal μ v) := by - rw [gaussianPdfReal_def] +lemma integrable_gaussianPDFReal (μ : ℝ) (v : ℝ≥0) : + Integrable (gaussianPDFReal μ v) := by + rw [gaussianPDFReal_def] by_cases hv : v = 0 · simp [hv] let g : ℝ → ℝ := fun x ↦ (Real.sqrt (2 * π * v))⁻¹ * rexp (- x ^ 2 / (2 * v)) @@ -93,14 +94,14 @@ lemma integrable_gaussianPdfReal (μ : ℝ) (v : ℝ≥0) : exact Integrable.comp_sub_right hg μ /-- The gaussian distribution pdf integrates to 1 when the variance is not zero. -/ -lemma lintegral_gaussianPdfReal_eq_one (μ : ℝ) {v : ℝ≥0} (h : v ≠ 0) : - ∫⁻ x, ENNReal.ofReal (gaussianPdfReal μ v x) = 1 := by +lemma lintegral_gaussianPDFReal_eq_one (μ : ℝ) {v : ℝ≥0} (h : v ≠ 0) : + ∫⁻ x, ENNReal.ofReal (gaussianPDFReal μ v x) = 1 := by rw [← ENNReal.toReal_eq_one_iff] - have hfm : AEStronglyMeasurable (gaussianPdfReal μ v) volume := - (stronglyMeasurable_gaussianPdfReal μ v).aestronglyMeasurable - have hf : 0 ≤ₐₛ gaussianPdfReal μ v := ae_of_all _ (gaussianPdfReal_nonneg μ v) + have hfm : AEStronglyMeasurable (gaussianPDFReal μ v) volume := + (stronglyMeasurable_gaussianPDFReal μ v).aestronglyMeasurable + have hf : 0 ≤ₐₛ gaussianPDFReal μ v := ae_of_all _ (gaussianPDFReal_nonneg μ v) rw [← integral_eq_lintegral_of_nonneg_ae hf hfm] - simp only [gaussianPdfReal, zero_lt_two, mul_nonneg_iff_of_pos_right, one_div, + simp only [gaussianPDFReal, zero_lt_two, mul_nonneg_iff_of_pos_right, one_div, Nat.cast_ofNat, integral_mul_left] rw [integral_sub_right_eq_self (μ := volume) (fun a ↦ rexp (-a ^ 2 / ((2 : ℝ) * v))) μ] simp only [zero_lt_two, mul_nonneg_iff_of_pos_right, div_eq_inv_mul, mul_inv_rev, @@ -112,25 +113,25 @@ lemma lintegral_gaussianPdfReal_eq_one (μ : ℝ) {v : ℝ≥0} (h : v ≠ 0) : · positivity /-- The gaussian distribution pdf integrates to 1 when the variance is not zero. -/ -lemma integral_gaussianPdfReal_eq_one (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) : - ∫ x, gaussianPdfReal μ v x = 1 := by - have h := lintegral_gaussianPdfReal_eq_one μ hv - rw [← ofReal_integral_eq_lintegral_ofReal (integrable_gaussianPdfReal _ _) - (ae_of_all _ (gaussianPdfReal_nonneg _ _)), ← ENNReal.ofReal_one] at h - rwa [← ENNReal.ofReal_eq_ofReal_iff (integral_nonneg (gaussianPdfReal_nonneg _ _)) zero_le_one] - -lemma gaussianPdfReal_sub {μ : ℝ} {v : ℝ≥0} (x y : ℝ) : - gaussianPdfReal μ v (x - y) = gaussianPdfReal (μ + y) v x := by - simp only [gaussianPdfReal] +lemma integral_gaussianPDFReal_eq_one (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) : + ∫ x, gaussianPDFReal μ v x = 1 := by + have h := lintegral_gaussianPDFReal_eq_one μ hv + rw [← ofReal_integral_eq_lintegral_ofReal (integrable_gaussianPDFReal _ _) + (ae_of_all _ (gaussianPDFReal_nonneg _ _)), ← ENNReal.ofReal_one] at h + rwa [← ENNReal.ofReal_eq_ofReal_iff (integral_nonneg (gaussianPDFReal_nonneg _ _)) zero_le_one] + +lemma gaussianPDFReal_sub {μ : ℝ} {v : ℝ≥0} (x y : ℝ) : + gaussianPDFReal μ v (x - y) = gaussianPDFReal (μ + y) v x := by + simp only [gaussianPDFReal] rw [sub_add_eq_sub_sub_swap] -lemma gaussianPdfReal_add {μ : ℝ} {v : ℝ≥0} (x y : ℝ) : - gaussianPdfReal μ v (x + y) = gaussianPdfReal (μ - y) v x := by - rw [sub_eq_add_neg, ← gaussianPdfReal_sub, sub_eq_add_neg, neg_neg] +lemma gaussianPDFReal_add {μ : ℝ} {v : ℝ≥0} (x y : ℝ) : + gaussianPDFReal μ v (x + y) = gaussianPDFReal (μ - y) v x := by + rw [sub_eq_add_neg, ← gaussianPDFReal_sub, sub_eq_add_neg, neg_neg] -lemma gaussianPdfReal_inv_mul {μ : ℝ} {v : ℝ≥0} {c : ℝ} (hc : c ≠ 0) (x : ℝ) : - gaussianPdfReal μ v (c⁻¹ * x) = |c| * gaussianPdfReal (c * μ) (⟨c^2, sq_nonneg _⟩ * v) x := by - simp only [gaussianPdfReal._eq_1, zero_lt_two, mul_nonneg_iff_of_pos_left, NNReal.zero_le_coe, +lemma gaussianPDFReal_inv_mul {μ : ℝ} {v : ℝ≥0} {c : ℝ} (hc : c ≠ 0) (x : ℝ) : + gaussianPDFReal μ v (c⁻¹ * x) = |c| * gaussianPDFReal (c * μ) (⟨c^2, sq_nonneg _⟩ * v) x := by + simp only [gaussianPDFReal._eq_1, zero_lt_two, mul_nonneg_iff_of_pos_left, NNReal.zero_le_coe, Real.sqrt_mul', one_div, mul_inv_rev, NNReal.coe_mul, NNReal.coe_mk, NNReal.coe_pos] rw [← mul_assoc] refine congr_arg₂ _ ?_ ?_ @@ -147,48 +148,48 @@ lemma gaussianPdfReal_inv_mul {μ : ℝ} {v : ℝ≥0} {c : ℝ} (hc : c ≠ 0) congr 1 ring -lemma gaussianPdfReal_mul {μ : ℝ} {v : ℝ≥0} {c : ℝ} (hc : c ≠ 0) (x : ℝ) : - gaussianPdfReal μ v (c * x) - = |c⁻¹| * gaussianPdfReal (c⁻¹ * μ) (⟨(c^2)⁻¹, inv_nonneg.mpr (sq_nonneg _)⟩ * v) x := by - conv_lhs => rw [← inv_inv c, gaussianPdfReal_inv_mul (inv_ne_zero hc)] +lemma gaussianPDFReal_mul {μ : ℝ} {v : ℝ≥0} {c : ℝ} (hc : c ≠ 0) (x : ℝ) : + gaussianPDFReal μ v (c * x) + = |c⁻¹| * gaussianPDFReal (c⁻¹ * μ) (⟨(c^2)⁻¹, inv_nonneg.mpr (sq_nonneg _)⟩ * v) x := by + conv_lhs => rw [← inv_inv c, gaussianPDFReal_inv_mul (inv_ne_zero hc)] simp /-- The pdf of a Gaussian distribution on ℝ with mean `μ` and variance `v`. -/ noncomputable -def gaussianPdf (μ : ℝ) (v : ℝ≥0) (x : ℝ) : ℝ≥0∞ := ENNReal.ofReal (gaussianPdfReal μ v x) +def gaussianPDF (μ : ℝ) (v : ℝ≥0) (x : ℝ) : ℝ≥0∞ := ENNReal.ofReal (gaussianPDFReal μ v x) -lemma gaussianPdf_def (μ : ℝ) (v : ℝ≥0) : - gaussianPdf μ v = fun x ↦ ENNReal.ofReal (gaussianPdfReal μ v x) := rfl +lemma gaussianPDF_def (μ : ℝ) (v : ℝ≥0) : + gaussianPDF μ v = fun x ↦ ENNReal.ofReal (gaussianPDFReal μ v x) := rfl @[simp] -lemma gaussianPdf_zero_var (μ : ℝ) : gaussianPdf μ 0 = 0 := by +lemma gaussianPDF_zero_var (μ : ℝ) : gaussianPDF μ 0 = 0 := by ext - simp [gaussianPdf] + simp [gaussianPDF] -lemma gaussianPdf_pos (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) (x : ℝ) : 0 < gaussianPdf μ v x := by - rw [gaussianPdf, ENNReal.ofReal_pos] - exact gaussianPdfReal_pos _ _ _ hv +lemma gaussianPDF_pos (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) (x : ℝ) : 0 < gaussianPDF μ v x := by + rw [gaussianPDF, ENNReal.ofReal_pos] + exact gaussianPDFReal_pos _ _ _ hv @[measurability] -lemma measurable_gaussianPdf (μ : ℝ) (v : ℝ≥0) : Measurable (gaussianPdf μ v) := - (measurable_gaussianPdfReal _ _).ennreal_ofReal +lemma measurable_gaussianPDF (μ : ℝ) (v : ℝ≥0) : Measurable (gaussianPDF μ v) := + (measurable_gaussianPDFReal _ _).ennreal_ofReal @[simp] -lemma lintegral_gaussianPdf_eq_one (μ : ℝ) {v : ℝ≥0} (h : v ≠ 0) : - ∫⁻ x, gaussianPdf μ v x = 1 := - lintegral_gaussianPdfReal_eq_one μ h +lemma lintegral_gaussianPDF_eq_one (μ : ℝ) {v : ℝ≥0} (h : v ≠ 0) : + ∫⁻ x, gaussianPDF μ v x = 1 := + lintegral_gaussianPDFReal_eq_one μ h -end GaussianPdf +end GaussianPDF section GaussianReal /-- A Gaussian distribution on `ℝ` with mean `μ` and variance `v`. -/ noncomputable def gaussianReal (μ : ℝ) (v : ℝ≥0) : Measure ℝ := - if v = 0 then Measure.dirac μ else volume.withDensity (gaussianPdf μ v) + if v = 0 then Measure.dirac μ else volume.withDensity (gaussianPDF μ v) lemma gaussianReal_of_var_ne_zero (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) : - gaussianReal μ v = volume.withDensity (gaussianPdf μ v) := if_neg hv + gaussianReal μ v = volume.withDensity (gaussianPDF μ v) := if_neg hv @[simp] lemma gaussianReal_zero_var (μ : ℝ) : gaussianReal μ 0 = Measure.dirac μ := if_pos rfl @@ -198,15 +199,15 @@ instance instIsProbabilityMeasureGaussianReal (μ : ℝ) (v : ℝ≥0) : measure_univ := by by_cases h : v = 0 <;> simp [gaussianReal_of_var_ne_zero, h] lemma gaussianReal_apply (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) (s : Set ℝ) : - gaussianReal μ v s = ∫⁻ x in s, gaussianPdf μ v x := by + gaussianReal μ v s = ∫⁻ x in s, gaussianPDF μ v x := by rw [gaussianReal_of_var_ne_zero _ hv, withDensity_apply' _ s] lemma gaussianReal_apply_eq_integral (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) (s : Set ℝ) : - gaussianReal μ v s = ENNReal.ofReal (∫ x in s, gaussianPdfReal μ v x) := by + gaussianReal μ v s = ENNReal.ofReal (∫ x in s, gaussianPDFReal μ v x) := by rw [gaussianReal_apply _ hv s, ofReal_integral_eq_lintegral_ofReal] · rfl - · exact (integrable_gaussianPdfReal _ _).restrict - · exact ae_of_all _ (gaussianPdfReal_nonneg _ _) + · exact (integrable_gaussianPDFReal _ _).restrict + · exact ae_of_all _ (gaussianPDFReal_nonneg _ _) lemma gaussianReal_absolutelyContinuous (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) : gaussianReal μ v ≪ volume := by @@ -217,18 +218,18 @@ lemma gaussianReal_absolutelyContinuous' (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) volume ≪ gaussianReal μ v := by rw [gaussianReal_of_var_ne_zero _ hv] refine withDensity_absolutelyContinuous' ?_ ?_ ?_ - · exact (measurable_gaussianPdf _ _).aemeasurable - · exact ae_of_all _ (fun _ ↦ (gaussianPdf_pos _ hv _).ne') + · exact (measurable_gaussianPDF _ _).aemeasurable + · exact ae_of_all _ (fun _ ↦ (gaussianPDF_pos _ hv _).ne') · exact ae_of_all _ (fun _ ↦ ENNReal.ofReal_ne_top) lemma rnDeriv_gaussianReal (μ : ℝ) (v : ℝ≥0) : - ∂(gaussianReal μ v)/∂volume =ₐₛ gaussianPdf μ v := by + ∂(gaussianReal μ v)/∂volume =ₐₛ gaussianPDF μ v := by by_cases hv : v = 0 - · simp only [hv, gaussianReal_zero_var, gaussianPdf_zero_var] + · simp only [hv, gaussianReal_zero_var, gaussianPDF_zero_var] refine (Measure.eq_rnDeriv measurable_zero (mutuallySingular_dirac μ volume) ?_).symm rw [withDensity_zero, add_zero] · rw [gaussianReal_of_var_ne_zero _ hv] - exact Measure.rnDeriv_withDensity _ (measurable_gaussianPdf μ v) + exact Measure.rnDeriv_withDensity _ (measurable_gaussianPDF μ v) section Transformations @@ -238,18 +239,18 @@ lemma _root_.MeasurableEmbedding.gaussianReal_comap_apply (hv : v ≠ 0) {f : ℝ → ℝ} (hf : MeasurableEmbedding f) {f' : ℝ → ℝ} (h_deriv : ∀ x, HasDerivAt f (f' x) x) {s : Set ℝ} (hs : MeasurableSet s) : (gaussianReal μ v).comap f s - = ENNReal.ofReal (∫ x in s, |f' x| * gaussianPdfReal μ v (f x)) := by - rw [gaussianReal_of_var_ne_zero _ hv, gaussianPdf_def] + = ENNReal.ofReal (∫ x in s, |f' x| * gaussianPDFReal μ v (f x)) := by + rw [gaussianReal_of_var_ne_zero _ hv, gaussianPDF_def] exact hf.withDensity_ofReal_comap_apply_eq_integral_abs_deriv_mul' hs h_deriv - (ae_of_all _ (gaussianPdfReal_nonneg _ _)) (integrable_gaussianPdfReal _ _) + (ae_of_all _ (gaussianPDFReal_nonneg _ _)) (integrable_gaussianPDFReal _ _) lemma _root_.MeasurableEquiv.gaussianReal_map_symm_apply (hv : v ≠ 0) (f : ℝ ≃ᵐ ℝ) {f' : ℝ → ℝ} (h_deriv : ∀ x, HasDerivAt f (f' x) x) {s : Set ℝ} (hs : MeasurableSet s) : (gaussianReal μ v).map f.symm s - = ENNReal.ofReal (∫ x in s, |f' x| * gaussianPdfReal μ v (f x)) := by - rw [gaussianReal_of_var_ne_zero _ hv, gaussianPdf_def] + = ENNReal.ofReal (∫ x in s, |f' x| * gaussianPDFReal μ v (f x)) := by + rw [gaussianReal_of_var_ne_zero _ hv, gaussianPDF_def] exact f.withDensity_ofReal_map_symm_apply_eq_integral_abs_deriv_mul' hs h_deriv - (ae_of_all _ (gaussianPdfReal_nonneg _ _)) (integrable_gaussianPdfReal _ _) + (ae_of_all _ (gaussianPDFReal_nonneg _ _)) (integrable_gaussianPDFReal _ _) /-- The map of a Gaussian distribution by addition of a constant is a Gaussian. -/ lemma gaussianReal_map_add_const (y : ℝ) : @@ -264,7 +265,7 @@ lemma gaussianReal_map_add_const (y : ℝ) : rw [MeasurableEquiv.gaussianReal_map_symm_apply hv e he' hs'] simp only [abs_neg, abs_one, MeasurableEquiv.coe_mk, Equiv.coe_fn_mk, one_mul, ne_eq] rw [gaussianReal_apply_eq_integral _ hv s'] - simp [gaussianPdfReal_sub _ y, Homeomorph.addRight, ← sub_eq_add_neg] + simp [gaussianPDFReal_sub _ y, Homeomorph.addRight, ← sub_eq_add_neg] /-- The map of a Gaussian distribution by addition of a constant is a Gaussian. -/ lemma gaussianReal_map_const_add (y : ℝ) : @@ -300,7 +301,7 @@ lemma gaussianReal_map_const_mul (c : ℝ) : simp [hc] simp only [Homeomorph.mulLeft₀, Equiv.toFun_as_coe, Equiv.mulLeft₀_apply, Equiv.invFun_as_coe, Equiv.mulLeft₀_symm_apply, Homeomorph.toMeasurableEquiv_coe, Homeomorph.homeomorph_mk_coe_symm, - Equiv.coe_fn_symm_mk, gaussianPdfReal_inv_mul hc] + Equiv.coe_fn_symm_mk, gaussianPDFReal_inv_mul hc] congr with x suffices |c⁻¹| * |c| = 1 by rw [← mul_assoc, this, one_mul] rw [abs_inv, inv_mul_cancel] diff --git a/Mathlib/Probability/Distributions/Geometric.lean b/Mathlib/Probability/Distributions/Geometric.lean new file mode 100644 index 0000000000000..31e97e360402d --- /dev/null +++ b/Mathlib/Probability/Distributions/Geometric.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2024 Josha Dekker. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Josha Dekker +-/ + +import Mathlib.Probability.Notation +import Mathlib.Probability.ProbabilityMassFunction.Basic + +/-! # Geometric distributions over ℕ + +Define the geometric measure over the natural numbers + +## Main definitions +* `geometricPMFReal`: the function `p n ↦ (1-p) ^ n * p` + for `n ∈ ℕ`, which is the probability density function of a geometric distribution with + success probability `p ∈ (0,1]`. +* `geometricPMF`: `ℝ≥0∞`-valued pmf, + `geometricPMF p = ENNReal.ofReal (geometricPMFReal p)`. +* `geometricMeasure`: a geometric measure on `ℕ`, parametrized by its success probability `p`. +-/ + +open scoped ENNReal NNReal + +open MeasureTheory Real Set Filter Topology + +namespace ProbabilityTheory + +variable {p : ℝ} + +section GeometricPMF + + +/-- The pmf of the geometric distribution depending on its success probability. -/ +noncomputable +def geometricPMFReal (p : ℝ) (n : ℕ) : ℝ := (1-p) ^ n * p + +lemma geometricPMFRealSum (hp_pos : 0 < p) (hp_le_one : p <= 1) : + HasSum (fun n ↦ geometricPMFReal p n) 1 := by + unfold geometricPMFReal + have := hasSum_geometric_of_lt_1 (sub_nonneg.mpr hp_le_one) (sub_lt_self 1 hp_pos) + apply (hasSum_mul_right_iff (hp_pos.ne')).mpr at this + simp only [sub_sub_cancel] at this + rw [inv_mul_eq_div, div_self hp_pos.ne'] at this + exact this + +/-- The geometric pmf is positive for all natural numbers -/ +lemma geometricPMFReal_pos {n : ℕ} (hp_pos : 0 < p) (hp_lt_one : p < 1) : + 0 < geometricPMFReal p n := by + rw [geometricPMFReal] + have : 0 < 1-p := sub_pos.mpr hp_lt_one + positivity + +lemma geometricPMFReal_nonneg {n : ℕ} (hp_pos : 0 < p) (hp_le_one : p <= 1) : + 0 ≤ geometricPMFReal p n := by + rw [geometricPMFReal] + have : 0 ≤ 1-p := sub_nonneg.mpr hp_le_one + positivity + +/-- Geometric distribution with success probability `p`. -/ +noncomputable +def geometricPMF (hp_pos : 0 < p) (hp_le_one : p <= 1) : PMF ℕ := by + refine ⟨fun n ↦ ENNReal.ofReal (geometricPMFReal p n), ?_⟩ + apply ENNReal.hasSum_coe.mpr + rw [← toNNReal_one] + exact (geometricPMFRealSum hp_pos hp_le_one).toNNReal + (fun n ↦ geometricPMFReal_nonneg hp_pos hp_le_one) + +/-- The geometric pmf is measurable. -/ +@[measurability] +lemma measurable_geometricPMFReal : Measurable (geometricPMFReal p) := by + measurability + +@[measurability] +lemma stronglyMeasurable_geometricPMFReal : + StronglyMeasurable (geometricPMFReal p) := + stronglyMeasurable_iff_measurable.mpr measurable_geometricPMFReal + +end GeometricPMF + +/-- Measure defined by the geometric distribution -/ +noncomputable +def geometricMeasure (hp_pos : 0 < p) (hp_le_one : p <= 1) : Measure ℕ := + (geometricPMF hp_pos hp_le_one).toMeasure + +lemma isProbabilityMeasureGeometric (hp_pos : 0 < p) (hp_le_one : p <= 1) : + IsProbabilityMeasure (geometricMeasure hp_pos hp_le_one) := + PMF.toMeasure.isProbabilityMeasure (geometricPMF hp_pos hp_le_one) + +end ProbabilityTheory diff --git a/Mathlib/Probability/Distributions/Poisson.lean b/Mathlib/Probability/Distributions/Poisson.lean new file mode 100644 index 0000000000000..7f356dadc5c60 --- /dev/null +++ b/Mathlib/Probability/Distributions/Poisson.lean @@ -0,0 +1,83 @@ +/- +Copyright (c) 2024 Josha Dekker. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Josha Dekker +-/ + +import Mathlib.Analysis.NormedSpace.Exponential +import Mathlib.Analysis.SpecialFunctions.Exponential +import Mathlib.Probability.Notation +import Mathlib.Probability.ProbabilityMassFunction.Basic + +/-! # Poisson distributions over ℕ + +Define the Poisson measure over the natural numbers + +## Main definitions +* `poissonPMFReal`: the function `λ n ↦ exp (- λ) * λ ^ n / n!` + for `n ∈ ℕ`, which is the probability density function of a Poisson distribution with + rate `λ > 0`. +* `poissonPMF`: `ℝ≥0∞`-valued pdf, + `poissonPMF λ = ENNReal.ofReal (poissonPMFReal λ)`. +* `poissonMeasure`: a Poisson measure on `ℕ`, parametrized by its rate `λ`. +-/ + +open scoped ENNReal NNReal Nat + +open MeasureTheory Real Set Filter Topology + +namespace ProbabilityTheory + +section PoissonPMF + +/-- The pmf of the Poisson distribution depending on its rate, as a function to ℝ -/ +noncomputable +def poissonPMFReal (r : ℝ≥0) (n : ℕ) : ℝ := (exp (- r) * r ^ n / n !) + +lemma poissonPMFRealSum (r : ℝ≥0) : HasSum (fun n ↦ poissonPMFReal r n) 1 := by + let r := r.toReal + unfold poissonPMFReal + apply (hasSum_mul_left_iff (exp_ne_zero r)).mp + simp only [mul_one] + have : (fun i ↦ rexp r * (rexp (-r) * r ^ i / ↑(Nat.factorial i))) = + fun i ↦ r ^ i / ↑(Nat.factorial i) := by + ext n + rw [mul_div_assoc, exp_neg, ← mul_assoc, ← div_eq_mul_inv, div_self (exp_ne_zero r), one_mul] + rw [this, exp_eq_exp_ℝ] + exact NormedSpace.expSeries_div_hasSum_exp ℝ r + +/-- The Poisson pmf is positive for all natural numbers -/ +lemma poissonPMFReal_pos {r : ℝ≥0} {n : ℕ} (hr : 0 < r) : 0 < poissonPMFReal r n := by + rw [poissonPMFReal] + positivity + +lemma poissonPMFReal_nonneg {r : ℝ≥0} {n : ℕ} : 0 ≤ poissonPMFReal r n := by + unfold poissonPMFReal + positivity + +/-- The pmf of the Poisson distribution depending on its rate, as a PMF. -/ +noncomputable +def poissonPMF (r : ℝ≥0) : PMF ℕ := by + refine ⟨fun n ↦ ENNReal.ofReal (poissonPMFReal r n), ?_⟩ + apply ENNReal.hasSum_coe.mpr + rw [← toNNReal_one] + exact (poissonPMFRealSum r).toNNReal (fun n ↦ poissonPMFReal_nonneg) + +/-- The Poisson pmf is measurable. -/ +@[measurability] +lemma measurable_poissonPMFReal (r : ℝ≥0) : Measurable (poissonPMFReal r) := by measurability + +@[measurability] +lemma stronglyMeasurable_poissonPMFReal (r : ℝ≥0) : StronglyMeasurable (poissonPMFReal r) := + stronglyMeasurable_iff_measurable.mpr (measurable_poissonPMFReal r) + +end PoissonPMF + +/-- Measure defined by the Poisson distribution -/ +noncomputable +def poissonMeasure (r : ℝ≥0) : Measure ℕ := (poissonPMF r).toMeasure + +instance isProbabilityMeasurePoisson (r : ℝ≥0) : + IsProbabilityMeasure (poissonMeasure r) := PMF.toMeasure.isProbabilityMeasure (poissonPMF r) + +end ProbabilityTheory diff --git a/Mathlib/Probability/Independence/Basic.lean b/Mathlib/Probability/Independence/Basic.lean index 1e461cc0a4f38..bb4e32d317337 100644 --- a/Mathlib/Probability/Independence/Basic.lean +++ b/Mathlib/Probability/Independence/Basic.lean @@ -704,7 +704,7 @@ lemma iIndepFun.indepFun_prod_mk_prod_mk (h_indep : iIndepFun m f μ) (hf : ∀ IndepFun (fun a ↦ (f i a, f j a)) (fun a ↦ (f k a, f l a)) μ := by classical let g (i j : ι) (v : Π x : ({i, j} : Finset ι), β x) : β i × β j := - ⟨v ⟨i, mem_insert_self _ _⟩, v ⟨j, mem_insert_of_mem $ mem_singleton_self _⟩⟩ + ⟨v ⟨i, mem_insert_self _ _⟩, v ⟨j, mem_insert_of_mem <| mem_singleton_self _⟩⟩ have hg (i j : ι) : Measurable (g i j) := by measurability exact (h_indep.indepFun_finset {i, j} {k, l} (by aesop) hf).comp (hg i j) (hg k l) diff --git a/Mathlib/Probability/Independence/Conditional.lean b/Mathlib/Probability/Independence/Conditional.lean index c0c12d16890ba..66aa6cc92c64b 100644 --- a/Mathlib/Probability/Independence/Conditional.lean +++ b/Mathlib/Probability/Independence/Conditional.lean @@ -723,7 +723,7 @@ lemma iCondIndepFun.condIndepFun_prod_mk_prod_mk (h_indep : iCondIndepFun m' hm' CondIndepFun m' hm' (fun a ↦ (f i a, f j a)) (fun a ↦ (f k a, f l a)) μ := by classical let g (i j : ι) (v : Π x : ({i, j} : Finset ι), β x) : β i × β j := - ⟨v ⟨i, mem_insert_self _ _⟩, v ⟨j, mem_insert_of_mem $ mem_singleton_self _⟩⟩ + ⟨v ⟨i, mem_insert_self _ _⟩, v ⟨j, mem_insert_of_mem <| mem_singleton_self _⟩⟩ have hg (i j : ι) : Measurable (g i j) := by measurability exact (h_indep.indepFun_finset {i, j} {k, l} (by aesop) hf).comp (hg i j) (hg k l) diff --git a/Mathlib/Probability/Independence/Kernel.lean b/Mathlib/Probability/Independence/Kernel.lean index 222525433f5ab..8e2ba9e5fd611 100644 --- a/Mathlib/Probability/Independence/Kernel.lean +++ b/Mathlib/Probability/Independence/Kernel.lean @@ -953,7 +953,7 @@ lemma iIndepFun.indepFun_prod_mk_prod_mk [IsMarkovKernel κ] (hf_indep : iIndepF IndepFun (fun a ↦ (f i a, f j a)) (fun a ↦ (f k a, f l a)) κ μ := by classical let g (i j : ι) (v : Π x : ({i, j} : Finset ι), β x) : β i × β j := - ⟨v ⟨i, mem_insert_self _ _⟩, v ⟨j, mem_insert_of_mem $ mem_singleton_self _⟩⟩ + ⟨v ⟨i, mem_insert_self _ _⟩, v ⟨j, mem_insert_of_mem <| mem_singleton_self _⟩⟩ have hg (i j : ι) : Measurable (g i j) := by measurability exact (hf_indep.indepFun_finset {i, j} {k, l} (by aesop) hf_meas).comp (hg i j) (hg k l) @@ -1027,16 +1027,16 @@ theorem iIndepFun.indepFun_finset_prod_of_not_mem (hf_Indep : iIndepFun (fun _ IndepFun (∏ j in s, f j) (f i) κ μ := by classical have h_right : f i = - (fun p : ∀ _j : ({i} : Finset ι), β => p ⟨i, Finset.mem_singleton_self i⟩) ∘ + (fun p : ({i} : Finset ι) → β => p ⟨i, Finset.mem_singleton_self i⟩) ∘ fun a (j : ({i} : Finset ι)) => f j a := rfl - have h_meas_right : Measurable fun p : ∀ _j : ({i} : Finset ι), β + have h_meas_right : Measurable fun p : ({i} : Finset ι) → β => p ⟨i, Finset.mem_singleton_self i⟩ := measurable_pi_apply ⟨i, Finset.mem_singleton_self i⟩ - have h_left : ∏ j in s, f j = (fun p : ∀ _j : s, β => ∏ j, p j) ∘ fun a (j : s) => f j a := by + have h_left : ∏ j in s, f j = (fun p : s → β => ∏ j, p j) ∘ fun a (j : s) => f j a := by ext1 a simp only [Function.comp_apply] have : (∏ j : ↥s, f (↑j) a) = (∏ j : ↥s, f ↑j) a := by rw [Finset.prod_apply] rw [this, Finset.prod_coe_sort] - have h_meas_left : Measurable fun p : ∀ _j : s, β => ∏ j, p j := + have h_meas_left : Measurable fun p : s → β => ∏ j, p j := Finset.univ.measurable_prod fun (j : ↥s) (_H : j ∈ Finset.univ) => measurable_pi_apply j rw [h_left, h_right] exact diff --git a/Mathlib/Probability/Kernel/Basic.lean b/Mathlib/Probability/Kernel/Basic.lean index b34bba212cc20..c05dad0306633 100644 --- a/Mathlib/Probability/Kernel/Basic.lean +++ b/Mathlib/Probability/Kernel/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ import Mathlib.MeasureTheory.Integral.Bochner -import Mathlib.MeasureTheory.Constructions.Prod.Basic +import Mathlib.MeasureTheory.Measure.GiryMonad #align_import probability.kernel.basic from "leanprover-community/mathlib"@"fd5edc43dc4f10b85abfe544b88f82cf13c5f844" @@ -64,9 +64,9 @@ noncomputable def kernel (α β : Type*) [MeasurableSpace α] [MeasurableSpace add_mem' hf hg := Measurable.add hf hg #align probability_theory.kernel ProbabilityTheory.kernel --- Porting note: using `FunLike` instead of `CoeFun` to use `FunLike.coe` +-- Porting note: using `FunLike` instead of `CoeFun` to use `DFunLike.coe` instance {α β : Type*} [MeasurableSpace α] [MeasurableSpace β] : - FunLike (kernel α β) α fun _ => Measure β where + FunLike (kernel α β) α (Measure β) where coe := Subtype.val coe_injective' := Subtype.val_injective @@ -177,10 +177,10 @@ instance (priority := 100) IsMarkovKernel.isFiniteKernel [IsMarkovKernel κ] : namespace kernel @[ext] -theorem ext {η : kernel α β} (h : ∀ a, κ a = η a) : κ = η := FunLike.ext _ _ h +theorem ext {η : kernel α β} (h : ∀ a, κ a = η a) : κ = η := DFunLike.ext _ _ h #align probability_theory.kernel.ext ProbabilityTheory.kernel.ext -theorem ext_iff {η : kernel α β} : κ = η ↔ ∀ a, κ a = η a := FunLike.ext_iff +theorem ext_iff {η : kernel α β} : κ = η ↔ ∀ a, κ a = η a := DFunLike.ext_iff #align probability_theory.kernel.ext_iff ProbabilityTheory.kernel.ext_iff theorem ext_iff' {η : kernel α β} : diff --git a/Mathlib/Probability/Kernel/Composition.lean b/Mathlib/Probability/Kernel/Composition.lean index 59cf8cb60ec83..03cfeed68e94b 100644 --- a/Mathlib/Probability/Kernel/Composition.lean +++ b/Mathlib/Probability/Kernel/Composition.lean @@ -565,7 +565,7 @@ section MapComap /-! ### map, comap -/ -variable {γ : Type*} {mγ : MeasurableSpace γ} {f : β → γ} {g : γ → α} +variable {γ δ : Type*} {mγ : MeasurableSpace γ} {mδ : MeasurableSpace δ} {f : β → γ} {g : γ → α} /-- The pushforward of a kernel along a measurable function. We include measurability in the assumptions instead of using junk values @@ -676,6 +676,12 @@ instance IsSFiniteKernel.comap (κ : kernel α β) [IsSFiniteKernel κ] (hg : Me ⟨⟨fun n => kernel.comap (seq κ n) g hg, inferInstance, (sum_comap_seq κ hg).symm⟩⟩ #align probability_theory.kernel.is_s_finite_kernel.comap ProbabilityTheory.kernel.IsSFiniteKernel.comap +lemma comap_map_comm (κ : kernel β γ) {f : α → β} {g : γ → δ} + (hf : Measurable f) (hg : Measurable g) : + comap (map κ g hg) f hf = map (comap κ f hf) g hg := by + ext x s _ + rw [comap_apply, map_apply, map_apply, comap_apply] + end MapComap open scoped ProbabilityTheory @@ -689,6 +695,10 @@ def prodMkLeft (γ : Type*) [MeasurableSpace γ] (κ : kernel α β) : kernel ( comap κ Prod.snd measurable_snd #align probability_theory.kernel.prod_mk_left ProbabilityTheory.kernel.prodMkLeft +/-- Define a `kernel (α × γ) β` from a `kernel α β` by taking the comap of the projection. -/ +def prodMkRight (γ : Type*) [MeasurableSpace γ] (κ : kernel α β) : kernel (α × γ) β := + comap κ Prod.fst measurable_fst + variable {γ : Type*} {mγ : MeasurableSpace γ} {f : β → γ} {g : γ → α} @[simp] @@ -696,32 +706,61 @@ theorem prodMkLeft_apply (κ : kernel α β) (ca : γ × α) : prodMkLeft γ κ rfl #align probability_theory.kernel.prod_mk_left_apply ProbabilityTheory.kernel.prodMkLeft_apply +@[simp] +theorem prodMkRight_apply (κ : kernel α β) (ca : α × γ) : prodMkRight γ κ ca = κ ca.fst := rfl + theorem prodMkLeft_apply' (κ : kernel α β) (ca : γ × α) (s : Set β) : prodMkLeft γ κ ca s = κ ca.snd s := rfl #align probability_theory.kernel.prod_mk_left_apply' ProbabilityTheory.kernel.prodMkLeft_apply' +theorem prodMkRight_apply' (κ : kernel α β) (ca : α × γ) (s : Set β) : + prodMkRight γ κ ca s = κ ca.fst s := rfl + @[simp] lemma prodMkLeft_zero : kernel.prodMkLeft α (0 : kernel β γ) = 0 := by - ext x s _; simp [kernel.prodMkLeft_apply'] + ext x s _; simp + +@[simp] +lemma prodMkRight_zero : kernel.prodMkRight α (0 : kernel β γ) = 0 := by + ext x s _; simp theorem lintegral_prodMkLeft (κ : kernel α β) (ca : γ × α) (g : β → ℝ≥0∞) : - ∫⁻ b, g b ∂prodMkLeft γ κ ca = ∫⁻ b, g b ∂κ ca.snd := - rfl + ∫⁻ b, g b ∂prodMkLeft γ κ ca = ∫⁻ b, g b ∂κ ca.snd := rfl #align probability_theory.kernel.lintegral_prod_mk_left ProbabilityTheory.kernel.lintegral_prodMkLeft +theorem lintegral_prodMkRight (κ : kernel α β) (ca : α × γ) (g : β → ℝ≥0∞) : + ∫⁻ b, g b ∂prodMkRight γ κ ca = ∫⁻ b, g b ∂κ ca.fst := rfl + instance IsMarkovKernel.prodMkLeft (κ : kernel α β) [IsMarkovKernel κ] : IsMarkovKernel (prodMkLeft γ κ) := by rw [kernel.prodMkLeft]; infer_instance #align probability_theory.kernel.is_markov_kernel.prod_mk_left ProbabilityTheory.kernel.IsMarkovKernel.prodMkLeft +instance IsMarkovKernel.prodMkRight (κ : kernel α β) [IsMarkovKernel κ] : + IsMarkovKernel (prodMkRight γ κ) := by rw [kernel.prodMkRight]; infer_instance + instance IsFiniteKernel.prodMkLeft (κ : kernel α β) [IsFiniteKernel κ] : IsFiniteKernel (prodMkLeft γ κ) := by rw [kernel.prodMkLeft]; infer_instance #align probability_theory.kernel.is_finite_kernel.prod_mk_left ProbabilityTheory.kernel.IsFiniteKernel.prodMkLeft +instance IsFiniteKernel.prodMkRight (κ : kernel α β) [IsFiniteKernel κ] : + IsFiniteKernel (prodMkRight γ κ) := by rw [kernel.prodMkRight]; infer_instance + instance IsSFiniteKernel.prodMkLeft (κ : kernel α β) [IsSFiniteKernel κ] : IsSFiniteKernel (prodMkLeft γ κ) := by rw [kernel.prodMkLeft]; infer_instance #align probability_theory.kernel.is_s_finite_kernel.prod_mk_left ProbabilityTheory.kernel.IsSFiniteKernel.prodMkLeft +instance IsSFiniteKernel.prodMkRight (κ : kernel α β) [IsSFiniteKernel κ] : + IsSFiniteKernel (prodMkRight γ κ) := by rw [kernel.prodMkRight]; infer_instance + +lemma map_prodMkLeft (γ : Type*) [MeasurableSpace γ] (κ : kernel α β) + {f : β → δ} (hf : Measurable f) : + map (prodMkLeft γ κ) f hf = prodMkLeft γ (map κ f hf) := rfl + +lemma map_prodMkRight (κ : kernel α β) (γ : Type*) [MeasurableSpace γ] + {f : β → δ} (hf : Measurable f) : + map (prodMkRight γ κ) f hf = prodMkRight γ (map κ f hf) := rfl + /-- Define a `kernel (β × α) γ` from a `kernel (α × β) γ` by taking the comap of `Prod.swap`. -/ def swapLeft (κ : kernel (α × β) γ) : kernel (β × α) γ := comap κ Prod.swap measurable_swap @@ -752,6 +791,12 @@ instance IsSFiniteKernel.swapLeft (κ : kernel (α × β) γ) [IsSFiniteKernel IsSFiniteKernel (swapLeft κ) := by rw [kernel.swapLeft]; infer_instance #align probability_theory.kernel.is_s_finite_kernel.swap_left ProbabilityTheory.kernel.IsSFiniteKernel.swapLeft +@[simp] lemma swapLeft_prodMkLeft (κ : kernel α β) (γ : Type*) [MeasurableSpace γ] : + swapLeft (prodMkLeft γ κ) = prodMkRight γ κ := rfl + +@[simp] lemma swapLeft_prodMkRight (κ : kernel α β) (γ : Type*) [MeasurableSpace γ] : + swapLeft (prodMkRight γ κ) = prodMkLeft γ κ := rfl + /-- Define a `kernel α (γ × β)` from a `kernel α (β × γ)` by taking the map of `Prod.swap`. -/ noncomputable def swapRight (κ : kernel α (β × γ)) : kernel α (γ × β) := map κ Prod.swap measurable_swap @@ -838,6 +883,12 @@ lemma fst_compProd (κ : kernel α β) (η : kernel (α × β) γ) [IsSFiniteKer simp_rw [this] rw [lintegral_indicator_const hs, one_mul] +lemma fst_prodMkLeft (δ : Type*) [MeasurableSpace δ] (κ : kernel α (β × γ)) : + fst (prodMkLeft δ κ) = prodMkLeft δ (fst κ) := rfl + +lemma fst_prodMkRight (κ : kernel α (β × γ)) (δ : Type*) [MeasurableSpace δ] : + fst (prodMkRight δ κ) = prodMkRight δ (fst κ) := rfl + /-- Define a `kernel α γ` from a `kernel α (β × γ)` by taking the map of the second projection. -/ noncomputable def snd (κ : kernel α (β × γ)) : kernel α γ := map κ Prod.snd measurable_snd @@ -879,6 +930,12 @@ lemma snd_map_prod (κ : kernel α β) {f : β → γ} {g : β → δ} · rfl · exact measurable_snd hs +lemma snd_prodMkLeft (δ : Type*) [MeasurableSpace δ] (κ : kernel α (β × γ)) : + snd (prodMkLeft δ κ) = prodMkLeft δ (snd κ) := rfl + +lemma snd_prodMkRight (κ : kernel α (β × γ)) (δ : Type*) [MeasurableSpace δ] : + snd (prodMkRight δ κ) = prodMkRight δ (snd κ) := rfl + @[simp] lemma fst_swapRight (κ : kernel α (β × γ)) : fst (swapRight κ) = snd κ := by ext a s hs @@ -982,11 +1039,23 @@ noncomputable def prod (κ : kernel α β) (η : kernel α γ) : kernel α (β scoped[ProbabilityTheory] infixl:100 " ×ₖ " => ProbabilityTheory.kernel.prod -theorem prod_apply (κ : kernel α β) [IsSFiniteKernel κ] (η : kernel α γ) [IsSFiniteKernel η] (a : α) - {s : Set (β × γ)} (hs : MeasurableSet s) : +theorem prod_apply' (κ : kernel α β) [IsSFiniteKernel κ] (η : kernel α γ) [IsSFiniteKernel η] + (a : α) {s : Set (β × γ)} (hs : MeasurableSet s) : (κ ×ₖ η) a s = ∫⁻ b : β, (η a) {c : γ | (b, c) ∈ s} ∂κ a := by simp_rw [prod, compProd_apply _ _ _ hs, swapLeft_apply _ _, prodMkLeft_apply, Prod.swap_prod_mk] -#align probability_theory.kernel.prod_apply ProbabilityTheory.kernel.prod_apply +#align probability_theory.kernel.prod_apply ProbabilityTheory.kernel.prod_apply' + +lemma prod_apply (κ : kernel α β) [IsSFiniteKernel κ] (η : kernel α γ) [IsSFiniteKernel η] + (a : α) : + (κ ×ₖ η) a = (κ a).prod (η a) := by + ext s hs + rw [prod_apply' _ _ _ hs, Measure.prod_apply hs] + rfl + +lemma prod_const (μ : Measure α) [SFinite μ] (ν : Measure β) [SFinite ν] : + const α μ ×ₖ const α ν = const α (μ.prod ν) := by + ext x + rw [const_apply, prod_apply, const_apply, const_apply] theorem lintegral_prod (κ : kernel α β) [IsSFiniteKernel κ] (η : kernel α γ) [IsSFiniteKernel η] (a : α) {g : β × γ → ℝ≥0∞} (hg : Measurable g) : @@ -1006,6 +1075,14 @@ instance IsSFiniteKernel.prod (κ : kernel α β) (η : kernel α γ) : IsSFiniteKernel (κ ×ₖ η) := by rw [kernel.prod]; infer_instance #align probability_theory.kernel.is_s_finite_kernel.prod ProbabilityTheory.kernel.IsSFiniteKernel.prod +@[simp] lemma fst_prod (κ : kernel α β) [IsSFiniteKernel κ] (η : kernel α γ) [IsMarkovKernel η] : + fst (κ ×ₖ η) = κ := by + rw [prod]; simp + +@[simp] lemma snd_prod (κ : kernel α β) [IsMarkovKernel κ] (η : kernel α γ) [IsSFiniteKernel η] : + snd (κ ×ₖ η) = η := by + ext x; simp [snd_apply, prod_apply] + end Prod end kernel diff --git a/Mathlib/Probability/Kernel/CondCdf.lean b/Mathlib/Probability/Kernel/CondCdf.lean index be65145c37494..2d223aba3e6ac 100644 --- a/Mathlib/Probability/Kernel/CondCdf.lean +++ b/Mathlib/Probability/Kernel/CondCdf.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ import Mathlib.MeasureTheory.Measure.Stieltjes -import Mathlib.Probability.Kernel.Composition import Mathlib.MeasureTheory.Decomposition.RadonNikodym +import Mathlib.MeasureTheory.Constructions.Prod.Basic #align_import probability.kernel.cond_cdf from "leanprover-community/mathlib"@"3b88f4005dc2e28d42f974cc1ce838f0dafb39b8" @@ -45,7 +45,7 @@ The construction of the conditional cdf in this file follows the proof of Theore open MeasureTheory Set Filter TopologicalSpace -open scoped NNReal ENNReal MeasureTheory Topology ProbabilityTheory +open scoped NNReal ENNReal MeasureTheory Topology section AuxLemmasToBeMoved @@ -289,101 +289,101 @@ the properties of a cdf for all `a : α`. We finally extend to `ℝ`. -/ satisfies the properties of a cdf (monotone with limit 0 at -∞ and 1 at +∞, right-continuous). We define this function on `ℚ` and not `ℝ` because `ℚ` is countable, which allows us to prove -properties of the form `∀ᵐ a ∂ρ.fst, ∀ q, P (pre_cdf q a)`, instead of the weaker -`∀ q, ∀ᵐ a ∂ρ.fst, P (pre_cdf q a)`. -/ -noncomputable def preCdf (ρ : Measure (α × ℝ)) (r : ℚ) : α → ℝ≥0∞ := +properties of the form `∀ᵐ a ∂ρ.fst, ∀ q, P (preCDF q a)`, instead of the weaker +`∀ q, ∀ᵐ a ∂ρ.fst, P (preCDF q a)`. -/ +noncomputable def preCDF (ρ : Measure (α × ℝ)) (r : ℚ) : α → ℝ≥0∞ := Measure.rnDeriv (ρ.IicSnd r) ρ.fst -#align probability_theory.pre_cdf ProbabilityTheory.preCdf +#align probability_theory.pre_cdf ProbabilityTheory.preCDF -theorem measurable_preCdf {ρ : Measure (α × ℝ)} {r : ℚ} : Measurable (preCdf ρ r) := +theorem measurable_preCDF {ρ : Measure (α × ℝ)} {r : ℚ} : Measurable (preCDF ρ r) := Measure.measurable_rnDeriv _ _ -#align probability_theory.measurable_pre_cdf ProbabilityTheory.measurable_preCdf +#align probability_theory.measurable_pre_cdf ProbabilityTheory.measurable_preCDF -theorem withDensity_preCdf (ρ : Measure (α × ℝ)) (r : ℚ) [IsFiniteMeasure ρ] : - ρ.fst.withDensity (preCdf ρ r) = ρ.IicSnd r := +theorem withDensity_preCDF (ρ : Measure (α × ℝ)) (r : ℚ) [IsFiniteMeasure ρ] : + ρ.fst.withDensity (preCDF ρ r) = ρ.IicSnd r := Measure.absolutelyContinuous_iff_withDensity_rnDeriv_eq.mp (Measure.IicSnd_ac_fst ρ r) -#align probability_theory.with_density_pre_cdf ProbabilityTheory.withDensity_preCdf +#align probability_theory.with_density_pre_cdf ProbabilityTheory.withDensity_preCDF -theorem set_lintegral_preCdf_fst (ρ : Measure (α × ℝ)) (r : ℚ) {s : Set α} (hs : MeasurableSet s) - [IsFiniteMeasure ρ] : ∫⁻ x in s, preCdf ρ r x ∂ρ.fst = ρ.IicSnd r s := by - have : ∀ r, ∫⁻ x in s, preCdf ρ r x ∂ρ.fst = ∫⁻ x in s, (preCdf ρ r * 1) x ∂ρ.fst := by +theorem set_lintegral_preCDF_fst (ρ : Measure (α × ℝ)) (r : ℚ) {s : Set α} (hs : MeasurableSet s) + [IsFiniteMeasure ρ] : ∫⁻ x in s, preCDF ρ r x ∂ρ.fst = ρ.IicSnd r s := by + have : ∀ r, ∫⁻ x in s, preCDF ρ r x ∂ρ.fst = ∫⁻ x in s, (preCDF ρ r * 1) x ∂ρ.fst := by simp only [mul_one, eq_self_iff_true, forall_const] - rw [this, ← set_lintegral_withDensity_eq_set_lintegral_mul _ measurable_preCdf _ hs] - · simp only [withDensity_preCdf ρ r, Pi.one_apply, lintegral_one, Measure.restrict_apply, + rw [this, ← set_lintegral_withDensity_eq_set_lintegral_mul _ measurable_preCDF _ hs] + · simp only [withDensity_preCDF ρ r, Pi.one_apply, lintegral_one, Measure.restrict_apply, MeasurableSet.univ, univ_inter] · rw [(_ : (1 : α → ℝ≥0∞) = fun _ => 1)] exacts [measurable_const, rfl] -#align probability_theory.set_lintegral_pre_cdf_fst ProbabilityTheory.set_lintegral_preCdf_fst +#align probability_theory.set_lintegral_pre_cdf_fst ProbabilityTheory.set_lintegral_preCDF_fst -theorem monotone_preCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : - ∀ᵐ a ∂ρ.fst, Monotone fun r => preCdf ρ r a := by +theorem monotone_preCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : + ∀ᵐ a ∂ρ.fst, Monotone fun r => preCDF ρ r a := by simp_rw [Monotone, ae_all_iff] refine' fun r r' hrr' => - ae_le_of_forall_set_lintegral_le_of_sigmaFinite measurable_preCdf measurable_preCdf + ae_le_of_forall_set_lintegral_le_of_sigmaFinite measurable_preCDF measurable_preCDF fun s hs _ => _ - rw [set_lintegral_preCdf_fst ρ r hs, set_lintegral_preCdf_fst ρ r' hs] + rw [set_lintegral_preCDF_fst ρ r hs, set_lintegral_preCDF_fst ρ r' hs] refine' Measure.IicSnd_mono ρ _ s hs exact mod_cast hrr' -#align probability_theory.monotone_pre_cdf ProbabilityTheory.monotone_preCdf +#align probability_theory.monotone_pre_cdf ProbabilityTheory.monotone_preCDF -theorem set_lintegral_iInf_gt_preCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (t : ℚ) {s : Set α} - (hs : MeasurableSet s) : ∫⁻ x in s, ⨅ r : Ioi t, preCdf ρ r x ∂ρ.fst = ρ.IicSnd t s := by +theorem set_lintegral_iInf_gt_preCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (t : ℚ) {s : Set α} + (hs : MeasurableSet s) : ∫⁻ x in s, ⨅ r : Ioi t, preCDF ρ r x ∂ρ.fst = ρ.IicSnd t s := by refine' le_antisymm _ _ - · have h : ∀ q : Ioi t, ∫⁻ x in s, ⨅ r : Ioi t, preCdf ρ r x ∂ρ.fst ≤ ρ.IicSnd q s := by + · have h : ∀ q : Ioi t, ∫⁻ x in s, ⨅ r : Ioi t, preCDF ρ r x ∂ρ.fst ≤ ρ.IicSnd q s := by intro q - rw [← set_lintegral_preCdf_fst ρ _ hs] - refine' set_lintegral_mono_ae _ measurable_preCdf _ - · exact measurable_iInf fun _ => measurable_preCdf - · filter_upwards [monotone_preCdf _] with a _ + rw [← set_lintegral_preCDF_fst ρ _ hs] + refine' set_lintegral_mono_ae _ measurable_preCDF _ + · exact measurable_iInf fun _ => measurable_preCDF + · filter_upwards [monotone_preCDF _] with a _ exact fun _ => iInf_le _ q calc - ∫⁻ x in s, ⨅ r : Ioi t, preCdf ρ r x ∂ρ.fst ≤ ⨅ q : Ioi t, ρ.IicSnd q s := le_iInf h + ∫⁻ x in s, ⨅ r : Ioi t, preCDF ρ r x ∂ρ.fst ≤ ⨅ q : Ioi t, ρ.IicSnd q s := le_iInf h _ = ρ.IicSnd t s := Measure.iInf_IicSnd_gt ρ t hs - · rw [(set_lintegral_preCdf_fst ρ t hs).symm] - refine' set_lintegral_mono_ae measurable_preCdf _ _ - · exact measurable_iInf fun _ => measurable_preCdf - · filter_upwards [monotone_preCdf _] with a ha_mono + · rw [(set_lintegral_preCDF_fst ρ t hs).symm] + refine' set_lintegral_mono_ae measurable_preCDF _ _ + · exact measurable_iInf fun _ => measurable_preCDF + · filter_upwards [monotone_preCDF _] with a ha_mono exact fun _ => le_iInf fun r => ha_mono (le_of_lt r.prop) -#align probability_theory.set_lintegral_infi_gt_pre_cdf ProbabilityTheory.set_lintegral_iInf_gt_preCdf +#align probability_theory.set_lintegral_infi_gt_pre_cdf ProbabilityTheory.set_lintegral_iInf_gt_preCDF -theorem preCdf_le_one (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : - ∀ᵐ a ∂ρ.fst, ∀ r, preCdf ρ r a ≤ 1 := by +theorem preCDF_le_one (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : + ∀ᵐ a ∂ρ.fst, ∀ r, preCDF ρ r a ≤ 1 := by rw [ae_all_iff] refine' fun r => - ae_le_of_forall_set_lintegral_le_of_sigmaFinite measurable_preCdf measurable_const + ae_le_of_forall_set_lintegral_le_of_sigmaFinite measurable_preCDF measurable_const fun s hs _ => _ - rw [set_lintegral_preCdf_fst ρ r hs] + rw [set_lintegral_preCDF_fst ρ r hs] simp only [Pi.one_apply, lintegral_one, Measure.restrict_apply, MeasurableSet.univ, univ_inter] exact Measure.IicSnd_le_fst ρ r s hs -#align probability_theory.pre_cdf_le_one ProbabilityTheory.preCdf_le_one +#align probability_theory.pre_cdf_le_one ProbabilityTheory.preCDF_le_one -theorem tendsto_lintegral_preCdf_atTop (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : - Tendsto (fun r => ∫⁻ a, preCdf ρ r a ∂ρ.fst) atTop (𝓝 (ρ univ)) := by +theorem tendsto_lintegral_preCDF_atTop (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : + Tendsto (fun r => ∫⁻ a, preCDF ρ r a ∂ρ.fst) atTop (𝓝 (ρ univ)) := by convert ρ.tendsto_IicSnd_atTop MeasurableSet.univ - · rw [← set_lintegral_univ, set_lintegral_preCdf_fst ρ _ MeasurableSet.univ] + · rw [← set_lintegral_univ, set_lintegral_preCDF_fst ρ _ MeasurableSet.univ] · exact Measure.fst_univ.symm -#align probability_theory.tendsto_lintegral_pre_cdf_at_top ProbabilityTheory.tendsto_lintegral_preCdf_atTop +#align probability_theory.tendsto_lintegral_pre_cdf_at_top ProbabilityTheory.tendsto_lintegral_preCDF_atTop -theorem tendsto_lintegral_preCdf_atBot (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : - Tendsto (fun r => ∫⁻ a, preCdf ρ r a ∂ρ.fst) atBot (𝓝 0) := by +theorem tendsto_lintegral_preCDF_atBot (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : + Tendsto (fun r => ∫⁻ a, preCDF ρ r a ∂ρ.fst) atBot (𝓝 0) := by convert ρ.tendsto_IicSnd_atBot MeasurableSet.univ - rw [← set_lintegral_univ, set_lintegral_preCdf_fst ρ _ MeasurableSet.univ] -#align probability_theory.tendsto_lintegral_pre_cdf_at_bot ProbabilityTheory.tendsto_lintegral_preCdf_atBot + rw [← set_lintegral_univ, set_lintegral_preCDF_fst ρ _ MeasurableSet.univ] +#align probability_theory.tendsto_lintegral_pre_cdf_at_bot ProbabilityTheory.tendsto_lintegral_preCDF_atBot -theorem tendsto_preCdf_atTop_one (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : - ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCdf ρ r a) atTop (𝓝 1) := by - -- We show first that `preCdf` has a limit almost everywhere. That limit has to be at most 1. - -- We then show that the integral of `preCdf` tends to the integral of 1, and that it also tends +theorem tendsto_preCDF_atTop_one (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : + ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCDF ρ r a) atTop (𝓝 1) := by + -- We show first that `preCDF` has a limit almost everywhere. That limit has to be at most 1. + -- We then show that the integral of `preCDF` tends to the integral of 1, and that it also tends -- to the integral of the limit. Since the limit is at most 1 and has same integral as 1, it is -- equal to 1 a.e. - have h_mono := monotone_preCdf ρ - have h_le_one := preCdf_le_one ρ - -- `preCdf` has a limit a.e. - have h_exists : ∀ᵐ a ∂ρ.fst, ∃ l, Tendsto (fun r => preCdf ρ r a) atTop (𝓝 l) := by + have h_mono := monotone_preCDF ρ + have h_le_one := preCDF_le_one ρ + -- `preCDF` has a limit a.e. + have h_exists : ∀ᵐ a ∂ρ.fst, ∃ l, Tendsto (fun r => preCDF ρ r a) atTop (𝓝 l) := by filter_upwards [h_mono, h_le_one] with a ha_mono ha_le_one have h_tendsto : - Tendsto (fun r => preCdf ρ r a) atTop atTop ∨ - ∃ l, Tendsto (fun r => preCdf ρ r a) atTop (𝓝 l) := + Tendsto (fun r => preCDF ρ r a) atTop atTop ∨ + ∃ l, Tendsto (fun r => preCDF ρ r a) atTop (𝓝 l) := tendsto_of_monotone ha_mono cases' h_tendsto with h_absurd h_tendsto · rw [Monotone.tendsto_atTop_atTop_iff ha_mono] at h_absurd @@ -391,18 +391,18 @@ theorem tendsto_preCdf_atTop_one (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] exact absurd (hr.trans (ha_le_one r)) ENNReal.one_lt_two.not_le · exact h_tendsto classical - -- let `F` be the pointwise limit of `preCdf` where it exists, and 0 elsewhere. + -- let `F` be the pointwise limit of `preCDF` where it exists, and 0 elsewhere. let F : α → ℝ≥0∞ := fun a => - if h : ∃ l, Tendsto (fun r => preCdf ρ r a) atTop (𝓝 l) then h.choose else 0 - have h_tendsto_ℚ : ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCdf ρ r a) atTop (𝓝 (F a)) := by + if h : ∃ l, Tendsto (fun r => preCDF ρ r a) atTop (𝓝 l) then h.choose else 0 + have h_tendsto_ℚ : ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCDF ρ r a) atTop (𝓝 (F a)) := by filter_upwards [h_exists] with a ha simp_rw [dif_pos ha] exact ha.choose_spec - have h_tendsto_ℕ : ∀ᵐ a ∂ρ.fst, Tendsto (fun n : ℕ => preCdf ρ n a) atTop (𝓝 (F a)) := by + have h_tendsto_ℕ : ∀ᵐ a ∂ρ.fst, Tendsto (fun n : ℕ => preCDF ρ n a) atTop (𝓝 (F a)) := by filter_upwards [h_tendsto_ℚ] with a ha using ha.comp tendsto_nat_cast_atTop_atTop have hF_ae_meas : AEMeasurable F ρ.fst := by refine' aemeasurable_of_tendsto_metrizable_ae _ (fun n => _) h_tendsto_ℚ - exact measurable_preCdf.aemeasurable + exact measurable_preCDF.aemeasurable have hF_le_one : ∀ᵐ a ∂ρ.fst, F a ≤ 1 := by filter_upwards [h_tendsto_ℚ, h_le_one] with a ha ha_le using le_of_tendsto' ha ha_le -- it suffices to show that the limit `F` is 1 a.e. @@ -413,19 +413,19 @@ theorem tendsto_preCdf_atTop_one (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] -- us that `F` is 1 a.e. have h_lintegral_eq : ∫⁻ a, F a ∂ρ.fst = ∫⁻ _, 1 ∂ρ.fst := by have h_lintegral : - Tendsto (fun r : ℕ => ∫⁻ a, preCdf ρ r a ∂ρ.fst) atTop (𝓝 (∫⁻ a, F a ∂ρ.fst)) := by + Tendsto (fun r : ℕ => ∫⁻ a, preCDF ρ r a ∂ρ.fst) atTop (𝓝 (∫⁻ a, F a ∂ρ.fst)) := by refine' lintegral_tendsto_of_tendsto_of_monotone (-- does this exist only for ℕ? - fun _ => measurable_preCdf.aemeasurable) + fun _ => measurable_preCDF.aemeasurable) _ h_tendsto_ℕ filter_upwards [h_mono] with a ha refine' fun n m hnm => ha _ exact mod_cast hnm have h_lintegral' : - Tendsto (fun r : ℕ => ∫⁻ a, preCdf ρ r a ∂ρ.fst) atTop (𝓝 (∫⁻ _, 1 ∂ρ.fst)) := by + Tendsto (fun r : ℕ => ∫⁻ a, preCDF ρ r a ∂ρ.fst) atTop (𝓝 (∫⁻ _, 1 ∂ρ.fst)) := by rw [lintegral_one, Measure.fst_univ] - exact (tendsto_lintegral_preCdf_atTop ρ).comp tendsto_nat_cast_atTop_atTop + exact (tendsto_lintegral_preCDF_atTop ρ).comp tendsto_nat_cast_atTop_atTop exact tendsto_nhds_unique h_lintegral h_lintegral' have : ∫⁻ a, 1 - F a ∂ρ.fst = 0 := by rw [lintegral_sub' hF_ae_meas _ hF_le_one, h_lintegral_eq, tsub_self] @@ -438,57 +438,57 @@ theorem tendsto_preCdf_atTop_one (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] filter_upwards [this, hF_le_one] with ha h_one_sub_eq_zero h_le_one rw [Pi.zero_apply, tsub_eq_zero_iff_le] at h_one_sub_eq_zero exact le_antisymm h_le_one h_one_sub_eq_zero -#align probability_theory.tendsto_pre_cdf_at_top_one ProbabilityTheory.tendsto_preCdf_atTop_one +#align probability_theory.tendsto_pre_cdf_at_top_one ProbabilityTheory.tendsto_preCDF_atTop_one -theorem tendsto_preCdf_atBot_zero (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : - ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCdf ρ r a) atBot (𝓝 0) := by - -- We show first that `preCdf` has a limit in ℝ≥0∞ almost everywhere. +theorem tendsto_preCDF_atBot_zero (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : + ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCDF ρ r a) atBot (𝓝 0) := by + -- We show first that `preCDF` has a limit in ℝ≥0∞ almost everywhere. -- We then show that the integral of `pre_cdf` tends to 0, and that it also tends -- to the integral of the limit. Since the limit has integral 0, it is equal to 0 a.e. - suffices ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCdf ρ (-r) a) atTop (𝓝 0) by + suffices ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCDF ρ (-r) a) atTop (𝓝 0) by filter_upwards [this] with a ha - have h_eq_neg : (fun r : ℚ => preCdf ρ r a) = fun r : ℚ => preCdf ρ (- -r) a := by + have h_eq_neg : (fun r : ℚ => preCDF ρ r a) = fun r : ℚ => preCDF ρ (- -r) a := by simp_rw [neg_neg] rw [h_eq_neg] exact ha.comp tendsto_neg_atBot_atTop - have h_exists : ∀ᵐ a ∂ρ.fst, ∃ l, Tendsto (fun r => preCdf ρ (-r) a) atTop (𝓝 l) := by - filter_upwards [monotone_preCdf ρ] with a ha - have h_anti : Antitone fun r => preCdf ρ (-r) a := fun p q hpq => ha (neg_le_neg hpq) + have h_exists : ∀ᵐ a ∂ρ.fst, ∃ l, Tendsto (fun r => preCDF ρ (-r) a) atTop (𝓝 l) := by + filter_upwards [monotone_preCDF ρ] with a ha + have h_anti : Antitone fun r => preCDF ρ (-r) a := fun p q hpq => ha (neg_le_neg hpq) have h_tendsto : - Tendsto (fun r => preCdf ρ (-r) a) atTop atBot ∨ - ∃ l, Tendsto (fun r => preCdf ρ (-r) a) atTop (𝓝 l) := + Tendsto (fun r => preCDF ρ (-r) a) atTop atBot ∨ + ∃ l, Tendsto (fun r => preCDF ρ (-r) a) atTop (𝓝 l) := tendsto_of_antitone h_anti cases' h_tendsto with h_bot h_tendsto · exact ⟨0, Tendsto.mono_right h_bot atBot_le_nhds_bot⟩ · exact h_tendsto classical let F : α → ℝ≥0∞ := fun a => - if h : ∃ l, Tendsto (fun r => preCdf ρ (-r) a) atTop (𝓝 l) then h.choose else 0 - have h_tendsto : ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCdf ρ (-r) a) atTop (𝓝 (F a)) := by + if h : ∃ l, Tendsto (fun r => preCDF ρ (-r) a) atTop (𝓝 l) then h.choose else 0 + have h_tendsto : ∀ᵐ a ∂ρ.fst, Tendsto (fun r => preCDF ρ (-r) a) atTop (𝓝 (F a)) := by filter_upwards [h_exists] with a ha simp_rw [dif_pos ha] exact ha.choose_spec suffices h_lintegral_eq : ∫⁻ a, F a ∂ρ.fst = 0 · have hF_ae_meas : AEMeasurable F ρ.fst := by refine' aemeasurable_of_tendsto_metrizable_ae _ (fun n => _) h_tendsto - exact measurable_preCdf.aemeasurable + exact measurable_preCDF.aemeasurable rw [lintegral_eq_zero_iff' hF_ae_meas] at h_lintegral_eq filter_upwards [h_tendsto, h_lintegral_eq] with a ha_tendsto ha_eq rwa [ha_eq] at ha_tendsto have h_lintegral : - Tendsto (fun r => ∫⁻ a, preCdf ρ (-r) a ∂ρ.fst) atTop (𝓝 (∫⁻ a, F a ∂ρ.fst)) := by + Tendsto (fun r => ∫⁻ a, preCDF ρ (-r) a ∂ρ.fst) atTop (𝓝 (∫⁻ a, F a ∂ρ.fst)) := by refine' tendsto_lintegral_filter_of_dominated_convergence (fun _ => 1) - (eventually_of_forall fun _ => measurable_preCdf) (eventually_of_forall fun _ => _) _ + (eventually_of_forall fun _ => measurable_preCDF) (eventually_of_forall fun _ => _) _ h_tendsto - · filter_upwards [preCdf_le_one ρ] with a ha using ha _ + · filter_upwards [preCDF_le_one ρ] with a ha using ha _ · rw [lintegral_one] exact measure_ne_top _ _ - have h_lintegral' : Tendsto (fun r => ∫⁻ a, preCdf ρ (-r) a ∂ρ.fst) atTop (𝓝 0) := by + have h_lintegral' : Tendsto (fun r => ∫⁻ a, preCDF ρ (-r) a ∂ρ.fst) atTop (𝓝 0) := by have h_lintegral_eq : - (fun r => ∫⁻ a, preCdf ρ (-r) a ∂ρ.fst) = fun r : ℚ => ρ (univ ×ˢ Iic (-r : ℝ)) := by + (fun r => ∫⁻ a, preCDF ρ (-r) a ∂ρ.fst) = fun r : ℚ => ρ (univ ×ˢ Iic (-r : ℝ)) := by ext1 n - rw [← set_lintegral_univ, set_lintegral_preCdf_fst ρ _ MeasurableSet.univ, + rw [← set_lintegral_univ, set_lintegral_preCDF_fst ρ _ MeasurableSet.univ, Measure.IicSnd_univ] norm_cast rw [h_lintegral_eq] @@ -506,144 +506,144 @@ theorem tendsto_preCdf_atBot_zero (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ refine' fun hxj => hxj.trans (neg_le_neg _) exact mod_cast hij exact tendsto_nhds_unique h_lintegral h_lintegral' -#align probability_theory.tendsto_pre_cdf_at_bot_zero ProbabilityTheory.tendsto_preCdf_atBot_zero +#align probability_theory.tendsto_pre_cdf_at_bot_zero ProbabilityTheory.tendsto_preCDF_atBot_zero -theorem inf_gt_preCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : - ∀ᵐ a ∂ρ.fst, ∀ t : ℚ, ⨅ r : Ioi t, preCdf ρ r a = preCdf ρ t a := by +theorem inf_gt_preCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : + ∀ᵐ a ∂ρ.fst, ∀ t : ℚ, ⨅ r : Ioi t, preCDF ρ r a = preCDF ρ t a := by rw [ae_all_iff] - refine' fun t => ae_eq_of_forall_set_lintegral_eq_of_sigmaFinite _ measurable_preCdf _ - · exact measurable_iInf fun i => measurable_preCdf + refine' fun t => ae_eq_of_forall_set_lintegral_eq_of_sigmaFinite _ measurable_preCDF _ + · exact measurable_iInf fun i => measurable_preCDF intro s hs _ - rw [set_lintegral_iInf_gt_preCdf ρ t hs, set_lintegral_preCdf_fst ρ t hs] -#align probability_theory.inf_gt_pre_cdf ProbabilityTheory.inf_gt_preCdf + rw [set_lintegral_iInf_gt_preCDF ρ t hs, set_lintegral_preCDF_fst ρ t hs] +#align probability_theory.inf_gt_pre_cdf ProbabilityTheory.inf_gt_preCDF -section HasCondCdf +section HasCondCDF -/-- A product measure on `α × ℝ` is said to have a conditional cdf at `a : α` if `preCdf` is +/-- A product measure on `α × ℝ` is said to have a conditional cdf at `a : α` if `preCDF` is monotone with limit 0 at -∞ and 1 at +∞, and is right continuous. This property holds almost everywhere (see `has_cond_cdf_ae`). -/ -structure HasCondCdf (ρ : Measure (α × ℝ)) (a : α) : Prop where - mono : Monotone fun r => preCdf ρ r a - le_one : ∀ r, preCdf ρ r a ≤ 1 - tendsto_atTop_one : Tendsto (fun r => preCdf ρ r a) atTop (𝓝 1) - tendsto_atBot_zero : Tendsto (fun r => preCdf ρ r a) atBot (𝓝 0) - iInf_rat_gt_eq : ∀ t : ℚ, ⨅ r : Ioi t, preCdf ρ r a = preCdf ρ t a -#align probability_theory.has_cond_cdf ProbabilityTheory.HasCondCdf - -theorem hasCondCdf_ae (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : ∀ᵐ a ∂ρ.fst, HasCondCdf ρ a := by - filter_upwards [monotone_preCdf ρ, preCdf_le_one ρ, tendsto_preCdf_atTop_one ρ, - tendsto_preCdf_atBot_zero ρ, inf_gt_preCdf ρ] with a h1 h2 h3 h4 h5 +structure HasCondCDF (ρ : Measure (α × ℝ)) (a : α) : Prop where + mono : Monotone fun r => preCDF ρ r a + le_one : ∀ r, preCDF ρ r a ≤ 1 + tendsto_atTop_one : Tendsto (fun r => preCDF ρ r a) atTop (𝓝 1) + tendsto_atBot_zero : Tendsto (fun r => preCDF ρ r a) atBot (𝓝 0) + iInf_rat_gt_eq : ∀ t : ℚ, ⨅ r : Ioi t, preCDF ρ r a = preCDF ρ t a +#align probability_theory.has_cond_cdf ProbabilityTheory.HasCondCDF + +theorem hasCondCDF_ae (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : ∀ᵐ a ∂ρ.fst, HasCondCDF ρ a := by + filter_upwards [monotone_preCDF ρ, preCDF_le_one ρ, tendsto_preCDF_atTop_one ρ, + tendsto_preCDF_atBot_zero ρ, inf_gt_preCDF ρ] with a h1 h2 h3 h4 h5 exact ⟨h1, h2, h3, h4, h5⟩ -#align probability_theory.has_cond_cdf_ae ProbabilityTheory.hasCondCdf_ae +#align probability_theory.has_cond_cdf_ae ProbabilityTheory.hasCondCDF_ae /-- A measurable set of elements of `α` such that `ρ` has a conditional cdf at all -`a ∈ condCdfSet`. -/ -def condCdfSet (ρ : Measure (α × ℝ)) : Set α := - (toMeasurable ρ.fst {b | ¬HasCondCdf ρ b})ᶜ -#align probability_theory.cond_cdf_set ProbabilityTheory.condCdfSet +`a ∈ condCDFSet`. -/ +def condCDFSet (ρ : Measure (α × ℝ)) : Set α := + (toMeasurable ρ.fst {b | ¬HasCondCDF ρ b})ᶜ +#align probability_theory.cond_cdf_set ProbabilityTheory.condCDFSet -theorem measurableSet_condCdfSet (ρ : Measure (α × ℝ)) : MeasurableSet (condCdfSet ρ) := +theorem measurableSet_condCDFSet (ρ : Measure (α × ℝ)) : MeasurableSet (condCDFSet ρ) := (measurableSet_toMeasurable _ _).compl -#align probability_theory.measurable_set_cond_cdf_set ProbabilityTheory.measurableSet_condCdfSet +#align probability_theory.measurable_set_cond_cdf_set ProbabilityTheory.measurableSet_condCDFSet -theorem hasCondCdf_of_mem_condCdfSet {ρ : Measure (α × ℝ)} {a : α} (h : a ∈ condCdfSet ρ) : - HasCondCdf ρ a := by - rw [condCdfSet, mem_compl_iff] at h - have h_ss := subset_toMeasurable ρ.fst {b | ¬HasCondCdf ρ b} +theorem hasCondCDF_of_mem_condCDFSet {ρ : Measure (α × ℝ)} {a : α} (h : a ∈ condCDFSet ρ) : + HasCondCDF ρ a := by + rw [condCDFSet, mem_compl_iff] at h + have h_ss := subset_toMeasurable ρ.fst {b | ¬HasCondCDF ρ b} by_contra ha exact h (h_ss ha) -#align probability_theory.has_cond_cdf_of_mem_cond_cdf_set ProbabilityTheory.hasCondCdf_of_mem_condCdfSet +#align probability_theory.has_cond_cdf_of_mem_cond_cdf_set ProbabilityTheory.hasCondCDF_of_mem_condCDFSet -theorem mem_condCdfSet_ae (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : - ∀ᵐ a ∂ρ.fst, a ∈ condCdfSet ρ := by - simp_rw [ae_iff, condCdfSet, not_mem_compl_iff, setOf_mem_eq, measure_toMeasurable] - exact hasCondCdf_ae ρ -#align probability_theory.mem_cond_cdf_set_ae ProbabilityTheory.mem_condCdfSet_ae +theorem mem_condCDFSet_ae (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] : + ∀ᵐ a ∂ρ.fst, a ∈ condCDFSet ρ := by + simp_rw [ae_iff, condCDFSet, not_mem_compl_iff, setOf_mem_eq, measure_toMeasurable] + exact hasCondCDF_ae ρ +#align probability_theory.mem_cond_cdf_set_ae ProbabilityTheory.mem_condCDFSet_ae -end HasCondCdf +end HasCondCDF open scoped Classical /-- Conditional cdf of the measure given the value on `α`, restricted to the rationals. -It is defined to be `pre_cdf` if `a ∈ condCdfSet`, and a default cdf-like function +It is defined to be `pre_cdf` if `a ∈ condCDFSet`, and a default cdf-like function otherwise. This is an auxiliary definition used to define `cond_cdf`. -/ -noncomputable def condCdfRat (ρ : Measure (α × ℝ)) : α → ℚ → ℝ := fun a => - if a ∈ condCdfSet ρ then fun r => (preCdf ρ r a).toReal else fun r => if r < 0 then 0 else 1 -#align probability_theory.cond_cdf_rat ProbabilityTheory.condCdfRat +noncomputable def condCDFRat (ρ : Measure (α × ℝ)) : α → ℚ → ℝ := fun a => + if a ∈ condCDFSet ρ then fun r => (preCDF ρ r a).toReal else fun r => if r < 0 then 0 else 1 +#align probability_theory.cond_cdf_rat ProbabilityTheory.condCDFRat -theorem condCdfRat_of_not_mem (ρ : Measure (α × ℝ)) (a : α) (h : a ∉ condCdfSet ρ) {r : ℚ} : - condCdfRat ρ a r = if r < 0 then 0 else 1 := by simp only [condCdfRat, h, if_false] -#align probability_theory.cond_cdf_rat_of_not_mem ProbabilityTheory.condCdfRat_of_not_mem +theorem condCDFRat_of_not_mem (ρ : Measure (α × ℝ)) (a : α) (h : a ∉ condCDFSet ρ) {r : ℚ} : + condCDFRat ρ a r = if r < 0 then 0 else 1 := by simp only [condCDFRat, h, if_false] +#align probability_theory.cond_cdf_rat_of_not_mem ProbabilityTheory.condCDFRat_of_not_mem -theorem condCdfRat_of_mem (ρ : Measure (α × ℝ)) (a : α) (h : a ∈ condCdfSet ρ) (r : ℚ) : - condCdfRat ρ a r = (preCdf ρ r a).toReal := by simp only [condCdfRat, h, if_true] -#align probability_theory.cond_cdf_rat_of_mem ProbabilityTheory.condCdfRat_of_mem +theorem condCDFRat_of_mem (ρ : Measure (α × ℝ)) (a : α) (h : a ∈ condCDFSet ρ) (r : ℚ) : + condCDFRat ρ a r = (preCDF ρ r a).toReal := by simp only [condCDFRat, h, if_true] +#align probability_theory.cond_cdf_rat_of_mem ProbabilityTheory.condCDFRat_of_mem -theorem monotone_condCdfRat (ρ : Measure (α × ℝ)) (a : α) : Monotone (condCdfRat ρ a) := by - by_cases h : a ∈ condCdfSet ρ - · simp only [condCdfRat, h, if_true, forall_const, and_self_iff] +theorem monotone_condCDFRat (ρ : Measure (α × ℝ)) (a : α) : Monotone (condCDFRat ρ a) := by + by_cases h : a ∈ condCDFSet ρ + · simp only [condCDFRat, h, if_true, forall_const, and_self_iff] intro r r' hrr' - have h' := hasCondCdf_of_mem_condCdfSet h - have h_ne_top : ∀ r, preCdf ρ r a ≠ ∞ := fun r => + have h' := hasCondCDF_of_mem_condCDFSet h + have h_ne_top : ∀ r, preCDF ρ r a ≠ ∞ := fun r => ((h'.le_one r).trans_lt ENNReal.one_lt_top).ne rw [ENNReal.toReal_le_toReal (h_ne_top _) (h_ne_top _)] exact h'.1 hrr' - · simp only [condCdfRat, h, if_false] + · simp only [condCDFRat, h, if_false] intro x y hxy dsimp only split_ifs with h_1 h_2 h_2 exacts [le_rfl, zero_le_one, absurd (hxy.trans_lt h_2) h_1, le_rfl] -#align probability_theory.monotone_cond_cdf_rat ProbabilityTheory.monotone_condCdfRat +#align probability_theory.monotone_cond_cdf_rat ProbabilityTheory.monotone_condCDFRat -theorem measurable_condCdfRat (ρ : Measure (α × ℝ)) (q : ℚ) : - Measurable fun a => condCdfRat ρ a q := by - simp_rw [condCdfRat, ite_apply] +theorem measurable_condCDFRat (ρ : Measure (α × ℝ)) (q : ℚ) : + Measurable fun a => condCDFRat ρ a q := by + simp_rw [condCDFRat, ite_apply] exact - Measurable.ite (measurableSet_condCdfSet ρ) measurable_preCdf.ennreal_toReal + Measurable.ite (measurableSet_condCDFSet ρ) measurable_preCDF.ennreal_toReal measurable_const -#align probability_theory.measurable_cond_cdf_rat ProbabilityTheory.measurable_condCdfRat +#align probability_theory.measurable_cond_cdf_rat ProbabilityTheory.measurable_condCDFRat -theorem condCdfRat_nonneg (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : 0 ≤ condCdfRat ρ a r := by +theorem condCDFRat_nonneg (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : 0 ≤ condCDFRat ρ a r := by -- Porting note: was - -- unfold condCdfRat; split_ifs; exacts [ENNReal.toReal_nonneg, le_rfl, zero_le_one] - unfold condCdfRat; split_ifs + -- unfold condCDFRat; split_ifs; exacts [ENNReal.toReal_nonneg, le_rfl, zero_le_one] + unfold condCDFRat; split_ifs · exact ENNReal.toReal_nonneg dsimp only split_ifs exacts [le_rfl, zero_le_one] -#align probability_theory.cond_cdf_rat_nonneg ProbabilityTheory.condCdfRat_nonneg +#align probability_theory.cond_cdf_rat_nonneg ProbabilityTheory.condCDFRat_nonneg -theorem condCdfRat_le_one (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : condCdfRat ρ a r ≤ 1 := by - unfold condCdfRat +theorem condCDFRat_le_one (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : condCDFRat ρ a r ≤ 1 := by + unfold condCDFRat split_ifs with h · refine' ENNReal.toReal_le_of_le_ofReal zero_le_one _ rw [ENNReal.ofReal_one] - exact (hasCondCdf_of_mem_condCdfSet h).le_one r + exact (hasCondCDF_of_mem_condCDFSet h).le_one r -- Porting note: added dsimp only; split_ifs exacts [zero_le_one, le_rfl] -#align probability_theory.cond_cdf_rat_le_one ProbabilityTheory.condCdfRat_le_one +#align probability_theory.cond_cdf_rat_le_one ProbabilityTheory.condCDFRat_le_one -theorem tendsto_condCdfRat_atBot (ρ : Measure (α × ℝ)) (a : α) : - Tendsto (condCdfRat ρ a) atBot (𝓝 0) := by - unfold condCdfRat +theorem tendsto_condCDFRat_atBot (ρ : Measure (α × ℝ)) (a : α) : + Tendsto (condCDFRat ρ a) atBot (𝓝 0) := by + unfold condCDFRat split_ifs with h · rw [← ENNReal.zero_toReal, ENNReal.tendsto_toReal_iff] - · exact (hasCondCdf_of_mem_condCdfSet h).tendsto_atBot_zero - · have h' := hasCondCdf_of_mem_condCdfSet h + · exact (hasCondCDF_of_mem_condCDFSet h).tendsto_atBot_zero + · have h' := hasCondCDF_of_mem_condCDFSet h exact fun r => ((h'.le_one r).trans_lt ENNReal.one_lt_top).ne · exact ENNReal.zero_ne_top · refine' (tendsto_congr' _).mp tendsto_const_nhds rw [EventuallyEq, eventually_atBot] refine' ⟨-1, fun q hq => (if_pos (hq.trans_lt _)).symm⟩ linarith -#align probability_theory.tendsto_cond_cdf_rat_at_bot ProbabilityTheory.tendsto_condCdfRat_atBot +#align probability_theory.tendsto_cond_cdf_rat_at_bot ProbabilityTheory.tendsto_condCDFRat_atBot -theorem tendsto_condCdfRat_atTop (ρ : Measure (α × ℝ)) (a : α) : - Tendsto (condCdfRat ρ a) atTop (𝓝 1) := by - unfold condCdfRat +theorem tendsto_condCDFRat_atTop (ρ : Measure (α × ℝ)) (a : α) : + Tendsto (condCDFRat ρ a) atTop (𝓝 1) := by + unfold condCDFRat split_ifs with h - · have h' := hasCondCdf_of_mem_condCdfSet h + · have h' := hasCondCDF_of_mem_condCDFSet h rw [← ENNReal.one_toReal, ENNReal.tendsto_toReal_iff] · exact h'.tendsto_atTop_one · exact fun r => ((h'.le_one r).trans_lt ENNReal.one_lt_top).ne @@ -651,30 +651,30 @@ theorem tendsto_condCdfRat_atTop (ρ : Measure (α × ℝ)) (a : α) : · refine' (tendsto_congr' _).mp tendsto_const_nhds rw [EventuallyEq, eventually_atTop] exact ⟨0, fun q hq => (if_neg (not_lt.mpr hq)).symm⟩ -#align probability_theory.tendsto_cond_cdf_rat_at_top ProbabilityTheory.tendsto_condCdfRat_atTop +#align probability_theory.tendsto_cond_cdf_rat_at_top ProbabilityTheory.tendsto_condCDFRat_atTop -theorem condCdfRat_ae_eq (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) : - (fun a => condCdfRat ρ a r) =ᵐ[ρ.fst] fun a => (preCdf ρ r a).toReal := by - filter_upwards [mem_condCdfSet_ae ρ] with a ha using condCdfRat_of_mem ρ a ha r -#align probability_theory.cond_cdf_rat_ae_eq ProbabilityTheory.condCdfRat_ae_eq +theorem condCDFRat_ae_eq (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) : + (fun a => condCDFRat ρ a r) =ᵐ[ρ.fst] fun a => (preCDF ρ r a).toReal := by + filter_upwards [mem_condCDFSet_ae ρ] with a ha using condCDFRat_of_mem ρ a ha r +#align probability_theory.cond_cdf_rat_ae_eq ProbabilityTheory.condCDFRat_ae_eq -theorem ofReal_condCdfRat_ae_eq (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) : - (fun a => ENNReal.ofReal (condCdfRat ρ a r)) =ᵐ[ρ.fst] preCdf ρ r := by - filter_upwards [condCdfRat_ae_eq ρ r, preCdf_le_one ρ] with a ha ha_le_one +theorem ofReal_condCDFRat_ae_eq (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) : + (fun a => ENNReal.ofReal (condCDFRat ρ a r)) =ᵐ[ρ.fst] preCDF ρ r := by + filter_upwards [condCDFRat_ae_eq ρ r, preCDF_le_one ρ] with a ha ha_le_one rw [ha, ENNReal.ofReal_toReal] exact ((ha_le_one r).trans_lt ENNReal.one_lt_top).ne -#align probability_theory.of_real_cond_cdf_rat_ae_eq ProbabilityTheory.ofReal_condCdfRat_ae_eq +#align probability_theory.of_real_cond_cdf_rat_ae_eq ProbabilityTheory.ofReal_condCDFRat_ae_eq -theorem inf_gt_condCdfRat (ρ : Measure (α × ℝ)) (a : α) (t : ℚ) : - ⨅ r : Ioi t, condCdfRat ρ a r = condCdfRat ρ a t := by - by_cases ha : a ∈ condCdfSet ρ - · simp_rw [condCdfRat_of_mem ρ a ha] - have ha' := hasCondCdf_of_mem_condCdfSet ha +theorem inf_gt_condCDFRat (ρ : Measure (α × ℝ)) (a : α) (t : ℚ) : + ⨅ r : Ioi t, condCDFRat ρ a r = condCDFRat ρ a t := by + by_cases ha : a ∈ condCDFSet ρ + · simp_rw [condCDFRat_of_mem ρ a ha] + have ha' := hasCondCDF_of_mem_condCDFSet ha rw [← ENNReal.toReal_iInf] - · suffices ⨅ i : ↥(Ioi t), preCdf ρ (↑i) a = preCdf ρ t a by rw [this] + · suffices ⨅ i : ↥(Ioi t), preCDF ρ (↑i) a = preCDF ρ t a by rw [this] rw [← ha'.iInf_rat_gt_eq] · exact fun r => ((ha'.le_one r).trans_lt ENNReal.one_lt_top).ne - · simp_rw [condCdfRat_of_not_mem ρ a ha] + · simp_rw [condCDFRat_of_not_mem ρ a ha] have h_bdd : BddBelow (range fun r : ↥(Ioi t) => ite ((r : ℚ) < 0) (0 : ℝ) 1) := by refine' ⟨0, fun x hx => _⟩ obtain ⟨y, rfl⟩ := mem_range.mpr hx @@ -700,21 +700,21 @@ theorem inf_gt_condCdfRat (ρ : Measure (α × ℝ)) (a : α) (t : ℚ) : rw [if_neg] rw [not_lt] at h ⊢ exact h.trans (mem_Ioi.mp x.prop).le -#align probability_theory.inf_gt_cond_cdf_rat ProbabilityTheory.inf_gt_condCdfRat +#align probability_theory.inf_gt_cond_cdf_rat ProbabilityTheory.inf_gt_condCDFRat /-- Conditional cdf of the measure given the value on `α`, as a plain function. This is an auxiliary definition used to define `cond_cdf`. -/ -noncomputable irreducible_def condCdf' (ρ : Measure (α × ℝ)) : α → ℝ → ℝ := fun a t => - ⨅ r : { r' : ℚ // t < r' }, condCdfRat ρ a r -#align probability_theory.cond_cdf' ProbabilityTheory.condCdf' +noncomputable irreducible_def condCDF' (ρ : Measure (α × ℝ)) : α → ℝ → ℝ := fun a t => + ⨅ r : { r' : ℚ // t < r' }, condCDFRat ρ a r +#align probability_theory.cond_cdf' ProbabilityTheory.condCDF' -theorem condCdf'_def' {ρ : Measure (α × ℝ)} {a : α} {x : ℝ} : - condCdf' ρ a x = ⨅ r : { r : ℚ // x < r }, condCdfRat ρ a r := by rw [condCdf'] -#align probability_theory.cond_cdf'_def ProbabilityTheory.condCdf'_def' +theorem condCDF'_def' {ρ : Measure (α × ℝ)} {a : α} {x : ℝ} : + condCDF' ρ a x = ⨅ r : { r : ℚ // x < r }, condCDFRat ρ a r := by rw [condCDF'] +#align probability_theory.cond_cdf'_def ProbabilityTheory.condCDF'_def' -theorem condCdf'_eq_condCdfRat (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : - condCdf' ρ a r = condCdfRat ρ a r := by - rw [← inf_gt_condCdfRat ρ a r, condCdf'] +theorem condCDF'_eq_condCDFRat (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : + condCDF' ρ a r = condCDFRat ρ a r := by + rw [← inf_gt_condCDFRat ρ a r, condCDF'] refine' Equiv.iInf_congr _ _ · exact { toFun := fun t => ⟨t.1, mod_cast t.2⟩ @@ -723,85 +723,85 @@ theorem condCdf'_eq_condCdfRat (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : right_inv := fun t => by simp only [Subtype.coe_eta] } · intro t simp only [Equiv.coe_fn_mk, Subtype.coe_mk] -#align probability_theory.cond_cdf'_eq_cond_cdf_rat ProbabilityTheory.condCdf'_eq_condCdfRat +#align probability_theory.cond_cdf'_eq_cond_cdf_rat ProbabilityTheory.condCDF'_eq_condCDFRat -theorem condCdf'_nonneg (ρ : Measure (α × ℝ)) (a : α) (r : ℝ) : 0 ≤ condCdf' ρ a r := by +theorem condCDF'_nonneg (ρ : Measure (α × ℝ)) (a : α) (r : ℝ) : 0 ≤ condCDF' ρ a r := by have : Nonempty { r' : ℚ // r < ↑r' } := by obtain ⟨r, hrx⟩ := exists_rat_gt r exact ⟨⟨r, hrx⟩⟩ - rw [condCdf'_def] - exact le_ciInf fun r' => condCdfRat_nonneg ρ a _ -#align probability_theory.cond_cdf'_nonneg ProbabilityTheory.condCdf'_nonneg + rw [condCDF'_def] + exact le_ciInf fun r' => condCDFRat_nonneg ρ a _ +#align probability_theory.cond_cdf'_nonneg ProbabilityTheory.condCDF'_nonneg -theorem bddBelow_range_condCdfRat_gt (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : - BddBelow (range fun r : { r' : ℚ // x < ↑r' } => condCdfRat ρ a r) := by - refine' ⟨0, fun z => _⟩; rintro ⟨u, rfl⟩; exact condCdfRat_nonneg ρ a _ -#align probability_theory.bdd_below_range_cond_cdf_rat_gt ProbabilityTheory.bddBelow_range_condCdfRat_gt +theorem bddBelow_range_condCDFRat_gt (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : + BddBelow (range fun r : { r' : ℚ // x < ↑r' } => condCDFRat ρ a r) := by + refine' ⟨0, fun z => _⟩; rintro ⟨u, rfl⟩; exact condCDFRat_nonneg ρ a _ +#align probability_theory.bdd_below_range_cond_cdf_rat_gt ProbabilityTheory.bddBelow_range_condCDFRat_gt -theorem monotone_condCdf' (ρ : Measure (α × ℝ)) (a : α) : Monotone (condCdf' ρ a) := by +theorem monotone_condCDF' (ρ : Measure (α × ℝ)) (a : α) : Monotone (condCDF' ρ a) := by intro x y hxy have : Nonempty { r' : ℚ // y < ↑r' } := by obtain ⟨r, hrx⟩ := exists_rat_gt y exact ⟨⟨r, hrx⟩⟩ - simp_rw [condCdf'_def] + simp_rw [condCDF'_def] refine' le_ciInf fun r => (ciInf_le _ _).trans_eq _ - · exact bddBelow_range_condCdfRat_gt ρ a x + · exact bddBelow_range_condCDFRat_gt ρ a x · exact ⟨r.1, hxy.trans_lt r.prop⟩ · rfl -#align probability_theory.monotone_cond_cdf' ProbabilityTheory.monotone_condCdf' +#align probability_theory.monotone_cond_cdf' ProbabilityTheory.monotone_condCDF' -theorem continuousWithinAt_condCdf'_Ici (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : - ContinuousWithinAt (condCdf' ρ a) (Ici x) x := by +theorem continuousWithinAt_condCDF'_Ici (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : + ContinuousWithinAt (condCDF' ρ a) (Ici x) x := by rw [← continuousWithinAt_Ioi_iff_Ici] - convert Monotone.tendsto_nhdsWithin_Ioi (monotone_condCdf' ρ a) x + convert Monotone.tendsto_nhdsWithin_Ioi (monotone_condCDF' ρ a) x rw [sInf_image'] - have h' : ⨅ r : Ioi x, condCdf' ρ a r = ⨅ r : { r' : ℚ // x < r' }, condCdf' ρ a r := by - refine' Real.iInf_Ioi_eq_iInf_rat_gt x _ (monotone_condCdf' ρ a) + have h' : ⨅ r : Ioi x, condCDF' ρ a r = ⨅ r : { r' : ℚ // x < r' }, condCDF' ρ a r := by + refine' Real.iInf_Ioi_eq_iInf_rat_gt x _ (monotone_condCDF' ρ a) refine' ⟨0, fun z => _⟩ rintro ⟨u, -, rfl⟩ - exact condCdf'_nonneg ρ a u + exact condCDF'_nonneg ρ a u have h'' : - ⨅ r : { r' : ℚ // x < r' }, condCdf' ρ a r = - ⨅ r : { r' : ℚ // x < r' }, condCdfRat ρ a r := by + ⨅ r : { r' : ℚ // x < r' }, condCDF' ρ a r = + ⨅ r : { r' : ℚ // x < r' }, condCDFRat ρ a r := by congr with r - exact condCdf'_eq_condCdfRat ρ a r + exact condCDF'_eq_condCDFRat ρ a r rw [h', h'', ContinuousWithinAt] congr! - exact condCdf'_def' -#align probability_theory.continuous_within_at_cond_cdf'_Ici ProbabilityTheory.continuousWithinAt_condCdf'_Ici + exact condCDF'_def' +#align probability_theory.continuous_within_at_cond_cdf'_Ici ProbabilityTheory.continuousWithinAt_condCDF'_Ici /-! ### Conditional cdf -/ /-- Conditional cdf of the measure given the value on `α`, as a Stieltjes function. -/ -noncomputable def condCdf (ρ : Measure (α × ℝ)) (a : α) : StieltjesFunction where - toFun := condCdf' ρ a - mono' := monotone_condCdf' ρ a - right_continuous' x := continuousWithinAt_condCdf'_Ici ρ a x -#align probability_theory.cond_cdf ProbabilityTheory.condCdf +noncomputable def condCDF (ρ : Measure (α × ℝ)) (a : α) : StieltjesFunction where + toFun := condCDF' ρ a + mono' := monotone_condCDF' ρ a + right_continuous' x := continuousWithinAt_condCDF'_Ici ρ a x +#align probability_theory.cond_cdf ProbabilityTheory.condCDF -theorem condCdf_eq_condCdfRat (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : - condCdf ρ a r = condCdfRat ρ a r := - condCdf'_eq_condCdfRat ρ a r -#align probability_theory.cond_cdf_eq_cond_cdf_rat ProbabilityTheory.condCdf_eq_condCdfRat +theorem condCDF_eq_condCDFRat (ρ : Measure (α × ℝ)) (a : α) (r : ℚ) : + condCDF ρ a r = condCDFRat ρ a r := + condCDF'_eq_condCDFRat ρ a r +#align probability_theory.cond_cdf_eq_cond_cdf_rat ProbabilityTheory.condCDF_eq_condCDFRat /-- The conditional cdf is non-negative for all `a : α`. -/ -theorem condCdf_nonneg (ρ : Measure (α × ℝ)) (a : α) (r : ℝ) : 0 ≤ condCdf ρ a r := - condCdf'_nonneg ρ a r -#align probability_theory.cond_cdf_nonneg ProbabilityTheory.condCdf_nonneg +theorem condCDF_nonneg (ρ : Measure (α × ℝ)) (a : α) (r : ℝ) : 0 ≤ condCDF ρ a r := + condCDF'_nonneg ρ a r +#align probability_theory.cond_cdf_nonneg ProbabilityTheory.condCDF_nonneg /-- The conditional cdf is lower or equal to 1 for all `a : α`. -/ -theorem condCdf_le_one (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : condCdf ρ a x ≤ 1 := by +theorem condCDF_le_one (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : condCDF ρ a x ≤ 1 := by obtain ⟨r, hrx⟩ := exists_rat_gt x rw [← StieltjesFunction.iInf_rat_gt_eq] - simp_rw [condCdf_eq_condCdfRat] - refine' ciInf_le_of_le (bddBelow_range_condCdfRat_gt ρ a x) _ (condCdfRat_le_one _ _ _) + simp_rw [condCDF_eq_condCDFRat] + refine' ciInf_le_of_le (bddBelow_range_condCDFRat_gt ρ a x) _ (condCDFRat_le_one _ _ _) exact ⟨r, hrx⟩ -#align probability_theory.cond_cdf_le_one ProbabilityTheory.condCdf_le_one +#align probability_theory.cond_cdf_le_one ProbabilityTheory.condCDF_le_one /-- The conditional cdf tends to 0 at -∞ for all `a : α`. -/ -theorem tendsto_condCdf_atBot (ρ : Measure (α × ℝ)) (a : α) : - Tendsto (condCdf ρ a) atBot (𝓝 0) := by +theorem tendsto_condCDF_atBot (ρ : Measure (α × ℝ)) (a : α) : + Tendsto (condCDF ρ a) atBot (𝓝 0) := by have h_exists : ∀ x : ℝ, ∃ q : ℚ, x < q ∧ ↑q < x + 1 := fun x => exists_rat_btwn (lt_add_one x) let qs : ℝ → ℚ := fun x => (h_exists x).choose have hqs_tendsto : Tendsto qs atBot atBot := by @@ -813,14 +813,14 @@ theorem tendsto_condCdf_atBot (ρ : Measure (α × ℝ)) (a : α) : exact mod_cast h_le refine' tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds - ((tendsto_condCdfRat_atBot ρ a).comp hqs_tendsto) (condCdf_nonneg ρ a) fun x => _ - rw [Function.comp_apply, ← condCdf_eq_condCdfRat] - exact (condCdf ρ a).mono (h_exists x).choose_spec.1.le -#align probability_theory.tendsto_cond_cdf_at_bot ProbabilityTheory.tendsto_condCdf_atBot + ((tendsto_condCDFRat_atBot ρ a).comp hqs_tendsto) (condCDF_nonneg ρ a) fun x => _ + rw [Function.comp_apply, ← condCDF_eq_condCDFRat] + exact (condCDF ρ a).mono (h_exists x).choose_spec.1.le +#align probability_theory.tendsto_cond_cdf_at_bot ProbabilityTheory.tendsto_condCDF_atBot /-- The conditional cdf tends to 1 at +∞ for all `a : α`. -/ -theorem tendsto_condCdf_atTop (ρ : Measure (α × ℝ)) (a : α) : - Tendsto (condCdf ρ a) atTop (𝓝 1) := by +theorem tendsto_condCDF_atTop (ρ : Measure (α × ℝ)) (a : α) : + Tendsto (condCDF ρ a) atTop (𝓝 1) := by have h_exists : ∀ x : ℝ, ∃ q : ℚ, x - 1 < q ∧ ↑q < x := fun x => exists_rat_btwn (sub_one_lt x) let qs : ℝ → ℚ := fun x => (h_exists x).choose have hqs_tendsto : Tendsto qs atTop atTop := by @@ -830,51 +830,51 @@ theorem tendsto_condCdf_atTop (ρ : Measure (α × ℝ)) (a : α) : rw [sub_le_iff_le_add] at h_le exact_mod_cast le_of_add_le_add_right (hy.trans h_le) refine' - tendsto_of_tendsto_of_tendsto_of_le_of_le ((tendsto_condCdfRat_atTop ρ a).comp hqs_tendsto) - tendsto_const_nhds _ (condCdf_le_one ρ a) + tendsto_of_tendsto_of_tendsto_of_le_of_le ((tendsto_condCDFRat_atTop ρ a).comp hqs_tendsto) + tendsto_const_nhds _ (condCDF_le_one ρ a) intro x - rw [Function.comp_apply, ← condCdf_eq_condCdfRat] - exact (condCdf ρ a).mono (le_of_lt (h_exists x).choose_spec.2) -#align probability_theory.tendsto_cond_cdf_at_top ProbabilityTheory.tendsto_condCdf_atTop - -theorem condCdf_ae_eq (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) : - (fun a => condCdf ρ a r) =ᵐ[ρ.fst] fun a => (preCdf ρ r a).toReal := by - filter_upwards [mem_condCdfSet_ae ρ] with a ha using - (condCdf_eq_condCdfRat ρ a r).trans (condCdfRat_of_mem ρ a ha r) -#align probability_theory.cond_cdf_ae_eq ProbabilityTheory.condCdf_ae_eq - -theorem ofReal_condCdf_ae_eq (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) : - (fun a => ENNReal.ofReal (condCdf ρ a r)) =ᵐ[ρ.fst] preCdf ρ r := by - filter_upwards [condCdf_ae_eq ρ r, preCdf_le_one ρ] with a ha ha_le_one + rw [Function.comp_apply, ← condCDF_eq_condCDFRat] + exact (condCDF ρ a).mono (le_of_lt (h_exists x).choose_spec.2) +#align probability_theory.tendsto_cond_cdf_at_top ProbabilityTheory.tendsto_condCDF_atTop + +theorem condCDF_ae_eq (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) : + (fun a => condCDF ρ a r) =ᵐ[ρ.fst] fun a => (preCDF ρ r a).toReal := by + filter_upwards [mem_condCDFSet_ae ρ] with a ha using + (condCDF_eq_condCDFRat ρ a r).trans (condCDFRat_of_mem ρ a ha r) +#align probability_theory.cond_cdf_ae_eq ProbabilityTheory.condCDF_ae_eq + +theorem ofReal_condCDF_ae_eq (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) : + (fun a => ENNReal.ofReal (condCDF ρ a r)) =ᵐ[ρ.fst] preCDF ρ r := by + filter_upwards [condCDF_ae_eq ρ r, preCDF_le_one ρ] with a ha ha_le_one rw [ha, ENNReal.ofReal_toReal] exact ((ha_le_one r).trans_lt ENNReal.one_lt_top).ne -#align probability_theory.of_real_cond_cdf_ae_eq ProbabilityTheory.ofReal_condCdf_ae_eq +#align probability_theory.of_real_cond_cdf_ae_eq ProbabilityTheory.ofReal_condCDF_ae_eq /-- The conditional cdf is a measurable function of `a : α` for all `x : ℝ`. -/ -theorem measurable_condCdf (ρ : Measure (α × ℝ)) (x : ℝ) : Measurable fun a => condCdf ρ a x := by - have : (fun a => condCdf ρ a x) = fun a => ⨅ r : { r' : ℚ // x < r' }, condCdfRat ρ a ↑r := by +theorem measurable_condCDF (ρ : Measure (α × ℝ)) (x : ℝ) : Measurable fun a => condCDF ρ a x := by + have : (fun a => condCDF ρ a x) = fun a => ⨅ r : { r' : ℚ // x < r' }, condCDFRat ρ a ↑r := by ext1 a rw [← StieltjesFunction.iInf_rat_gt_eq] congr with q - rw [condCdf_eq_condCdfRat] + rw [condCDF_eq_condCDFRat] rw [this] - exact measurable_iInf (fun q => measurable_condCdfRat ρ q) -#align probability_theory.measurable_cond_cdf ProbabilityTheory.measurable_condCdf + exact measurable_iInf (fun q => measurable_condCDFRat ρ q) +#align probability_theory.measurable_cond_cdf ProbabilityTheory.measurable_condCDF /-- Auxiliary lemma for `set_lintegral_cond_cdf`. -/ -theorem set_lintegral_condCdf_rat (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) {s : Set α} +theorem set_lintegral_condCDF_rat (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (r : ℚ) {s : Set α} (hs : MeasurableSet s) : - ∫⁻ a in s, ENNReal.ofReal (condCdf ρ a r) ∂ρ.fst = ρ (s ×ˢ Iic (r : ℝ)) := by - have : ∀ᵐ a ∂ρ.fst, a ∈ s → ENNReal.ofReal (condCdf ρ a r) = preCdf ρ r a := by - filter_upwards [ofReal_condCdf_ae_eq ρ r] with a ha using fun _ => ha - rw [set_lintegral_congr_fun hs this, set_lintegral_preCdf_fst ρ r hs] + ∫⁻ a in s, ENNReal.ofReal (condCDF ρ a r) ∂ρ.fst = ρ (s ×ˢ Iic (r : ℝ)) := by + have : ∀ᵐ a ∂ρ.fst, a ∈ s → ENNReal.ofReal (condCDF ρ a r) = preCDF ρ r a := by + filter_upwards [ofReal_condCDF_ae_eq ρ r] with a ha using fun _ => ha + rw [set_lintegral_congr_fun hs this, set_lintegral_preCDF_fst ρ r hs] exact ρ.IicSnd_apply r hs -#align probability_theory.set_lintegral_cond_cdf_rat ProbabilityTheory.set_lintegral_condCdf_rat +#align probability_theory.set_lintegral_cond_cdf_rat ProbabilityTheory.set_lintegral_condCDF_rat -theorem set_lintegral_condCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) {s : Set α} - (hs : MeasurableSet s) : ∫⁻ a in s, ENNReal.ofReal (condCdf ρ a x) ∂ρ.fst = ρ (s ×ˢ Iic x) := by - -- We have the result for `x : ℚ` thanks to `set_lintegral_cond_cdf_rat`. We use the equality - -- `cond_cdf ρ a x = ⨅ r : {r' : ℚ // x < r'}, cond_cdf ρ a r` and a monotone convergence +theorem set_lintegral_condCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) {s : Set α} + (hs : MeasurableSet s) : ∫⁻ a in s, ENNReal.ofReal (condCDF ρ a x) ∂ρ.fst = ρ (s ×ˢ Iic x) := by + -- We have the result for `x : ℚ` thanks to `set_lintegral_condCDF_rat`. We use the equality + -- `condCDF ρ a x = ⨅ r : {r' : ℚ // x < r'}, condCDF ρ a r` and a monotone convergence -- argument to extend it to the reals. by_cases hρ_zero : ρ.fst.restrict s = 0 · rw [hρ_zero, lintegral_zero_measure] @@ -885,10 +885,10 @@ theorem set_lintegral_condCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x _ = ρ.fst.restrict s univ := by rw [Measure.restrict_apply_univ] _ = 0 := by simp only [hρ_zero, Measure.coe_zero, Pi.zero_apply] have h : - ∫⁻ a in s, ENNReal.ofReal (condCdf ρ a x) ∂ρ.fst = - ∫⁻ a in s, ENNReal.ofReal (⨅ r : { r' : ℚ // x < r' }, condCdf ρ a r) ∂ρ.fst := by + ∫⁻ a in s, ENNReal.ofReal (condCDF ρ a x) ∂ρ.fst = + ∫⁻ a in s, ENNReal.ofReal (⨅ r : { r' : ℚ // x < r' }, condCDF ρ a r) ∂ρ.fst := by congr with a : 1 - rw [← (condCdf ρ a).iInf_rat_gt_eq x] + rw [← (condCDF ρ a).iInf_rat_gt_eq x] have h_nonempty : Nonempty { r' : ℚ // x < ↑r' } := by obtain ⟨r, hrx⟩ := exists_rat_gt x exact ⟨⟨r, hrx⟩⟩ @@ -896,15 +896,15 @@ theorem set_lintegral_condCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x simp_rw [ENNReal.ofReal_cinfi] have h_coe : ∀ b : { r' : ℚ // x < ↑r' }, (b : ℝ) = ((b : ℚ) : ℝ) := fun _ => by congr rw [lintegral_iInf_directed_of_measurable hρ_zero fun q : { r' : ℚ // x < ↑r' } => - (measurable_condCdf ρ q).ennreal_ofReal] + (measurable_condCDF ρ q).ennreal_ofReal] rotate_left · intro b - rw [set_lintegral_condCdf_rat ρ _ hs] + rw [set_lintegral_condCDF_rat ρ _ hs] exact measure_ne_top ρ _ - · refine' Monotone.directed_ge fun i j hij a => ENNReal.ofReal_le_ofReal ((condCdf ρ a).mono _) + · refine' Monotone.directed_ge fun i j hij a => ENNReal.ofReal_le_ofReal ((condCDF ρ a).mono _) rw [h_coe, h_coe] exact mod_cast hij - simp_rw [set_lintegral_condCdf_rat ρ _ hs] + simp_rw [set_lintegral_condCDF_rat ρ _ hs] rw [← measure_iInter_eq_iInf] · rw [← prod_iInter] congr with y @@ -915,93 +915,93 @@ theorem set_lintegral_condCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x refine' prod_subset_prod_iff.mpr (Or.inl ⟨subset_rfl, Iic_subset_Iic.mpr _⟩) exact mod_cast hij · exact ⟨h_nonempty.some, measure_ne_top _ _⟩ -#align probability_theory.set_lintegral_cond_cdf ProbabilityTheory.set_lintegral_condCdf +#align probability_theory.set_lintegral_cond_cdf ProbabilityTheory.set_lintegral_condCDF -theorem lintegral_condCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) : - ∫⁻ a, ENNReal.ofReal (condCdf ρ a x) ∂ρ.fst = ρ (univ ×ˢ Iic x) := by - rw [← set_lintegral_univ, set_lintegral_condCdf ρ _ MeasurableSet.univ] -#align probability_theory.lintegral_cond_cdf ProbabilityTheory.lintegral_condCdf +theorem lintegral_condCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) : + ∫⁻ a, ENNReal.ofReal (condCDF ρ a x) ∂ρ.fst = ρ (univ ×ˢ Iic x) := by + rw [← set_lintegral_univ, set_lintegral_condCDF ρ _ MeasurableSet.univ] +#align probability_theory.lintegral_cond_cdf ProbabilityTheory.lintegral_condCDF /-- The conditional cdf is a strongly measurable function of `a : α` for all `x : ℝ`. -/ -theorem stronglyMeasurable_condCdf (ρ : Measure (α × ℝ)) (x : ℝ) : - StronglyMeasurable fun a => condCdf ρ a x := - (measurable_condCdf ρ x).stronglyMeasurable -#align probability_theory.strongly_measurable_cond_cdf ProbabilityTheory.stronglyMeasurable_condCdf +theorem stronglyMeasurable_condCDF (ρ : Measure (α × ℝ)) (x : ℝ) : + StronglyMeasurable fun a => condCDF ρ a x := + (measurable_condCDF ρ x).stronglyMeasurable +#align probability_theory.strongly_measurable_cond_cdf ProbabilityTheory.stronglyMeasurable_condCDF -theorem integrable_condCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) : - Integrable (fun a => condCdf ρ a x) ρ.fst := by +theorem integrable_condCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) : + Integrable (fun a => condCDF ρ a x) ρ.fst := by refine' integrable_of_forall_fin_meas_le _ (measure_lt_top ρ.fst univ) _ fun t _ _ => _ - · exact (stronglyMeasurable_condCdf ρ _).aestronglyMeasurable - · have : ∀ y, (‖condCdf ρ y x‖₊ : ℝ≥0∞) ≤ 1 := by + · exact (stronglyMeasurable_condCDF ρ _).aestronglyMeasurable + · have : ∀ y, (‖condCDF ρ y x‖₊ : ℝ≥0∞) ≤ 1 := by intro y - rw [Real.nnnorm_of_nonneg (condCdf_nonneg _ _ _)] - -- Porting note: was exact_mod_cast condCdf_le_one _ _ _ + rw [Real.nnnorm_of_nonneg (condCDF_nonneg _ _ _)] + -- Porting note: was exact_mod_cast condCDF_le_one _ _ _ simp only [ENNReal.coe_le_one_iff] - exact condCdf_le_one _ _ _ + exact condCDF_le_one _ _ _ refine' - (set_lintegral_mono (measurable_condCdf _ _).ennnorm measurable_one fun y _ => this y).trans + (set_lintegral_mono (measurable_condCDF _ _).ennnorm measurable_one fun y _ => this y).trans _ simp only [Pi.one_apply, lintegral_one, Measure.restrict_apply, MeasurableSet.univ, univ_inter] exact measure_mono (subset_univ _) -#align probability_theory.integrable_cond_cdf ProbabilityTheory.integrable_condCdf +#align probability_theory.integrable_cond_cdf ProbabilityTheory.integrable_condCDF -theorem set_integral_condCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) {s : Set α} - (hs : MeasurableSet s) : ∫ a in s, condCdf ρ a x ∂ρ.fst = (ρ (s ×ˢ Iic x)).toReal := by - have h := set_lintegral_condCdf ρ x hs +theorem set_integral_condCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) {s : Set α} + (hs : MeasurableSet s) : ∫ a in s, condCDF ρ a x ∂ρ.fst = (ρ (s ×ˢ Iic x)).toReal := by + have h := set_lintegral_condCDF ρ x hs rw [← ofReal_integral_eq_lintegral_ofReal] at h · rw [← h, ENNReal.toReal_ofReal] - exact integral_nonneg fun _ => condCdf_nonneg _ _ _ - · exact (integrable_condCdf _ _).integrableOn - · exact eventually_of_forall fun _ => condCdf_nonneg _ _ _ -#align probability_theory.set_integral_cond_cdf ProbabilityTheory.set_integral_condCdf + exact integral_nonneg fun _ => condCDF_nonneg _ _ _ + · exact (integrable_condCDF _ _).integrableOn + · exact eventually_of_forall fun _ => condCDF_nonneg _ _ _ +#align probability_theory.set_integral_cond_cdf ProbabilityTheory.set_integral_condCDF -theorem integral_condCdf (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) : - ∫ a, condCdf ρ a x ∂ρ.fst = (ρ (univ ×ˢ Iic x)).toReal := by - rw [← set_integral_condCdf ρ _ MeasurableSet.univ, Measure.restrict_univ] -#align probability_theory.integral_cond_cdf ProbabilityTheory.integral_condCdf +theorem integral_condCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) : + ∫ a, condCDF ρ a x ∂ρ.fst = (ρ (univ ×ˢ Iic x)).toReal := by + rw [← set_integral_condCDF ρ _ MeasurableSet.univ, Measure.restrict_univ] +#align probability_theory.integral_cond_cdf ProbabilityTheory.integral_condCDF section Measure -theorem measure_condCdf_Iic (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : - (condCdf ρ a).measure (Iic x) = ENNReal.ofReal (condCdf ρ a x) := by - rw [← sub_zero (condCdf ρ a x)] - exact (condCdf ρ a).measure_Iic (tendsto_condCdf_atBot ρ a) _ -#align probability_theory.measure_cond_cdf_Iic ProbabilityTheory.measure_condCdf_Iic +theorem measure_condCDF_Iic (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : + (condCDF ρ a).measure (Iic x) = ENNReal.ofReal (condCDF ρ a x) := by + rw [← sub_zero (condCDF ρ a x)] + exact (condCDF ρ a).measure_Iic (tendsto_condCDF_atBot ρ a) _ +#align probability_theory.measure_cond_cdf_Iic ProbabilityTheory.measure_condCDF_Iic -theorem measure_condCdf_univ (ρ : Measure (α × ℝ)) (a : α) : (condCdf ρ a).measure univ = 1 := by +theorem measure_condCDF_univ (ρ : Measure (α × ℝ)) (a : α) : (condCDF ρ a).measure univ = 1 := by rw [← ENNReal.ofReal_one, ← sub_zero (1 : ℝ)] - exact StieltjesFunction.measure_univ _ (tendsto_condCdf_atBot ρ a) (tendsto_condCdf_atTop ρ a) -#align probability_theory.measure_cond_cdf_univ ProbabilityTheory.measure_condCdf_univ + exact StieltjesFunction.measure_univ _ (tendsto_condCDF_atBot ρ a) (tendsto_condCDF_atTop ρ a) +#align probability_theory.measure_cond_cdf_univ ProbabilityTheory.measure_condCDF_univ instance instIsProbabilityMeasure (ρ : Measure (α × ℝ)) (a : α) : - IsProbabilityMeasure (condCdf ρ a).measure := - ⟨measure_condCdf_univ ρ a⟩ + IsProbabilityMeasure (condCDF ρ a).measure := + ⟨measure_condCDF_univ ρ a⟩ -/-- The function `a ↦ (condCdf ρ a).measure` is measurable. -/ -theorem measurable_measure_condCdf (ρ : Measure (α × ℝ)) : - Measurable fun a => (condCdf ρ a).measure := by +/-- The function `a ↦ (condCDF ρ a).measure` is measurable. -/ +theorem measurable_measure_condCDF (ρ : Measure (α × ℝ)) : + Measurable fun a => (condCDF ρ a).measure := by rw [Measure.measurable_measure] refine' fun s hs => ?_ -- Porting note: supplied `C` refine' MeasurableSpace.induction_on_inter - (C := fun s => Measurable fun b ↦ StieltjesFunction.measure (condCdf ρ b) s) + (C := fun s => Measurable fun b ↦ StieltjesFunction.measure (condCDF ρ b) s) (borel_eq_generateFrom_Iic ℝ) isPiSystem_Iic _ _ _ _ hs · simp only [measure_empty, measurable_const] · rintro S ⟨u, rfl⟩ - simp_rw [measure_condCdf_Iic ρ _ u] - exact (measurable_condCdf ρ u).ennreal_ofReal + simp_rw [measure_condCDF_Iic ρ _ u] + exact (measurable_condCDF ρ u).ennreal_ofReal · intro t ht ht_cd_meas have : - (fun a => (condCdf ρ a).measure tᶜ) = - (fun a => (condCdf ρ a).measure univ) - fun a => (condCdf ρ a).measure t := by + (fun a => (condCDF ρ a).measure tᶜ) = + (fun a => (condCDF ρ a).measure univ) - fun a => (condCDF ρ a).measure t := by ext1 a - rw [measure_compl ht (measure_ne_top (condCdf ρ a).measure _), Pi.sub_apply] - simp_rw [this, measure_condCdf_univ ρ] + rw [measure_compl ht (measure_ne_top (condCDF ρ a).measure _), Pi.sub_apply] + simp_rw [this, measure_condCDF_univ ρ] exact Measurable.sub measurable_const ht_cd_meas · intro f hf_disj hf_meas hf_cd_meas simp_rw [measure_iUnion hf_disj hf_meas] exact Measurable.ennreal_tsum hf_cd_meas -#align probability_theory.measurable_measure_cond_cdf ProbabilityTheory.measurable_measure_condCdf +#align probability_theory.measurable_measure_cond_cdf ProbabilityTheory.measurable_measure_condCDF end Measure diff --git a/Mathlib/Probability/Kernel/CondDistrib.lean b/Mathlib/Probability/Kernel/CondDistrib.lean index 23ad0e41d9a08..3cbd488e58506 100644 --- a/Mathlib/Probability/Kernel/CondDistrib.lean +++ b/Mathlib/Probability/Kernel/CondDistrib.lean @@ -69,6 +69,15 @@ instance [MeasurableSpace β] : IsMarkovKernel (condDistrib Y X μ) := by variable {mβ : MeasurableSpace β} {s : Set Ω} {t : Set β} {f : β × Ω → F} +/-- If the singleton `{x}` has non-zero mass for `μ.map X`, then for all `s : Set Ω`, +`condDistrib Y X μ x s = (μ.map X {x})⁻¹ * μ.map (fun a => (X a, Y a)) ({x} ×ˢ s)` . -/ +lemma condDistrib_apply_of_ne_zero [MeasurableSingletonClass β] + (hY : Measurable Y) (x : β) (hX : μ.map X {x} ≠ 0) (s : Set Ω) : + condDistrib Y X μ x s = (μ.map X {x})⁻¹ * μ.map (fun a => (X a, Y a)) ({x} ×ˢ s) := by + rw [condDistrib, condKernel_apply_of_ne_zero _ s] + · rw [Measure.fst_map_prod_mk hY] + · rwa [Measure.fst_map_prod_mk hY] + section Measurability theorem measurable_condDistrib (hs : MeasurableSet s) : diff --git a/Mathlib/Probability/Kernel/Disintegration.lean b/Mathlib/Probability/Kernel/Disintegration.lean index a5bd21c7640d4..b59c70d867087 100644 --- a/Mathlib/Probability/Kernel/Disintegration.lean +++ b/Mathlib/Probability/Kernel/Disintegration.lean @@ -25,7 +25,7 @@ where `ρ.fst` is the marginal measure of `ρ` on `α`. In particular, `ρ = ρ. In order to obtain a disintegration for any standard Borel space, we use that these spaces embed measurably into `ℝ`: it then suffices to define a suitable kernel for `Ω = ℝ`. In the real case, we define a conditional kernel by taking for each `a : α` the measure associated to the Stieltjes -function `condCdf ρ a` (the conditional cumulative distribution function). +function `condCDF ρ a` (the conditional cumulative distribution function). ## Main definitions @@ -61,22 +61,22 @@ section Real /-- Conditional measure on the second space of the product given the value on the first, as a kernel. Use the more general `condKernel`. -/ noncomputable def condKernelReal (ρ : Measure (α × ℝ)) : kernel α ℝ where - val a := (condCdf ρ a).measure - property := measurable_measure_condCdf ρ + val a := (condCDF ρ a).measure + property := measurable_measure_condCDF ρ #align probability_theory.cond_kernel_real ProbabilityTheory.condKernelReal instance (ρ : Measure (α × ℝ)) : IsMarkovKernel (condKernelReal ρ) := ⟨fun a => by rw [condKernelReal]; exact instIsProbabilityMeasure ρ a⟩ theorem condKernelReal_Iic (ρ : Measure (α × ℝ)) (a : α) (x : ℝ) : - condKernelReal ρ a (Iic x) = ENNReal.ofReal (condCdf ρ a x) := - measure_condCdf_Iic ρ a x + condKernelReal ρ a (Iic x) = ENNReal.ofReal (condCDF ρ a x) := + measure_condCDF_Iic ρ a x #align probability_theory.cond_kernel_real_Iic ProbabilityTheory.condKernelReal_Iic theorem set_lintegral_condKernelReal_Iic (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℝ) {s : Set α} (hs : MeasurableSet s) : ∫⁻ a in s, condKernelReal ρ a (Iic x) ∂ρ.fst = ρ (s ×ˢ Iic x) := by - simp_rw [condKernelReal_Iic]; exact set_lintegral_condCdf ρ x hs + simp_rw [condKernelReal_Iic]; exact set_lintegral_condCDF ρ x hs #align probability_theory.set_lintegral_cond_kernel_real_Iic ProbabilityTheory.set_lintegral_condKernelReal_Iic theorem set_lintegral_condKernelReal_univ (ρ : Measure (α × ℝ)) {s : Set α} (hs : MeasurableSet s) : @@ -369,6 +369,44 @@ theorem kernel.const_eq_compProd (γ : Type*) [MeasurableSpace γ] (ρ : Measure kernel.ext_iff'.mp (kernel.const_unit_eq_compProd ρ) () s hs #align probability_theory.kernel.const_eq_comp_prod ProbabilityTheory.kernel.const_eq_compProd +/-- Auxiliary lemma for `condKernel_apply_of_ne_zero`. -/ +lemma condKernel_apply_of_ne_zero_of_measurableSet [MeasurableSingletonClass α] + {ρ : Measure (α × Ω)} [IsFiniteMeasure ρ] + {x : α} (hx : ρ.fst {x} ≠ 0) {s : Set Ω} (hs : MeasurableSet s) : + ρ.condKernel x s = (ρ.fst {x})⁻¹ * ρ ({x} ×ˢ s) := by + nth_rewrite 3 [measure_eq_compProd ρ] + rw [Measure.compProd_apply (measurableSet_prod.mpr (Or.inl ⟨measurableSet_singleton x, hs⟩))] + classical + have : ∀ a, ρ.condKernel a (Prod.mk a ⁻¹' {x} ×ˢ s) + = ({x} : Set α).indicator (fun a ↦ ρ.condKernel a s) a := by + intro a + by_cases hax : a = x + · simp only [hax, Set.singleton_prod, Set.mem_singleton_iff, Set.indicator_of_mem] + congr with y + simp + · simp only [Set.singleton_prod, Set.mem_singleton_iff, hax, not_false_eq_true, + Set.indicator_of_not_mem] + have : Prod.mk a ⁻¹' (Prod.mk x '' s) = ∅ := by + ext y + simp [Ne.symm hax] + simp only [this, measure_empty] + simp_rw [this] + rw [MeasureTheory.lintegral_indicator _ (measurableSet_singleton x)] + simp only [Measure.restrict_singleton, lintegral_smul_measure, lintegral_dirac] + rw [← mul_assoc, ENNReal.inv_mul_cancel hx (measure_ne_top ρ.fst _), one_mul] + +/-- If the singleton `{x}` has non-zero mass for `ρ.fst`, then for all `s : Set Ω`, +`ρ.condKernel x s = (ρ.fst {x})⁻¹ * ρ ({x} ×ˢ s)` . -/ +lemma condKernel_apply_of_ne_zero [MeasurableSingletonClass α] + {ρ : Measure (α × Ω)} [IsFiniteMeasure ρ] {x : α} (hx : ρ.fst {x} ≠ 0) + (s : Set Ω) : + ρ.condKernel x s = (ρ.fst {x})⁻¹ * ρ ({x} ×ˢ s) := by + have : ρ.condKernel x s = ((ρ.fst {x})⁻¹ • ρ).comap (fun (y : Ω) ↦ (x, y)) s := by + congr 2 with s hs + simp [condKernel_apply_of_ne_zero_of_measurableSet hx hs, + (measurableEmbedding_prod_mk_left x).comap_apply] + simp [this, (measurableEmbedding_prod_mk_left x).comap_apply, hx] + theorem lintegral_condKernel_mem {s : Set (α × Ω)} (hs : MeasurableSet s) : ∫⁻ a, ρ.condKernel a {x | (a, x) ∈ s} ∂ρ.fst = ρ s := by conv_rhs => rw [measure_eq_compProd ρ] diff --git a/Mathlib/Probability/Kernel/MeasurableIntegral.lean b/Mathlib/Probability/Kernel/MeasurableIntegral.lean index 42d3e826d0c6a..e8bcc5522e718 100644 --- a/Mathlib/Probability/Kernel/MeasurableIntegral.lean +++ b/Mathlib/Probability/Kernel/MeasurableIntegral.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ import Mathlib.Probability.Kernel.Basic +import Mathlib.MeasureTheory.Constructions.Prod.Basic #align_import probability.kernel.measurable_integral from "leanprover-community/mathlib"@"28b2a92f2996d28e580450863c130955de0ed398" diff --git a/Mathlib/Probability/Martingale/BorelCantelli.lean b/Mathlib/Probability/Martingale/BorelCantelli.lean index 51614440bfad9..03144368acea5 100644 --- a/Mathlib/Probability/Martingale/BorelCantelli.lean +++ b/Mathlib/Probability/Martingale/BorelCantelli.lean @@ -200,7 +200,7 @@ theorem Submartingale.bddAbove_iff_exists_tendsto [IsFiniteMeasure μ] (hf : Sub · refine' ⟨fun h => _, fun h => _⟩ <;> obtain ⟨b, hb⟩ := h <;> refine' ⟨b + |f 0 ω|, fun y hy => _⟩ <;> obtain ⟨n, rfl⟩ := hy · simp_rw [sub_eq_add_neg] - exact add_le_add (hb ⟨n, rfl⟩) (neg_le_abs_self _) + exact add_le_add (hb ⟨n, rfl⟩) (neg_le_abs _) · exact sub_le_iff_le_add.1 (le_trans (sub_le_sub_left (le_abs_self _) _) (hb ⟨n, rfl⟩)) · refine' ⟨fun h => _, fun h => _⟩ <;> obtain ⟨c, hc⟩ := h · exact ⟨c - f 0 ω, hc.sub_const _⟩ diff --git a/Mathlib/Probability/Martingale/Convergence.lean b/Mathlib/Probability/Martingale/Convergence.lean index d4383382f162c..7428a5436ce0e 100644 --- a/Mathlib/Probability/Martingale/Convergence.lean +++ b/Mathlib/Probability/Martingale/Convergence.lean @@ -175,9 +175,8 @@ theorem Submartingale.upcrossings_ae_lt_top' [IsFiniteMeasure μ] (hf : Submarti refine' lintegral_mono fun ω => _ rw [ENNReal.ofReal_le_iff_le_toReal, ENNReal.coe_toReal, coe_nnnorm] by_cases hnonneg : 0 ≤ f n ω - a - · rw [LatticeOrderedGroup.pos_of_nonneg _ hnonneg, Real.norm_eq_abs, - abs_of_nonneg hnonneg] - · rw [LatticeOrderedGroup.pos_of_nonpos _ (not_le.1 hnonneg).le] + · rw [posPart_eq_self.2 hnonneg, Real.norm_eq_abs, abs_of_nonneg hnonneg] + · rw [posPart_eq_zero.2 (not_le.1 hnonneg).le] exact norm_nonneg _ · simp only [Ne.def, ENNReal.coe_ne_top, not_false_iff] · simp only [hab, Ne.def, ENNReal.ofReal_eq_zero, sub_nonpos, not_le] @@ -207,7 +206,7 @@ theorem Submartingale.exists_ae_trim_tendsto_of_bdd [IsFiniteMeasure μ] (hf : S letI := (⨆ n, ℱ n) rw [ae_iff, trim_measurableSet_eq] · exact hf.exists_ae_tendsto_of_bdd hbdd - · exact MeasurableSet.compl $ measurableSet_exists_tendsto + · exact MeasurableSet.compl <| measurableSet_exists_tendsto fun n => (hf.stronglyMeasurable n).measurable.mono (le_sSup ⟨n, rfl⟩) le_rfl #align measure_theory.submartingale.exists_ae_trim_tendsto_of_bdd MeasureTheory.Submartingale.exists_ae_trim_tendsto_of_bdd diff --git a/Mathlib/Probability/Martingale/OptionalStopping.lean b/Mathlib/Probability/Martingale/OptionalStopping.lean index 8495f5fc33eda..872c4f3198074 100644 --- a/Mathlib/Probability/Martingale/OptionalStopping.lean +++ b/Mathlib/Probability/Martingale/OptionalStopping.lean @@ -215,7 +215,7 @@ theorem maximal_ineq [IsFiniteMeasure μ] (hsub : Submartingale f 𝒢 μ) (hnon refine' ENNReal.ofReal_le_ofReal _ rw [← stoppedValue_const f n] exact hsub.expected_stoppedValue_mono (hitting_isStoppingTime hsub.adapted measurableSet_Ici) - (isStoppingTime_const _ _) (fun ω => hitting_le ω) (fun _ => le_rfl : ∀ _, n ≤ n) + (isStoppingTime_const _ _) (fun ω => hitting_le ω) (fun _ => le_refl n) #align measure_theory.maximal_ineq MeasureTheory.maximal_ineq end Maximal diff --git a/Mathlib/Probability/Martingale/Upcrossing.lean b/Mathlib/Probability/Martingale/Upcrossing.lean index 727525fecc760..93a2f588efbe5 100644 --- a/Mathlib/Probability/Martingale/Upcrossing.lean +++ b/Mathlib/Probability/Martingale/Upcrossing.lean @@ -675,12 +675,10 @@ theorem crossing_pos_eq (hab : a < b) : intro i ω refine' ⟨fun h => _, fun h => _⟩ · rwa [← sub_le_sub_iff_right a, ← - LatticeOrderedGroup.pos_eq_self_of_pos_pos (lt_of_lt_of_le hab' h)] + posPart_eq_of_posPart_pos (lt_of_lt_of_le hab' h)] · rw [← sub_le_sub_iff_right a] at h - rwa [LatticeOrderedGroup.pos_of_nonneg _ (le_trans hab'.le h)] - have hf' : ∀ ω i, (f i ω - a)⁺ ≤ 0 ↔ f i ω ≤ a := by - intro ω i - rw [LatticeOrderedGroup.pos_nonpos_iff, sub_nonpos] + rwa [posPart_eq_self.2 (le_trans hab'.le h)] + have hf' (ω i) : (f i ω - a)⁺ ≤ 0 ↔ f i ω ≤ a := by rw [posPart_nonpos, sub_nonpos] induction' n with k ih · refine' ⟨rfl, _⟩ simp (config := { unfoldPartialApp := true }) only [lowerCrossingTime_zero, hitting, @@ -726,8 +724,8 @@ theorem mul_integral_upcrossingsBefore_le_integral_pos_part_aux [IsFiniteMeasure (b - a) * μ[upcrossingsBefore a b f N] ≤ μ[fun ω => (f N ω - a)⁺] := by refine' le_trans (le_of_eq _) (integral_mul_upcrossingsBefore_le_integral (hf.sub_martingale (martingale_const _ _ _)).pos - (fun ω => LatticeOrderedGroup.pos_nonneg _) - (fun ω => LatticeOrderedGroup.pos_nonneg _) (sub_pos.2 hab)) + (fun ω => posPart_nonneg _) + (fun ω => posPart_nonneg _) (sub_pos.2 hab)) simp_rw [sub_zero, ← upcrossingsBefore_pos_eq hab] rfl #align measure_theory.mul_integral_upcrossings_before_le_integral_pos_part_aux MeasureTheory.mul_integral_upcrossingsBefore_le_integral_pos_part_aux @@ -743,7 +741,7 @@ theorem Submartingale.mul_integral_upcrossingsBefore_le_integral_pos_part [IsFin · exact mul_integral_upcrossingsBefore_le_integral_pos_part_aux hf hab · rw [not_lt, ← sub_nonpos] at hab exact le_trans (mul_nonpos_of_nonpos_of_nonneg hab (integral_nonneg fun ω => Nat.cast_nonneg _)) - (integral_nonneg fun ω => LatticeOrderedGroup.pos_nonneg _) + (integral_nonneg fun ω => posPart_nonneg _) #align measure_theory.submartingale.mul_integral_upcrossings_before_le_integral_pos_part MeasureTheory.Submartingale.mul_integral_upcrossingsBefore_le_integral_pos_part /-! @@ -859,7 +857,7 @@ theorem Submartingale.mul_lintegral_upcrossings_le_lintegral_pos_part [IsFiniteM intro N rw [ofReal_integral_eq_lintegral_ofReal] · exact (hf.sub_martingale (martingale_const _ _ _)).pos.integrable _ - · exact eventually_of_forall fun ω => LatticeOrderedGroup.pos_nonneg _ + · exact eventually_of_forall fun ω => posPart_nonneg _ rw [lintegral_iSup'] · simp_rw [this, ENNReal.mul_iSup, iSup_le_iff] intro N diff --git a/Mathlib/Probability/Notation.lean b/Mathlib/Probability/Notation.lean index 596ebcc961833..fc7c92f31ac4b 100644 --- a/Mathlib/Probability/Notation.lean +++ b/Mathlib/Probability/Notation.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ -import Mathlib.Probability.ProbabilityMassFunction.Basic import Mathlib.MeasureTheory.Function.ConditionalExpectation.Basic import Mathlib.MeasureTheory.Decomposition.Lebesgue diff --git a/Mathlib/Probability/ProbabilityMassFunction/Basic.lean b/Mathlib/Probability/ProbabilityMassFunction/Basic.lean index 5c0bc84c368bb..534d8ba8d2636 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Basic.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Basic.lean @@ -46,18 +46,18 @@ def PMF.{u} (α : Type u) : Type u := namespace PMF -instance funLike : FunLike (PMF α) α fun _ => ℝ≥0∞ where +instance instFunLike : FunLike (PMF α) α ℝ≥0∞ where coe p a := p.1 a coe_injective' _ _ h := Subtype.eq h -#align pmf.fun_like PMF.funLike +#align pmf.fun_like PMF.instFunLike @[ext] protected theorem ext {p q : PMF α} (h : ∀ x, p x = q x) : p = q := - FunLike.ext p q h + DFunLike.ext p q h #align pmf.ext PMF.ext theorem ext_iff {p q : PMF α} : p = q ↔ ∀ x, p x = q x := - FunLike.ext_iff + DFunLike.ext_iff #align pmf.ext_iff PMF.ext_iff theorem hasSum_coe_one (p : PMF α) : HasSum p 1 := diff --git a/Mathlib/Probability/ProbabilityMassFunction/Binomial.lean b/Mathlib/Probability/ProbabilityMassFunction/Binomial.lean index dea0165accca0..165c6a9ec6008 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Binomial.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Binomial.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joachim Breitner -/ import Mathlib.Probability.ProbabilityMassFunction.Constructions -import Mathlib.Data.Nat.Choose.Multinomial import Mathlib.Tactic.FinCases /-! diff --git a/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean b/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean index 4161abcc3eb58..441f624ca3816 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean @@ -35,7 +35,7 @@ theorem integral_eq_tsum (p : PMF α) (f : α → E) (hf : Integrable f p.toMeas congr with x; congr apply PMF.toMeasure_apply_singleton p x (MeasurableSet.singleton _) _ = ∑' a, (p a).toReal • f a := - tsum_subtype_eq_of_support_subset $ by calc + tsum_subtype_eq_of_support_subset <| by calc (fun a ↦ (p a).toReal • f a).support ⊆ (fun a ↦ (p a).toReal).support := Function.support_smul_subset_left _ _ _ ⊆ support p := fun x h1 h2 => h1 (by simp [h2]) diff --git a/Mathlib/Probability/ProbabilityMassFunction/Monad.lean b/Mathlib/Probability/ProbabilityMassFunction/Monad.lean index 8877e3ae36065..120024a5468bb 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Monad.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Monad.lean @@ -286,7 +286,7 @@ theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF split_ifs with h _ h_1 _ h_2 any_goals ring1 · have := h_1 a' - simp? [h] at this says simp only [h, dite_false, mul_eq_zero, false_or] at this + simp? [h] at this says simp only [h, ↓reduceDite, mul_eq_zero, false_or] at this contradiction · simp [h_2] #align pmf.bind_on_support_bind_on_support PMF.bindOnSupport_bindOnSupport diff --git a/Mathlib/Probability/Process/Filtration.lean b/Mathlib/Probability/Process/Filtration.lean index 51ae0bae3a6a1..63bc542af7417 100644 --- a/Mathlib/Probability/Process/Filtration.lean +++ b/Mathlib/Probability/Process/Filtration.lean @@ -148,7 +148,7 @@ noncomputable instance : InfSet (Filtration ι m) := { seq := fun i => if Set.Nonempty s then sInf ((fun f : Filtration ι m => f i) '' s) else m mono' := fun i j hij => by by_cases h_nonempty : Set.Nonempty s - swap; · simp only [h_nonempty, Set.nonempty_image_iff, if_false, le_refl] + swap; · simp only [h_nonempty, Set.image_nonempty, if_false, le_refl] simp only [h_nonempty, if_true, le_sInf_iff, Set.mem_image, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] refine' fun f hf_mem => le_trans _ (f.mono hij) diff --git a/Mathlib/Probability/Process/Stopping.lean b/Mathlib/Probability/Process/Stopping.lean index 0d98a9b4bff96..c895a8b4f0216 100644 --- a/Mathlib/Probability/Process/Stopping.lean +++ b/Mathlib/Probability/Process/Stopping.lean @@ -77,8 +77,8 @@ theorem IsStoppingTime.measurableSet_lt_of_pred [PredOrder ι] (hτ : IsStopping simp only [Set.mem_setOf_eq, Set.mem_empty_iff_false, iff_false_iff] rw [isMin_iff_forall_not_lt] at hi_min exact hi_min (τ ω) - have : {ω : Ω | τ ω < i} = τ ⁻¹' Set.Iio i := rfl - rw [this, ← Iic_pred_of_not_isMin hi_min] + have : {ω : Ω | τ ω < i} = τ ⁻¹' Set.Iic (pred i) := by ext; simp [Iic_pred_of_not_isMin hi_min] + rw [this] exact f.mono (pred_le i) _ (hτ.measurableSet_le <| pred i) #align measure_theory.is_stopping_time.measurable_set_lt_of_pred MeasureTheory.IsStoppingTime.measurableSet_lt_of_pred @@ -98,19 +98,14 @@ protected theorem measurableSet_eq_of_countable_range (hτ : IsStoppingTime f τ Set.mem_diff, Set.mem_iUnion, exists_prop, not_exists, not_and, not_le] constructor <;> intro h · simp only [h, lt_iff_le_not_le, le_refl, and_imp, imp_self, imp_true_iff, and_self_iff] - · have h_lt_or_eq : τ a < i ∨ τ a = i := lt_or_eq_of_le h.1 - rcases h_lt_or_eq with (h_lt | rfl) - · exfalso - exact h.2 a h_lt (le_refl (τ a)) - · rfl + · exact h.1.eq_or_lt.resolve_right fun h_lt => h.2 a h_lt le_rfl rw [this] refine' (hτ.measurableSet_le i).diff _ refine' MeasurableSet.biUnion h_countable fun j _ => _ - by_cases hji : j < i - · simp only [hji, Set.iUnion_true] - exact f.mono hji.le _ (hτ.measurableSet_le j) - · simp only [hji, Set.iUnion_false] - exact @MeasurableSet.empty _ (f i) + rw [Set.iUnion_eq_if] + split_ifs with hji + · exact f.mono hji.le _ (hτ.measurableSet_le j) + · exact @MeasurableSet.empty _ (f i) #align measure_theory.is_stopping_time.measurable_set_eq_of_countable_range MeasureTheory.IsStoppingTime.measurableSet_eq_of_countable_range protected theorem measurableSet_eq_of_countable [Countable ι] (hτ : IsStoppingTime f τ) (i : ι) : @@ -164,7 +159,7 @@ section TopologicalSpace variable [TopologicalSpace ι] [OrderTopology ι] [FirstCountableTopology ι] -/-- Auxiliary lemma for `is_stopping_time.measurable_set_lt`. -/ +/-- Auxiliary lemma for `MeasureTheory.IsStoppingTime.measurableSet_lt`. -/ theorem IsStoppingTime.measurableSet_lt_of_isLUB (hτ : IsStoppingTime f τ) (i : ι) (h_lub : IsLUB (Set.Iio i) i) : MeasurableSet[f i] {ω | τ ω < i} := by by_cases hi_min : IsMin i @@ -173,8 +168,8 @@ theorem IsStoppingTime.measurableSet_lt_of_isLUB (hτ : IsStoppingTime f τ) (i simp only [Set.mem_setOf_eq, Set.mem_empty_iff_false, iff_false_iff] exact isMin_iff_forall_not_lt.mp hi_min (τ ω) obtain ⟨seq, -, -, h_tendsto, h_bound⟩ : - ∃ seq : ℕ → ι, Monotone seq ∧ (∀ j, seq j ≤ i) ∧ Tendsto seq atTop (𝓝 i) ∧ ∀ j, seq j < i - exact h_lub.exists_seq_monotone_tendsto (not_isMin_iff.mp hi_min) + ∃ seq : ℕ → ι, Monotone seq ∧ (∀ j, seq j ≤ i) ∧ Tendsto seq atTop (𝓝 i) ∧ ∀ j, seq j < i := + h_lub.exists_seq_monotone_tendsto (not_isMin_iff.mp hi_min) have h_Ioi_eq_Union : Set.Iio i = ⋃ j, {k | k ≤ seq j} := by ext1 k simp only [Set.mem_Iio, Set.mem_iUnion, Set.mem_setOf_eq] @@ -291,8 +286,8 @@ theorem add_const_nat {f : Filtration ℕ m} {τ : Ω → ℕ} (hτ : IsStopping · rw [not_le] at hij convert @MeasurableSet.empty _ (f.1 j) ext ω - simp only [Set.mem_empty_iff_false, iff_false_iff] - rintro (hx : τ ω + i = j) + simp only [Set.mem_empty_iff_false, iff_false_iff, Set.mem_setOf] + intro hx linarith #align measure_theory.is_stopping_time.add_const_nat MeasureTheory.IsStoppingTime.add_const_nat @@ -382,7 +377,7 @@ theorem measurableSpace_le {ι} [SemilatticeSup ι] {f : Filtration ι m} {τ : cases isEmpty_or_nonempty ι · haveI : IsEmpty Ω := ⟨fun ω => IsEmpty.false (τ ω)⟩ intro s _ - suffices hs : s = ∅; · rw [hs]; exact MeasurableSet.empty + suffices hs : s = ∅ by rw [hs]; exact MeasurableSet.empty haveI : Unique (Set Ω) := Set.uniqueEmpty rw [Unique.eq_default s, Unique.eq_default ∅] exact measurableSpace_le' hτ @@ -687,9 +682,8 @@ theorem measurableSet_le_stopping_time [TopologicalSpace ι] [SecondCountableTop and_congr_left_iff] intro h simp only [h, or_self_iff, and_true_iff] - by_cases hj : j ≤ π ω - · simp only [hj, h.trans hj, or_self_iff] - · simp only [hj, or_false_iff] + rw [Iff.comm, or_iff_left_iff_imp] + exact h.trans rw [this] refine' MeasurableSet.inter _ (hτ.measurableSet_le j) apply @measurableSet_le _ _ _ _ _ (Filtration.seq f j) _ _ _ _ _ ?_ ?_ @@ -924,14 +918,13 @@ theorem stoppedProcess_eq_of_mem_finset [LinearOrder ι] [AddCommMonoid E] {s : exact (hm.2.trans_le h).ne' · exact h · rw [stoppedProcess_eq_of_ge (le_of_lt h), Finset.sum_eq_single_of_mem (τ ω)] - · rw [Set.indicator_of_not_mem, zero_add, Set.indicator_of_mem] - · exact rfl - -- refl does not work - · exact not_le.2 h + · rw [Set.indicator_of_not_mem, zero_add, Set.indicator_of_mem] <;> rw [Set.mem_setOf] + exact not_le.2 h · rw [Finset.mem_filter] exact ⟨hbdd ω h, h⟩ · intro b _ hneq rw [Set.indicator_of_not_mem] + rw [Set.mem_setOf] exact hneq.symm #align measure_theory.stopped_process_eq_of_mem_finset MeasureTheory.stoppedProcess_eq_of_mem_finset @@ -1102,9 +1095,9 @@ theorem stoppedProcess_eq' (n : ℕ) : stoppedProcess u τ n = Set.indicator {a {a | n + 1 ≤ τ a}.indicator (u n) + {a | τ a = n}.indicator (u n) := by ext x rw [add_comm, Pi.add_apply, ← Set.indicator_union_of_not_mem_inter] - · simp_rw [@eq_comm _ _ n, @le_iff_eq_or_lt _ _ n, Nat.succ_le_iff] - rfl + · simp_rw [@eq_comm _ _ n, @le_iff_eq_or_lt _ _ n, Nat.succ_le_iff, Set.setOf_or] · rintro ⟨h₁, h₂⟩ + rw [Set.mem_setOf] at h₁ h₂ exact (Nat.succ_le_iff.1 h₂).ne h₁.symm rw [stoppedProcess_eq, this, Finset.sum_range_succ_comm, ← add_assoc] #align measure_theory.stopped_process_eq' MeasureTheory.stoppedProcess_eq' diff --git a/Mathlib/Probability/StrongLaw.lean b/Mathlib/Probability/StrongLaw.lean index b383b9836cc94..02c13ecbd4a43 100644 --- a/Mathlib/Probability/StrongLaw.lean +++ b/Mathlib/Probability/StrongLaw.lean @@ -445,7 +445,7 @@ theorem strong_law_aux1 {c : ℝ} (c_one : 1 < c) {ε : ℝ} (εpos : 0 < ε) : refine' sum_nbij' (fun p ↦ ⟨p.2, p.1⟩) (fun p ↦ ⟨p.2, p.1⟩) _ _ _ _ _ · simp only [mem_sigma, mem_range, filter_congr_decidable, mem_filter, and_imp, Sigma.forall] - exact fun a b haN hb ↦ ⟨hb.trans_le $ u_mono $ Nat.le_pred_of_lt haN, haN, hb⟩ + exact fun a b haN hb ↦ ⟨hb.trans_le <| u_mono <| Nat.le_pred_of_lt haN, haN, hb⟩ all_goals aesop _ ≤ ∑ j in range (u (N - 1)), c ^ 5 * (c - 1)⁻¹ ^ 3 / ↑j ^ 2 * Var[Y j] := by apply sum_le_sum fun j hj => ?_ @@ -512,7 +512,7 @@ theorem strong_law_aux2 {c : ℝ} (c_one : 1 < c) : apply Asymptotics.isLittleO_iff.2 fun ε εpos => ?_ obtain ⟨i, hi⟩ : ∃ i, v i < ε := ((tendsto_order.1 v_lim).2 ε εpos).exists filter_upwards [hω i] with n hn - simp only [Real.norm_eq_abs, LatticeOrderedGroup.abs_abs, Nat.abs_cast] + simp only [Real.norm_eq_abs, abs_abs, Nat.abs_cast] exact hn.le.trans (mul_le_mul_of_nonneg_right hi.le (Nat.cast_nonneg _)) #align probability_theory.strong_law_aux2 ProbabilityTheory.strong_law_aux2 diff --git a/Mathlib/Probability/Variance.lean b/Mathlib/Probability/Variance.lean index d322b513073a0..cc4a471daf474 100644 --- a/Mathlib/Probability/Variance.lean +++ b/Mathlib/Probability/Variance.lean @@ -365,7 +365,7 @@ theorem IndepFun.variance_sum [@IsProbabilityMeasure Ω _ ℙ] {ι : Type*} {X : Memℒp.integrable one_le_two (hs _ (mem_insert_of_mem hi)), mul_sum, mul_sum, ← sum_sub_distrib] apply Finset.sum_eq_zero fun i hi => ?_ - have : ∀ (a : Ω), @OfNat.ofNat (Ω → ℝ) 2 instOfNat a = (2 : ℝ) := fun a => rfl + have : ∀ (a : Ω), @OfNat.ofNat (Ω → ℝ) 2 instOfNatAtLeastTwo a = (2 : ℝ) := fun a => rfl conv_lhs => enter [1, 2, a]; rw [this] rw [integral_mul_left, IndepFun.integral_mul', sub_self] · apply h (mem_insert_self _ _) (mem_insert_of_mem hi) diff --git a/Mathlib/RepresentationTheory/Action/Basic.lean b/Mathlib/RepresentationTheory/Action/Basic.lean index 9054980591c1f..00a1f49e4f427 100644 --- a/Mathlib/RepresentationTheory/Action/Basic.lean +++ b/Mathlib/RepresentationTheory/Action/Basic.lean @@ -9,7 +9,7 @@ import Mathlib.CategoryTheory.Limits.FunctorCategory import Mathlib.CategoryTheory.Limits.Preserves.Basic import Mathlib.CategoryTheory.Adjunction.Limits import Mathlib.CategoryTheory.Conj -import Mathlib.Algebra.Algebra.Basic +import Mathlib.Data.Fin.Basic #align_import representation_theory.Action from "leanprover-community/mathlib"@"95a87616d63b3cb49d3fe678d416fbe9c4217bf4" @@ -362,65 +362,6 @@ set_option linter.uppercaseLean3 false in -- TODO promote `res` to a pseudofunctor from -- the locally discrete bicategory constructed from `Monᵒᵖ` to `Cat`, sending `G` to `Action V G`. -/-- Bundles a type `H` with a multiplicative action of `G` as an `Action`. -/ -def ofMulAction (G H : Type u) [Monoid G] [MulAction G H] : Action (Type u) (MonCat.of G) where - V := H - ρ := @MulAction.toEndHom _ _ _ (by assumption) -set_option linter.uppercaseLean3 false in -#align Action.of_mul_action Action.ofMulAction - -@[simp] -theorem ofMulAction_apply {G H : Type u} [Monoid G] [MulAction G H] (g : G) (x : H) : - (ofMulAction G H).ρ g x = (g • x : H) := - rfl -set_option linter.uppercaseLean3 false in -#align Action.of_mul_action_apply Action.ofMulAction_apply - -/-- Given a family `F` of types with `G`-actions, this is the limit cone demonstrating that the -product of `F` as types is a product in the category of `G`-sets. -/ -def ofMulActionLimitCone {ι : Type v} (G : Type max v u) [Monoid G] (F : ι → Type max v u) - [∀ i : ι, MulAction G (F i)] : - LimitCone (Discrete.functor fun i : ι => Action.ofMulAction G (F i)) where - cone := - { pt := Action.ofMulAction G (∀ i : ι, F i) - π := Discrete.natTrans (fun i => ⟨fun x => x i.as, fun g => rfl⟩) } - isLimit := - { lift := fun s => - { hom := fun x i => (s.π.app ⟨i⟩).hom x - comm := fun g => by - ext x - funext j - exact congr_fun ((s.π.app ⟨j⟩).comm g) x } - fac := fun s j => rfl - uniq := fun s f h => by - ext x - funext j - dsimp at * - rw [← h ⟨j⟩] - rfl } -set_option linter.uppercaseLean3 false in -#align Action.of_mul_action_limit_cone Action.ofMulActionLimitCone - -/-- The `G`-set `G`, acting on itself by left multiplication. -/ -@[simps!] -def leftRegular (G : Type u) [Monoid G] : Action (Type u) (MonCat.of G) := - Action.ofMulAction G G -set_option linter.uppercaseLean3 false in -#align Action.left_regular Action.leftRegular - -/-- The `G`-set `Gⁿ`, acting on itself by left multiplication. -/ -@[simps!] -def diagonal (G : Type u) [Monoid G] (n : ℕ) : Action (Type u) (MonCat.of G) := - Action.ofMulAction G (Fin n → G) -set_option linter.uppercaseLean3 false in -#align Action.diagonal Action.diagonal - -/-- We have `fin 1 → G ≅ G` as `G`-sets, with `G` acting by left multiplication. -/ -def diagonalOneIsoLeftRegular (G : Type u) [Monoid G] : diagonal G 1 ≅ leftRegular G := - Action.mkIso (Equiv.funUnique _ _).toIso fun _ => rfl -set_option linter.uppercaseLean3 false in -#align Action.diagonal_one_iso_left_regular Action.diagonalOneIsoLeftRegular - end Action namespace CategoryTheory.Functor diff --git a/Mathlib/RepresentationTheory/Action/Concrete.lean b/Mathlib/RepresentationTheory/Action/Concrete.lean new file mode 100644 index 0000000000000..9d2a3a7cb4af2 --- /dev/null +++ b/Mathlib/RepresentationTheory/Action/Concrete.lean @@ -0,0 +1,79 @@ +/- +Copyright (c) 2020 Scott Morrison. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Morrison +-/ +import Mathlib.RepresentationTheory.Action.Basic + +/-! +# Constructors for `Action V G` for some concrete categories + +We construct `Action (Type u) G` from a `[MulAction G X]` instance and give some applications. +-/ + +universe u v + +open CategoryTheory Limits + +namespace Action + +/-- Bundles a type `H` with a multiplicative action of `G` as an `Action`. -/ +def ofMulAction (G H : Type u) [Monoid G] [MulAction G H] : Action (Type u) (MonCat.of G) where + V := H + ρ := @MulAction.toEndHom _ _ _ (by assumption) +set_option linter.uppercaseLean3 false in +#align Action.of_mul_action Action.ofMulAction + +@[simp] +theorem ofMulAction_apply {G H : Type u} [Monoid G] [MulAction G H] (g : G) (x : H) : + (ofMulAction G H).ρ g x = (g • x : H) := + rfl +set_option linter.uppercaseLean3 false in +#align Action.of_mul_action_apply Action.ofMulAction_apply + +/-- Given a family `F` of types with `G`-actions, this is the limit cone demonstrating that the +product of `F` as types is a product in the category of `G`-sets. -/ +def ofMulActionLimitCone {ι : Type v} (G : Type max v u) [Monoid G] (F : ι → Type max v u) + [∀ i : ι, MulAction G (F i)] : + LimitCone (Discrete.functor fun i : ι => Action.ofMulAction G (F i)) where + cone := + { pt := Action.ofMulAction G (∀ i : ι, F i) + π := Discrete.natTrans (fun i => ⟨fun x => x i.as, fun g => rfl⟩) } + isLimit := + { lift := fun s => + { hom := fun x i => (s.π.app ⟨i⟩).hom x + comm := fun g => by + ext x + funext j + exact congr_fun ((s.π.app ⟨j⟩).comm g) x } + fac := fun s j => rfl + uniq := fun s f h => by + ext x + funext j + dsimp at * + rw [← h ⟨j⟩] + rfl } +set_option linter.uppercaseLean3 false in +#align Action.of_mul_action_limit_cone Action.ofMulActionLimitCone + +/-- The `G`-set `G`, acting on itself by left multiplication. -/ +@[simps!] +def leftRegular (G : Type u) [Monoid G] : Action (Type u) (MonCat.of G) := + Action.ofMulAction G G +set_option linter.uppercaseLean3 false in +#align Action.left_regular Action.leftRegular + +/-- The `G`-set `Gⁿ`, acting on itself by left multiplication. -/ +@[simps!] +def diagonal (G : Type u) [Monoid G] (n : ℕ) : Action (Type u) (MonCat.of G) := + Action.ofMulAction G (Fin n → G) +set_option linter.uppercaseLean3 false in +#align Action.diagonal Action.diagonal + +/-- We have `fin 1 → G ≅ G` as `G`-sets, with `G` acting by left multiplication. -/ +def diagonalOneIsoLeftRegular (G : Type u) [Monoid G] : diagonal G 1 ≅ leftRegular G := + Action.mkIso (Equiv.funUnique _ _).toIso fun _ => rfl +set_option linter.uppercaseLean3 false in +#align Action.diagonal_one_iso_left_regular Action.diagonalOneIsoLeftRegular + +end Action diff --git a/Mathlib/RepresentationTheory/Action/Limits.lean b/Mathlib/RepresentationTheory/Action/Limits.lean index 2807c710b5f1a..1edf19ff530d7 100644 --- a/Mathlib/RepresentationTheory/Action/Limits.lean +++ b/Mathlib/RepresentationTheory/Action/Limits.lean @@ -19,7 +19,7 @@ We show: * When `V` is preadditive, linear, or abelian so is `Action V G`. -/ -universe u v +universe u v w₁ w₂ t₁ t₂ open CategoryTheory Limits @@ -40,6 +40,11 @@ instance [HasFiniteLimits V] : HasFiniteLimits (Action V G) where instance [HasLimits V] : HasLimits (Action V G) := Adjunction.has_limits_of_equivalence (Action.functorCategoryEquivalence _ _).functor +/-- If `V` has limits of shape `J`, so does `Action V G`.-/ +instance hasLimitsOfShape {J : Type w₁} [Category.{w₂} J] [HasLimitsOfShape J V] : + HasLimitsOfShape J (Action V G) := + Adjunction.hasLimitsOfShape_of_equivalence (Action.functorCategoryEquivalence _ _).functor + instance [HasFiniteCoproducts V] : HasFiniteCoproducts (Action V G) where out _ := Adjunction.hasColimitsOfShape_of_equivalence (Action.functorCategoryEquivalence _ _).functor @@ -51,8 +56,151 @@ instance [HasFiniteColimits V] : HasFiniteColimits (Action V G) where instance [HasColimits V] : HasColimits (Action V G) := Adjunction.has_colimits_of_equivalence (Action.functorCategoryEquivalence _ _).functor +/-- If `V` has colimits of shape `J`, so does `Action V G`.-/ +instance hasColimitsOfShape {J : Type w₁} [Category.{w₂} J] + [HasColimitsOfShape J V] : HasColimitsOfShape J (Action V G) := + Adjunction.hasColimitsOfShape_of_equivalence (Action.functorCategoryEquivalence _ _).functor + end Limits +section Preservation + +variable {C : Type t₁} [Category.{t₂} C] + +/-- `F : C ⥤ SingleObj G ⥤ V` preserves the limit of some `K : J ⥤ C` if it does +evaluated at `SingleObj.star G`.-/ +private def SingleObj.preservesLimit (F : C ⥤ SingleObj G ⥤ V) + {J : Type w₁} [Category.{w₂} J] (K : J ⥤ C) + (h : PreservesLimit K (F ⋙ (evaluation (SingleObj G) V).obj (SingleObj.star G))) : + PreservesLimit K F := by + apply preservesLimitOfEvaluation + intro _ + exact h + +/-- `F : C ⥤ Action V G` preserves the limit of some `K : J ⥤ C` if +if it does after postcomposing with the forgetful functor `Action V G ⥤ V`. -/ +def preservesLimitOfPreserves (F : C ⥤ Action V G) {J : Type w₁} + [Category.{w₂} J] (K : J ⥤ C) + (h : PreservesLimit K (F ⋙ Action.forget V G)) : PreservesLimit K F := by + let F' : C ⥤ SingleObj G ⥤ V := F ⋙ (Action.functorCategoryEquivalence V G).functor + have : PreservesLimit K F' := SingleObj.preservesLimit _ _ h + apply preservesLimitOfReflectsOfPreserves F (Action.functorCategoryEquivalence V G).functor + +/-- `F : C ⥤ Action V G` preserves limits of some shape `J` +if it does after postcomposing with the forgetful functor `Action V G ⥤ V`. -/ +def preservesLimitsOfShapeOfPreserves (F : C ⥤ Action V G) {J : Type w₁} + [Category.{w₂} J] (h : PreservesLimitsOfShape J (F ⋙ Action.forget V G)) : + PreservesLimitsOfShape J F := by + constructor + intro K + apply Action.preservesLimitOfPreserves + exact PreservesLimitsOfShape.preservesLimit + +/-- `F : C ⥤ Action V G` preserves limits of some size +if it does after postcomposing with the forgetful functor `Action V G ⥤ V`. -/ +def preservesLimitsOfSizeOfPreserves (F : C ⥤ Action V G) + (h : PreservesLimitsOfSize.{w₂, w₁} (F ⋙ Action.forget V G)) : + PreservesLimitsOfSize.{w₂, w₁} F := by + constructor + intro J _ + apply Action.preservesLimitsOfShapeOfPreserves + exact PreservesLimitsOfSize.preservesLimitsOfShape + +/-- `F : C ⥤ SingleObj G ⥤ V` preserves the colimit of some `K : J ⥤ C` if it does +evaluated at `SingleObj.star G`.-/ +private def SingleObj.preservesColimit (F : C ⥤ SingleObj G ⥤ V) + {J : Type w₁} [Category.{w₂} J] (K : J ⥤ C) + (h : PreservesColimit K (F ⋙ (evaluation (SingleObj G) V).obj (SingleObj.star G))) : + PreservesColimit K F := by + apply preservesColimitOfEvaluation + intro _ + exact h + +/-- `F : C ⥤ Action V G` preserves the colimit of some `K : J ⥤ C` if +if it does after postcomposing with the forgetful functor `Action V G ⥤ V`. -/ +def preservesColimitOfPreserves (F : C ⥤ Action V G) {J : Type w₁} + [Category.{w₂} J] (K : J ⥤ C) + (h : PreservesColimit K (F ⋙ Action.forget V G)) : PreservesColimit K F := by + let F' : C ⥤ SingleObj G ⥤ V := F ⋙ (Action.functorCategoryEquivalence V G).functor + have : PreservesColimit K F' := SingleObj.preservesColimit _ _ h + apply preservesColimitOfReflectsOfPreserves F (Action.functorCategoryEquivalence V G).functor + +/-- `F : C ⥤ Action V G` preserves colimits of some shape `J` +if it does after postcomposing with the forgetful functor `Action V G ⥤ V`. -/ +def preservesColimitsOfShapeOfPreserves (F : C ⥤ Action V G) {J : Type w₁} + [Category.{w₂} J] (h : PreservesColimitsOfShape J (F ⋙ Action.forget V G)) : + PreservesColimitsOfShape J F := by + constructor + intro K + apply Action.preservesColimitOfPreserves + exact PreservesColimitsOfShape.preservesColimit + +/-- `F : C ⥤ Action V G` preserves colimits of some size +if it does after postcomposing with the forgetful functor `Action V G ⥤ V`. -/ +def preservesColimitsOfSizeOfPreserves (F : C ⥤ Action V G) + (h : PreservesColimitsOfSize.{w₂, w₁} (F ⋙ Action.forget V G)) : + PreservesColimitsOfSize.{w₂, w₁} F := by + constructor + intro J _ + apply Action.preservesColimitsOfShapeOfPreserves + exact PreservesColimitsOfSize.preservesColimitsOfShape + +end Preservation + +section Forget + +noncomputable instance {J : Type w₁} [Category.{w₂} J] [HasLimitsOfShape J V] : + PreservesLimitsOfShape J (Action.forget V G) := by + show PreservesLimitsOfShape J ((Action.functorCategoryEquivalence V G).functor ⋙ + (evaluation (SingleObj G) V).obj (SingleObj.star G)) + infer_instance + +noncomputable instance {J : Type w₁} [Category.{w₂} J] [HasColimitsOfShape J V] : + PreservesColimitsOfShape J (Action.forget V G) := by + show PreservesColimitsOfShape J ((Action.functorCategoryEquivalence V G).functor ⋙ + (evaluation (SingleObj G) V).obj (SingleObj.star G)) + infer_instance + +noncomputable instance [HasFiniteLimits V] : PreservesFiniteLimits (Action.forget V G) := by + show PreservesFiniteLimits ((Action.functorCategoryEquivalence V G).functor ⋙ + (evaluation (SingleObj G) V).obj (SingleObj.star G)) + have : PreservesFiniteLimits ((evaluation (SingleObj G) V).obj (SingleObj.star G)) := by + constructor + intro _ _ _ + infer_instance + apply compPreservesFiniteLimits + +noncomputable instance [HasFiniteColimits V] : PreservesFiniteColimits (Action.forget V G) := by + show PreservesFiniteColimits ((Action.functorCategoryEquivalence V G).functor ⋙ + (evaluation (SingleObj G) V).obj (SingleObj.star G)) + have : PreservesFiniteColimits ((evaluation (SingleObj G) V).obj (SingleObj.star G)) := by + constructor + intro _ _ _ + infer_instance + apply compPreservesFiniteColimits + +instance {J : Type w₁} [Category.{w₂} J] (F : J ⥤ Action V G) : + ReflectsLimit F (Action.forget V G) where + reflects h := by + apply isLimitOfReflects ((Action.functorCategoryEquivalence V G).functor) + exact evaluationJointlyReflectsLimits _ (fun _ => h) + +instance {J : Type w₁} [Category.{w₂} J] : ReflectsLimitsOfShape J (Action.forget V G) where + +instance : ReflectsLimits (Action.forget V G) where + +instance {J : Type w₁} [Category.{w₂} J] (F : J ⥤ Action V G) : + ReflectsColimit F (Action.forget V G) where + reflects h := by + apply isColimitOfReflects ((Action.functorCategoryEquivalence V G).functor) + exact evaluationJointlyReflectsColimits _ (fun _ => h) + +instance {J : Type w₁} [Category.{w₂} J] : ReflectsColimitsOfShape J (Action.forget V G) where + +instance : ReflectsColimits (Action.forget V G) where + +end Forget + section HasZeroMorphisms variable [HasZeroMorphisms V] diff --git a/Mathlib/RepresentationTheory/Action/Monoidal.lean b/Mathlib/RepresentationTheory/Action/Monoidal.lean index 050d09ba67536..ef0eb9e025b10 100644 --- a/Mathlib/RepresentationTheory/Action/Monoidal.lean +++ b/Mathlib/RepresentationTheory/Action/Monoidal.lean @@ -4,13 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Mathlib.RepresentationTheory.Action.Limits +import Mathlib.RepresentationTheory.Action.Concrete import Mathlib.CategoryTheory.Monoidal.FunctorCategory import Mathlib.CategoryTheory.Monoidal.Transport import Mathlib.CategoryTheory.Monoidal.Rigid.OfEquivalence import Mathlib.CategoryTheory.Monoidal.Rigid.FunctorCategory import Mathlib.CategoryTheory.Monoidal.Linear import Mathlib.CategoryTheory.Monoidal.Braided -import Mathlib.CategoryTheory.Monoidal.Types.Symmetric +import Mathlib.CategoryTheory.Monoidal.Types.Basic /-! # Induced monoidal structure on `Action V G` diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Hilbert90.lean b/Mathlib/RepresentationTheory/GroupCohomology/Hilbert90.lean index 33d5a299aebdb..3fedb4e41ccac 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Hilbert90.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Hilbert90.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Amelia Livingston. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Amelia Livingston -/ -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Fixed import Mathlib.RepresentationTheory.GroupCohomology.LowDegree import Mathlib.LinearAlgebra.LinearIndependent @@ -61,10 +61,10 @@ linear independence of characters -/ have : LinearIndependent L (fun (f : L ≃ₐ[K] L) => (f : L → L)) := LinearIndependent.comp (ι' := L ≃ₐ[K] L) (linearIndependent_monoidHom L L) (fun f => f) - (fun x y h => by ext; exact FunLike.ext_iff.1 h _) + (fun x y h => by ext; exact DFunLike.ext_iff.1 h _) have h := linearIndependent_iff.1 this (Finsupp.equivFunOnFinite.symm (fun φ => (f φ : L))) - fun H => Units.ne_zero (f 1) (FunLike.ext_iff.1 (h H) 1) + fun H => Units.ne_zero (f 1) (DFunLike.ext_iff.1 (h H) 1) end Hilbert90 section @@ -76,7 +76,7 @@ theorem hilbert90 (f : (L ≃ₐ[K] L) → Lˣ) ∃ β : Lˣ, ∀ g : (L ≃ₐ[K] L), f g * Units.map g β = β := by /- Let `z : L` be such that `∑ f(h) * h(z) ≠ 0`, for `h ∈ Aut_K(L)` -/ obtain ⟨z, hz⟩ : ∃ z, aux K L f z ≠ 0 := - not_forall.1 (fun H => aux_ne_zero K L f $ funext fun x => H x) + not_forall.1 (fun H => aux_ne_zero K L f <| funext fun x => H x) have : aux K L f z = ∑ h, f h * h z := by simp [aux, Finsupp.total, Finsupp.sum_fintype] /- Let `β = ∑ f(h) * h(z).` -/ use Units.mk0 (aux K L f z) hz diff --git a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean index 3ef48ae74ca4d..9dfbe451ab3ed 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean @@ -218,7 +218,7 @@ variable {A} theorem mem_oneCocycles_def (f : G → A) : f ∈ oneCocycles A ↔ ∀ g h : G, A.ρ g (f h) - f (g * h) + f g = 0 := - LinearMap.mem_ker.trans $ by + LinearMap.mem_ker.trans <| by rw [Function.funext_iff] simp only [dOne_apply, Pi.zero_apply, Prod.forall] @@ -269,7 +269,7 @@ variable {A} theorem mem_twoCocycles_def (f : G × G → A) : f ∈ twoCocycles A ↔ ∀ g h j : G, A.ρ g (f (h, j)) - f (g * h, j) + f (g, h * j) - f (g, h) = 0 := - LinearMap.mem_ker.trans $ by + LinearMap.mem_ker.trans <| by rw [Function.funext_iff] simp only [dTwo_apply, Prod.mk.eta, Pi.zero_apply, Prod.forall] diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean index 50ec517bfd44f..f8e40bfc88a03 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean @@ -627,7 +627,7 @@ theorem forget₂ToModuleCatHomotopyEquiv_f_0_eq : simp only [HomologicalComplex.comp_f] dsimp convert Category.id_comp (X := (forget₂ToModuleCat k G).X 0) _ - · dsimp only [HomotopyEquiv.ofIso, compForgetAugmentedIso, map_alternatingFaceMapComplex] + · dsimp only [HomotopyEquiv.ofIso, compForgetAugmentedIso] simp only [Iso.symm_hom, eqToIso.inv, HomologicalComplex.eqToHom_f, eqToHom_refl] trans (Finsupp.total _ _ _ fun _ => (1 : k)).comp ((ModuleCat.free k).map (terminal.from _)) · dsimp diff --git a/Mathlib/RepresentationTheory/Maschke.lean b/Mathlib/RepresentationTheory/Maschke.lean index bd18ba1829858..d0dc49e4c1611 100644 --- a/Mathlib/RepresentationTheory/Maschke.lean +++ b/Mathlib/RepresentationTheory/Maschke.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Mathlib.Algebra.MonoidAlgebra.Basic -import Mathlib.Algebra.CharP.Invertible import Mathlib.LinearAlgebra.Basis.VectorSpace #align_import representation_theory.maschke from "leanprover-community/mathlib"@"70fd9563a21e7b963887c9360bd29b2393e6225a" @@ -155,8 +154,8 @@ theorem exists_leftInverse_of_injective (f : V →ₗ[MonoidAlgebra k G] W) ∃ g : W →ₗ[MonoidAlgebra k G] V, g.comp f = LinearMap.id := by obtain ⟨φ, hφ⟩ := (f.restrictScalars k).exists_leftInverse_of_injective <| by simp only [hf, Submodule.restrictScalars_bot, LinearMap.ker_restrictScalars] - refine ⟨φ.equivariantProjection G, FunLike.ext _ _ ?_⟩ - exact φ.equivariantProjection_condition G _ <| FunLike.congr_fun hφ + refine ⟨φ.equivariantProjection G, DFunLike.ext _ _ ?_⟩ + exact φ.equivariantProjection_condition G _ <| DFunLike.congr_fun hφ #align monoid_algebra.exists_left_inverse_of_injective MonoidAlgebra.exists_leftInverse_of_injective namespace Submodule @@ -166,7 +165,7 @@ theorem exists_isCompl (p : Submodule (MonoidAlgebra k G) V) : have : IsScalarTower k (MonoidAlgebra k G) p := p.isScalarTower' rcases MonoidAlgebra.exists_leftInverse_of_injective p.subtype p.ker_subtype with ⟨f, hf⟩ refine ⟨LinearMap.ker f, LinearMap.isCompl_of_proj ?_⟩ - exact FunLike.congr_fun hf + exact DFunLike.congr_fun hf #align monoid_algebra.submodule.exists_is_compl MonoidAlgebra.Submodule.exists_isCompl /-- This also implies an instance `IsSemisimpleModule (MonoidAlgebra k G) V`. -/ diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index 2e3ffb1318b84..942fdff322de9 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -3,10 +3,10 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.Algebra.Category.ModuleCat.Abelian import Mathlib.Algebra.Category.ModuleCat.Adjunctions +import Mathlib.Algebra.Category.ModuleCat.Limits import Mathlib.Algebra.Category.ModuleCat.Colimits -import Mathlib.Algebra.Category.ModuleCat.Monoidal.Closed +import Mathlib.Algebra.Category.ModuleCat.Monoidal.Symmetric import Mathlib.CategoryTheory.Elementwise import Mathlib.RepresentationTheory.Action.Monoidal import Mathlib.RepresentationTheory.Basic diff --git a/Mathlib/RingTheory/Adjoin/Basic.lean b/Mathlib/RingTheory/Adjoin/Basic.lean index 5f486e6c4a101..b83640a2dd310 100644 --- a/Mathlib/RingTheory/Adjoin/Basic.lean +++ b/Mathlib/RingTheory/Adjoin/Basic.lean @@ -480,4 +480,52 @@ def Subring.closureEquivAdjoinInt {R : Type*} [Ring R] (s : Set R) : Subring.closure s ≃ₐ[ℤ] Algebra.adjoin ℤ s := Subalgebra.equivOfEq (subalgebraOfSubring <| Subring.closure s) _ (adjoin_int s).symm - end NatInt +end NatInt + +section + +variable (F E : Type*) {K : Type*} [CommSemiring E] [Semiring K] [SMul F E] [Algebra E K] + +/-- If `K / E / F` is a ring extension tower, `L` is a submonoid of `K / F` which is generated by +`S` as an `F`-module, then `E[L]` is generated by `S` as an `E`-module. -/ +theorem Submonoid.adjoin_eq_span_of_eq_span [Semiring F] [Module F K] [IsScalarTower F E K] + (L : Submonoid K) {S : Set K} (h : (L : Set K) = span F S) : + toSubmodule (adjoin E (L : Set K)) = span E S := by + rw [adjoin_eq_span, L.closure_eq, h] + exact (span_le.mpr <| span_subset_span _ _ _).antisymm (span_mono subset_span) + +variable [CommSemiring F] [Algebra F K] [IsScalarTower F E K] (L : Subalgebra F K) {F} + +/-- If `K / E / F` is a ring extension tower, `L` is a subalgebra of `K / F` which is generated by +`S` as an `F`-module, then `E[L]` is generated by `S` as an `E`-module. -/ +theorem Subalgebra.adjoin_eq_span_of_eq_span {S : Set K} (h : toSubmodule L = span F S) : + toSubmodule (adjoin E (L : Set K)) = span E S := + L.toSubmonoid.adjoin_eq_span_of_eq_span F E (congr_arg ((↑) : _ → Set K) h) + +/-- If `K / E / F` is a ring extension tower, `L` is a subalgebra of `K / F`, +then `E[L]` is generated by any basis of `L / F` as an `E`-module. -/ +theorem Subalgebra.adjoin_eq_span_basis {ι : Type*} (bL : Basis ι F L) : + toSubmodule (adjoin E (L : Set K)) = span E (Set.range fun i : ι ↦ (bL i).1) := + L.adjoin_eq_span_of_eq_span E <| by + simpa only [← L.range_val, Submodule.map_span, Submodule.map_top, ← Set.range_comp] + using congr_arg (Submodule.map L.val) bL.span_eq.symm + +theorem Algebra.restrictScalars_adjoin (F : Type*) [CommSemiring F] {E : Type*} [CommSemiring E] + [Algebra F E] (K : Subalgebra F E) (S : Set E) : + (Algebra.adjoin K S).restrictScalars F = Algebra.adjoin F (K ∪ S) := by + conv_lhs => rw [← Algebra.adjoin_eq K, ← Algebra.adjoin_union_eq_adjoin_adjoin] + +/-- If `E / L / F` and `E / L' / F` are two ring extension towers, `L ≃ₐ[F] L'` is an isomorphism +compatible with `E / L` and `E / L'`, then for any subset `S` of `E`, `L[S]` and `L'[S]` are +equal as subalgebras of `E / F`. -/ +theorem Algebra.restrictScalars_adjoin_of_algEquiv + {F E L L' : Type*} [CommSemiring F] [CommSemiring L] [CommSemiring L'] [Semiring E] + [Algebra F L] [Algebra L E] [Algebra F L'] [Algebra L' E] [Algebra F E] + [IsScalarTower F L E] [IsScalarTower F L' E] (i : L ≃ₐ[F] L') + (hi : algebraMap L E = (algebraMap L' E) ∘ i) (S : Set E) : + (Algebra.adjoin L S).restrictScalars F = (Algebra.adjoin L' S).restrictScalars F := by + apply_fun Subalgebra.toSubsemiring using fun K K' h ↦ by rwa [SetLike.ext'_iff] at h ⊢ + change Subsemiring.closure _ = Subsemiring.closure _ + erw [hi, Set.range_comp, i.toEquiv.range_eq_univ, Set.image_univ] + +end diff --git a/Mathlib/RingTheory/Adjoin/Field.lean b/Mathlib/RingTheory/Adjoin/Field.lean index 71d1adc086ce5..fae2248b50a76 100644 --- a/Mathlib/RingTheory/Adjoin/Field.lean +++ b/Mathlib/RingTheory/Adjoin/Field.lean @@ -95,10 +95,27 @@ theorem IsIntegral.mem_range_algebraMap_of_minpoly_splits [Algebra K L] [IsScala x ∈ (algebraMap K L).range := int.mem_range_algHom_of_minpoly_splits h (IsScalarTower.toAlgHom R K L) -theorem IsIntegral.minpoly_splits_tower_top - [Algebra K L] [IsScalarTower R K L] [Algebra K M] [IsScalarTower R K M] - {x : M} (int : IsIntegral R x) (h : Splits (algebraMap R L) (minpoly R x)) : +variable [Algebra K M] [IsScalarTower R K M] {x : M} (int : IsIntegral R x) + +theorem IsIntegral.minpoly_splits_tower_top' {f : K →+* L} + (h : Splits (f.comp <| algebraMap R K) (minpoly R x)) : + Splits f (minpoly K x) := + splits_of_splits_of_dvd _ ((minpoly.monic int).map _).ne_zero + ((splits_map_iff _ _).mpr h) (minpoly.dvd_map_of_isScalarTower R _ x) + +theorem IsIntegral.minpoly_splits_tower_top [Algebra K L] [IsScalarTower R K L] + (h : Splits (algebraMap R L) (minpoly R x)) : Splits (algebraMap K L) (minpoly K x) := by rw [IsScalarTower.algebraMap_eq R K L] at h - exact splits_of_splits_of_dvd _ ((minpoly.monic int).map _).ne_zero - ((splits_map_iff _ _).mpr h) (minpoly.dvd_map_of_isScalarTower R _ x) + exact int.minpoly_splits_tower_top' h + +/-- If `K / E / F` is a ring extension tower, `L` is a subalgebra of `K / F`, +then `[E[L] : E] ≤ [L : F]`. -/ +lemma Subalgebra.adjoin_rank_le {F : Type*} (E : Type*) {K : Type*} + [CommRing F] [StrongRankCondition F] [CommRing E] [StrongRankCondition E] [Ring K] + [SMul F E] [Algebra E K] [Algebra F K] [IsScalarTower F E K] + (L : Subalgebra F K) [Module.Free F L] : + Module.rank E (Algebra.adjoin E (L : Set K)) ≤ Module.rank F L := by + rw [← rank_toSubmodule, Module.Free.rank_eq_card_chooseBasisIndex F L, + L.adjoin_eq_span_basis E (Module.Free.chooseBasis F L)] + exact rank_span_le _ |>.trans Cardinal.mk_range_le diff --git a/Mathlib/RingTheory/Adjoin/PowerBasis.lean b/Mathlib/RingTheory/Adjoin/PowerBasis.lean index ee90ad66100b9..4ca35a8bd844d 100644 --- a/Mathlib/RingTheory/Adjoin/PowerBasis.lean +++ b/Mathlib/RingTheory/Adjoin/PowerBasis.lean @@ -134,7 +134,8 @@ theorem repr_mul_isIntegral [IsDomain S] {x y : A} (hx : ∀ i, IsIntegral R (B. (hmin : minpoly S B.gen = (minpoly R B.gen).map (algebraMap R S)) : ∀ i, IsIntegral R (B.basis.repr (x * y) i) := by intro i - rw [← B.basis.sum_repr x, ← B.basis.sum_repr y, Finset.sum_mul_sum, map_sum, Finset.sum_apply'] + rw [← B.basis.sum_repr x, ← B.basis.sum_repr y, Finset.sum_mul_sum, ← Finset.sum_product', + map_sum, Finset.sum_apply'] refine' IsIntegral.sum _ fun I _ => _ simp only [Algebra.smul_mul_assoc, Algebra.mul_smul_comm, LinearEquiv.map_smulₛₗ, RingHom.id_apply, Finsupp.coe_smul, Pi.smul_apply, id.smul_eq_mul] diff --git a/Mathlib/RingTheory/AdjoinRoot.lean b/Mathlib/RingTheory/AdjoinRoot.lean index b7a1a6927ebdf..1e562581c6d08 100644 --- a/Mathlib/RingTheory/AdjoinRoot.lean +++ b/Mathlib/RingTheory/AdjoinRoot.lean @@ -923,3 +923,14 @@ theorem quotientEquivQuotientMinpolyMap_symm_apply_mk (pb : PowerBasis R S) (I : #align power_basis.quotient_equiv_quotient_minpoly_map_symm_apply_mk PowerBasis.quotientEquivQuotientMinpolyMap_symm_apply_mk end PowerBasis + +/-- If `L / K` is an integral extension, `K` is a domain, `L` is a field, then any irreducible +polynomial over `L` divides some monic irreducible polynomial over `K`. -/ +theorem Irreducible.exists_dvd_monic_irreducible_of_isIntegral {K L : Type*} + [CommRing K] [IsDomain K] [Field L] [Algebra K L] (H : Algebra.IsIntegral K L) {f : L[X]} + (hf : Irreducible f) : ∃ g : K[X], g.Monic ∧ Irreducible g ∧ f ∣ g.map (algebraMap K L) := by + haveI := Fact.mk hf + have h := hf.ne_zero + have h2 := isIntegral_trans H _ (AdjoinRoot.isIntegral_root h) + have h3 := (AdjoinRoot.minpoly_root h) ▸ minpoly.dvd_map_of_isScalarTower K L (AdjoinRoot.root f) + exact ⟨_, minpoly.monic h2, minpoly.irreducible h2, dvd_of_mul_right_dvd h3⟩ diff --git a/Mathlib/RingTheory/AlgebraTower.lean b/Mathlib/RingTheory/AlgebraTower.lean index 4765721769b2e..a097bec87f69b 100644 --- a/Mathlib/RingTheory/AlgebraTower.lean +++ b/Mathlib/RingTheory/AlgebraTower.lean @@ -108,9 +108,9 @@ universe v₁ w₁ variable {R S A} -variable [CommSemiring R] [Semiring S] [AddCommMonoid A] +variable [Semiring R] [Semiring S] [AddCommMonoid A] -variable [Algebra R S] [Module S A] [Module R A] [IsScalarTower R S A] +variable [Module R S] [Module S A] [Module R A] [IsScalarTower R S A] theorem linearIndependent_smul {ι : Type v₁} {b : ι → S} {ι' : Type w₁} {c : ι' → A} (hb : LinearIndependent R b) (hc : LinearIndependent S c) : @@ -128,10 +128,23 @@ theorem linearIndependent_smul {ι : Type v₁} {b : ι → S} {ι' : Type w₁} exact hg _ hik #align linear_independent_smul linearIndependent_smul +variable (R) + +-- LinearIndependent is enough if S is a ring rather than semiring. +theorem Basis.isScalarTower_of_nonempty {ι} [Nonempty ι] (b : Basis ι S A) : IsScalarTower R S S := + (b.repr.symm.comp <| lsingle <| Classical.arbitrary ι).isScalarTower_of_injective R + (b.repr.symm.injective.comp <| single_injective _) + +theorem Basis.isScalarTower_finsupp {ι} (b : Basis ι S A) : IsScalarTower R S (ι →₀ S) := + b.repr.symm.isScalarTower_of_injective R b.repr.symm.injective + +variable {R} + /-- `Basis.SMul (b : Basis ι R S) (c : Basis ι S A)` is the `R`-basis on `A` where the `(i, j)`th basis vector is `b i • c j`. -/ noncomputable def Basis.smul {ι : Type v₁} {ι' : Type w₁} (b : Basis ι R S) (c : Basis ι' S A) : Basis (ι × ι') R A := + haveI := c.isScalarTower_finsupp R .ofRepr (c.repr.restrictScalars R ≪≫ₗ (Finsupp.lcongr (Equiv.refl _) b.repr ≪≫ₗ @@ -141,7 +154,7 @@ noncomputable def Basis.smul {ι : Type v₁} {ι' : Type w₁} (b : Basis ι R @[simp] theorem Basis.smul_repr {ι : Type v₁} {ι' : Type w₁} (b : Basis ι R S) (c : Basis ι' S A) (x ij) : - (b.smul c).repr x ij = b.repr (c.repr x ij.2) ij.1 := by simp [Basis.smul] + (b.smul c).repr x ij = b.repr (c.repr x ij.2) ij.1 := by simp [Basis.smul]; rfl #align basis.smul_repr Basis.smul_repr theorem Basis.smul_repr_mk {ι : Type v₁} {ι' : Type w₁} (b : Basis ι R S) (c : Basis ι' S A) diff --git a/Mathlib/RingTheory/AlgebraicIndependent.lean b/Mathlib/RingTheory/AlgebraicIndependent.lean index 0ae5c8068b4ed..ef7d53ebd004a 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent.lean @@ -181,7 +181,7 @@ theorem algebraicIndependent_of_subsingleton [Subsingleton R] : AlgebraicIndepen theorem algebraicIndependent_equiv (e : ι ≃ ι') {f : ι' → A} : AlgebraicIndependent R (f ∘ e) ↔ AlgebraicIndependent R f := - ⟨fun h => Function.comp.right_id f ▸ e.self_comp_symm ▸ h.comp _ e.symm.injective, + ⟨fun h => Function.comp_id f ▸ e.self_comp_symm ▸ h.comp _ e.symm.injective, fun h => h.comp _ e.injective⟩ #align algebraic_independent_equiv algebraicIndependent_equiv diff --git a/Mathlib/RingTheory/Binomial.lean b/Mathlib/RingTheory/Binomial.lean new file mode 100644 index 0000000000000..1e9b4f445fffa --- /dev/null +++ b/Mathlib/RingTheory/Binomial.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2023 Scott Carnahan. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Carnahan +-/ + +import Mathlib.RingTheory.Polynomial.Pochhammer + +/-! +# Binomial rings + +In this file we introduce the binomial property as a mixin, and define the `multichoose` +and `choose` functions generalizing binomial coefficients. + +According to our main reference [elliott2006binomial] (which lists many equivalent conditions), a +binomial ring is a torsion-free commutative ring `R` such that for any `x ∈ R` and any `k ∈ ℕ`, the +product `x(x-1)⋯(x-k+1)` is divisible by `k!`. The torsion-free condition lets us divide by `k!` +unambiguously, so we get uniquely defined binomial coefficients. + +The defining condition doesn't require commutativity (or associativity), and we get a theory with +essentially the same power by replacing subtraction with addition. Thus, we consider a semiring `R` +in which multiplication by factorials is injective, and demand that the evaluation of the ascending +Pochhammer polynomial `X(X+1)⋯(X+(k-1))` at any element is divisible by `k!`. The quotient is called +`multichoose r k`, following the convention given for natural numbers. + +## References + +* [J. Elliott, *Binomial rings, integer-valued polynomials, and λ-rings*][elliott2006binomial] + +## TODO + +* Replace `Nat.multichoose` with `Ring.multichoose`. +* `Ring.choose` for binomial rings. +* Generalize to the power-associative case, when power-associativity is implemented. + +-/ + +open Function + +/-- A binomial ring is a ring for which ascending Pochhammer evaluations are uniquely divisible by +suitable factorials. We define this notion for semirings, but retain the ring name. We introduce +`Ring.multichoose` as the uniquely defined quotient. -/ +class BinomialRing (R : Type*) [Semiring R] where + /-- Multiplication by positive integers is injective -/ + nsmul_right_injective (n : ℕ) (h : n ≠ 0) : Injective (n • · : R → R) + /-- A multichoose function, giving the quotient of Pochhammer evaluations by factorials. -/ + multichoose : R → ℕ → R + /-- `ascPochhammer R n` evaluated at any `r` is divisible by n! (witnessed by multichoose) -/ + factorial_nsmul_multichoose (r : R) (n : ℕ) : + n.factorial • multichoose r n = Polynomial.eval r (ascPochhammer R n) + +section Binomial + +namespace Ring + +variable {R : Type*} [Semiring R] [BinomialRing R] + +theorem nsmul_right_injective (n : ℕ) (h : n ≠ 0) : + Injective (n • · : R → R) := BinomialRing.nsmul_right_injective n h + +/-- The multichoose function is the quotient of ascending Pochhammer evaluation by the corresponding +factorial. When applied to natural numbers, `multichoose k n` describes choosing a multiset of `n` +items from a group of `k`, i.e., choosing with replacement. -/ +def multichoose (r : R) (n : ℕ) : R := BinomialRing.multichoose r n + +@[simp] +theorem multichoose_eq_multichoose (r : R) (n : ℕ) : + BinomialRing.multichoose r n = multichoose r n := rfl + +theorem factorial_nsmul_multichoose_eq_eval_ascPochhammer (r : R) (n : ℕ) : + n.factorial • multichoose r n = Polynomial.eval r (ascPochhammer R n) := + BinomialRing.factorial_nsmul_multichoose r n + +end Ring + +instance Nat.instBinomialRing : BinomialRing ℕ where + nsmul_right_injective n hn r s hrs := Nat.eq_of_mul_eq_mul_left (Nat.pos_of_ne_zero hn) hrs + multichoose := Nat.multichoose + factorial_nsmul_multichoose r n := by + rw [Nat.multichoose_eq, smul_eq_mul, ← Nat.descFactorial_eq_factorial_mul_choose, + ascPochhammer_nat_eq_descFactorial] + +/-- The multichoose function for integers. -/ +def Int.multichoose (n : ℤ) (k : ℕ) : ℤ := + match n with + | ofNat n => (Nat.choose (n + k - 1) k : ℤ) + | negSucc n => (-1) ^ k * Nat.choose n.succ k + +instance Int.instBinomialRing : BinomialRing ℤ where + nsmul_right_injective n hn r s hrs := Int.eq_of_mul_eq_mul_left (Int.ofNat_ne_zero.mpr hn) hrs + multichoose := Int.multichoose + factorial_nsmul_multichoose r k := by + rw [Int.multichoose, nsmul_eq_mul] + cases r with + | ofNat n => + simp only [Int.ofNat_eq_coe, Int.ofNat_mul_out] + rw [← Nat.descFactorial_eq_factorial_mul_choose, ← ascPochhammer_nat_eq_descFactorial, + ascPochhammer_eval_cast] + | negSucc n => + rw [mul_comm, mul_assoc, ← Nat.cast_mul, mul_comm _ (k.factorial), + ← Nat.descFactorial_eq_factorial_mul_choose, ← descPochhammer_int_eq_descFactorial, + ← Int.neg_ofNat_succ, ascPochhammer_eval_neg_eq_descPochhammer] + +end Binomial diff --git a/Mathlib/RingTheory/Congruence.lean b/Mathlib/RingTheory/Congruence.lean index b38c683735c3b..6e63cb7bb0007 100644 --- a/Mathlib/RingTheory/Congruence.lean +++ b/Mathlib/RingTheory/Congruence.lean @@ -74,7 +74,7 @@ variable [Add R] [Mul R] (c : RingCon R) --Porting note: upgrade to `FunLike` /-- A coercion from a congruence relation to its underlying binary relation. -/ -instance : FunLike (RingCon R) R fun _ => R → Prop := +instance : FunLike (RingCon R) R (R → Prop) := { coe := fun c => c.r, coe_injective' := fun x y h => by rcases x with ⟨⟨x, _⟩, _⟩ @@ -119,7 +119,7 @@ theorem rel_mk {s : Con R} {h a b} : RingCon.mk s h a b ↔ s a b := Iff.rfl /-- The map sending a congruence relation to its underlying binary relation is injective. -/ -theorem ext' {c d : RingCon R} (H : ⇑c = ⇑d) : c = d := FunLike.coe_injective H +theorem ext' {c d : RingCon R} (H : ⇑c = ⇑d) : c = d := DFunLike.coe_injective H /-- Extensionality rule for congruence relations. -/ theorem ext {c d : RingCon R} (H : ∀ x y, c x y ↔ d x y) : c = d := diff --git a/Mathlib/RingTheory/Coprime/Basic.lean b/Mathlib/RingTheory/Coprime/Basic.lean index 08bb6c238c26c..a846d9875adf1 100644 --- a/Mathlib/RingTheory/Coprime/Basic.lean +++ b/Mathlib/RingTheory/Coprime/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.GroupPower.Ring import Mathlib.Algebra.Ring.Divisibility.Basic import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.GroupTheory.GroupAction.Units +import Mathlib.Logic.Basic import Mathlib.Tactic.Ring #align_import ring_theory.coprime.basic from "leanprover-community/mathlib"@"a95b16cbade0f938fc24abd05412bde1e84bab9b" diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index ed723c0b17f4a..60e67104362ba 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -6,11 +6,9 @@ Authors: Kenji Nakagawa, Anne Baanen, Filippo A. E. Nuccio import Mathlib.Algebra.Algebra.Subalgebra.Pointwise import Mathlib.AlgebraicGeometry.PrimeSpectrum.Maximal import Mathlib.AlgebraicGeometry.PrimeSpectrum.Noetherian -import Mathlib.Order.Hom.Basic -import Mathlib.RingTheory.DedekindDomain.Basic -import Mathlib.RingTheory.FractionalIdeal -import Mathlib.RingTheory.PrincipalIdealDomain import Mathlib.RingTheory.ChainOfDivisors +import Mathlib.RingTheory.DedekindDomain.Basic +import Mathlib.RingTheory.FractionalIdeal.Operations #align_import ring_theory.dedekind_domain.ideal from "leanprover-community/mathlib"@"2bbc7e3884ba234309d2a43b19144105a753292e" diff --git a/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean b/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean index 5bd0cedbb4f68..55f859eff3955 100644 --- a/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean +++ b/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenji Nakagawa, Anne Baanen, Filippo A. E. Nuccio -/ import Mathlib.LinearAlgebra.FreeModule.PID +import Mathlib.LinearAlgebra.FreeModule.Finite.Basic import Mathlib.LinearAlgebra.BilinearForm.DualLattice import Mathlib.RingTheory.DedekindDomain.Basic import Mathlib.RingTheory.Localization.Module @@ -201,10 +202,10 @@ theorem IsIntegralClosure.isNoetherianRing [IsIntegrallyClosed A] [IsNoetherianR and `L` has no zero smul divisors by `A`, the integral closure `C` of `A` in `L` is a free `A`-module. -/ theorem IsIntegralClosure.module_free [NoZeroSMulDivisors A L] [IsPrincipalIdealRing A] : - Module.Free A C := by + Module.Free A C := haveI : NoZeroSMulDivisors A C := IsIntegralClosure.noZeroSMulDivisors A L haveI : IsNoetherian A C := IsIntegralClosure.isNoetherian A K L _ - exact Module.free_of_finite_type_torsion_free' + inferInstance #align is_integral_closure.module_free IsIntegralClosure.module_free /- If `L` is a finite separable extension of `K = Frac(A)`, where `A` is a principal ring diff --git a/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean b/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean index 34923818c66eb..0693ae1a410a3 100644 --- a/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean +++ b/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean @@ -6,7 +6,6 @@ Authors: David Kurniadi Angdinata import Mathlib.Algebra.Group.Equiv.TypeTags import Mathlib.Data.ZMod.Quotient import Mathlib.RingTheory.DedekindDomain.AdicValuation -import Mathlib.RingTheory.Norm #align_import ring_theory.dedekind_domain.selmer_group from "leanprover-community/mathlib"@"2032a878972d5672e7c27c957e7a6e297b044973" diff --git a/Mathlib/RingTheory/Derivation/Basic.lean b/Mathlib/RingTheory/Derivation/Basic.lean index e6873ac4a86f2..812ad10c1b66d 100644 --- a/Mathlib/RingTheory/Derivation/Basic.lean +++ b/Mathlib/RingTheory/Derivation/Basic.lean @@ -64,14 +64,14 @@ variable (D : Derivation R A M) {D1 D2 : Derivation R A M} (r : R) (a b : A) instance : AddMonoidHomClass (Derivation R A M) A M where coe D := D.toFun - coe_injective' D1 D2 h := by cases D1; cases D2; congr; exact FunLike.coe_injective h + coe_injective' D1 D2 h := by cases D1; cases D2; congr; exact DFunLike.coe_injective h map_add D := D.toLinearMap.map_add' map_zero D := D.toLinearMap.map_zero -/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (Derivation R A M) fun _ => A → M := - ⟨FunLike.coe⟩ + ⟨DFunLike.coe⟩ -- Not a simp lemma because it can be proved via `coeFn_coe` + `toLinearMap_eq_coe` theorem toFun_eq_coe : D.toFun = ⇑D := @@ -101,17 +101,17 @@ theorem coeFn_coe (f : Derivation R A M) : ⇑(f : A →ₗ[R] M) = f := rfl #align derivation.coe_fn_coe Derivation.coeFn_coe -theorem coe_injective : @Function.Injective (Derivation R A M) (A → M) FunLike.coe := - FunLike.coe_injective +theorem coe_injective : @Function.Injective (Derivation R A M) (A → M) DFunLike.coe := + DFunLike.coe_injective #align derivation.coe_injective Derivation.coe_injective @[ext] theorem ext (H : ∀ a, D1 a = D2 a) : D1 = D2 := - FunLike.ext _ _ H + DFunLike.ext _ _ H #align derivation.ext Derivation.ext theorem congr_fun (h : D1 = D2) (a : A) : D1 a = D2 a := - FunLike.congr_fun h a + DFunLike.congr_fun h a #align derivation.congr_fun Derivation.congr_fun protected theorem map_add : D (a + b) = D a + D b := diff --git a/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean b/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean index 94f6f695c3917..653b13d39610a 100644 --- a/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean +++ b/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean @@ -201,9 +201,7 @@ theorem tfae_of_isNoetherianRing_of_localRing_of_isDomain by_cases hJ : J = ⊥; · subst hJ; right; exact bot_le obtain ⟨n, rfl⟩ := H I hI obtain ⟨m, rfl⟩ := H J hJ - rcases le_total m n with h' | h' - · left; exact Ideal.pow_le_pow_right h' - · right; exact Ideal.pow_le_pow_right h' + exact (le_total m n).imp Ideal.pow_le_pow_right Ideal.pow_le_pow_right tfae_finish /-- diff --git a/Mathlib/RingTheory/Discriminant.lean b/Mathlib/RingTheory/Discriminant.lean index ef1f4f28f3aa8..913246ac17054 100644 --- a/Mathlib/RingTheory/Discriminant.lean +++ b/Mathlib/RingTheory/Discriminant.lean @@ -266,11 +266,11 @@ theorem discr_powerBasis_eq_norm [IsSeparable K L] : implies_true, forall_const, Equiv.symm_apply_apply, Sigma.ext_iff, Equiv.symm_apply_eq, heq_eq_eq, and_true] at * · simpa only [aeval_def, eval₂_eq_eval_map] using hσ.2.2 - · exact fun a b hba ↦ ⟨fun h ↦ hba $ e.injective $ pb.algHom_ext h.symm, hroots _⟩ + · exact fun a b hba ↦ ⟨fun h ↦ hba <| e.injective <| pb.algHom_ext h.symm, hroots _⟩ · rintro a b hba ha rw [ha, PowerBasis.lift_gen] at hba exact hba.1 rfl - · exact fun a b _ ↦ pb.algHom_ext $ pb.lift_gen _ _ + · exact fun a b _ ↦ pb.algHom_ext <| pb.lift_gen _ _ #align algebra.discr_power_basis_eq_norm Algebra.discr_powerBasis_eq_norm section Integral diff --git a/Mathlib/RingTheory/EisensteinCriterion.lean b/Mathlib/RingTheory/EisensteinCriterion.lean index 08244107ff76e..dbbe2ca79548b 100644 --- a/Mathlib/RingTheory/EisensteinCriterion.lean +++ b/Mathlib/RingTheory/EisensteinCriterion.lean @@ -6,7 +6,7 @@ Authors: Chris Hughes import Mathlib.Data.Nat.Cast.WithTop import Mathlib.RingTheory.Prime import Mathlib.RingTheory.Polynomial.Content -import Mathlib.RingTheory.Ideal.QuotientOperations +import Mathlib.RingTheory.Ideal.Quotient #align_import ring_theory.eisenstein_criterion from "leanprover-community/mathlib"@"da420a8c6dd5bdfb85c4ced85c34388f633bc6ff" diff --git a/Mathlib/RingTheory/Filtration.lean b/Mathlib/RingTheory/Filtration.lean index 24b66f943c582..942e5408fef0d 100644 --- a/Mathlib/RingTheory/Filtration.lean +++ b/Mathlib/RingTheory/Filtration.lean @@ -9,6 +9,7 @@ import Mathlib.RingTheory.Noetherian import Mathlib.RingTheory.ReesAlgebra import Mathlib.RingTheory.Finiteness import Mathlib.Data.Polynomial.Module +import Mathlib.Order.Basic import Mathlib.Order.Hom.Lattice #align_import ring_theory.filtration from "leanprover-community/mathlib"@"70fd9563a21e7b963887c9360bd29b2393e6225a" diff --git a/Mathlib/RingTheory/FiniteType.lean b/Mathlib/RingTheory/FiniteType.lean index c14c1cba38d24..e957e1f3117d1 100644 --- a/Mathlib/RingTheory/FiniteType.lean +++ b/Mathlib/RingTheory/FiniteType.lean @@ -461,7 +461,7 @@ theorem mvPolynomial_aeval_of_surjective_of_closure [AddCommMonoid M] [CommSemir intro f induction' f using induction_on with m f g ihf ihg r f ih · have : m ∈ closure S := hS.symm ▸ mem_top _ - refine' closure_induction this (fun m hm => _) _ _ + refine' AddSubmonoid.closure_induction this (fun m hm => _) _ _ · exact ⟨MvPolynomial.X ⟨m, hm⟩, MvPolynomial.aeval_X _ _⟩ · exact ⟨1, AlgHom.map_one _⟩ · rintro m₁ m₂ ⟨P₁, hP₁⟩ ⟨P₂, hP₂⟩ @@ -487,7 +487,7 @@ theorem freeAlgebra_lift_of_surjective_of_closure [CommSemiring R] {S : Set M} intro f induction' f using induction_on with m f g ihf ihg r f ih · have : m ∈ closure S := hS.symm ▸ mem_top _ - refine' closure_induction this (fun m hm => _) _ _ + refine' AddSubmonoid.closure_induction this (fun m hm => _) _ _ · exact ⟨FreeAlgebra.ι R ⟨m, hm⟩, FreeAlgebra.lift_ι_apply _ _⟩ · exact ⟨1, AlgHom.map_one _⟩ · rintro m₁ m₂ ⟨P₁, hP₁⟩ ⟨P₂, hP₂⟩ @@ -640,7 +640,7 @@ theorem mvPolynomial_aeval_of_surjective_of_closure [CommMonoid M] [CommSemiring intro f induction' f using induction_on with m f g ihf ihg r f ih · have : m ∈ closure S := hS.symm ▸ mem_top _ - refine' closure_induction this (fun m hm => _) _ _ + refine' Submonoid.closure_induction this (fun m hm => _) _ _ · exact ⟨MvPolynomial.X ⟨m, hm⟩, MvPolynomial.aeval_X _ _⟩ · exact ⟨1, AlgHom.map_one _⟩ · rintro m₁ m₂ ⟨P₁, hP₁⟩ ⟨P₂, hP₂⟩ @@ -665,7 +665,7 @@ theorem freeAlgebra_lift_of_surjective_of_closure [CommSemiring R] {S : Set M} intro f induction' f using induction_on with m f g ihf ihg r f ih · have : m ∈ closure S := hS.symm ▸ mem_top _ - refine' closure_induction this (fun m hm => _) _ _ + refine' Submonoid.closure_induction this (fun m hm => _) _ _ · exact ⟨FreeAlgebra.ι R ⟨m, hm⟩, FreeAlgebra.lift_ι_apply _ _⟩ · exact ⟨1, AlgHom.map_one _⟩ · rintro m₁ m₂ ⟨P₁, hP₁⟩ ⟨P₂, hP₂⟩ diff --git a/Mathlib/RingTheory/Finiteness.lean b/Mathlib/RingTheory/Finiteness.lean index ae455e22ea73e..3116ef0cab85b 100644 --- a/Mathlib/RingTheory/Finiteness.lean +++ b/Mathlib/RingTheory/Finiteness.lean @@ -412,7 +412,7 @@ theorem fg_iff_compact (s : Submodule R M) : s.FG ↔ CompleteLattice.IsCompactE -- Porting note: had to split this out of the `obtain` have := Finset.subset_image_iff.mp huspan obtain ⟨t, ⟨-, rfl⟩⟩ := this - rw [Finset.sup_image, Function.comp.left_id, Finset.sup_eq_iSup, supr_rw, ← + rw [Finset.sup_image, Function.id_comp, Finset.sup_eq_iSup, supr_rw, ← span_eq_iSup_of_singleton_spans, eq_comm] at ssup exact ⟨t, ssup⟩ #align submodule.fg_iff_compact Submodule.fg_iff_compact @@ -676,7 +676,7 @@ variable {R} section Algebra -theorem trans {R : Type*} (A M : Type*) [CommSemiring R] [Semiring A] [Algebra R A] +theorem trans {R : Type*} (A M : Type*) [Semiring R] [Semiring A] [Module R A] [AddCommMonoid M] [Module R M] [Module A M] [IsScalarTower R A M] : ∀ [Finite R A] [Finite A M], Finite R M | ⟨⟨s, hs⟩⟩, ⟨⟨t, ht⟩⟩ => @@ -695,8 +695,10 @@ lemma of_equiv_equiv {A₁ B₁ A₂ B₂ : Type*} [CommRing A₁] [CommRing B letI := ((algebraMap A₁ B₁).comp e₁.symm.toRingHom).toAlgebra haveI : IsScalarTower A₁ A₂ B₁ := IsScalarTower.of_algebraMap_eq (fun x ↦ by simp [RingHom.algebraMap_toAlgebra]) - let e : B₁ ≃ₐ[A₂] B₂ := { e₂ with commutes' := fun r ↦ by simpa [RingHom.algebraMap_toAlgebra] - using FunLike.congr_fun he.symm (e₁.symm r) } + let e : B₁ ≃ₐ[A₂] B₂ := + { e₂ with + commutes' := fun r ↦ by + simpa [RingHom.algebraMap_toAlgebra] using DFunLike.congr_fun he.symm (e₁.symm r) } haveI := Module.Finite.of_restrictScalars_finite A₁ A₂ B₁ exact Module.Finite.equiv e.toLinearEquiv diff --git a/Mathlib/RingTheory/Flat.lean b/Mathlib/RingTheory/Flat.lean index 80ce3c049cbd1..507b55a8b0ca7 100644 --- a/Mathlib/RingTheory/Flat.lean +++ b/Mathlib/RingTheory/Flat.lean @@ -3,12 +3,12 @@ Copyright (c) 2020 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.RingTheory.Noetherian import Mathlib.Algebra.DirectSum.Module import Mathlib.Algebra.DirectSum.Finsupp +import Mathlib.Algebra.Module.Projective import Mathlib.LinearAlgebra.DirectSum.TensorProduct import Mathlib.LinearAlgebra.FreeModule.Basic -import Mathlib.Algebra.Module.Projective +import Mathlib.RingTheory.Finiteness #align_import ring_theory.flat from "leanprover-community/mathlib"@"62c0a4ef1441edb463095ea02a06e87f3dfe135c" diff --git a/Mathlib/RingTheory/FractionalIdeal/Basic.lean b/Mathlib/RingTheory/FractionalIdeal/Basic.lean new file mode 100644 index 0000000000000..72a48f0a57473 --- /dev/null +++ b/Mathlib/RingTheory/FractionalIdeal/Basic.lean @@ -0,0 +1,746 @@ +/- +Copyright (c) 2020 Anne Baanen. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Anne Baanen, Filippo A. E. Nuccio +-/ +import Mathlib.RingTheory.Localization.Integer +import Mathlib.RingTheory.Localization.Submodule + +#align_import ring_theory.fractional_ideal from "leanprover-community/mathlib"@"ed90a7d327c3a5caf65a6faf7e8a0d63c4605df7" + +/-! +# Fractional ideals + +This file defines fractional ideals of an integral domain and proves basic facts about them. + +## Main definitions +Let `S` be a submonoid of an integral domain `R` and `P` the localization of `R` at `S`. + * `IsFractional` defines which `R`-submodules of `P` are fractional ideals + * `FractionalIdeal S P` is the type of fractional ideals in `P` + * a coercion `coeIdeal : Ideal R → FractionalIdeal S P` + * `CommSemiring (FractionalIdeal S P)` instance: + the typical ideal operations generalized to fractional ideals + * `Lattice (FractionalIdeal S P)` instance + +## Main statements + + * `mul_left_mono` and `mul_right_mono` state that ideal multiplication is monotone + * `mul_div_self_cancel_iff` states that `1 / I` is the inverse of `I` if one exists + +## Implementation notes + +Fractional ideals are considered equal when they contain the same elements, +independent of the denominator `a : R` such that `a I ⊆ R`. +Thus, we define `FractionalIdeal` to be the subtype of the predicate `IsFractional`, +instead of having `FractionalIdeal` be a structure of which `a` is a field. + +Most definitions in this file specialize operations from submodules to fractional ideals, +proving that the result of this operation is fractional if the input is fractional. +Exceptions to this rule are defining `(+) := (⊔)` and `⊥ := 0`, +in order to re-use their respective proof terms. +We can still use `simp` to show `↑I + ↑J = ↑(I + J)` and `↑⊥ = ↑0`. + +Many results in fact do not need that `P` is a localization, only that `P` is an +`R`-algebra. We omit the `IsLocalization` parameter whenever this is practical. +Similarly, we don't assume that the localization is a field until we need it to +define ideal quotients. When this assumption is needed, we replace `S` with `R⁰`, +making the localization a field. + +## References + + * https://en.wikipedia.org/wiki/Fractional_ideal + +## Tags + +fractional ideal, fractional ideals, invertible ideal +-/ + + +open IsLocalization Pointwise nonZeroDivisors + +section Defs + +variable {R : Type*} [CommRing R] {S : Submonoid R} {P : Type*} [CommRing P] + +variable [Algebra R P] + +variable (S) + +/-- A submodule `I` is a fractional ideal if `a I ⊆ R` for some `a ≠ 0`. -/ +def IsFractional (I : Submodule R P) := + ∃ a ∈ S, ∀ b ∈ I, IsInteger R (a • b) +#align is_fractional IsFractional + +variable (P) + +/-- The fractional ideals of a domain `R` are ideals of `R` divided by some `a ∈ R`. + +More precisely, let `P` be a localization of `R` at some submonoid `S`, +then a fractional ideal `I ⊆ P` is an `R`-submodule of `P`, +such that there is a nonzero `a : R` with `a I ⊆ R`. +-/ +def FractionalIdeal := + { I : Submodule R P // IsFractional S I } +#align fractional_ideal FractionalIdeal + +end Defs + +namespace FractionalIdeal + +open Set Submodule + +variable {R : Type*} [CommRing R] {S : Submonoid R} {P : Type*} [CommRing P] + +variable [Algebra R P] [loc : IsLocalization S P] + +/-- Map a fractional ideal `I` to a submodule by forgetting that `∃ a, a I ⊆ R`. + +This implements the coercion `FractionalIdeal S P → Submodule R P`. +-/ +@[coe] +def coeToSubmodule (I : FractionalIdeal S P) : Submodule R P := + I.val + +/-- Map a fractional ideal `I` to a submodule by forgetting that `∃ a, a I ⊆ R`. + +This coercion is typically called `coeToSubmodule` in lemma names +(or `coe` when the coercion is clear from the context), +not to be confused with `IsLocalization.coeSubmodule : Ideal R → Submodule R P` +(which we use to define `coe : Ideal R → FractionalIdeal S P`). +-/ +instance : CoeOut (FractionalIdeal S P) (Submodule R P) := + ⟨coeToSubmodule⟩ + +protected theorem isFractional (I : FractionalIdeal S P) : IsFractional S (I : Submodule R P) := + I.prop +#align fractional_ideal.is_fractional FractionalIdeal.isFractional + +/-- An element of `S` such that `I.den • I = I.num`, see `FractionalIdeal.num` and +`FractionalIdeal.den_mul_eq_num`. -/ +noncomputable def den (I : FractionalIdeal S P) : S := + ⟨I.2.choose, I.2.choose_spec.1⟩ + +/-- An ideal of `R` such that `I.den • I = I.num`, see `FractionalIdeal.den` and +`FractionalIdeal.den_mul_eq_num`. -/ +noncomputable def num (I : FractionalIdeal S P) : Ideal R := + (I.den • (I : Submodule R P)).comap (Algebra.linearMap R P) + +theorem den_mul_self_eq_num (I : FractionalIdeal S P) : + I.den • (I : Submodule R P) = Submodule.map (Algebra.linearMap R P) I.num := by + rw [den, num, Submodule.map_comap_eq] + refine (inf_of_le_right ?_).symm + rintro _ ⟨a, ha, rfl⟩ + exact I.2.choose_spec.2 a ha + +/-- The linear equivalence between the fractional ideal `I` and the integral ideal `I.num` +defined by mapping `x` to `den I • x`. -/ +noncomputable def equivNum [Nontrivial P] [NoZeroSMulDivisors R P] + {I : FractionalIdeal S P} (h_nz : (I.den : R) ≠ 0) : I ≃ₗ[R] I.num := by + refine LinearEquiv.trans + (LinearEquiv.ofBijective ((DistribMulAction.toLinearMap R P I.den).restrict fun _ hx ↦ ?_) + ⟨fun _ _ hxy ↦ ?_, fun ⟨y, hy⟩ ↦ ?_⟩) + (Submodule.equivMapOfInjective (Algebra.linearMap R P) + (NoZeroSMulDivisors.algebraMap_injective R P) (num I)).symm + · rw [← den_mul_self_eq_num] + exact Submodule.smul_mem_pointwise_smul _ _ _ hx + · simp_rw [LinearMap.restrict_apply, DistribMulAction.toLinearMap_apply, Subtype.mk.injEq] at hxy + rwa [Submonoid.smul_def, Submonoid.smul_def, smul_right_inj h_nz, SetCoe.ext_iff] at hxy + · rw [← den_mul_self_eq_num] at hy + obtain ⟨x, hx, hxy⟩ := hy + exact ⟨⟨x, hx⟩, by simp_rw [LinearMap.restrict_apply, Subtype.ext_iff, ← hxy]; rfl⟩ + +section SetLike + +instance : SetLike (FractionalIdeal S P) P where + coe I := ↑(I : Submodule R P) + coe_injective' := SetLike.coe_injective.comp Subtype.coe_injective + +@[simp] +theorem mem_coe {I : FractionalIdeal S P} {x : P} : x ∈ (I : Submodule R P) ↔ x ∈ I := + Iff.rfl +#align fractional_ideal.mem_coe FractionalIdeal.mem_coe + +@[ext] +theorem ext {I J : FractionalIdeal S P} : (∀ x, x ∈ I ↔ x ∈ J) → I = J := + SetLike.ext +#align fractional_ideal.ext FractionalIdeal.ext + +@[simp] + theorem equivNum_apply [Nontrivial P] [NoZeroSMulDivisors R P] {I : FractionalIdeal S P} + (h_nz : (I.den : R) ≠ 0) (x : I) : + algebraMap R P (equivNum h_nz x) = I.den • x := by + change Algebra.linearMap R P _ = _ + rw [equivNum, LinearEquiv.trans_apply, LinearEquiv.ofBijective_apply, LinearMap.restrict_apply, + Submodule.map_equivMapOfInjective_symm_apply, Subtype.coe_mk, + DistribMulAction.toLinearMap_apply] + +/-- Copy of a `FractionalIdeal` with a new underlying set equal to the old one. +Useful to fix definitional equalities. -/ +protected def copy (p : FractionalIdeal S P) (s : Set P) (hs : s = ↑p) : FractionalIdeal S P := + ⟨Submodule.copy p s hs, by + convert p.isFractional + ext + simp only [hs] + rfl⟩ +#align fractional_ideal.copy FractionalIdeal.copy + +@[simp] +theorem coe_copy (p : FractionalIdeal S P) (s : Set P) (hs : s = ↑p) : ↑(p.copy s hs) = s := + rfl +#align fractional_ideal.coe_copy FractionalIdeal.coe_copy + +theorem coe_eq (p : FractionalIdeal S P) (s : Set P) (hs : s = ↑p) : p.copy s hs = p := + SetLike.coe_injective hs +#align fractional_ideal.coe_eq FractionalIdeal.coe_eq + +end SetLike + +-- Porting note: this seems to be needed a lot more than in Lean 3 +@[simp] +theorem val_eq_coe (I : FractionalIdeal S P) : I.val = I := + rfl +#align fractional_ideal.val_eq_coe FractionalIdeal.val_eq_coe + +-- Porting note: had to rephrase this to make it clear to `simp` what was going on. +@[simp, norm_cast] +theorem coe_mk (I : Submodule R P) (hI : IsFractional S I) : + coeToSubmodule ⟨I, hI⟩ = I := + rfl +#align fractional_ideal.coe_mk FractionalIdeal.coe_mk + +-- Porting note: added this lemma because Lean can't see through the composition of coercions. +theorem coeToSet_coeToSubmodule (I : FractionalIdeal S P) : + ((I : Submodule R P) : Set P) = I := + rfl + +/-! Transfer instances from `Submodule R P` to `FractionalIdeal S P`. -/ + +instance (I : FractionalIdeal S P) : Module R I := + Submodule.module (I : Submodule R P) + +theorem coeToSubmodule_injective : + Function.Injective (fun (I : FractionalIdeal S P) ↦ (I : Submodule R P)) := + Subtype.coe_injective +#align fractional_ideal.coe_to_submodule_injective FractionalIdeal.coeToSubmodule_injective + +theorem coeToSubmodule_inj {I J : FractionalIdeal S P} : (I : Submodule R P) = J ↔ I = J := + coeToSubmodule_injective.eq_iff +#align fractional_ideal.coe_to_submodule_inj FractionalIdeal.coeToSubmodule_inj + +theorem isFractional_of_le_one (I : Submodule R P) (h : I ≤ 1) : IsFractional S I := by + use 1, S.one_mem + intro b hb + rw [one_smul] + obtain ⟨b', b'_mem, rfl⟩ := h hb + exact Set.mem_range_self b' +#align fractional_ideal.is_fractional_of_le_one FractionalIdeal.isFractional_of_le_one + +theorem isFractional_of_le {I : Submodule R P} {J : FractionalIdeal S P} (hIJ : I ≤ J) : + IsFractional S I := by + obtain ⟨a, a_mem, ha⟩ := J.isFractional + use a, a_mem + intro b b_mem + exact ha b (hIJ b_mem) +#align fractional_ideal.is_fractional_of_le FractionalIdeal.isFractional_of_le + +/-- Map an ideal `I` to a fractional ideal by forgetting `I` is integral. + +This is the function that implements the coercion `Ideal R → FractionalIdeal S P`. -/ +@[coe] +def coeIdeal (I : Ideal R) : FractionalIdeal S P := + ⟨coeSubmodule P I, + isFractional_of_le_one _ <| by simpa using coeSubmodule_mono P (le_top : I ≤ ⊤)⟩ + +-- Is a `CoeTC` rather than `Coe` to speed up failing inference, see library note [use has_coe_t] +/-- Map an ideal `I` to a fractional ideal by forgetting `I` is integral. + +This is a bundled version of `IsLocalization.coeSubmodule : Ideal R → Submodule R P`, +which is not to be confused with the `coe : FractionalIdeal S P → Submodule R P`, +also called `coeToSubmodule` in theorem names. + +This map is available as a ring hom, called `FractionalIdeal.coeIdealHom`. +-/ +instance : CoeTC (Ideal R) (FractionalIdeal S P) := + ⟨fun I => coeIdeal I⟩ + +@[simp, norm_cast] +theorem coe_coeIdeal (I : Ideal R) : + ((I : FractionalIdeal S P) : Submodule R P) = coeSubmodule P I := + rfl +#align fractional_ideal.coe_coe_ideal FractionalIdeal.coe_coeIdeal + +variable (S) + +@[simp] +theorem mem_coeIdeal {x : P} {I : Ideal R} : + x ∈ (I : FractionalIdeal S P) ↔ ∃ x', x' ∈ I ∧ algebraMap R P x' = x := + mem_coeSubmodule _ _ +#align fractional_ideal.mem_coe_ideal FractionalIdeal.mem_coeIdeal + +theorem mem_coeIdeal_of_mem {x : R} {I : Ideal R} (hx : x ∈ I) : + algebraMap R P x ∈ (I : FractionalIdeal S P) := + (mem_coeIdeal S).mpr ⟨x, hx, rfl⟩ +#align fractional_ideal.mem_coe_ideal_of_mem FractionalIdeal.mem_coeIdeal_of_mem + +theorem coeIdeal_le_coeIdeal' [IsLocalization S P] (h : S ≤ nonZeroDivisors R) {I J : Ideal R} : + (I : FractionalIdeal S P) ≤ J ↔ I ≤ J := + coeSubmodule_le_coeSubmodule h +#align fractional_ideal.coe_ideal_le_coe_ideal' FractionalIdeal.coeIdeal_le_coeIdeal' + +@[simp] +theorem coeIdeal_le_coeIdeal (K : Type*) [CommRing K] [Algebra R K] [IsFractionRing R K] + {I J : Ideal R} : (I : FractionalIdeal R⁰ K) ≤ J ↔ I ≤ J := + IsFractionRing.coeSubmodule_le_coeSubmodule +#align fractional_ideal.coe_ideal_le_coe_ideal FractionalIdeal.coeIdeal_le_coeIdeal + +instance : Zero (FractionalIdeal S P) := + ⟨(0 : Ideal R)⟩ + +@[simp] +theorem mem_zero_iff {x : P} : x ∈ (0 : FractionalIdeal S P) ↔ x = 0 := + ⟨fun ⟨x', x'_mem_zero, x'_eq_x⟩ => by + have x'_eq_zero : x' = 0 := x'_mem_zero + simp [x'_eq_x.symm, x'_eq_zero], fun hx => ⟨0, rfl, by simp [hx]⟩⟩ +#align fractional_ideal.mem_zero_iff FractionalIdeal.mem_zero_iff + +variable {S} + +@[simp, norm_cast] +theorem coe_zero : ↑(0 : FractionalIdeal S P) = (⊥ : Submodule R P) := + Submodule.ext fun _ => mem_zero_iff S +#align fractional_ideal.coe_zero FractionalIdeal.coe_zero + +@[simp, norm_cast] +theorem coeIdeal_bot : ((⊥ : Ideal R) : FractionalIdeal S P) = 0 := + rfl +#align fractional_ideal.coe_ideal_bot FractionalIdeal.coeIdeal_bot + +variable (P) + +@[simp] +theorem exists_mem_algebraMap_eq {x : R} {I : Ideal R} (h : S ≤ nonZeroDivisors R) : + (∃ x', x' ∈ I ∧ algebraMap R P x' = algebraMap R P x) ↔ x ∈ I := + ⟨fun ⟨_, hx', Eq⟩ => IsLocalization.injective _ h Eq ▸ hx', fun h => ⟨x, h, rfl⟩⟩ +#align fractional_ideal.exists_mem_to_map_eq FractionalIdeal.exists_mem_algebraMap_eq + +variable {P} + +theorem coeIdeal_injective' (h : S ≤ nonZeroDivisors R) : + Function.Injective (fun (I : Ideal R) ↦ (I : FractionalIdeal S P)) := fun _ _ h' => + ((coeIdeal_le_coeIdeal' S h).mp h'.le).antisymm ((coeIdeal_le_coeIdeal' S h).mp + h'.ge) +#align fractional_ideal.coe_ideal_injective' FractionalIdeal.coeIdeal_injective' + +theorem coeIdeal_inj' (h : S ≤ nonZeroDivisors R) {I J : Ideal R} : + (I : FractionalIdeal S P) = J ↔ I = J := + (coeIdeal_injective' h).eq_iff +#align fractional_ideal.coe_ideal_inj' FractionalIdeal.coeIdeal_inj' + +-- Porting note: doesn't need to be @[simp] because it can be proved by coeIdeal_eq_zero +theorem coeIdeal_eq_zero' {I : Ideal R} (h : S ≤ nonZeroDivisors R) : + (I : FractionalIdeal S P) = 0 ↔ I = (⊥ : Ideal R) := + coeIdeal_inj' h +#align fractional_ideal.coe_ideal_eq_zero' FractionalIdeal.coeIdeal_eq_zero' + +theorem coeIdeal_ne_zero' {I : Ideal R} (h : S ≤ nonZeroDivisors R) : + (I : FractionalIdeal S P) ≠ 0 ↔ I ≠ (⊥ : Ideal R) := + not_iff_not.mpr <| coeIdeal_eq_zero' h +#align fractional_ideal.coe_ideal_ne_zero' FractionalIdeal.coeIdeal_ne_zero' + +theorem coeToSubmodule_eq_bot {I : FractionalIdeal S P} : (I : Submodule R P) = ⊥ ↔ I = 0 := + ⟨fun h => coeToSubmodule_injective (by simp [h]), fun h => by simp [h]⟩ +#align fractional_ideal.coe_to_submodule_eq_bot FractionalIdeal.coeToSubmodule_eq_bot + +theorem coeToSubmodule_ne_bot {I : FractionalIdeal S P} : ↑I ≠ (⊥ : Submodule R P) ↔ I ≠ 0 := + not_iff_not.mpr coeToSubmodule_eq_bot +#align fractional_ideal.coe_to_submodule_ne_bot FractionalIdeal.coeToSubmodule_ne_bot + +instance : Inhabited (FractionalIdeal S P) := + ⟨0⟩ + +instance : One (FractionalIdeal S P) := + ⟨(⊤ : Ideal R)⟩ + +theorem zero_of_num_eq_bot [NoZeroSMulDivisors R P] (hS : 0 ∉ S) {I : FractionalIdeal S P} + (hI : I.num = ⊥) : I = 0 := by + rw [← coeToSubmodule_eq_bot, eq_bot_iff] + intro x hx + suffices (den I : R) • x = 0 from + (smul_eq_zero.mp this).resolve_left (ne_of_mem_of_not_mem (SetLike.coe_mem _) hS) + have h_eq : I.den • (I : Submodule R P) = ⊥ := by rw [den_mul_self_eq_num, hI, Submodule.map_bot] + exact (Submodule.eq_bot_iff _).mp h_eq (den I • x) ⟨x, hx, rfl⟩ + +theorem num_zero_eq (h_inj : Function.Injective (algebraMap R P)) : + num (0 : FractionalIdeal S P) = 0 := by + simpa [num, LinearMap.ker_eq_bot] using h_inj + +variable (S) + +@[simp, norm_cast] +theorem coeIdeal_top : ((⊤ : Ideal R) : FractionalIdeal S P) = 1 := + rfl +#align fractional_ideal.coe_ideal_top FractionalIdeal.coeIdeal_top + +theorem mem_one_iff {x : P} : x ∈ (1 : FractionalIdeal S P) ↔ ∃ x' : R, algebraMap R P x' = x := + Iff.intro (fun ⟨x', _, h⟩ => ⟨x', h⟩) fun ⟨x', h⟩ => ⟨x', ⟨⟩, h⟩ +#align fractional_ideal.mem_one_iff FractionalIdeal.mem_one_iff + +theorem coe_mem_one (x : R) : algebraMap R P x ∈ (1 : FractionalIdeal S P) := + (mem_one_iff S).mpr ⟨x, rfl⟩ +#align fractional_ideal.coe_mem_one FractionalIdeal.coe_mem_one + +theorem one_mem_one : (1 : P) ∈ (1 : FractionalIdeal S P) := + (mem_one_iff S).mpr ⟨1, RingHom.map_one _⟩ +#align fractional_ideal.one_mem_one FractionalIdeal.one_mem_one + +variable {S} + +/-- `(1 : FractionalIdeal S P)` is defined as the R-submodule `f(R) ≤ P`. + +However, this is not definitionally equal to `1 : Submodule R P`, +which is proved in the actual `simp` lemma `coe_one`. -/ +theorem coe_one_eq_coeSubmodule_top : ↑(1 : FractionalIdeal S P) = coeSubmodule P (⊤ : Ideal R) := + rfl +#align fractional_ideal.coe_one_eq_coe_submodule_top FractionalIdeal.coe_one_eq_coeSubmodule_top + +@[simp, norm_cast] +theorem coe_one : (↑(1 : FractionalIdeal S P) : Submodule R P) = 1 := by + rw [coe_one_eq_coeSubmodule_top, coeSubmodule_top] +#align fractional_ideal.coe_one FractionalIdeal.coe_one + +section Lattice + +/-! +### `Lattice` section + +Defines the order on fractional ideals as inclusion of their underlying sets, +and ports the lattice structure on submodules to fractional ideals. +-/ + + +@[simp] +theorem coe_le_coe {I J : FractionalIdeal S P} : + (I : Submodule R P) ≤ (J : Submodule R P) ↔ I ≤ J := + Iff.rfl +#align fractional_ideal.coe_le_coe FractionalIdeal.coe_le_coe + +theorem zero_le (I : FractionalIdeal S P) : 0 ≤ I := by + intro x hx + -- Porting note: changed the proof from convert; simp into rw; exact + rw [(mem_zero_iff _).mp hx] + exact zero_mem (I : Submodule R P) +#align fractional_ideal.zero_le FractionalIdeal.zero_le + +instance orderBot : OrderBot (FractionalIdeal S P) where + bot := 0 + bot_le := zero_le +#align fractional_ideal.order_bot FractionalIdeal.orderBot + +@[simp] +theorem bot_eq_zero : (⊥ : FractionalIdeal S P) = 0 := + rfl +#align fractional_ideal.bot_eq_zero FractionalIdeal.bot_eq_zero + +@[simp] +theorem le_zero_iff {I : FractionalIdeal S P} : I ≤ 0 ↔ I = 0 := + le_bot_iff +#align fractional_ideal.le_zero_iff FractionalIdeal.le_zero_iff + +theorem eq_zero_iff {I : FractionalIdeal S P} : I = 0 ↔ ∀ x ∈ I, x = (0 : P) := + ⟨fun h x hx => by simpa [h, mem_zero_iff] using hx, fun h => + le_bot_iff.mp fun x hx => (mem_zero_iff S).mpr (h x hx)⟩ +#align fractional_ideal.eq_zero_iff FractionalIdeal.eq_zero_iff + +theorem _root_.IsFractional.sup {I J : Submodule R P} : + IsFractional S I → IsFractional S J → IsFractional S (I ⊔ J) + | ⟨aI, haI, hI⟩, ⟨aJ, haJ, hJ⟩ => + ⟨aI * aJ, S.mul_mem haI haJ, fun b hb => by + rcases mem_sup.mp hb with ⟨bI, hbI, bJ, hbJ, rfl⟩ + rw [smul_add] + apply isInteger_add + · rw [mul_smul, smul_comm] + exact isInteger_smul (hI bI hbI) + · rw [mul_smul] + exact isInteger_smul (hJ bJ hbJ)⟩ +#align is_fractional.sup IsFractional.sup + +theorem _root_.IsFractional.inf_right {I : Submodule R P} : + IsFractional S I → ∀ J, IsFractional S (I ⊓ J) + | ⟨aI, haI, hI⟩, J => + ⟨aI, haI, fun b hb => by + rcases mem_inf.mp hb with ⟨hbI, _⟩ + exact hI b hbI⟩ +#align is_fractional.inf_right IsFractional.inf_right + +instance : Inf (FractionalIdeal S P) := + ⟨fun I J => ⟨I ⊓ J, I.isFractional.inf_right J⟩⟩ + +@[simp, norm_cast] +theorem coe_inf (I J : FractionalIdeal S P) : ↑(I ⊓ J) = (I ⊓ J : Submodule R P) := + rfl +#align fractional_ideal.coe_inf FractionalIdeal.coe_inf + +instance : Sup (FractionalIdeal S P) := + ⟨fun I J => ⟨I ⊔ J, I.isFractional.sup J.isFractional⟩⟩ + +@[norm_cast] +theorem coe_sup (I J : FractionalIdeal S P) : ↑(I ⊔ J) = (I ⊔ J : Submodule R P) := + rfl +#align fractional_ideal.coe_sup FractionalIdeal.coe_sup + +instance lattice : Lattice (FractionalIdeal S P) := + Function.Injective.lattice _ Subtype.coe_injective coe_sup coe_inf +#align fractional_ideal.lattice FractionalIdeal.lattice + +instance : SemilatticeSup (FractionalIdeal S P) := + { FractionalIdeal.lattice with } + +end Lattice + +section Semiring + +instance : Add (FractionalIdeal S P) := + ⟨(· ⊔ ·)⟩ + +@[simp] +theorem sup_eq_add (I J : FractionalIdeal S P) : I ⊔ J = I + J := + rfl +#align fractional_ideal.sup_eq_add FractionalIdeal.sup_eq_add + +@[simp, norm_cast] +theorem coe_add (I J : FractionalIdeal S P) : (↑(I + J) : Submodule R P) = I + J := + rfl +#align fractional_ideal.coe_add FractionalIdeal.coe_add + +@[simp, norm_cast] +theorem coeIdeal_sup (I J : Ideal R) : ↑(I ⊔ J) = (I + J : FractionalIdeal S P) := + coeToSubmodule_injective <| coeSubmodule_sup _ _ _ +#align fractional_ideal.coe_ideal_sup FractionalIdeal.coeIdeal_sup + +theorem _root_.IsFractional.nsmul {I : Submodule R P} : + ∀ n : ℕ, IsFractional S I → IsFractional S (n • I : Submodule R P) + | 0, _ => by + rw [zero_smul] + convert ((0 : Ideal R) : FractionalIdeal S P).isFractional + simp + | n + 1, h => by + rw [succ_nsmul] + exact h.sup (IsFractional.nsmul n h) +#align is_fractional.nsmul IsFractional.nsmul + +instance : SMul ℕ (FractionalIdeal S P) where smul n I := ⟨n • ↑I, I.isFractional.nsmul n⟩ + +@[norm_cast] +theorem coe_nsmul (n : ℕ) (I : FractionalIdeal S P) : + (↑(n • I) : Submodule R P) = n • (I : Submodule R P) := + rfl +#align fractional_ideal.coe_nsmul FractionalIdeal.coe_nsmul + +theorem _root_.IsFractional.mul {I J : Submodule R P} : + IsFractional S I → IsFractional S J → IsFractional S (I * J : Submodule R P) + | ⟨aI, haI, hI⟩, ⟨aJ, haJ, hJ⟩ => + ⟨aI * aJ, S.mul_mem haI haJ, fun b hb => by + refine Submodule.mul_induction_on hb ?_ ?_ + · intro m hm n hn + obtain ⟨n', hn'⟩ := hJ n hn + rw [mul_smul, mul_comm m, ← smul_mul_assoc, ← hn', ← Algebra.smul_def] + apply hI + exact Submodule.smul_mem _ _ hm + · intro x y hx hy + rw [smul_add] + apply isInteger_add hx hy⟩ +#align is_fractional.mul IsFractional.mul + +theorem _root_.IsFractional.pow {I : Submodule R P} (h : IsFractional S I) : + ∀ n : ℕ, IsFractional S (I ^ n : Submodule R P) + | 0 => isFractional_of_le_one _ (pow_zero _).le + | n + 1 => (pow_succ I n).symm ▸ h.mul (IsFractional.pow h n) +#align is_fractional.pow IsFractional.pow + +/-- `FractionalIdeal.mul` is the product of two fractional ideals, +used to define the `Mul` instance. + +This is only an auxiliary definition: the preferred way of writing `I.mul J` is `I * J`. + +Elaborated terms involving `FractionalIdeal` tend to grow quite large, +so by making definitions irreducible, we hope to avoid deep unfolds. +-/ +irreducible_def mul (lemma := mul_def') (I J : FractionalIdeal S P) : FractionalIdeal S P := + ⟨I * J, I.isFractional.mul J.isFractional⟩ +#align fractional_ideal.mul FractionalIdeal.mul + +-- local attribute [semireducible] mul +instance : Mul (FractionalIdeal S P) := + ⟨fun I J => mul I J⟩ + +@[simp] +theorem mul_eq_mul (I J : FractionalIdeal S P) : mul I J = I * J := + rfl +#align fractional_ideal.mul_eq_mul FractionalIdeal.mul_eq_mul + +theorem mul_def (I J : FractionalIdeal S P) : I * J = ⟨I * J, I.isFractional.mul J.isFractional⟩ := + by simp only [← mul_eq_mul, mul] +#align fractional_ideal.mul_def FractionalIdeal.mul_def + +@[simp, norm_cast] +theorem coe_mul (I J : FractionalIdeal S P) : (↑(I * J) : Submodule R P) = I * J := by + simp only [mul_def, coe_mk] +#align fractional_ideal.coe_mul FractionalIdeal.coe_mul + +@[simp, norm_cast] +theorem coeIdeal_mul (I J : Ideal R) : (↑(I * J) : FractionalIdeal S P) = I * J := by + simp only [mul_def] + exact coeToSubmodule_injective (coeSubmodule_mul _ _ _) +#align fractional_ideal.coe_ideal_mul FractionalIdeal.coeIdeal_mul + +theorem mul_left_mono (I : FractionalIdeal S P) : Monotone (I * ·) := by + intro J J' h + simp only [mul_def] + exact mul_le.mpr fun x hx y hy => mul_mem_mul hx (h hy) +#align fractional_ideal.mul_left_mono FractionalIdeal.mul_left_mono + +theorem mul_right_mono (I : FractionalIdeal S P) : Monotone fun J => J * I := by + intro J J' h + simp only [mul_def] + exact mul_le.mpr fun x hx y hy => mul_mem_mul (h hx) hy +#align fractional_ideal.mul_right_mono FractionalIdeal.mul_right_mono + +theorem mul_mem_mul {I J : FractionalIdeal S P} {i j : P} (hi : i ∈ I) (hj : j ∈ J) : + i * j ∈ I * J := by + simp only [mul_def] + exact Submodule.mul_mem_mul hi hj +#align fractional_ideal.mul_mem_mul FractionalIdeal.mul_mem_mul + +theorem mul_le {I J K : FractionalIdeal S P} : I * J ≤ K ↔ ∀ i ∈ I, ∀ j ∈ J, i * j ∈ K := by + simp only [mul_def] + exact Submodule.mul_le +#align fractional_ideal.mul_le FractionalIdeal.mul_le + +instance : Pow (FractionalIdeal S P) ℕ := + ⟨fun I n => ⟨(I : Submodule R P) ^ n, I.isFractional.pow n⟩⟩ + +@[simp, norm_cast] +theorem coe_pow (I : FractionalIdeal S P) (n : ℕ) : ↑(I ^ n) = (I : Submodule R P) ^ n := + rfl +#align fractional_ideal.coe_pow FractionalIdeal.coe_pow + +@[elab_as_elim] +protected theorem mul_induction_on {I J : FractionalIdeal S P} {C : P → Prop} {r : P} + (hr : r ∈ I * J) (hm : ∀ i ∈ I, ∀ j ∈ J, C (i * j)) (ha : ∀ x y, C x → C y → C (x + y)) : + C r := by + simp only [mul_def] at hr + exact Submodule.mul_induction_on hr hm ha +#align fractional_ideal.mul_induction_on FractionalIdeal.mul_induction_on + +instance : NatCast (FractionalIdeal S P) := + ⟨Nat.unaryCast⟩ + +theorem coe_nat_cast (n : ℕ) : ((n : FractionalIdeal S P) : Submodule R P) = n := + show ((n.unaryCast : FractionalIdeal S P) : Submodule R P) = n + by induction n <;> simp [*, Nat.unaryCast] +#align fractional_ideal.coe_nat_cast FractionalIdeal.coe_nat_cast + +instance commSemiring : CommSemiring (FractionalIdeal S P) := + Function.Injective.commSemiring _ Subtype.coe_injective coe_zero coe_one coe_add coe_mul + (fun _ _ => coe_nsmul _ _) coe_pow coe_nat_cast + +end Semiring + +variable (S P) + +/-- `FractionalIdeal.coeToSubmodule` as a bundled `RingHom`. -/ +@[simps] +def coeSubmoduleHom : FractionalIdeal S P →+* Submodule R P where + toFun := coeToSubmodule + map_one' := coe_one + map_mul' := coe_mul + map_zero' := coe_zero (S := S) + map_add' := coe_add +#align fractional_ideal.coe_submodule_hom FractionalIdeal.coeSubmoduleHom + +variable {S P} + +section Order + +theorem add_le_add_left {I J : FractionalIdeal S P} (hIJ : I ≤ J) (J' : FractionalIdeal S P) : + J' + I ≤ J' + J := + sup_le_sup_left hIJ J' +#align fractional_ideal.add_le_add_left FractionalIdeal.add_le_add_left + +theorem mul_le_mul_left {I J : FractionalIdeal S P} (hIJ : I ≤ J) (J' : FractionalIdeal S P) : + J' * I ≤ J' * J := + mul_le.mpr fun _ hk _ hj => mul_mem_mul hk (hIJ hj) +#align fractional_ideal.mul_le_mul_left FractionalIdeal.mul_le_mul_left + +theorem le_self_mul_self {I : FractionalIdeal S P} (hI : 1 ≤ I) : I ≤ I * I := by + convert mul_left_mono I hI + exact (mul_one I).symm +#align fractional_ideal.le_self_mul_self FractionalIdeal.le_self_mul_self + +theorem mul_self_le_self {I : FractionalIdeal S P} (hI : I ≤ 1) : I * I ≤ I := by + convert mul_left_mono I hI + exact (mul_one I).symm +#align fractional_ideal.mul_self_le_self FractionalIdeal.mul_self_le_self + +theorem coeIdeal_le_one {I : Ideal R} : (I : FractionalIdeal S P) ≤ 1 := fun _ hx => + let ⟨y, _, hy⟩ := (mem_coeIdeal S).mp hx + (mem_one_iff S).mpr ⟨y, hy⟩ +#align fractional_ideal.coe_ideal_le_one FractionalIdeal.coeIdeal_le_one + +theorem le_one_iff_exists_coeIdeal {J : FractionalIdeal S P} : + J ≤ (1 : FractionalIdeal S P) ↔ ∃ I : Ideal R, ↑I = J := by + constructor + · intro hJ + refine' ⟨⟨⟨⟨{ x : R | algebraMap R P x ∈ J }, _⟩, _⟩, _⟩, _⟩ + · intro a b ha hb + rw [mem_setOf, RingHom.map_add] + exact J.val.add_mem ha hb + · rw [mem_setOf, RingHom.map_zero] + exact J.val.zero_mem + · intro c x hx + rw [smul_eq_mul, mem_setOf, RingHom.map_mul, ← Algebra.smul_def] + exact J.val.smul_mem c hx + · ext x + constructor + · rintro ⟨y, hy, eq_y⟩ + rwa [← eq_y] + · intro hx + obtain ⟨y, rfl⟩ := (mem_one_iff S).mp (hJ hx) + exact mem_setOf.mpr ⟨y, hx, rfl⟩ + · rintro ⟨I, hI⟩ + rw [← hI] + apply coeIdeal_le_one +#align fractional_ideal.le_one_iff_exists_coe_ideal FractionalIdeal.le_one_iff_exists_coeIdeal + +@[simp] +theorem one_le {I : FractionalIdeal S P} : 1 ≤ I ↔ (1 : P) ∈ I := by + rw [← coe_le_coe, coe_one, Submodule.one_le, mem_coe] +#align fractional_ideal.one_le FractionalIdeal.one_le + +variable (S P) + +/-- `coeIdealHom (S : Submonoid R) P` is `(↑) : Ideal R → FractionalIdeal S P` as a ring hom -/ +@[simps] +def coeIdealHom : Ideal R →+* FractionalIdeal S P where + toFun := coeIdeal + map_add' := coeIdeal_sup + map_mul' := coeIdeal_mul + map_one' := by rw [Ideal.one_eq_top, coeIdeal_top] + map_zero' := coeIdeal_bot +#align fractional_ideal.coe_ideal_hom FractionalIdeal.coeIdealHom + +theorem coeIdeal_pow (I : Ideal R) (n : ℕ) : ↑(I ^ n) = (I : FractionalIdeal S P) ^ n := + (coeIdealHom S P).map_pow _ n +#align fractional_ideal.coe_ideal_pow FractionalIdeal.coeIdeal_pow + +open BigOperators + +theorem coeIdeal_finprod [IsLocalization S P] {α : Sort*} {f : α → Ideal R} + (hS : S ≤ nonZeroDivisors R) : + ((∏ᶠ a : α, f a : Ideal R) : FractionalIdeal S P) = ∏ᶠ a : α, (f a : FractionalIdeal S P) := + MonoidHom.map_finprod_of_injective (coeIdealHom S P).toMonoidHom (coeIdeal_injective' hS) f +#align fractional_ideal.coe_ideal_finprod FractionalIdeal.coeIdeal_finprod + +end Order + +end FractionalIdeal diff --git a/Mathlib/RingTheory/FractionalIdeal/Norm.lean b/Mathlib/RingTheory/FractionalIdeal/Norm.lean new file mode 100644 index 0000000000000..d635a4f4ed5f0 --- /dev/null +++ b/Mathlib/RingTheory/FractionalIdeal/Norm.lean @@ -0,0 +1,150 @@ +/- +Copyright (c) 2024 Xavier Roblot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Xavier Roblot +-/ +import Mathlib.RingTheory.FractionalIdeal.Basic +import Mathlib.RingTheory.Ideal.Norm + +/-! + +# Fractional ideal norms + +This file defines the absolute ideal norm of a fractional ideal `I : FractionalIdeal R⁰ K` where +`K` is a fraction field of `R`. The norm is defined by +`FractionalIdeal.absNorm I = Ideal.absNorm I.num / |Algebra.norm ℤ I.den|` where `I.num` is an +ideal of `R` and `I.den` an element of `R⁰` such that `I.den • I = I.num`. + +## Main definitions and results + + * `FractionalIdeal.absNorm`: the norm as a zero preserving morphism with values in `ℚ`. + * `FractionalIdeal.absNorm_eq'`: the value of the norm does not depend on the choice of + `I.num` and `I.den`. + * `FractionalIdeal.abs_det_basis_change`: the norm is given by the determinant + of the basis change matrix. + * `FractionalIdeal.absNorm_span_singleton`: the norm of a principal fractional ideal is the + norm of its generator +-/ + +namespace FractionalIdeal + +open scoped Pointwise nonZeroDivisors + +variable {R : Type*} [CommRing R] [IsDedekindDomain R] [Module.Free ℤ R] [Module.Finite ℤ R] + +variable {K : Type*} [CommRing K] [Algebra R K] [IsFractionRing R K] + +theorem absNorm_div_norm_eq_absNorm_div_norm {I : FractionalIdeal R⁰ K} (a : R⁰) (I₀ : Ideal R) + (h : a • (I : Submodule R K) = Submodule.map (Algebra.linearMap R K) I₀) : + (Ideal.absNorm I.num : ℚ) / |Algebra.norm ℤ (I.den:R)| = + (Ideal.absNorm I₀ : ℚ) / |Algebra.norm ℤ (a:R)| := by + rw [div_eq_div_iff] + · replace h := congr_arg (I.den • ·) h + have h' := congr_arg (a • ·) (den_mul_self_eq_num I) + dsimp only at h h' + rw [smul_comm] at h + rw [h, Submonoid.smul_def, Submonoid.smul_def, ← Submodule.ideal_span_singleton_smul, + ← Submodule.ideal_span_singleton_smul, ← Submodule.map_smul'', ← Submodule.map_smul'', + (LinearMap.map_injective ?_).eq_iff, smul_eq_mul, smul_eq_mul] at h' + · simp_rw [← Int.cast_natAbs, ← Nat.cast_mul, ← Ideal.absNorm_span_singleton] + rw [← _root_.map_mul, ← _root_.map_mul, mul_comm, ← h', mul_comm] + · exact LinearMap.ker_eq_bot.mpr (IsFractionRing.injective R K) + all_goals simpa [Algebra.norm_eq_zero_iff] using nonZeroDivisors.coe_ne_zero _ + +/-- The absolute norm of the fractional ideal `I` extending by multiplicativity the absolute norm +on (integral) ideals. -/ +noncomputable def absNorm : FractionalIdeal R⁰ K →*₀ ℚ where + toFun I := (Ideal.absNorm I.num : ℚ) / |Algebra.norm ℤ (I.den : R)| + map_zero' := by + dsimp only + rw [num_zero_eq, Submodule.zero_eq_bot, Ideal.absNorm_bot, Nat.cast_zero, zero_div] + exact IsFractionRing.injective R K + map_one' := by + dsimp only + rw [absNorm_div_norm_eq_absNorm_div_norm 1 ⊤ (by simp [Submodule.one_eq_range]), + Ideal.absNorm_top, Nat.cast_one, OneMemClass.coe_one, _root_.map_one, abs_one, Int.cast_one, + one_div_one] + map_mul' I J := by + dsimp only + rw [absNorm_div_norm_eq_absNorm_div_norm (I.den * J.den) (I.num * J.num) (by + have : Algebra.linearMap R K = (IsScalarTower.toAlgHom R R K).toLinearMap := rfl + rw [coe_mul, this, Submodule.map_mul, ← this, ← den_mul_self_eq_num, ← den_mul_self_eq_num] + exact Submodule.mul_smul_mul_eq_smul_mul_smul _ _ _ _), + Submonoid.coe_mul, _root_.map_mul, _root_.map_mul, Nat.cast_mul, div_mul_div_comm, + Int.cast_abs, Int.cast_abs, Int.cast_abs, ← abs_mul, Int.cast_mul] + +theorem absNorm_eq (I : FractionalIdeal R⁰ K) : + absNorm I = (Ideal.absNorm I.num : ℚ) / |Algebra.norm ℤ (I.den : R)| := rfl + +theorem absNorm_eq' {I : FractionalIdeal R⁰ K} (a : R⁰) (I₀ : Ideal R) + (h : a • (I : Submodule R K) = Submodule.map (Algebra.linearMap R K) I₀) : + absNorm I = (Ideal.absNorm I₀ : ℚ) / |Algebra.norm ℤ (a:R)| := by + rw [absNorm, ← absNorm_div_norm_eq_absNorm_div_norm a I₀ h, MonoidWithZeroHom.coe_mk, + ZeroHom.coe_mk] + +theorem absNorm_nonneg (I : FractionalIdeal R⁰ K) : 0 ≤ absNorm I := by dsimp [absNorm]; positivity + +theorem absNorm_bot : absNorm (⊥ : FractionalIdeal R⁰ K) = 0 := absNorm.map_zero' + +theorem absNorm_one : absNorm (1 : FractionalIdeal R⁰ K) = 1 := by convert absNorm.map_one' + +theorem absNorm_eq_zero_iff [NoZeroDivisors K] {I : FractionalIdeal R⁰ K} : + absNorm I = 0 ↔ I = 0 := by + refine ⟨fun h ↦ zero_of_num_eq_bot zero_not_mem_nonZeroDivisors ?_, fun h ↦ h ▸ absNorm_bot⟩ + rw [absNorm_eq, div_eq_zero_iff] at h + refine Ideal.absNorm_eq_zero_iff.mp <| Nat.cast_eq_zero.mp <| h.resolve_right ?_ + simpa [Algebra.norm_eq_zero_iff] using nonZeroDivisors.coe_ne_zero _ + +theorem coeIdeal_absNorm (I₀ : Ideal R) : + absNorm (I₀ : FractionalIdeal R⁰ K) = Ideal.absNorm I₀ := by + rw [absNorm_eq' 1 I₀ (by rw [one_smul]; rfl), OneMemClass.coe_one, _root_.map_one, abs_one, + Int.cast_one, _root_.div_one] + +section IsLocalization + +variable [IsLocalization (Algebra.algebraMapSubmonoid R ℤ⁰) K] [Algebra ℚ K] + +theorem abs_det_basis_change [NoZeroDivisors K] {ι : Type*} [Fintype ι] + [DecidableEq ι] (b : Basis ι ℤ R) (I : FractionalIdeal R⁰ K) (bI : Basis ι ℤ I) : + |(b.localizationLocalization ℚ ℤ⁰ K).det ((↑) ∘ bI)| = absNorm I := by + have := IsFractionRing.nontrivial R K + let b₀ : Basis ι ℚ K := b.localizationLocalization ℚ ℤ⁰ K + let bI.num : Basis ι ℤ I.num := bI.map + ((equivNum (nonZeroDivisors.coe_ne_zero _)).restrictScalars ℤ) + rw [absNorm_eq, ← Ideal.natAbs_det_basis_change b I.num bI.num, Int.cast_natAbs, Int.cast_abs, + Int.cast_abs, Basis.det_apply, Basis.det_apply] + change _ = |algebraMap ℤ ℚ _| / _ + rw [RingHom.map_det, show RingHom.mapMatrix (algebraMap ℤ ℚ) (b.toMatrix ((↑) ∘ bI.num)) = + b₀.toMatrix ((algebraMap R K (den I : R)) • ((↑) ∘ bI)) by + ext : 2 + simp_rw [RingHom.mapMatrix_apply, Matrix.map_apply, Basis.toMatrix_apply, + ← Basis.localizationLocalization_repr_algebraMap ℚ ℤ⁰ K, Function.comp_apply, + Basis.map_apply, LinearEquiv.restrictScalars_apply, equivNum_apply, Submonoid.smul_def, + Algebra.smul_def] + rfl] + rw [Basis.toMatrix_smul, Matrix.det_mul, abs_mul, ← Algebra.norm_eq_matrix_det, + Algebra.norm_localization ℤ ℤ⁰, show (Algebra.norm ℤ (den I: R) : ℚ) = + algebraMap ℤ ℚ (Algebra.norm ℤ (den I: R)) by rfl, mul_div_assoc, mul_div_cancel' _ (by + rw [ne_eq, abs_eq_zero, IsFractionRing.to_map_eq_zero_iff, Algebra.norm_eq_zero_iff_of_basis b] + exact nonZeroDivisors.coe_ne_zero _)] + +variable (R) in +@[simp] +theorem absNorm_span_singleton [Module.Finite ℚ K] (x : K) : + absNorm (spanSingleton R⁰ x) = |(Algebra.norm ℚ x)| := by + have : IsDomain K := IsFractionRing.isDomain R + obtain ⟨d, ⟨r, hr⟩⟩ := IsLocalization.exists_integer_multiple R⁰ x + rw [absNorm_eq' d (Ideal.span {r})] + · rw [Ideal.absNorm_span_singleton] + simp_rw [Int.cast_natAbs, Int.cast_abs, show ((Algebra.norm ℤ _) : ℚ) = algebraMap ℤ ℚ + (Algebra.norm ℤ _) by rfl, ← Algebra.norm_localization ℤ ℤ⁰ (Sₘ := K) _] + rw [hr, Algebra.smul_def, _root_.map_mul, abs_mul, mul_div_assoc, mul_div_cancel' _ (by + rw [ne_eq, abs_eq_zero, Algebra.norm_eq_zero_iff, IsFractionRing.to_map_eq_zero_iff] + exact nonZeroDivisors.coe_ne_zero _)] + · ext + simp_rw [← SetLike.mem_coe, Submodule.coe_pointwise_smul, Set.mem_smul_set, SetLike.mem_coe, + mem_coe, mem_spanSingleton, Submodule.mem_map, Algebra.linearMap_apply, Submonoid.smul_def, + Ideal.mem_span_singleton', exists_exists_eq_and, _root_.map_mul, hr, ← Algebra.smul_def, + smul_comm (d : R)] + +end IsLocalization diff --git a/Mathlib/RingTheory/FractionalIdeal.lean b/Mathlib/RingTheory/FractionalIdeal/Operations.lean similarity index 62% rename from Mathlib/RingTheory/FractionalIdeal.lean rename to Mathlib/RingTheory/FractionalIdeal/Operations.lean index 473ec81a78ef3..1f93dee3a7a0b 100644 --- a/Mathlib/RingTheory/FractionalIdeal.lean +++ b/Mathlib/RingTheory/FractionalIdeal/Operations.lean @@ -3,30 +3,15 @@ Copyright (c) 2020 Anne Baanen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen, Filippo A. E. Nuccio -/ -import Mathlib.Algebra.BigOperators.Finprod import Mathlib.RingTheory.IntegralClosure -import Mathlib.RingTheory.Localization.Integer -import Mathlib.RingTheory.Localization.Submodule -import Mathlib.RingTheory.Noetherian -import Mathlib.RingTheory.PrincipalIdealDomain -import Mathlib.Tactic.FieldSimp +import Mathlib.RingTheory.FractionalIdeal.Basic #align_import ring_theory.fractional_ideal from "leanprover-community/mathlib"@"ed90a7d327c3a5caf65a6faf7e8a0d63c4605df7" /-! -# Fractional ideals - -This file defines fractional ideals of an integral domain and proves basic facts about them. +# More operations on fractional ideals ## Main definitions -Let `S` be a submonoid of an integral domain `R`, `P` the localization of `R` at `S`, and `f` the -natural ring hom from `R` to `P`. - * `IsFractional` defines which `R`-submodules of `P` are fractional ideals - * `FractionalIdeal S P` is the type of fractional ideals in `P` - * a coercion `coeIdeal : Ideal R → FractionalIdeal S P` - * `CommSemiring (FractionalIdeal S P)` instance: - the typical ideal operations generalized to fractional ideals - * `Lattice (FractionalIdeal S P)` instance * `map` is the pushforward of a fractional ideal along an algebra morphism Let `K` be the localization of `R` at `R⁰ = R \ {0}` (i.e. the field of fractions). @@ -34,31 +19,10 @@ Let `K` be the localization of `R` at `R⁰ = R \ {0}` (i.e. the field of fracti * `Div (FractionalIdeal R⁰ K)` instance: the ideal quotient `I / J` (typically written $I : J$, but a `:` operator cannot be defined) -## Main statements +## Main statement - * `mul_left_mono` and `mul_right_mono` state that ideal multiplication is monotone - * `mul_div_self_cancel_iff` states that `1 / I` is the inverse of `I` if one exists * `isNoetherian` states that every fractional ideal of a noetherian integral domain is noetherian -## Implementation notes - -Fractional ideals are considered equal when they contain the same elements, -independent of the denominator `a : R` such that `a I ⊆ R`. -Thus, we define `FractionalIdeal` to be the subtype of the predicate `IsFractional`, -instead of having `FractionalIdeal` be a structure of which `a` is a field. - -Most definitions in this file specialize operations from submodules to fractional ideals, -proving that the result of this operation is fractional if the input is fractional. -Exceptions to this rule are defining `(+) := (⊔)` and `⊥ := 0`, -in order to re-use their respective proof terms. -We can still use `simp` to show `↑I + ↑J = ↑(I + J)` and `↑⊥ = ↑0`. - -Many results in fact do not need that `P` is a localization, only that `P` is an -`R`-algebra. We omit the `IsLocalization` parameter whenever this is practical. -Similarly, we don't assume that the localization is a field until we need it to -define ideal quotients. When this assumption is needed, we replace `S` with `R⁰`, -making the localization a field. - ## References * https://en.wikipedia.org/wiki/Fractional_ideal @@ -69,640 +33,17 @@ fractional ideal, fractional ideals, invertible ideal -/ -open IsLocalization - -open Pointwise - -open nonZeroDivisors - -section Defs - -variable {R : Type*} [CommRing R] {S : Submonoid R} {P : Type*} [CommRing P] - -variable [Algebra R P] - -variable (S) - -/-- A submodule `I` is a fractional ideal if `a I ⊆ R` for some `a ≠ 0`. -/ -def IsFractional (I : Submodule R P) := - ∃ a ∈ S, ∀ b ∈ I, IsInteger R (a • b) -#align is_fractional IsFractional - -variable (P) - -/-- The fractional ideals of a domain `R` are ideals of `R` divided by some `a ∈ R`. - -More precisely, let `P` be a localization of `R` at some submonoid `S`, -then a fractional ideal `I ⊆ P` is an `R`-submodule of `P`, -such that there is a nonzero `a : R` with `a I ⊆ R`. --/ -def FractionalIdeal := - { I : Submodule R P // IsFractional S I } -#align fractional_ideal FractionalIdeal - -end Defs +open IsLocalization Pointwise nonZeroDivisors namespace FractionalIdeal -open Set - -open Submodule +open Set Submodule variable {R : Type*} [CommRing R] {S : Submonoid R} {P : Type*} [CommRing P] variable [Algebra R P] [loc : IsLocalization S P] -/-- Map a fractional ideal `I` to a submodule by forgetting that `∃ a, a I ⊆ R`. - -This implements the coercion `FractionalIdeal S P → Submodule R P`. --/ -@[coe] -def coeToSubmodule (I : FractionalIdeal S P) : Submodule R P := - I.val - -/-- Map a fractional ideal `I` to a submodule by forgetting that `∃ a, a I ⊆ R`. - -This coercion is typically called `coeToSubmodule` in lemma names -(or `coe` when the coercion is clear from the context), -not to be confused with `IsLocalization.coeSubmodule : Ideal R → Submodule R P` -(which we use to define `coe : Ideal R → FractionalIdeal S P`). --/ -instance : CoeOut (FractionalIdeal S P) (Submodule R P) := - ⟨coeToSubmodule⟩ - -protected theorem isFractional (I : FractionalIdeal S P) : IsFractional S (I : Submodule R P) := - I.prop -#align fractional_ideal.is_fractional FractionalIdeal.isFractional - -section SetLike - -instance : SetLike (FractionalIdeal S P) P where - coe I := ↑(I : Submodule R P) - coe_injective' := SetLike.coe_injective.comp Subtype.coe_injective - -@[simp] -theorem mem_coe {I : FractionalIdeal S P} {x : P} : x ∈ (I : Submodule R P) ↔ x ∈ I := - Iff.rfl -#align fractional_ideal.mem_coe FractionalIdeal.mem_coe - -@[ext] -theorem ext {I J : FractionalIdeal S P} : (∀ x, x ∈ I ↔ x ∈ J) → I = J := - SetLike.ext -#align fractional_ideal.ext FractionalIdeal.ext - -/-- Copy of a `FractionalIdeal` with a new underlying set equal to the old one. -Useful to fix definitional equalities. -/ -protected def copy (p : FractionalIdeal S P) (s : Set P) (hs : s = ↑p) : FractionalIdeal S P := - ⟨Submodule.copy p s hs, by - convert p.isFractional - ext - simp only [hs] - rfl⟩ -#align fractional_ideal.copy FractionalIdeal.copy - -@[simp] -theorem coe_copy (p : FractionalIdeal S P) (s : Set P) (hs : s = ↑p) : ↑(p.copy s hs) = s := - rfl -#align fractional_ideal.coe_copy FractionalIdeal.coe_copy - -theorem coe_eq (p : FractionalIdeal S P) (s : Set P) (hs : s = ↑p) : p.copy s hs = p := - SetLike.coe_injective hs -#align fractional_ideal.coe_eq FractionalIdeal.coe_eq - -end SetLike - --- Porting note: this seems to be needed a lot more than in Lean 3 -@[simp] -theorem val_eq_coe (I : FractionalIdeal S P) : I.val = I := - rfl -#align fractional_ideal.val_eq_coe FractionalIdeal.val_eq_coe - --- Porting note: had to rephrase this to make it clear to `simp` what was going on. -@[simp, norm_cast] -theorem coe_mk (I : Submodule R P) (hI : IsFractional S I) : - coeToSubmodule ⟨I, hI⟩ = I := - rfl -#align fractional_ideal.coe_mk FractionalIdeal.coe_mk - --- Porting note: added this lemma because Lean can't see through the composition of coercions. -theorem coeToSet_coeToSubmodule (I : FractionalIdeal S P) : - ((I : Submodule R P) : Set P) = I := - rfl - -/-! Transfer instances from `Submodule R P` to `FractionalIdeal S P`. -/ - -instance (I : FractionalIdeal S P) : Module R I := - Submodule.module (I : Submodule R P) - -theorem coeToSubmodule_injective : - Function.Injective (fun (I : FractionalIdeal S P) ↦ (I : Submodule R P)) := - Subtype.coe_injective -#align fractional_ideal.coe_to_submodule_injective FractionalIdeal.coeToSubmodule_injective - -theorem coeToSubmodule_inj {I J : FractionalIdeal S P} : (I : Submodule R P) = J ↔ I = J := - coeToSubmodule_injective.eq_iff -#align fractional_ideal.coe_to_submodule_inj FractionalIdeal.coeToSubmodule_inj - -theorem isFractional_of_le_one (I : Submodule R P) (h : I ≤ 1) : IsFractional S I := by - use 1, S.one_mem - intro b hb - rw [one_smul] - obtain ⟨b', b'_mem, rfl⟩ := h hb - exact Set.mem_range_self b' -#align fractional_ideal.is_fractional_of_le_one FractionalIdeal.isFractional_of_le_one - -theorem isFractional_of_le {I : Submodule R P} {J : FractionalIdeal S P} (hIJ : I ≤ J) : - IsFractional S I := by - obtain ⟨a, a_mem, ha⟩ := J.isFractional - use a, a_mem - intro b b_mem - exact ha b (hIJ b_mem) -#align fractional_ideal.is_fractional_of_le FractionalIdeal.isFractional_of_le - -/-- Map an ideal `I` to a fractional ideal by forgetting `I` is integral. - -This is the function that implements the coercion `Ideal R → FractionalIdeal S P`. -/ -@[coe] -def coeIdeal (I : Ideal R) : FractionalIdeal S P := - ⟨coeSubmodule P I, - isFractional_of_le_one _ <| by simpa using coeSubmodule_mono P (le_top : I ≤ ⊤)⟩ - --- Is a `CoeTC` rather than `Coe` to speed up failing inference, see library note [use has_coe_t] -/-- Map an ideal `I` to a fractional ideal by forgetting `I` is integral. - -This is a bundled version of `IsLocalization.coeSubmodule : Ideal R → Submodule R P`, -which is not to be confused with the `coe : FractionalIdeal S P → Submodule R P`, -also called `coeToSubmodule` in theorem names. - -This map is available as a ring hom, called `FractionalIdeal.coeIdealHom`. --/ -instance : CoeTC (Ideal R) (FractionalIdeal S P) := - ⟨fun I => coeIdeal I⟩ - -@[simp, norm_cast] -theorem coe_coeIdeal (I : Ideal R) : - ((I : FractionalIdeal S P) : Submodule R P) = coeSubmodule P I := - rfl -#align fractional_ideal.coe_coe_ideal FractionalIdeal.coe_coeIdeal - -variable (S) - -@[simp] -theorem mem_coeIdeal {x : P} {I : Ideal R} : - x ∈ (I : FractionalIdeal S P) ↔ ∃ x', x' ∈ I ∧ algebraMap R P x' = x := - mem_coeSubmodule _ _ -#align fractional_ideal.mem_coe_ideal FractionalIdeal.mem_coeIdeal - -theorem mem_coeIdeal_of_mem {x : R} {I : Ideal R} (hx : x ∈ I) : - algebraMap R P x ∈ (I : FractionalIdeal S P) := - (mem_coeIdeal S).mpr ⟨x, hx, rfl⟩ -#align fractional_ideal.mem_coe_ideal_of_mem FractionalIdeal.mem_coeIdeal_of_mem - -theorem coeIdeal_le_coeIdeal' [IsLocalization S P] (h : S ≤ nonZeroDivisors R) {I J : Ideal R} : - (I : FractionalIdeal S P) ≤ J ↔ I ≤ J := - coeSubmodule_le_coeSubmodule h -#align fractional_ideal.coe_ideal_le_coe_ideal' FractionalIdeal.coeIdeal_le_coeIdeal' - -@[simp] -theorem coeIdeal_le_coeIdeal (K : Type*) [CommRing K] [Algebra R K] [IsFractionRing R K] - {I J : Ideal R} : (I : FractionalIdeal R⁰ K) ≤ J ↔ I ≤ J := - IsFractionRing.coeSubmodule_le_coeSubmodule -#align fractional_ideal.coe_ideal_le_coe_ideal FractionalIdeal.coeIdeal_le_coeIdeal - -instance : Zero (FractionalIdeal S P) := - ⟨(0 : Ideal R)⟩ - -@[simp] -theorem mem_zero_iff {x : P} : x ∈ (0 : FractionalIdeal S P) ↔ x = 0 := - ⟨fun ⟨x', x'_mem_zero, x'_eq_x⟩ => by - have x'_eq_zero : x' = 0 := x'_mem_zero - simp [x'_eq_x.symm, x'_eq_zero], fun hx => ⟨0, rfl, by simp [hx]⟩⟩ -#align fractional_ideal.mem_zero_iff FractionalIdeal.mem_zero_iff - -variable {S} - -@[simp, norm_cast] -theorem coe_zero : ↑(0 : FractionalIdeal S P) = (⊥ : Submodule R P) := - Submodule.ext fun _ => mem_zero_iff S -#align fractional_ideal.coe_zero FractionalIdeal.coe_zero - -@[simp, norm_cast] -theorem coeIdeal_bot : ((⊥ : Ideal R) : FractionalIdeal S P) = 0 := - rfl -#align fractional_ideal.coe_ideal_bot FractionalIdeal.coeIdeal_bot - -variable (P) - -@[simp] -theorem exists_mem_algebraMap_eq {x : R} {I : Ideal R} (h : S ≤ nonZeroDivisors R) : - (∃ x', x' ∈ I ∧ algebraMap R P x' = algebraMap R P x) ↔ x ∈ I := - ⟨fun ⟨_, hx', Eq⟩ => IsLocalization.injective _ h Eq ▸ hx', fun h => ⟨x, h, rfl⟩⟩ -#align fractional_ideal.exists_mem_to_map_eq FractionalIdeal.exists_mem_algebraMap_eq - -variable {P} - -theorem coeIdeal_injective' (h : S ≤ nonZeroDivisors R) : - Function.Injective (fun (I : Ideal R) ↦ (I : FractionalIdeal S P)) := fun _ _ h' => - ((coeIdeal_le_coeIdeal' S h).mp h'.le).antisymm ((coeIdeal_le_coeIdeal' S h).mp - h'.ge) -#align fractional_ideal.coe_ideal_injective' FractionalIdeal.coeIdeal_injective' - -theorem coeIdeal_inj' (h : S ≤ nonZeroDivisors R) {I J : Ideal R} : - (I : FractionalIdeal S P) = J ↔ I = J := - (coeIdeal_injective' h).eq_iff -#align fractional_ideal.coe_ideal_inj' FractionalIdeal.coeIdeal_inj' - --- Porting note: doesn't need to be @[simp] because it can be proved by coeIdeal_eq_zero -theorem coeIdeal_eq_zero' {I : Ideal R} (h : S ≤ nonZeroDivisors R) : - (I : FractionalIdeal S P) = 0 ↔ I = (⊥ : Ideal R) := - coeIdeal_inj' h -#align fractional_ideal.coe_ideal_eq_zero' FractionalIdeal.coeIdeal_eq_zero' - -theorem coeIdeal_ne_zero' {I : Ideal R} (h : S ≤ nonZeroDivisors R) : - (I : FractionalIdeal S P) ≠ 0 ↔ I ≠ (⊥ : Ideal R) := - not_iff_not.mpr <| coeIdeal_eq_zero' h -#align fractional_ideal.coe_ideal_ne_zero' FractionalIdeal.coeIdeal_ne_zero' - -theorem coeToSubmodule_eq_bot {I : FractionalIdeal S P} : (I : Submodule R P) = ⊥ ↔ I = 0 := - ⟨fun h => coeToSubmodule_injective (by simp [h]), fun h => by simp [h]⟩ -#align fractional_ideal.coe_to_submodule_eq_bot FractionalIdeal.coeToSubmodule_eq_bot - -theorem coeToSubmodule_ne_bot {I : FractionalIdeal S P} : ↑I ≠ (⊥ : Submodule R P) ↔ I ≠ 0 := - not_iff_not.mpr coeToSubmodule_eq_bot -#align fractional_ideal.coe_to_submodule_ne_bot FractionalIdeal.coeToSubmodule_ne_bot - -instance : Inhabited (FractionalIdeal S P) := - ⟨0⟩ - -instance : One (FractionalIdeal S P) := - ⟨(⊤ : Ideal R)⟩ - -variable (S) - -@[simp, norm_cast] -theorem coeIdeal_top : ((⊤ : Ideal R) : FractionalIdeal S P) = 1 := - rfl -#align fractional_ideal.coe_ideal_top FractionalIdeal.coeIdeal_top - -theorem mem_one_iff {x : P} : x ∈ (1 : FractionalIdeal S P) ↔ ∃ x' : R, algebraMap R P x' = x := - Iff.intro (fun ⟨x', _, h⟩ => ⟨x', h⟩) fun ⟨x', h⟩ => ⟨x', ⟨⟩, h⟩ -#align fractional_ideal.mem_one_iff FractionalIdeal.mem_one_iff - -theorem coe_mem_one (x : R) : algebraMap R P x ∈ (1 : FractionalIdeal S P) := - (mem_one_iff S).mpr ⟨x, rfl⟩ -#align fractional_ideal.coe_mem_one FractionalIdeal.coe_mem_one - -theorem one_mem_one : (1 : P) ∈ (1 : FractionalIdeal S P) := - (mem_one_iff S).mpr ⟨1, RingHom.map_one _⟩ -#align fractional_ideal.one_mem_one FractionalIdeal.one_mem_one - -variable {S} - -/-- `(1 : FractionalIdeal S P)` is defined as the R-submodule `f(R) ≤ P`. - -However, this is not definitionally equal to `1 : Submodule R P`, -which is proved in the actual `simp` lemma `coe_one`. -/ -theorem coe_one_eq_coeSubmodule_top : ↑(1 : FractionalIdeal S P) = coeSubmodule P (⊤ : Ideal R) := - rfl -#align fractional_ideal.coe_one_eq_coe_submodule_top FractionalIdeal.coe_one_eq_coeSubmodule_top - -@[simp, norm_cast] -theorem coe_one : (↑(1 : FractionalIdeal S P) : Submodule R P) = 1 := by - rw [coe_one_eq_coeSubmodule_top, coeSubmodule_top] -#align fractional_ideal.coe_one FractionalIdeal.coe_one - -section Lattice - -/-! -### `Lattice` section - -Defines the order on fractional ideals as inclusion of their underlying sets, -and ports the lattice structure on submodules to fractional ideals. --/ - - -@[simp] -theorem coe_le_coe {I J : FractionalIdeal S P} : - (I : Submodule R P) ≤ (J : Submodule R P) ↔ I ≤ J := - Iff.rfl -#align fractional_ideal.coe_le_coe FractionalIdeal.coe_le_coe - -theorem zero_le (I : FractionalIdeal S P) : 0 ≤ I := by - intro x hx - -- Porting note: changed the proof from convert; simp into rw; exact - rw [(mem_zero_iff _).mp hx] - exact zero_mem (I : Submodule R P) -#align fractional_ideal.zero_le FractionalIdeal.zero_le - -instance orderBot : OrderBot (FractionalIdeal S P) where - bot := 0 - bot_le := zero_le -#align fractional_ideal.order_bot FractionalIdeal.orderBot - -@[simp] -theorem bot_eq_zero : (⊥ : FractionalIdeal S P) = 0 := - rfl -#align fractional_ideal.bot_eq_zero FractionalIdeal.bot_eq_zero - -@[simp] -theorem le_zero_iff {I : FractionalIdeal S P} : I ≤ 0 ↔ I = 0 := - le_bot_iff -#align fractional_ideal.le_zero_iff FractionalIdeal.le_zero_iff - -theorem eq_zero_iff {I : FractionalIdeal S P} : I = 0 ↔ ∀ x ∈ I, x = (0 : P) := - ⟨fun h x hx => by simpa [h, mem_zero_iff] using hx, fun h => - le_bot_iff.mp fun x hx => (mem_zero_iff S).mpr (h x hx)⟩ -#align fractional_ideal.eq_zero_iff FractionalIdeal.eq_zero_iff - -theorem _root_.IsFractional.sup {I J : Submodule R P} : - IsFractional S I → IsFractional S J → IsFractional S (I ⊔ J) - | ⟨aI, haI, hI⟩, ⟨aJ, haJ, hJ⟩ => - ⟨aI * aJ, S.mul_mem haI haJ, fun b hb => by - rcases mem_sup.mp hb with ⟨bI, hbI, bJ, hbJ, rfl⟩ - rw [smul_add] - apply isInteger_add - · rw [mul_smul, smul_comm] - exact isInteger_smul (hI bI hbI) - · rw [mul_smul] - exact isInteger_smul (hJ bJ hbJ)⟩ -#align is_fractional.sup IsFractional.sup - -theorem _root_.IsFractional.inf_right {I : Submodule R P} : - IsFractional S I → ∀ J, IsFractional S (I ⊓ J) - | ⟨aI, haI, hI⟩, J => - ⟨aI, haI, fun b hb => by - rcases mem_inf.mp hb with ⟨hbI, _⟩ - exact hI b hbI⟩ -#align is_fractional.inf_right IsFractional.inf_right - -instance : Inf (FractionalIdeal S P) := - ⟨fun I J => ⟨I ⊓ J, I.isFractional.inf_right J⟩⟩ - -@[simp, norm_cast] -theorem coe_inf (I J : FractionalIdeal S P) : ↑(I ⊓ J) = (I ⊓ J : Submodule R P) := - rfl -#align fractional_ideal.coe_inf FractionalIdeal.coe_inf - -instance : Sup (FractionalIdeal S P) := - ⟨fun I J => ⟨I ⊔ J, I.isFractional.sup J.isFractional⟩⟩ - -@[norm_cast] -theorem coe_sup (I J : FractionalIdeal S P) : ↑(I ⊔ J) = (I ⊔ J : Submodule R P) := - rfl -#align fractional_ideal.coe_sup FractionalIdeal.coe_sup - -instance lattice : Lattice (FractionalIdeal S P) := - Function.Injective.lattice _ Subtype.coe_injective coe_sup coe_inf -#align fractional_ideal.lattice FractionalIdeal.lattice - -instance : SemilatticeSup (FractionalIdeal S P) := - { FractionalIdeal.lattice with } - -end Lattice - -section Semiring - -instance : Add (FractionalIdeal S P) := - ⟨(· ⊔ ·)⟩ - -@[simp] -theorem sup_eq_add (I J : FractionalIdeal S P) : I ⊔ J = I + J := - rfl -#align fractional_ideal.sup_eq_add FractionalIdeal.sup_eq_add - -@[simp, norm_cast] -theorem coe_add (I J : FractionalIdeal S P) : (↑(I + J) : Submodule R P) = I + J := - rfl -#align fractional_ideal.coe_add FractionalIdeal.coe_add - -@[simp, norm_cast] -theorem coeIdeal_sup (I J : Ideal R) : ↑(I ⊔ J) = (I + J : FractionalIdeal S P) := - coeToSubmodule_injective <| coeSubmodule_sup _ _ _ -#align fractional_ideal.coe_ideal_sup FractionalIdeal.coeIdeal_sup - -theorem _root_.IsFractional.nsmul {I : Submodule R P} : - ∀ n : ℕ, IsFractional S I → IsFractional S (n • I : Submodule R P) - | 0, _ => by - rw [zero_smul] - convert ((0 : Ideal R) : FractionalIdeal S P).isFractional - simp - | n + 1, h => by - rw [succ_nsmul] - exact h.sup (IsFractional.nsmul n h) -#align is_fractional.nsmul IsFractional.nsmul - -instance : SMul ℕ (FractionalIdeal S P) where smul n I := ⟨n • ↑I, I.isFractional.nsmul n⟩ - -@[norm_cast] -theorem coe_nsmul (n : ℕ) (I : FractionalIdeal S P) : - (↑(n • I) : Submodule R P) = n • (I : Submodule R P) := - rfl -#align fractional_ideal.coe_nsmul FractionalIdeal.coe_nsmul - -theorem _root_.IsFractional.mul {I J : Submodule R P} : - IsFractional S I → IsFractional S J → IsFractional S (I * J : Submodule R P) - | ⟨aI, haI, hI⟩, ⟨aJ, haJ, hJ⟩ => - ⟨aI * aJ, S.mul_mem haI haJ, fun b hb => by - refine Submodule.mul_induction_on hb ?_ ?_ - · intro m hm n hn - obtain ⟨n', hn'⟩ := hJ n hn - rw [mul_smul, mul_comm m, ← smul_mul_assoc, ← hn', ← Algebra.smul_def] - apply hI - exact Submodule.smul_mem _ _ hm - · intro x y hx hy - rw [smul_add] - apply isInteger_add hx hy⟩ -#align is_fractional.mul IsFractional.mul - -theorem _root_.IsFractional.pow {I : Submodule R P} (h : IsFractional S I) : - ∀ n : ℕ, IsFractional S (I ^ n : Submodule R P) - | 0 => isFractional_of_le_one _ (pow_zero _).le - | n + 1 => (pow_succ I n).symm ▸ h.mul (IsFractional.pow h n) -#align is_fractional.pow IsFractional.pow - -/-- `FractionalIdeal.mul` is the product of two fractional ideals, -used to define the `Mul` instance. - -This is only an auxiliary definition: the preferred way of writing `I.mul J` is `I * J`. - -Elaborated terms involving `FractionalIdeal` tend to grow quite large, -so by making definitions irreducible, we hope to avoid deep unfolds. --/ -irreducible_def mul (lemma := mul_def') (I J : FractionalIdeal S P) : FractionalIdeal S P := - ⟨I * J, I.isFractional.mul J.isFractional⟩ -#align fractional_ideal.mul FractionalIdeal.mul - --- local attribute [semireducible] mul -instance : Mul (FractionalIdeal S P) := - ⟨fun I J => mul I J⟩ - -@[simp] -theorem mul_eq_mul (I J : FractionalIdeal S P) : mul I J = I * J := - rfl -#align fractional_ideal.mul_eq_mul FractionalIdeal.mul_eq_mul - -theorem mul_def (I J : FractionalIdeal S P) : I * J = ⟨I * J, I.isFractional.mul J.isFractional⟩ := - by simp only [← mul_eq_mul, mul] -#align fractional_ideal.mul_def FractionalIdeal.mul_def - -@[simp, norm_cast] -theorem coe_mul (I J : FractionalIdeal S P) : (↑(I * J) : Submodule R P) = I * J := by - simp only [mul_def, coe_mk] -#align fractional_ideal.coe_mul FractionalIdeal.coe_mul - -@[simp, norm_cast] -theorem coeIdeal_mul (I J : Ideal R) : (↑(I * J) : FractionalIdeal S P) = I * J := by - simp only [mul_def] - exact coeToSubmodule_injective (coeSubmodule_mul _ _ _) -#align fractional_ideal.coe_ideal_mul FractionalIdeal.coeIdeal_mul - -theorem mul_left_mono (I : FractionalIdeal S P) : Monotone (I * ·) := by - intro J J' h - simp only [mul_def] - exact mul_le.mpr fun x hx y hy => mul_mem_mul hx (h hy) -#align fractional_ideal.mul_left_mono FractionalIdeal.mul_left_mono - -theorem mul_right_mono (I : FractionalIdeal S P) : Monotone fun J => J * I := by - intro J J' h - simp only [mul_def] - exact mul_le.mpr fun x hx y hy => mul_mem_mul (h hx) hy -#align fractional_ideal.mul_right_mono FractionalIdeal.mul_right_mono - -theorem mul_mem_mul {I J : FractionalIdeal S P} {i j : P} (hi : i ∈ I) (hj : j ∈ J) : - i * j ∈ I * J := by - simp only [mul_def] - exact Submodule.mul_mem_mul hi hj -#align fractional_ideal.mul_mem_mul FractionalIdeal.mul_mem_mul - -theorem mul_le {I J K : FractionalIdeal S P} : I * J ≤ K ↔ ∀ i ∈ I, ∀ j ∈ J, i * j ∈ K := by - simp only [mul_def] - exact Submodule.mul_le -#align fractional_ideal.mul_le FractionalIdeal.mul_le - -instance : Pow (FractionalIdeal S P) ℕ := - ⟨fun I n => ⟨(I : Submodule R P) ^ n, I.isFractional.pow n⟩⟩ - -@[simp, norm_cast] -theorem coe_pow (I : FractionalIdeal S P) (n : ℕ) : ↑(I ^ n) = (I : Submodule R P) ^ n := - rfl -#align fractional_ideal.coe_pow FractionalIdeal.coe_pow - -@[elab_as_elim] -protected theorem mul_induction_on {I J : FractionalIdeal S P} {C : P → Prop} {r : P} - (hr : r ∈ I * J) (hm : ∀ i ∈ I, ∀ j ∈ J, C (i * j)) (ha : ∀ x y, C x → C y → C (x + y)) : - C r := by - simp only [mul_def] at hr - exact Submodule.mul_induction_on hr hm ha -#align fractional_ideal.mul_induction_on FractionalIdeal.mul_induction_on - -instance : NatCast (FractionalIdeal S P) := - ⟨Nat.unaryCast⟩ - -theorem coe_nat_cast (n : ℕ) : ((n : FractionalIdeal S P) : Submodule R P) = n := - show ((n.unaryCast : FractionalIdeal S P) : Submodule R P) = n - by induction n <;> simp [*, Nat.unaryCast] -#align fractional_ideal.coe_nat_cast FractionalIdeal.coe_nat_cast - -instance commSemiring : CommSemiring (FractionalIdeal S P) := - Function.Injective.commSemiring _ Subtype.coe_injective coe_zero coe_one coe_add coe_mul - (fun _ _ => coe_nsmul _ _) coe_pow coe_nat_cast - -variable (S P) - -/-- `FractionalIdeal.coeToSubmodule` as a bundled `RingHom`. -/ -@[simps] -def coeSubmoduleHom : FractionalIdeal S P →+* Submodule R P where - toFun := coeToSubmodule - map_one' := coe_one - map_mul' := coe_mul - map_zero' := coe_zero (S := S) - map_add' := coe_add -#align fractional_ideal.coe_submodule_hom FractionalIdeal.coeSubmoduleHom - -variable {S P} - -section Order - -theorem add_le_add_left {I J : FractionalIdeal S P} (hIJ : I ≤ J) (J' : FractionalIdeal S P) : - J' + I ≤ J' + J := - sup_le_sup_left hIJ J' -#align fractional_ideal.add_le_add_left FractionalIdeal.add_le_add_left - -theorem mul_le_mul_left {I J : FractionalIdeal S P} (hIJ : I ≤ J) (J' : FractionalIdeal S P) : - J' * I ≤ J' * J := - mul_le.mpr fun _ hk _ hj => mul_mem_mul hk (hIJ hj) -#align fractional_ideal.mul_le_mul_left FractionalIdeal.mul_le_mul_left - -theorem le_self_mul_self {I : FractionalIdeal S P} (hI : 1 ≤ I) : I ≤ I * I := by - convert mul_left_mono I hI - exact (mul_one I).symm -#align fractional_ideal.le_self_mul_self FractionalIdeal.le_self_mul_self - -theorem mul_self_le_self {I : FractionalIdeal S P} (hI : I ≤ 1) : I * I ≤ I := by - convert mul_left_mono I hI - exact (mul_one I).symm -#align fractional_ideal.mul_self_le_self FractionalIdeal.mul_self_le_self - -theorem coeIdeal_le_one {I : Ideal R} : (I : FractionalIdeal S P) ≤ 1 := fun _ hx => - let ⟨y, _, hy⟩ := (mem_coeIdeal S).mp hx - (mem_one_iff S).mpr ⟨y, hy⟩ -#align fractional_ideal.coe_ideal_le_one FractionalIdeal.coeIdeal_le_one - -theorem le_one_iff_exists_coeIdeal {J : FractionalIdeal S P} : - J ≤ (1 : FractionalIdeal S P) ↔ ∃ I : Ideal R, ↑I = J := by - constructor - · intro hJ - refine' ⟨⟨⟨⟨{ x : R | algebraMap R P x ∈ J }, _⟩, _⟩, _⟩, _⟩ - · intro a b ha hb - rw [mem_setOf, RingHom.map_add] - exact J.val.add_mem ha hb - · rw [mem_setOf, RingHom.map_zero] - exact J.val.zero_mem - · intro c x hx - rw [smul_eq_mul, mem_setOf, RingHom.map_mul, ← Algebra.smul_def] - exact J.val.smul_mem c hx - · ext x - constructor - · rintro ⟨y, hy, eq_y⟩ - rwa [← eq_y] - · intro hx - obtain ⟨y, rfl⟩ := (mem_one_iff S).mp (hJ hx) - exact mem_setOf.mpr ⟨y, hx, rfl⟩ - · rintro ⟨I, hI⟩ - rw [← hI] - apply coeIdeal_le_one -#align fractional_ideal.le_one_iff_exists_coe_ideal FractionalIdeal.le_one_iff_exists_coeIdeal - -@[simp] -theorem one_le {I : FractionalIdeal S P} : 1 ≤ I ↔ (1 : P) ∈ I := by - rw [← coe_le_coe, coe_one, Submodule.one_le, mem_coe] -#align fractional_ideal.one_le FractionalIdeal.one_le - -variable (S P) - -/-- `coeIdealHom (S : Submonoid R) P` is `(↑) : Ideal R → FractionalIdeal S P` as a ring hom -/ -@[simps] -def coeIdealHom : Ideal R →+* FractionalIdeal S P where - toFun := coeIdeal - map_add' := coeIdeal_sup - map_mul' := coeIdeal_mul - map_one' := by rw [Ideal.one_eq_top, coeIdeal_top] - map_zero' := coeIdeal_bot -#align fractional_ideal.coe_ideal_hom FractionalIdeal.coeIdealHom - -theorem coeIdeal_pow (I : Ideal R) (n : ℕ) : ↑(I ^ n) = (I : FractionalIdeal S P) ^ n := - (coeIdealHom S P).map_pow _ n -#align fractional_ideal.coe_ideal_pow FractionalIdeal.coeIdeal_pow - -open BigOperators - -theorem coeIdeal_finprod [IsLocalization S P] {α : Sort*} {f : α → Ideal R} - (hS : S ≤ nonZeroDivisors R) : - ((∏ᶠ a : α, f a : Ideal R) : FractionalIdeal S P) = ∏ᶠ a : α, (f a : FractionalIdeal S P) := - MonoidHom.map_finprod_of_injective (coeIdealHom S P).toMonoidHom (coeIdeal_injective' hS) f -#align fractional_ideal.coe_ideal_finprod FractionalIdeal.coeIdeal_finprod - -end Order +section variable {P' : Type*} [CommRing P'] [Algebra R P'] [loc' : IsLocalization S P'] @@ -947,7 +288,7 @@ theorem canonicalEquiv_self : canonicalEquiv S P P = RingEquiv.refl _ := by exact (canonicalEquiv_symm S P P).symm #align fractional_ideal.canonical_equiv_self FractionalIdeal.canonicalEquiv_self -end Semiring +end section IsFractionRing @@ -1018,6 +359,10 @@ theorem coeIdeal_ne_one {I : Ideal R} : (I : FractionalIdeal R⁰ K) ≠ 1 ↔ I not_iff_not.mpr coeIdeal_eq_one #align fractional_ideal.coe_ideal_ne_one FractionalIdeal.coeIdeal_ne_one +theorem num_eq_zero_iff [Nontrivial R] {I : FractionalIdeal R⁰ K} : I.num = 0 ↔ I = 0 := + ⟨fun h ↦ zero_of_num_eq_bot zero_not_mem_nonZeroDivisors h, + fun h ↦ h ▸ num_zero_eq (IsFractionRing.injective R K)⟩ + end IsFractionRing section Quotient @@ -1228,7 +573,7 @@ theorem eq_zero_or_one_of_isField (hF : IsField R₁) (I : FractionalIdeal R₁ end Field -section PrincipalIdealRing +section PrincipalIdeal variable {R₁ : Type*} [CommRing R₁] {K : Type*} [Field K] @@ -1305,6 +650,17 @@ theorem mem_spanSingleton_self (x : P) : x ∈ spanSingleton S x := (mem_spanSingleton S).mpr ⟨1, one_smul _ _⟩ #align fractional_ideal.mem_span_singleton_self FractionalIdeal.mem_spanSingleton_self +/-- A version of `FractionalIdeal.den_mul_self_eq_num` in terms of fractional ideals. -/ +theorem den_mul_self_eq_num' (I : FractionalIdeal S P) : + spanSingleton S (algebraMap R P I.den) * I = I.num := by + apply coeToSubmodule_injective + dsimp only + rw [coe_mul, ← smul_eq_mul, coe_spanSingleton, smul_eq_mul, Submodule.span_singleton_mul] + convert I.den_mul_self_eq_num using 1 + ext + erw [Set.mem_smul_set, Set.mem_smul_set] + simp [Algebra.smul_def] + variable {S} @[simp] @@ -1534,7 +890,14 @@ theorem eq_spanSingleton_mul {x : P} {I J : FractionalIdeal S P} : simp only [le_antisymm_iff, le_spanSingleton_mul_iff, spanSingleton_mul_le_iff] #align fractional_ideal.eq_span_singleton_mul FractionalIdeal.eq_spanSingleton_mul -end PrincipalIdealRing +theorem num_le (I : FractionalIdeal S P) : + (I.num : FractionalIdeal S P) ≤ I := by + rw [← I.den_mul_self_eq_num', spanSingleton_mul_le_iff] + intro _ h + rw [← Algebra.smul_def] + exact Submodule.smul_mem _ _ h + +end PrincipalIdeal variable {R₁ : Type*} [CommRing R₁] diff --git a/Mathlib/RingTheory/HahnSeries.lean b/Mathlib/RingTheory/HahnSeries.lean index 435fb14b91c90..69a8bda3091f6 100644 --- a/Mathlib/RingTheory/HahnSeries.lean +++ b/Mathlib/RingTheory/HahnSeries.lean @@ -7,7 +7,7 @@ import Mathlib.Order.WellFoundedSet import Mathlib.Algebra.BigOperators.Finprod import Mathlib.RingTheory.Valuation.Basic import Mathlib.RingTheory.PowerSeries.Basic -import Mathlib.Data.Finsupp.Pwo +import Mathlib.Data.Finsupp.PWO import Mathlib.Data.Finset.MulAntidiagonal import Mathlib.Algebra.Order.Group.WithTop @@ -63,7 +63,7 @@ noncomputable section @[ext] structure HahnSeries (Γ : Type*) (R : Type*) [PartialOrder Γ] [Zero R] where coeff : Γ → R - isPwo_support' : (Function.support coeff).IsPwo + isPWO_support' : (Function.support coeff).IsPWO #align hahn_series HahnSeries variable {Γ : Type*} {R : Type*} @@ -90,14 +90,14 @@ nonrec def support (x : HahnSeries Γ R) : Set Γ := #align hahn_series.support HahnSeries.support @[simp] -theorem isPwo_support (x : HahnSeries Γ R) : x.support.IsPwo := - x.isPwo_support' -#align hahn_series.is_pwo_support HahnSeries.isPwo_support +theorem isPWO_support (x : HahnSeries Γ R) : x.support.IsPWO := + x.isPWO_support' +#align hahn_series.is_pwo_support HahnSeries.isPWO_support @[simp] -theorem isWf_support (x : HahnSeries Γ R) : x.support.IsWf := - x.isPwo_support.isWf -#align hahn_series.is_wf_support HahnSeries.isWf_support +theorem isWF_support (x : HahnSeries Γ R) : x.support.IsWF := + x.isPWO_support.isWF +#align hahn_series.is_wf_support HahnSeries.isWF_support @[simp] theorem mem_support (x : HahnSeries Γ R) (a : Γ) : a ∈ x.support ↔ x.coeff a ≠ 0 := @@ -106,7 +106,7 @@ theorem mem_support (x : HahnSeries Γ R) (a : Γ) : a ∈ x.support ↔ x.coeff instance : Zero (HahnSeries Γ R) := ⟨{ coeff := 0 - isPwo_support' := by simp }⟩ + isPWO_support' := by simp }⟩ instance : Inhabited (HahnSeries Γ R) := ⟨0⟩ @@ -147,7 +147,7 @@ theorem support_eq_empty_iff {x : HahnSeries Γ R} : x.support = ∅ ↔ x = 0 : def single (a : Γ) : ZeroHom R (HahnSeries Γ R) where toFun r := { coeff := Pi.single a r - isPwo_support' := (Set.isPwo_singleton a).mono Pi.support_single_subset } + isPWO_support' := (Set.isPWO_singleton a).mono Pi.support_single_subset } map_zero' := HahnSeries.ext _ _ (Pi.single_zero _) #align hahn_series.single HahnSeries.single @@ -212,7 +212,7 @@ variable [Zero Γ] /-- The order of a nonzero Hahn series `x` is a minimal element of `Γ` where `x` has a nonzero coefficient, the order of 0 is 0. -/ def order (x : HahnSeries Γ R) : Γ := - if h : x = 0 then 0 else x.isWf_support.min (support_nonempty_iff.2 h) + if h : x = 0 then 0 else x.isWF_support.min (support_nonempty_iff.2 h) #align hahn_series.order HahnSeries.order @[simp] @@ -221,26 +221,26 @@ theorem order_zero : order (0 : HahnSeries Γ R) = 0 := #align hahn_series.order_zero HahnSeries.order_zero theorem order_of_ne {x : HahnSeries Γ R} (hx : x ≠ 0) : - order x = x.isWf_support.min (support_nonempty_iff.2 hx) := + order x = x.isWF_support.min (support_nonempty_iff.2 hx) := dif_neg hx #align hahn_series.order_of_ne HahnSeries.order_of_ne theorem coeff_order_ne_zero {x : HahnSeries Γ R} (hx : x ≠ 0) : x.coeff x.order ≠ 0 := by rw [order_of_ne hx] - exact x.isWf_support.min_mem (support_nonempty_iff.2 hx) + exact x.isWF_support.min_mem (support_nonempty_iff.2 hx) #align hahn_series.coeff_order_ne_zero HahnSeries.coeff_order_ne_zero theorem order_le_of_coeff_ne_zero {Γ} [LinearOrderedCancelAddCommMonoid Γ] {x : HahnSeries Γ R} {g : Γ} (h : x.coeff g ≠ 0) : x.order ≤ g := le_trans (le_of_eq (order_of_ne (ne_zero_of_coeff_ne_zero h))) - (Set.IsWf.min_le _ _ ((mem_support _ _).2 h)) + (Set.IsWF.min_le _ _ ((mem_support _ _).2 h)) #align hahn_series.order_le_of_coeff_ne_zero HahnSeries.order_le_of_coeff_ne_zero @[simp] theorem order_single (h : r ≠ 0) : (single a r).order = a := (order_of_ne (single_ne_zero h)).trans (support_single_subset - ((single a r).isWf_support.min_mem (support_nonempty_iff.2 (single_ne_zero h)))) + ((single a r).isWF_support.min_mem (support_nonempty_iff.2 (single_ne_zero h)))) #align hahn_series.order_single HahnSeries.order_single theorem coeff_eq_zero_of_lt_order {x : HahnSeries Γ R} {i : Γ} (hi : i < x.order) : @@ -250,7 +250,7 @@ theorem coeff_eq_zero_of_lt_order {x : HahnSeries Γ R} {i : Γ} (hi : i < x.ord contrapose! hi rw [← mem_support] at hi rw [order_of_ne hx] - exact Set.IsWf.not_lt_min _ _ hi + exact Set.IsWF.not_lt_min _ _ hi #align hahn_series.coeff_eq_zero_of_lt_order HahnSeries.coeff_eq_zero_of_lt_order end Order @@ -262,8 +262,8 @@ variable {Γ' : Type*} [PartialOrder Γ'] /-- Extends the domain of a `HahnSeries` by an `OrderEmbedding`. -/ def embDomain (f : Γ ↪o Γ') : HahnSeries Γ R → HahnSeries Γ' R := fun x => { coeff := fun b : Γ' => if h : b ∈ f '' x.support then x.coeff (Classical.choose h) else 0 - isPwo_support' := - (x.isPwo_support.image_of_monotone f.monotone).mono fun b hb => by + isPWO_support' := + (x.isPWO_support.image_of_monotone f.monotone).mono fun b hb => by contrapose! hb rw [Function.mem_support, dif_neg hb, Classical.not_not] } #align hahn_series.emb_domain HahnSeries.embDomain @@ -347,7 +347,7 @@ variable [AddMonoid R] instance : Add (HahnSeries Γ R) where add x y := { coeff := x.coeff + y.coeff - isPwo_support' := (x.isPwo_support.union y.isPwo_support).mono (Function.support_add _ _) } + isPWO_support' := (x.isPWO_support.union y.isPWO_support).mono (Function.support_add _ _) } instance : AddMonoid (HahnSeries Γ R) where zero := 0 @@ -379,13 +379,13 @@ theorem support_add_subset {x y : HahnSeries Γ R} : support (x + y) ⊆ support rw [ha.1, ha.2, add_zero] #align hahn_series.support_add_subset HahnSeries.support_add_subset -theorem min_order_le_order_add {Γ} [LinearOrderedCancelAddCommMonoid Γ] {x y : HahnSeries Γ R} +theorem min_order_le_order_add {Γ} [Zero Γ] [LinearOrder Γ] {x y : HahnSeries Γ R} (hxy : x + y ≠ 0) : min x.order y.order ≤ (x + y).order := by by_cases hx : x = 0; · simp [hx] by_cases hy : y = 0; · simp [hy] rw [order_of_ne hx, order_of_ne hy, order_of_ne hxy] - refine' le_of_eq_of_le _ (Set.IsWf.min_le_min_of_subset (support_add_subset (x := x) (y := y))) - exact (Set.IsWf.min_union _ _ _ _).symm + refine' le_of_eq_of_le _ (Set.IsWF.min_le_min_of_subset (support_add_subset (x := x) (y := y))) + exact (Set.IsWF.min_union _ _ _ _).symm #align hahn_series.min_order_le_order_add HahnSeries.min_order_le_order_add /-- `single` as an additive monoid/group homomorphism -/ @@ -436,9 +436,9 @@ instance : AddGroup (HahnSeries Γ R) := { inferInstanceAs (AddMonoid (HahnSeries Γ R)) with neg := fun x => { coeff := fun a => -x.coeff a - isPwo_support' := by + isPWO_support' := by rw [Function.support_neg] - exact x.isPwo_support } + exact x.isPWO_support } add_left_neg := fun x => by ext apply add_left_neg } @@ -490,7 +490,7 @@ variable [PartialOrder Γ] {V : Type*} [Monoid R] [AddMonoid V] [DistribMulActio instance : SMul R (HahnSeries Γ V) := ⟨fun r x => { coeff := r • x.coeff - isPwo_support' := x.isPwo_support.mono (Function.support_smul_subset_right r x.coeff) }⟩ + isPWO_support' := x.isPWO_support.mono (Function.support_smul_subset_right r x.coeff) }⟩ @[simp] theorem smul_coeff {r : R} {x : HahnSeries Γ V} {a : Γ} : (r • x).coeff a = r • x.coeff a := @@ -612,31 +612,31 @@ theorem order_one [MulZeroOneClass R] : order (1 : HahnSeries Γ R) = 0 := by instance [NonUnitalNonAssocSemiring R] : Mul (HahnSeries Γ R) where mul x y := { coeff := fun a => - ∑ ij in addAntidiagonal x.isPwo_support y.isPwo_support a, x.coeff ij.fst * y.coeff ij.snd - isPwo_support' := + ∑ ij in addAntidiagonal x.isPWO_support y.isPWO_support a, x.coeff ij.fst * y.coeff ij.snd + isPWO_support' := haveI h : { a : Γ | - (∑ ij : Γ × Γ in addAntidiagonal x.isPwo_support y.isPwo_support a, + (∑ ij : Γ × Γ in addAntidiagonal x.isPWO_support y.isPWO_support a, x.coeff ij.fst * y.coeff ij.snd) ≠ 0 } ⊆ - { a : Γ | (addAntidiagonal x.isPwo_support y.isPwo_support a).Nonempty } := by + { a : Γ | (addAntidiagonal x.isPWO_support y.isPWO_support a).Nonempty } := by intro a ha contrapose! ha simp [not_nonempty_iff_eq_empty.1 ha] - isPwo_support_addAntidiagonal.mono h } + isPWO_support_addAntidiagonal.mono h } /-@[simp] Porting note: removing simp. RHS is more complicated and it makes linter failures elsewhere-/ theorem mul_coeff [NonUnitalNonAssocSemiring R] {x y : HahnSeries Γ R} {a : Γ} : (x * y).coeff a = - ∑ ij in addAntidiagonal x.isPwo_support y.isPwo_support a, x.coeff ij.fst * y.coeff ij.snd := + ∑ ij in addAntidiagonal x.isPWO_support y.isPWO_support a, x.coeff ij.fst * y.coeff ij.snd := rfl #align hahn_series.mul_coeff HahnSeries.mul_coeff theorem mul_coeff_right' [NonUnitalNonAssocSemiring R] {x y : HahnSeries Γ R} {a : Γ} {s : Set Γ} - (hs : s.IsPwo) (hys : y.support ⊆ s) : + (hs : s.IsPWO) (hys : y.support ⊆ s) : (x * y).coeff a = - ∑ ij in addAntidiagonal x.isPwo_support hs a, x.coeff ij.fst * y.coeff ij.snd := by + ∑ ij in addAntidiagonal x.isPWO_support hs a, x.coeff ij.fst * y.coeff ij.snd := by rw [mul_coeff] apply sum_subset_zero_on_sdiff (addAntidiagonal_mono_right hys) _ fun _ _ => rfl intro b hb @@ -645,9 +645,9 @@ theorem mul_coeff_right' [NonUnitalNonAssocSemiring R] {x y : HahnSeries Γ R} { #align hahn_series.mul_coeff_right' HahnSeries.mul_coeff_right' theorem mul_coeff_left' [NonUnitalNonAssocSemiring R] {x y : HahnSeries Γ R} {a : Γ} {s : Set Γ} - (hs : s.IsPwo) (hxs : x.support ⊆ s) : + (hs : s.IsPWO) (hxs : x.support ⊆ s) : (x * y).coeff a = - ∑ ij in addAntidiagonal hs y.isPwo_support a, x.coeff ij.fst * y.coeff ij.snd := by + ∑ ij in addAntidiagonal hs y.isPWO_support a, x.coeff ij.fst * y.coeff ij.snd := by rw [mul_coeff] apply sum_subset_zero_on_sdiff (addAntidiagonal_mono_left hxs) _ fun _ _ => rfl intro b hb @@ -660,7 +660,7 @@ instance [NonUnitalNonAssocSemiring R] : Distrib (HahnSeries Γ R) := inferInstanceAs (Add (HahnSeries Γ R)) with left_distrib := fun x y z => by ext a - have hwf := y.isPwo_support.union z.isPwo_support + have hwf := y.isPWO_support.union z.isPWO_support rw [mul_coeff_right' hwf, add_coeff, mul_coeff_right' hwf (Set.subset_union_right _ _), mul_coeff_right' hwf (Set.subset_union_left _ _)] · simp only [add_coeff, mul_add, sum_add_distrib] @@ -671,7 +671,7 @@ instance [NonUnitalNonAssocSemiring R] : Distrib (HahnSeries Γ R) := rw [h.1, h.2, add_zero] right_distrib := fun x y z => by ext a - have hwf := x.isPwo_support.union y.isPwo_support + have hwf := x.isPWO_support.union y.isPWO_support rw [mul_coeff_left' hwf, add_coeff, mul_coeff_left' hwf (Set.subset_union_right _ _), mul_coeff_left' hwf (Set.subset_union_left _ _)] · simp only [add_coeff, add_mul, sum_add_distrib] @@ -757,8 +757,8 @@ theorem single_zero_mul_eq_smul [Semiring R] {r : R} {x : HahnSeries Γ R} : theorem support_mul_subset_add_support [NonUnitalNonAssocSemiring R] {x y : HahnSeries Γ R} : support (x * y) ⊆ support x + support y := by apply Set.Subset.trans (fun x hx => _) support_addAntidiagonal_subset_add - · exact x.isPwo_support - · exact y.isPwo_support + · exact x.isPWO_support + · exact y.isPWO_support intro x hx contrapose! hx simp only [not_nonempty_iff_eq_empty, Ne.def, Set.mem_setOf_eq] at hx @@ -777,8 +777,8 @@ theorem mul_coeff_order_add_order {Γ} [LinearOrderedCancelAddCommMonoid Γ] private theorem mul_assoc' [NonUnitalSemiring R] (x y z : HahnSeries Γ R) : x * y * z = x * (y * z) := by ext b - rw [mul_coeff_left' (x.isPwo_support.add y.isPwo_support) support_mul_subset_add_support, - mul_coeff_right' (y.isPwo_support.add z.isPwo_support) support_mul_subset_add_support] + rw [mul_coeff_left' (x.isPWO_support.add y.isPWO_support) support_mul_subset_add_support, + mul_coeff_right' (y.isPWO_support.add z.isPWO_support) support_mul_subset_add_support] simp only [mul_coeff, add_coeff, sum_mul, mul_sum, sum_sigma'] apply Finset.sum_nbij' (fun ⟨⟨_i, j⟩, ⟨k, l⟩⟩ ↦ ⟨(k, l + j), (l, j)⟩) (fun ⟨⟨i, _j⟩, ⟨k, l⟩⟩ ↦ ⟨(i + k, l), (i, k)⟩) <;> @@ -817,7 +817,7 @@ instance [NonUnitalCommSemiring R] : NonUnitalCommSemiring (HahnSeries Γ R) whe mul_comm x y := by ext simp_rw [mul_coeff, mul_comm] - exact Finset.sum_equiv (Equiv.prodComm _ _) (fun _ ↦ swap_mem_addAntidiagonal.symm) $ by simp + exact Finset.sum_equiv (Equiv.prodComm _ _) (fun _ ↦ swap_mem_addAntidiagonal.symm) <| by simp instance [CommSemiring R] : CommSemiring (HahnSeries Γ R) := { inferInstanceAs (NonUnitalCommSemiring (HahnSeries Γ R)), @@ -868,8 +868,8 @@ theorem order_mul {Γ} [LinearOrderedCancelAddCommMonoid Γ] [NonUnitalNonAssocS · apply order_le_of_coeff_ne_zero rw [mul_coeff_order_add_order x y] exact mul_ne_zero (coeff_order_ne_zero hx) (coeff_order_ne_zero hy) - · rw [order_of_ne hx, order_of_ne hy, order_of_ne (mul_ne_zero hx hy), ← Set.IsWf.min_add] - exact Set.IsWf.min_le_min_of_subset support_mul_subset_add_support + · rw [order_of_ne hx, order_of_ne hy, order_of_ne (mul_ne_zero hx hy), ← Set.IsWF.min_add] + exact Set.IsWF.min_le_min_of_subset support_mul_subset_add_support #align hahn_series.order_mul HahnSeries.order_mul @[simp] @@ -972,7 +972,7 @@ theorem embDomain_mul [NonUnitalNonAssocSemiring R] (f : Γ ↪o Γ') simp only [mul_coeff, embDomain_coeff] trans ∑ ij in - (addAntidiagonal x.isPwo_support y.isPwo_support g).map + (addAntidiagonal x.isPWO_support y.isPWO_support g).map (Function.Embedding.prodMap f.toEmbedding f.toEmbedding), (embDomain f x).coeff ij.1 * (embDomain f y).coeff ij.2 · simp @@ -1082,7 +1082,7 @@ variable [Semiring R] @[simps] def toPowerSeries : HahnSeries ℕ R ≃+* PowerSeries R where toFun f := PowerSeries.mk f.coeff - invFun f := ⟨fun n => PowerSeries.coeff R n f, (Nat.lt_wfRel.wf.isWf _).isPwo⟩ + invFun f := ⟨fun n => PowerSeries.coeff R n f, (Nat.lt_wfRel.wf.isWF _).isPWO⟩ left_inv f := by ext simp @@ -1094,9 +1094,9 @@ def toPowerSeries : HahnSeries ℕ R ≃+* PowerSeries R where simp map_mul' f g := by ext n - simp only [PowerSeries.coeff_mul, PowerSeries.coeff_mk, mul_coeff, isPwo_support] + simp only [PowerSeries.coeff_mul, PowerSeries.coeff_mk, mul_coeff, isPWO_support] classical - refine (sum_filter_ne_zero _).symm.trans $ (sum_congr ?_ fun _ _ ↦ rfl).trans $ + refine (sum_filter_ne_zero _).symm.trans <| (sum_congr ?_ fun _ _ ↦ rfl).trans <| sum_filter_ne_zero _ ext m simp only [mem_antidiagonal, mem_addAntidiagonal, and_congr_left_iff, mem_filter, @@ -1195,7 +1195,7 @@ After importing `Algebra.Order.Pi` the ring `HahnSeries (σ → ℕ) R` could be @[simps] def toMvPowerSeries {σ : Type*} [Fintype σ] : HahnSeries (σ →₀ ℕ) R ≃+* MvPowerSeries σ R where toFun f := f.coeff - invFun f := ⟨(f : (σ →₀ ℕ) → R), Finsupp.isPwo _⟩ + invFun f := ⟨(f : (σ →₀ ℕ) → R), Finsupp.isPWO _⟩ left_inv f := by ext simp @@ -1211,7 +1211,7 @@ def toMvPowerSeries {σ : Type*} [Fintype σ] : HahnSeries (σ →₀ ℕ) R ≃ classical change (f * g).coeff n = _ simp_rw [mul_coeff] - refine' (sum_filter_ne_zero _).symm.trans $ (sum_congr _ fun _ _ ↦ rfl).trans $ + refine' (sum_filter_ne_zero _).symm.trans <| (sum_congr _ fun _ _ ↦ rfl).trans <| sum_filter_ne_zero _ ext m simp only [and_congr_left_iff, mem_addAntidiagonal, mem_filter, mem_support, @@ -1298,7 +1298,7 @@ def addVal : AddValuation (HahnSeries Γ R) (WithTop Γ) := · by_cases hy : y = 0 <;> · simp [hx, hy] · by_cases hy : y = 0 · simp [hx, hy] - · simp only [hx, hy, support_nonempty_iff, if_neg, not_false_iff, isWf_support] + · simp only [hx, hy, support_nonempty_iff, if_neg, not_false_iff, isWF_support] by_cases hxy : x + y = 0 · simp [hxy] rw [if_neg hxy, ← WithTop.coe_min, WithTop.coe_le_coe] @@ -1333,9 +1333,9 @@ theorem addVal_le_of_coeff_ne_zero {x : HahnSeries Γ R} {g : Γ} (h : x.coeff g end Valuation -theorem isPwo_iUnion_support_powers [LinearOrderedCancelAddCommMonoid Γ] [Ring R] [IsDomain R] - {x : HahnSeries Γ R} (hx : 0 < addVal Γ R x) : (⋃ n : ℕ, (x ^ n).support).IsPwo := by - apply (x.isWf_support.isPwo.addSubmonoid_closure _).mono _ +theorem isPWO_iUnion_support_powers [LinearOrderedCancelAddCommMonoid Γ] [Ring R] [IsDomain R] + {x : HahnSeries Γ R} (hx : 0 < addVal Γ R x) : (⋃ n : ℕ, (x ^ n).support).IsPWO := by + apply (x.isWF_support.isPWO.addSubmonoid_closure _).mono _ · exact fun g hg => WithTop.coe_le_coe.1 (le_trans (le_of_lt hx) (addVal_le_of_coeff_ne_zero hg)) refine' Set.iUnion_subset fun n => _ induction' n with n ih <;> intro g hn @@ -1344,7 +1344,7 @@ theorem isPwo_iUnion_support_powers [LinearOrderedCancelAddCommMonoid Γ] [Ring exact AddSubmonoid.zero_mem _ · obtain ⟨i, hi, j, hj, rfl⟩ := support_mul_subset_add_support hn exact SetLike.mem_coe.2 (AddSubmonoid.add_mem _ (AddSubmonoid.subset_closure hi) (ih hj)) -#align hahn_series.is_pwo_Union_support_powers HahnSeries.isPwo_iUnion_support_powers +#align hahn_series.is_pwo_Union_support_powers HahnSeries.isPWO_iUnion_support_powers section @@ -1355,7 +1355,7 @@ variable (Γ) (R) [PartialOrder Γ] [AddCommMonoid R] and that only finitely many series are nonzero at any given coefficient. -/ structure SummableFamily (α : Type*) where toFun : α → HahnSeries Γ R - isPwo_iUnion_support' : Set.IsPwo (⋃ a : α, (toFun a).support) + isPWO_iUnion_support' : Set.IsPWO (⋃ a : α, (toFun a).support) finite_co_support' : ∀ g : Γ, { a | (toFun a).coeff g ≠ 0 }.Finite #align hahn_series.summable_family HahnSeries.SummableFamily @@ -1367,13 +1367,13 @@ section AddCommMonoid variable [PartialOrder Γ] [AddCommMonoid R] {α : Type*} -instance : FunLike (SummableFamily Γ R α) α fun _ => HahnSeries Γ R where +instance : FunLike (SummableFamily Γ R α) α (HahnSeries Γ R) where coe := toFun coe_injective' | ⟨_, _, _⟩, ⟨_, _, _⟩, rfl => rfl -theorem isPwo_iUnion_support (s : SummableFamily Γ R α) : Set.IsPwo (⋃ a : α, (s a).support) := - s.isPwo_iUnion_support' -#align hahn_series.summable_family.is_pwo_Union_support HahnSeries.SummableFamily.isPwo_iUnion_support +theorem isPWO_iUnion_support (s : SummableFamily Γ R α) : Set.IsPWO (⋃ a : α, (s a).support) := + s.isPWO_iUnion_support' +#align hahn_series.summable_family.is_pwo_Union_support HahnSeries.SummableFamily.isPWO_iUnion_support theorem finite_co_support (s : SummableFamily Γ R α) (g : Γ) : (Function.support fun a => (s a).coeff g).Finite := @@ -1381,19 +1381,19 @@ theorem finite_co_support (s : SummableFamily Γ R α) (g : Γ) : #align hahn_series.summable_family.finite_co_support HahnSeries.SummableFamily.finite_co_support theorem coe_injective : @Function.Injective (SummableFamily Γ R α) (α → HahnSeries Γ R) (⇑) := - FunLike.coe_injective + DFunLike.coe_injective #align hahn_series.summable_family.coe_injective HahnSeries.SummableFamily.coe_injective @[ext] theorem ext {s t : SummableFamily Γ R α} (h : ∀ a : α, s a = t a) : s = t := - FunLike.ext s t h + DFunLike.ext s t h #align hahn_series.summable_family.ext HahnSeries.SummableFamily.ext instance : Add (SummableFamily Γ R α) := ⟨fun x y => { toFun := x + y - isPwo_iUnion_support' := - (x.isPwo_iUnion_support.union y.isPwo_iUnion_support).mono + isPWO_iUnion_support' := + (x.isPWO_iUnion_support.union y.isPWO_iUnion_support).mono (by rw [← Set.iUnion_union_distrib] exact Set.iUnion_mono fun a => support_add_subset) @@ -1449,8 +1449,8 @@ instance : AddCommMonoid (SummableFamily Γ R α) where /-- The infinite sum of a `SummableFamily` of Hahn series. -/ def hsum (s : SummableFamily Γ R α) : HahnSeries Γ R where coeff g := ∑ᶠ i, (s i).coeff g - isPwo_support' := - s.isPwo_iUnion_support.mono fun g => by + isPWO_support' := + s.isPWO_iUnion_support.mono fun g => by contrapose rw [Set.mem_iUnion, not_exists, Function.mem_support, Classical.not_not] simp_rw [mem_support, Classical.not_not] @@ -1488,9 +1488,9 @@ instance : AddCommGroup (SummableFamily Γ R α) := { inferInstanceAs (AddCommMonoid (SummableFamily Γ R α)) with neg := fun s => { toFun := fun a => -s a - isPwo_iUnion_support' := by + isPWO_iUnion_support' := by simp_rw [support_neg] - exact s.isPwo_iUnion_support' + exact s.isPWO_iUnion_support' finite_co_support' := fun g => by simp only [neg_coeff', Pi.neg_apply, Ne.def, neg_eq_zero] exact s.finite_co_support g } @@ -1525,22 +1525,22 @@ variable [OrderedCancelAddCommMonoid Γ] [Semiring R] {α : Type*} instance : SMul (HahnSeries Γ R) (SummableFamily Γ R α) where smul x s := { toFun := fun a => x * s a - isPwo_iUnion_support' := by - apply (x.isPwo_support.add s.isPwo_iUnion_support).mono + isPWO_iUnion_support' := by + apply (x.isPWO_support.add s.isPWO_iUnion_support).mono refine' Set.Subset.trans (Set.iUnion_mono fun a => support_mul_subset_add_support) _ intro g simp only [Set.mem_iUnion, exists_imp] exact fun a ha => (Set.add_subset_add (Set.Subset.refl _) (Set.subset_iUnion _ a)) ha finite_co_support' := fun g => by refine' - ((addAntidiagonal x.isPwo_support s.isPwo_iUnion_support g).finite_toSet.biUnion' + ((addAntidiagonal x.isPWO_support s.isPWO_iUnion_support g).finite_toSet.biUnion' fun ij _ => _).subset fun a ha => _ · exact fun ij _ => Function.support fun a => (s a).coeff ij.2 · apply s.finite_co_support · obtain ⟨i, hi, j, hj, rfl⟩ := support_mul_subset_add_support ha simp only [exists_prop, Set.mem_iUnion, mem_addAntidiagonal, mul_coeff, mem_support, - isPwo_support, Prod.exists] + isPWO_support, Prod.exists] exact ⟨i, j, mem_coe.2 (mem_addAntidiagonal.2 ⟨hi, Set.mem_iUnion.2 ⟨a, hj⟩, rfl⟩), hj⟩ } @[simp] @@ -1563,7 +1563,7 @@ theorem hsum_smul {x : HahnSeries Γ R} {s : SummableFamily Γ R α} : (x • s) simp only [mul_coeff, hsum_coeff, smul_apply] refine' (Eq.trans (finsum_congr fun a => _) - (finsum_sum_comm (addAntidiagonal x.isPwo_support s.isPwo_iUnion_support g) + (finsum_sum_comm (addAntidiagonal x.isPWO_support s.isPWO_iUnion_support g) (fun i ij => x.coeff (Prod.fst ij) * (s i).coeff ij.snd) _)).trans _ · refine' sum_subset (addAntidiagonal_mono_right @@ -1613,8 +1613,8 @@ variable [PartialOrder Γ] [AddCommMonoid R] {α : Type*} /-- A family with only finitely many nonzero elements is summable. -/ def ofFinsupp (f : α →₀ HahnSeries Γ R) : SummableFamily Γ R α where toFun := f - isPwo_iUnion_support' := by - apply (f.support.isPwo_bUnion.2 fun a _ => (f a).isPwo_support).mono + isPWO_iUnion_support' := by + apply (f.support.isPWO_bUnion.2 fun a _ => (f a).isPWO_support).mono refine' Set.iUnion_subset_iff.2 fun a g hg => _ have haf : a ∈ f.support := by rw [Finsupp.mem_support_iff, ← support_nonempty_iff] @@ -1654,8 +1654,8 @@ variable [PartialOrder Γ] [AddCommMonoid R] {α β : Type*} /-- A summable family can be reindexed by an embedding without changing its sum. -/ def embDomain (s : SummableFamily Γ R α) (f : α ↪ β) : SummableFamily Γ R β where toFun b := if h : b ∈ Set.range f then s (Classical.choose h) else 0 - isPwo_iUnion_support' := by - refine' s.isPwo_iUnion_support.mono (Set.iUnion_subset fun b g h => _) + isPWO_iUnion_support' := by + refine' s.isPWO_iUnion_support.mono (Set.iUnion_subset fun b g h => _) by_cases hb : b ∈ Set.range f · dsimp only at h rw [dif_pos hb] at h @@ -1708,15 +1708,15 @@ variable [LinearOrderedCancelAddCommMonoid Γ] [CommRing R] [IsDomain R] /-- The powers of an element of positive valuation form a summable family. -/ def powers (x : HahnSeries Γ R) (hx : 0 < addVal Γ R x) : SummableFamily Γ R ℕ where toFun n := x ^ n - isPwo_iUnion_support' := isPwo_iUnion_support_powers hx + isPWO_iUnion_support' := isPWO_iUnion_support_powers hx finite_co_support' g := by - have hpwo := isPwo_iUnion_support_powers hx + have hpwo := isPWO_iUnion_support_powers hx by_cases hg : g ∈ ⋃ n : ℕ, { g | (x ^ n).coeff g ≠ 0 } swap; · exact Set.finite_empty.subset fun n hn => hg (Set.mem_iUnion.2 ⟨n, hn⟩) - apply hpwo.isWf.induction hg + apply hpwo.isWF.induction hg intro y ys hy refine' - ((((addAntidiagonal x.isPwo_support hpwo y).finite_toSet.biUnion fun ij hij => + ((((addAntidiagonal x.isPWO_support hpwo y).finite_toSet.biUnion fun ij hij => hy ij.snd _ _).image Nat.succ).union (Set.finite_singleton 0)).subset diff --git a/Mathlib/RingTheory/Ideal/IdempotentFG.lean b/Mathlib/RingTheory/Ideal/IdempotentFG.lean index f78f0f2353333..13dcd5eb4a570 100644 --- a/Mathlib/RingTheory/Ideal/IdempotentFG.lean +++ b/Mathlib/RingTheory/Ideal/IdempotentFG.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro, Kevin Buzzard -/ import Mathlib.Algebra.Ring.Idempotents import Mathlib.RingTheory.Finiteness +import Mathlib.Order.Basic #align_import ring_theory.ideal.idempotent_fg from "leanprover-community/mathlib"@"25cf7631da8ddc2d5f957c388bf5e4b25a77d8dc" diff --git a/Mathlib/RingTheory/Ideal/LocalRing.lean b/Mathlib/RingTheory/Ideal/LocalRing.lean index 2112cf2dab28d..d775d029dbf13 100644 --- a/Mathlib/RingTheory/Ideal/LocalRing.lean +++ b/Mathlib/RingTheory/Ideal/LocalRing.lean @@ -434,13 +434,13 @@ theorem map_residue (f : R →+* S) [IsLocalRingHom f] (r : R) : #align local_ring.residue_field.map_residue LocalRing.ResidueField.map_residue theorem map_id_apply (x : ResidueField R) : map (RingHom.id R) x = x := - FunLike.congr_fun map_id x + DFunLike.congr_fun map_id x #align local_ring.residue_field.map_id_apply LocalRing.ResidueField.map_id_apply @[simp] theorem map_map (f : R →+* S) (g : S →+* T) (x : ResidueField R) [IsLocalRingHom f] [IsLocalRingHom g] : map g (map f x) = map (g.comp f) x := - FunLike.congr_fun (map_comp f g).symm x + DFunLike.congr_fun (map_comp f g).symm x #align local_ring.residue_field.map_map LocalRing.ResidueField.map_map /-- A ring isomorphism defines an isomorphism of residue fields. -/ diff --git a/Mathlib/RingTheory/Ideal/MinimalPrime.lean b/Mathlib/RingTheory/Ideal/MinimalPrime.lean index 0c316125e9cfd..6ce0c3e520b16 100644 --- a/Mathlib/RingTheory/Ideal/MinimalPrime.lean +++ b/Mathlib/RingTheory/Ideal/MinimalPrime.lean @@ -32,7 +32,7 @@ We provide various results concerning the minimal primes above an ideal section -variable {R S : Type*} [CommRing R] [CommRing S] (I J : Ideal R) +variable {R S : Type*} [CommSemiring R] [CommSemiring S] (I J : Ideal R) /-- `I.minimalPrimes` is the set of ideals that are minimal primes over `I`. -/ protected def Ideal.minimalPrimes : Set (Ideal R) := @@ -41,11 +41,11 @@ protected def Ideal.minimalPrimes : Set (Ideal R) := /-- `minimalPrimes R` is the set of minimal primes of `R`. This is defined as `Ideal.minimalPrimes ⊥`. -/ -def minimalPrimes (R : Type*) [CommRing R] : Set (Ideal R) := +def minimalPrimes (R : Type*) [CommSemiring R] : Set (Ideal R) := Ideal.minimalPrimes ⊥ #align minimal_primes minimalPrimes -lemma minimalPrimes_eq_minimals {R} [CommRing R] : +lemma minimalPrimes_eq_minimals {R} [CommSemiring R] : minimalPrimes R = minimals (· ≤ ·) (setOf Ideal.IsPrime) := congr_arg (minimals (· ≤ ·)) (by simp) @@ -124,6 +124,12 @@ theorem Ideal.exists_comap_eq_of_mem_minimalPrimes_of_injective {f : R →+* S} apply IsLocalization.map_units _ (show p.primeCompl from ⟨x, h⟩) #align ideal.exists_comap_eq_of_mem_minimal_primes_of_injective Ideal.exists_comap_eq_of_mem_minimalPrimes_of_injective +end + +section + +variable {R S : Type*} [CommRing R] [CommRing S] {I J : Ideal R} + theorem Ideal.exists_comap_eq_of_mem_minimalPrimes {I : Ideal S} (f : R →+* S) (p) (H : p ∈ (I.comap f).minimalPrimes) : ∃ p' : Ideal S, p'.IsPrime ∧ I ≤ p' ∧ p'.comap f = p := by have := H.1.1 diff --git a/Mathlib/RingTheory/Ideal/Norm.lean b/Mathlib/RingTheory/Ideal/Norm.lean index 0b72971ea4213..10789e949ed54 100644 --- a/Mathlib/RingTheory/Ideal/Norm.lean +++ b/Mathlib/RingTheory/Ideal/Norm.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen, Alex J. Best -/ import Mathlib.Algebra.CharP.Quotient +import Mathlib.Algebra.GroupWithZero.NonZeroDivisors import Mathlib.Data.Finsupp.Fintype import Mathlib.Data.Int.AbsoluteValue import Mathlib.Data.Int.Associated @@ -247,17 +248,19 @@ theorem cardQuot_mul [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ #align card_quot_mul cardQuot_mul /-- The absolute norm of the ideal `I : Ideal R` is the cardinality of the quotient `R ⧸ I`. -/ -noncomputable def Ideal.absNorm [Infinite S] [IsDedekindDomain S] [Module.Free ℤ S] +noncomputable def Ideal.absNorm [Nontrivial S] [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ S] : Ideal S →*₀ ℕ where toFun := Submodule.cardQuot map_mul' I J := by dsimp only; rw [cardQuot_mul] map_one' := by dsimp only; rw [Ideal.one_eq_top, cardQuot_top] - map_zero' := by rw [Ideal.zero_eq_bot, cardQuot_bot] + map_zero' := by + have : Infinite S := Module.Free.infinite ℤ S + rw [Ideal.zero_eq_bot, cardQuot_bot] #align ideal.abs_norm Ideal.absNorm namespace Ideal -variable [Infinite S] [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ S] +variable [Nontrivial S] [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ S] theorem absNorm_apply (I : Ideal S) : absNorm I = cardQuot I := rfl #align ideal.abs_norm_apply Ideal.absNorm_apply diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index ca89ba46b2aa5..7b71a4d175c94 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -6,10 +6,12 @@ Authors: Kenny Lau import Mathlib.Algebra.Algebra.Operations import Mathlib.Algebra.Ring.Equiv import Mathlib.Data.Nat.Choose.Sum -import Mathlib.LinearAlgebra.Basis.Bilinear +import Mathlib.Data.Fintype.Lattice import Mathlib.RingTheory.Coprime.Lemmas import Mathlib.RingTheory.Ideal.Basic import Mathlib.Algebra.GroupWithZero.NonZeroDivisors +import Mathlib.LinearAlgebra.Basis +import Mathlib.LinearAlgebra.Quotient #align_import ring_theory.ideal.operations from "leanprover-community/mathlib"@"e7f0ddbf65bd7181a85edb74b64bdc35ba4bdc74" @@ -829,6 +831,10 @@ theorem mul_eq_bot {R : Type*} [CommSemiring R] [NoZeroDivisors R] {I J : Ideal instance {R : Type*} [CommSemiring R] [NoZeroDivisors R] : NoZeroDivisors (Ideal R) where eq_zero_or_eq_zero_of_mul_eq_zero := mul_eq_bot.1 +instance {R : Type*} [CommSemiring R] {S : Type*} [CommRing S] [Algebra R S] + [NoZeroSMulDivisors R S] {I : Ideal S} : NoZeroSMulDivisors R I := + Submodule.noZeroSMulDivisors (Submodule.restrictScalars R I) + /-- A product of ideals in an integral domain is zero if and only if one of the terms is zero. -/ @[simp] lemma multiset_prod_eq_bot {R : Type*} [CommRing R] [IsDomain R] {s : Multiset (Ideal R)} : @@ -2108,6 +2114,10 @@ lemma _root_.Pi.ker_ringHom {ι : Type*} {R : ι → Type*} [∀ i, Semiring (R ext x simp [mem_ker, Ideal.mem_iInf, Function.funext_iff] +@[simp] +theorem ker_rangeSRestrict (f : R →+* S) : ker f.rangeSRestrict = ker f := + Ideal.ext fun _ ↦ Subtype.ext_iff + end Semiring section Ring diff --git a/Mathlib/RingTheory/Ideal/Quotient.lean b/Mathlib/RingTheory/Ideal/Quotient.lean index 911a046677a77..733ef8b6b8f46 100644 --- a/Mathlib/RingTheory/Ideal/Quotient.lean +++ b/Mathlib/RingTheory/Ideal/Quotient.lean @@ -3,8 +3,6 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Chris Hughes, Mario Carneiro, Anne Baanen -/ -import Mathlib.Algebra.Ring.Fin -import Mathlib.Algebra.Ring.Prod import Mathlib.LinearAlgebra.Quotient import Mathlib.RingTheory.Congruence import Mathlib.RingTheory.Ideal.Basic @@ -251,7 +249,7 @@ theorem maximal_ideal_iff_isField_quotient (I : Ideal R) : I.IsMaximal ↔ IsFie maximal_of_isField _⟩ #align ideal.quotient.maximal_ideal_iff_is_field_quotient Ideal.Quotient.maximal_ideal_iff_isField_quotient -variable [CommRing S] +variable [Semiring S] /-- Given a ring homomorphism `f : R →+* S` sending all elements of an ideal to zero, lift it to the quotient by this ideal. -/ @@ -324,7 +322,7 @@ variable (ι : Type v) /-- `R^n/I^n` is a `R/I`-module. -/ instance modulePi : Module (R ⧸ I) ((ι → R) ⧸ I.pi ι) where smul c m := - Quotient.liftOn₂' c m (fun r m => Submodule.Quotient.mk <| r • m) $ by + Quotient.liftOn₂' c m (fun r m => Submodule.Quotient.mk <| r • m) <| by intro c₁ m₁ c₂ m₂ hc hm apply Ideal.Quotient.eq.2 rw [Submodule.quotientRel_r_def] at hc hm diff --git a/Mathlib/RingTheory/Ideal/QuotientOperations.lean b/Mathlib/RingTheory/Ideal/QuotientOperations.lean index cb0f1b1d75627..3451f0b0e29d4 100644 --- a/Mathlib/RingTheory/Ideal/QuotientOperations.lean +++ b/Mathlib/RingTheory/Ideal/QuotientOperations.lean @@ -5,6 +5,7 @@ Authors: Kenny Lau, Patrick Massot -/ import Mathlib.RingTheory.Ideal.Operations import Mathlib.RingTheory.Ideal.Quotient +import Mathlib.Algebra.Ring.Fin #align_import ring_theory.ideal.quotient_operations from "leanprover-community/mathlib"@"b88d81c84530450a8989e918608e5960f015e6c8" @@ -14,6 +15,8 @@ import Mathlib.RingTheory.Ideal.Quotient ## Main results: - `quotientKerEquivRange` : the **first isomorphism theorem** for commutative rings. + - `quotientKerEquivRangeS` : the **first isomorphism theorem** + for a morphism from a commutative ring to a semiring. - `Ideal.quotientInfRingEquivPiQuotient`: the **Chinese Remainder Theorem**, version for coprime ideals (see also `ZMod.prodEquivPi` in `Data.ZMod.Quotient` for elementary versions about `ZMod`). @@ -23,7 +26,7 @@ universe u v w namespace RingHom -variable {R : Type u} {S : Type v} [CommRing R] [CommRing S] (f : R →+* S) +variable {R : Type u} {S : Type v} [CommRing R] [Semiring S] (f : R →+* S) /-- The induced map from the quotient by the kernel to the codomain. @@ -39,12 +42,6 @@ theorem kerLift_mk (f : R →+* S) (r : R) : kerLift f (Ideal.Quotient.mk (ker f Ideal.Quotient.lift_mk _ _ _ #align ring_hom.ker_lift_mk RingHom.kerLift_mk -/-- The induced map from the quotient by the kernel is injective. -/ -theorem kerLift_injective (f : R →+* S) : Function.Injective (kerLift f) := fun a b => - Quotient.inductionOn₂' a b fun a b (h : f a = f b) => - Ideal.Quotient.eq.2 <| show a - b ∈ ker f by rw [mem_ker, map_sub, h, sub_self] -#align ring_hom.ker_lift_injective RingHom.kerLift_injective - theorem lift_injective_of_ker_le_ideal (I : Ideal R) {f : R →+* S} (H : ∀ a : R, a ∈ I → f a = 0) (hI : ker f ≤ I) : Function.Injective (Ideal.Quotient.lift I f H) := by rw [RingHom.injective_iff_ker_eq_bot, RingHom.ker_eq_bot_iff_eq_zero] @@ -55,6 +52,12 @@ theorem lift_injective_of_ker_le_ideal (I : Ideal R) {f : R →+* S} (H : ∀ a exact hI ((RingHom.mem_ker f).mpr hu) #align ring_hom.lift_injective_of_ker_le_ideal RingHom.lift_injective_of_ker_le_ideal +/-- The induced map from the quotient by the kernel is injective. -/ +theorem kerLift_injective [Semiring S] (f : R →+* S) : Function.Injective (kerLift f) := + lift_injective_of_ker_le_ideal (ker f) (fun a => by simp only [mem_ker, imp_self]) le_rfl +#align ring_hom.ker_lift_injective RingHom.kerLift_injective + + variable {f} /-- The **first isomorphism theorem for commutative rings**, computable version. -/ @@ -88,7 +91,14 @@ noncomputable def quotientKerEquivOfSurjective (hf : Function.Surjective f) : R quotientKerEquivOfRightInverse (Classical.choose_spec hf.hasRightInverse) #align ring_hom.quotient_ker_equiv_of_surjective RingHom.quotientKerEquivOfSurjective -/-- The **first isomorphism theorem** for commutative rings. -/ +/-- The **first isomorphism theorem** for commutative rings (`RingHom.rangeS` version). -/ +noncomputable def quotientKerEquivRangeS (f : R →+* S) : R ⧸ ker f ≃+* f.rangeS := + (Ideal.quotEquivOfEq f.ker_rangeSRestrict.symm).trans <| + quotientKerEquivOfSurjective f.rangeSRestrict_surjective + +variable {S : Type v} [Ring S] (f : R →+* S) + +/-- The **first isomorphism theorem** for commutative rings (`RingHom.range` version). -/ noncomputable def quotientKerEquivRange (f : R →+* S) : R ⧸ ker f ≃+* f.range := (Ideal.quotEquivOfEq f.ker_rangeRestrict.symm).trans <| quotientKerEquivOfSurjective f.rangeRestrict_surjective @@ -98,7 +108,7 @@ end RingHom namespace Ideal open Function RingHom -variable {R : Type u} {S : Type v} {F : Type w} [CommRing R] [CommRing S] +variable {R : Type u} {S : Type v} {F : Type w} [CommRing R] [Semiring S] @[simp] theorem map_quotient_self (I : Ideal R) : map (Quotient.mk I) I = ⊥ := @@ -121,7 +131,7 @@ theorem map_mk_eq_bot_of_le {I J : Ideal R} (h : I ≤ J) : I.map (Quotient.mk J exact h #align ideal.map_mk_eq_bot_of_le Ideal.map_mk_eq_bot_of_le -theorem ker_quotient_lift {S : Type v} [CommRing S] {I : Ideal R} (f : R →+* S) +theorem ker_quotient_lift {I : Ideal R} (f : R →+* S) (H : I ≤ ker f) : ker (Ideal.Quotient.lift I f H) = f.ker.map (Quotient.mk I) := by apply Ideal.ext @@ -276,13 +286,13 @@ section QuotientAlgebra variable (R₁ R₂ : Type*) {A B : Type*} -variable [CommSemiring R₁] [CommSemiring R₂] [CommRing A] [CommRing B] +variable [CommSemiring R₁] [CommSemiring R₂] [CommRing A] -variable [Algebra R₁ A] [Algebra R₂ A] [Algebra R₁ B] +variable [Algebra R₁ A] [Algebra R₂ A] /-- The `R₁`-algebra structure on `A/I` for an `R₁`-algebra `A` -/ instance Quotient.algebra {I : Ideal A} : Algebra R₁ (A ⧸ I) := - { toRingHom := (Ideal.Quotient.mk I).comp (algebraMap R₁ A) + { toRingHom := (Ideal.Quotient.mk I).comp (algebraMap R₁ A) smul_def' := fun _ x => Quotient.inductionOn' x fun _ => ((Quotient.mk I).congr_arg <| Algebra.smul_def _ _).trans (RingHom.map_mul _ _ _) @@ -352,6 +362,10 @@ theorem Quotient.mkₐ_ker (I : Ideal A) : RingHom.ker (Quotient.mkₐ R₁ I : variable {R₁} +section + +variable [Semiring B] [Algebra R₁ B] + /-- `Ideal.quotient.lift` as an `AlgHom`. -/ def Quotient.liftₐ (I : Ideal A) (f : A →ₐ[R₁] B) (hI : ∀ a : A, a ∈ I → f a = 0) : A ⧸ I →ₐ[R₁] B := @@ -450,6 +464,11 @@ noncomputable def quotientKerAlgEquivOfSurjective {f : A →ₐ[R₁] B} (hf : F quotientKerAlgEquivOfRightInverse (Classical.choose_spec hf.hasRightInverse) #align ideal.quotient_ker_alg_equiv_of_surjective Ideal.quotientKerAlgEquivOfSurjective +end + +section CommRing_CommRing + +variable {S : Type v} [CommRing S] /-- The ring hom `R/I →+* S/J` induced by a ring hom `f : R →+* S` with `I ≤ f⁻¹(J)` -/ def quotientMap {I : Ideal R} (J : Ideal S) (f : R →+* S) (hIJ : I ≤ J.comap f) : R ⧸ I →+* S ⧸ J := Quotient.lift I ((Quotient.mk J).comp f) fun _ ha => by @@ -549,6 +568,13 @@ theorem comp_quotientMap_eq_of_comp_eq {R' S' : Type*} [CommRing R'] [CommRing S (hfg ▸ f'.comp_apply g r)) #align ideal.comp_quotient_map_eq_of_comp_eq Ideal.comp_quotientMap_eq_of_comp_eq +end CommRing_CommRing + + +section + +variable [CommRing B] [Algebra R₁ B] + /-- The algebra hom `A/I →+* B/J` induced by an algebra hom `f : A →ₐ[R₁] B` with `I ≤ f⁻¹(J)`. -/ def quotientMapₐ {I : Ideal A} (J : Ideal B) (f : A →ₐ[R₁] B) (hIJ : I ≤ J.comap f) : A ⧸ I →ₐ[R₁] B ⧸ J := @@ -574,12 +600,15 @@ def quotientEquivAlg (I : Ideal A) (J : Ideal B) (f : A ≃ₐ[R₁] B) (hIJ : J { quotientEquiv I J (f : A ≃+* B) hIJ with commutes' := fun r => by -- Porting note: Needed to add the below lemma because Equivs coerce weird - have : ∀ (e : RingEquiv (A ⧸ I) (B ⧸ J)), Equiv.toFun e.toEquiv = FunLike.coe e := fun _ ↦ rfl + have : ∀ (e : RingEquiv (A ⧸ I) (B ⧸ J)), Equiv.toFun e.toEquiv = DFunLike.coe e := + fun _ ↦ rfl rw [this] simp only [quotientEquiv_apply, RingHom.toFun_eq_coe, quotientMap_algebraMap, RingEquiv.coe_toRingHom, AlgEquiv.coe_ringEquiv, AlgEquiv.commutes, Quotient.mk_algebraMap]} #align ideal.quotient_equiv_alg Ideal.quotientEquivAlg +end + instance (priority := 100) quotientAlgebra {I : Ideal A} [Algebra R A] : Algebra (R ⧸ I.comap (algebraMap R A)) (A ⧸ I) := (quotientMap I (algebraMap R A) (le_of_eq rfl)).toAlgebra diff --git a/Mathlib/RingTheory/Int/Basic.lean b/Mathlib/RingTheory/Int/Basic.lean index 7bcb9fc5d5e92..be74db7eee10d 100644 --- a/Mathlib/RingTheory/Int/Basic.lean +++ b/Mathlib/RingTheory/Int/Basic.lean @@ -136,8 +136,8 @@ section GCDMonoid instance : GCDMonoid ℤ where gcd a b := Int.gcd a b lcm a b := Int.lcm a b - gcd_dvd_left a b := Int.gcd_dvd_left _ _ - gcd_dvd_right a b := Int.gcd_dvd_right _ _ + gcd_dvd_left a b := Int.gcd_dvd_left + gcd_dvd_right a b := Int.gcd_dvd_right dvd_gcd := dvd_gcd gcd_mul_lcm a b := by rw [← Int.ofNat_mul, gcd_mul_lcm, coe_natAbs, abs_eq_normalize] @@ -246,7 +246,7 @@ theorem natAbs_euclideanDomain_gcd (a b : ℤ) : · rw [Int.natAbs_dvd] exact Int.dvd_gcd (EuclideanDomain.gcd_dvd_left _ _) (EuclideanDomain.gcd_dvd_right _ _) · rw [Int.dvd_natAbs] - exact EuclideanDomain.dvd_gcd (Int.gcd_dvd_left _ _) (Int.gcd_dvd_right _ _) + exact EuclideanDomain.dvd_gcd Int.gcd_dvd_left Int.gcd_dvd_right #align int.nat_abs_euclidean_domain_gcd Int.natAbs_euclideanDomain_gcd end Int diff --git a/Mathlib/RingTheory/IntegralRestrict.lean b/Mathlib/RingTheory/IntegralRestrict.lean index 6b8c14ce86206..415e1998fb769 100644 --- a/Mathlib/RingTheory/IntegralRestrict.lean +++ b/Mathlib/RingTheory/IntegralRestrict.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.RingTheory.IntegrallyClosed -import Mathlib.RingTheory.Norm +import Mathlib.RingTheory.LocalProperties +import Mathlib.RingTheory.Localization.NormTrace +import Mathlib.RingTheory.Localization.LocalizationLocalization import Mathlib.RingTheory.DedekindDomain.IntegralClosure /-! # Restriction of various maps between fields to integrally closed subrings. @@ -15,9 +17,10 @@ We call this the AKLB setup. ## Main definition - `galRestrict`: The restriction `Aut(L/K) → Aut(B/A)` as an `MulEquiv` in an AKLB setup. - -## TODO -Define the restriction of norms and traces. +- `Algebra.intTrace`: The trace map of a finite extension of integrally closed domains `B/A` is +defined to be the restriction of the trace map of `Frac(B)/Frac(A)`. +- `Algebra.intNorm`: The norm map of a finite extension of integrally closed domains `B/A` is +defined to be the restriction of the norm map of `Frac(B)/Frac(A)`. -/ open BigOperators nonZeroDivisors @@ -27,6 +30,8 @@ variable (A K L B : Type*) [CommRing A] [CommRing B] [Algebra A B] [Field K] [Fi [Algebra K L] [Algebra A L] [IsScalarTower A B L] [IsScalarTower A K L] [IsIntegralClosure B A L] [FiniteDimensional K L] +section galois + /-- The lift `End(B/A) → End(L/K)` in an ALKB setup. This is inverse to the restriction. See `galRestrictHom`. -/ noncomputable @@ -46,7 +51,7 @@ def galLift (σ : B →ₐ[A] B) : L →ₐ[K] L := simp only [RingHom.coe_comp, Function.comp_apply, ← IsScalarTower.algebraMap_apply A K L, IsScalarTower.algebraMap_apply A B L, IsLocalization.lift_eq, RingHom.coe_coe, AlgHom.commutes] - { IsLocalization.lift (S := L) H with commutes' := FunLike.congr_fun H_eq } + { IsLocalization.lift (S := L) H with commutes' := DFunLike.congr_fun H_eq } /-- The restriction `End(L/K) → End(B/A)` in an AKLB setup. Also see `galRestrict` for the `AlgEquiv` version. -/ @@ -119,3 +124,337 @@ lemma prod_galRestrict_eq_norm [IsGalois K L] [IsIntegrallyClosed A] (x : B) : rw [← IsScalarTower.algebraMap_apply, IsScalarTower.algebraMap_eq A K L] simp only [map_prod, algebraMap_galRestrict_apply, IsIntegralClosure.algebraMap_mk', Algebra.norm_eq_prod_automorphisms, AlgHom.coe_coe, RingHom.coe_comp, Function.comp_apply] + +end galois + +attribute [local instance] FractionRing.liftAlgebra FractionRing.isScalarTower_liftAlgebra + +noncomputable +instance (priority := 900) [IsDomain A] [IsDomain B] [IsIntegrallyClosed B] + [Module.Finite A B] [NoZeroSMulDivisors A B] : Fintype (B ≃ₐ[A] B) := + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (Algebra.algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + Fintype.ofEquiv _ (galRestrict A (FractionRing A) (FractionRing B) B).toEquiv + +variable {Aₘ Bₘ} [CommRing Aₘ] [CommRing Bₘ] [Algebra Aₘ Bₘ] [Algebra A Aₘ] [Algebra B Bₘ] +variable [Algebra A Bₘ] [IsScalarTower A Aₘ Bₘ] [IsScalarTower A B Bₘ] +variable (M : Submonoid A) [IsLocalization M Aₘ] +variable [IsLocalization (Algebra.algebraMapSubmonoid B M) Bₘ] + +section trace + +/-- The restriction of the trace on `L/K` restricted onto `B/A` in an AKLB setup. +See `Algebra.intTrace` instead. -/ +noncomputable +def Algebra.intTraceAux [IsIntegrallyClosed A] : + B →ₗ[A] A := + (IsIntegralClosure.equiv A (integralClosure A K) K A).toLinearMap.comp + ((((Algebra.trace K L).restrictScalars A).comp + (IsScalarTower.toAlgHom A B L).toLinearMap).codRestrict + (Subalgebra.toSubmodule <| integralClosure A K) (fun x ↦ isIntegral_trace + (IsIntegral.algebraMap (IsIntegralClosure.isIntegral A L x)))) + +variable {A K L B} + +lemma Algebra.map_intTraceAux [IsIntegrallyClosed A] (x : B) : + algebraMap A K (Algebra.intTraceAux A K L B x) = Algebra.trace K L (algebraMap B L x) := + IsIntegralClosure.algebraMap_equiv A (integralClosure A K) K A _ + +variable (A B) + +variable [IsDomain A] [IsIntegrallyClosed A] [IsDomain B] [IsIntegrallyClosed B] +variable [Module.Finite A B] [NoZeroSMulDivisors A B] + +/-- The trace of a finite extension of integrally closed domains `B/A` is the restriction of +the trace on `Frac(B)/Frac(A)` onto `B/A`. See `Algebra.algebraMap_intTrace`. -/ +noncomputable +def Algebra.intTrace : B →ₗ[A] A := + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite _ _) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + Algebra.intTraceAux A (FractionRing A) (FractionRing B) B + +variable {A B} + +lemma Algebra.algebraMap_intTrace (x : B) : + algebraMap A K (Algebra.intTrace A B x) = Algebra.trace K L (algebraMap B L x) := by + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + haveI := IsIntegralClosure.isFractionRing_of_finite_extension A K L B + apply (FractionRing.algEquiv A K).symm.injective + rw [AlgEquiv.commutes, Algebra.intTrace, Algebra.map_intTraceAux, + ← AlgEquiv.commutes (FractionRing.algEquiv B L)] + apply Algebra.trace_eq_of_equiv_equiv (FractionRing.algEquiv A K).toRingEquiv + (FractionRing.algEquiv B L).toRingEquiv + apply IsLocalization.ringHom_ext A⁰ + simp only [AlgEquiv.toRingEquiv_eq_coe, ← AlgEquiv.coe_ringHom_commutes, RingHom.comp_assoc, + AlgHom.comp_algebraMap_of_tower, ← IsScalarTower.algebraMap_eq, RingHom.comp_assoc] + +lemma Algebra.algebraMap_intTrace_fractionRing (x : B) : + algebraMap A (FractionRing A) (Algebra.intTrace A B x) = + Algebra.trace (FractionRing A) (FractionRing B) (algebraMap B _ x) := by + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + exact Algebra.map_intTraceAux x + +variable (A B) + +lemma Algebra.intTrace_eq_trace [Module.Free A B] : Algebra.intTrace A B = Algebra.trace A B := by + ext x + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + apply IsFractionRing.injective A (FractionRing A) + rw [Algebra.algebraMap_intTrace_fractionRing, Algebra.trace_localization A A⁰] + +open nonZeroDivisors + +variable [IsDomain Aₘ] [IsIntegrallyClosed Aₘ] [IsDomain Bₘ] [IsIntegrallyClosed Bₘ] +variable [NoZeroSMulDivisors Aₘ Bₘ] [Module.Finite Aₘ Bₘ] + +lemma Algebra.intTrace_eq_of_isLocalization + (x : B) : + algebraMap A Aₘ (Algebra.intTrace A B x) = Algebra.intTrace Aₘ Bₘ (algebraMap B Bₘ x) := by + by_cases hM : 0 ∈ M + · have := IsLocalization.uniqueOfZeroMem (S := Aₘ) hM + exact Subsingleton.elim _ _ + replace hM : M ≤ A⁰ := fun x hx ↦ mem_nonZeroDivisors_iff_ne_zero.mpr (fun e ↦ hM (e ▸ hx)) + let K := FractionRing A + let L := FractionRing B + have : IsIntegralClosure B A L := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + have : IsLocalization (algebraMapSubmonoid B A⁰) L := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + let f : Aₘ →+* K := IsLocalization.map _ (T := A⁰) (RingHom.id A) hM + letI := f.toAlgebra + have : IsScalarTower A Aₘ K := IsScalarTower.of_algebraMap_eq' + (by rw [RingHom.algebraMap_toAlgebra, IsLocalization.map_comp, RingHomCompTriple.comp_eq]) + letI := IsFractionRing.isFractionRing_of_isDomain_of_isLocalization M Aₘ K + let g : Bₘ →+* L := IsLocalization.map _ + (M := algebraMapSubmonoid B M) (T := algebraMapSubmonoid B A⁰) + (RingHom.id B) (Submonoid.monotone_map hM) + letI := g.toAlgebra + have : IsScalarTower B Bₘ L := IsScalarTower.of_algebraMap_eq' + (by rw [RingHom.algebraMap_toAlgebra, IsLocalization.map_comp, RingHomCompTriple.comp_eq]) + letI := ((algebraMap K L).comp f).toAlgebra + have : IsScalarTower Aₘ K L := IsScalarTower.of_algebraMap_eq' rfl + have : IsScalarTower Aₘ Bₘ L := by + apply IsScalarTower.of_algebraMap_eq' + apply IsLocalization.ringHom_ext M + rw [RingHom.algebraMap_toAlgebra, RingHom.algebraMap_toAlgebra (R := Bₘ), RingHom.comp_assoc, + RingHom.comp_assoc, ← IsScalarTower.algebraMap_eq, IsScalarTower.algebraMap_eq A B Bₘ, + IsLocalization.map_comp, RingHom.comp_id, ← RingHom.comp_assoc, IsLocalization.map_comp, + RingHom.comp_id, ← IsScalarTower.algebraMap_eq, ← IsScalarTower.algebraMap_eq] + letI := IsFractionRing.isFractionRing_of_isDomain_of_isLocalization + (algebraMapSubmonoid B M) Bₘ L + have : FiniteDimensional K L := Module.Finite_of_isLocalization A B _ _ A⁰ + have : IsIntegralClosure Bₘ Aₘ L := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite Aₘ Bₘ) + apply IsFractionRing.injective Aₘ K + rw [← IsScalarTower.algebraMap_apply, Algebra.algebraMap_intTrace_fractionRing, + Algebra.algebraMap_intTrace (L := L), ← IsScalarTower.algebraMap_apply] + +end trace + +section norm + +variable [IsIntegrallyClosed A] + +/-- The restriction of the norm on `L/K` restricted onto `B/A` in an AKLB setup. +See `Algebra.intNorm` instead. -/ +noncomputable +def Algebra.intNormAux [IsIntegrallyClosed A] [IsSeparable K L] : + B →* A where + toFun := fun s ↦ IsIntegralClosure.mk' (R := A) A (Algebra.norm K (algebraMap B L s)) + (isIntegral_norm K <| IsIntegral.map (IsScalarTower.toAlgHom A B L) + (IsIntegralClosure.isIntegral A L s)) + map_one' := by simp + map_mul' := fun x y ↦ by simpa using IsIntegralClosure.mk'_mul _ _ _ _ _ + +variable {A K L B} + +lemma Algebra.map_intNormAux [IsIntegrallyClosed A] [IsSeparable K L] (x : B) : + algebraMap A K (Algebra.intNormAux A K L B x) = Algebra.norm K (algebraMap B L x) := by + dsimp [Algebra.intNormAux] + exact IsIntegralClosure.algebraMap_mk' _ _ _ + +variable (A B) + +variable [IsDomain A] [IsIntegrallyClosed A] [IsDomain B] [IsIntegrallyClosed B] +variable [Module.Finite A B] [NoZeroSMulDivisors A B] +variable [IsSeparable (FractionRing A) (FractionRing B)] -- TODO: remove this + +/-- The norm of a finite extension of integrally closed domains `B/A` is the restriction of +the norm on `Frac(B)/Frac(A)` onto `B/A`. See `Algebra.algebraMap_intNorm`. -/ +noncomputable +def Algebra.intNorm : B →* A := + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + Algebra.intNormAux A (FractionRing A) (FractionRing B) B + +variable {A B} + +lemma Algebra.algebraMap_intNorm (x : B) : + algebraMap A K (Algebra.intNorm A B x) = Algebra.norm K (algebraMap B L x) := by + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + haveI := IsIntegralClosure.isFractionRing_of_finite_extension A K L B + apply (FractionRing.algEquiv A K).symm.injective + rw [AlgEquiv.commutes, Algebra.intNorm, Algebra.map_intNormAux, + ← AlgEquiv.commutes (FractionRing.algEquiv B L)] + apply Algebra.norm_eq_of_equiv_equiv (FractionRing.algEquiv A K).toRingEquiv + (FractionRing.algEquiv B L).toRingEquiv + apply IsLocalization.ringHom_ext A⁰ + simp only [AlgEquiv.toRingEquiv_eq_coe, ← AlgEquiv.coe_ringHom_commutes, RingHom.comp_assoc, + AlgHom.comp_algebraMap_of_tower, ← IsScalarTower.algebraMap_eq, RingHom.comp_assoc] + +@[simp] +lemma Algebra.algebraMap_intNorm_fractionRing (x : B) : + algebraMap A (FractionRing A) (Algebra.intNorm A B x) = + Algebra.norm (FractionRing A) (algebraMap B (FractionRing B) x) := by + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + exact Algebra.map_intNormAux x + +variable (A B) + +lemma Algebra.intNorm_eq_norm [Module.Free A B] : Algebra.intNorm A B = Algebra.norm A := by + ext x + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + apply IsFractionRing.injective A (FractionRing A) + rw [Algebra.algebraMap_intNorm_fractionRing, Algebra.norm_localization A A⁰] + +@[simp] +lemma Algebra.intNorm_zero : Algebra.intNorm A B 0 = 0 := by + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + apply (IsFractionRing.injective A (FractionRing A)) + simp only [algebraMap_intNorm_fractionRing, map_zero, norm_zero] + +variable {A B} + +@[simp] +lemma Algebra.intNorm_eq_zero {x : B} : Algebra.intNorm A B x = 0 ↔ x = 0 := by + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + rw [← (IsFractionRing.injective A (FractionRing A)).eq_iff, + ← (IsFractionRing.injective B (FractionRing B)).eq_iff] + simp only [algebraMap_intNorm_fractionRing, map_zero, norm_eq_zero_iff] + +lemma Algebra.intNorm_ne_zero {x : B} : Algebra.intNorm A B x ≠ 0 ↔ x ≠ 0 := by simp + +variable [IsDomain Aₘ] [IsIntegrallyClosed Aₘ] [IsDomain Bₘ] [IsIntegrallyClosed Bₘ] +variable [NoZeroSMulDivisors Aₘ Bₘ] [Module.Finite Aₘ Bₘ] +variable [IsSeparable (FractionRing Aₘ) (FractionRing Bₘ)] + +lemma Algebra.intNorm_eq_of_isLocalization + [IsSeparable (FractionRing Aₘ) (FractionRing Bₘ)] (x : B) : + algebraMap A Aₘ (Algebra.intNorm A B x) = Algebra.intNorm Aₘ Bₘ (algebraMap B Bₘ x) := by + by_cases hM : 0 ∈ M + · have := IsLocalization.uniqueOfZeroMem (S := Aₘ) hM + exact Subsingleton.elim _ _ + replace hM : M ≤ A⁰ := fun x hx ↦ mem_nonZeroDivisors_iff_ne_zero.mpr (fun e ↦ hM (e ▸ hx)) + let K := FractionRing A + let L := FractionRing B + have : IsIntegralClosure B A L := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + have : IsLocalization (algebraMapSubmonoid B A⁰) L := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + let f : Aₘ →+* K := IsLocalization.map _ (T := A⁰) (RingHom.id A) hM + letI := f.toAlgebra + have : IsScalarTower A Aₘ K := IsScalarTower.of_algebraMap_eq' + (by rw [RingHom.algebraMap_toAlgebra, IsLocalization.map_comp, RingHomCompTriple.comp_eq]) + letI := IsFractionRing.isFractionRing_of_isDomain_of_isLocalization M Aₘ K + let g : Bₘ →+* L := IsLocalization.map _ + (M := algebraMapSubmonoid B M) (T := algebraMapSubmonoid B A⁰) + (RingHom.id B) (Submonoid.monotone_map hM) + letI := g.toAlgebra + have : IsScalarTower B Bₘ L := IsScalarTower.of_algebraMap_eq' + (by rw [RingHom.algebraMap_toAlgebra, IsLocalization.map_comp, RingHomCompTriple.comp_eq]) + letI := ((algebraMap K L).comp f).toAlgebra + have : IsScalarTower Aₘ K L := IsScalarTower.of_algebraMap_eq' rfl + have : IsScalarTower Aₘ Bₘ L := by + apply IsScalarTower.of_algebraMap_eq' + apply IsLocalization.ringHom_ext M + rw [RingHom.algebraMap_toAlgebra, RingHom.algebraMap_toAlgebra (R := Bₘ), RingHom.comp_assoc, + RingHom.comp_assoc, ← IsScalarTower.algebraMap_eq, IsScalarTower.algebraMap_eq A B Bₘ, + IsLocalization.map_comp, RingHom.comp_id, ← RingHom.comp_assoc, IsLocalization.map_comp, + RingHom.comp_id, ← IsScalarTower.algebraMap_eq, ← IsScalarTower.algebraMap_eq] + letI := IsFractionRing.isFractionRing_of_isDomain_of_isLocalization + (algebraMapSubmonoid B M) Bₘ L + have : FiniteDimensional K L := Module.Finite_of_isLocalization A B _ _ A⁰ + have : IsIntegralClosure Bₘ Aₘ L := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite Aₘ Bₘ) + apply IsFractionRing.injective Aₘ K + rw [← IsScalarTower.algebraMap_apply, Algebra.algebraMap_intNorm_fractionRing, + Algebra.algebraMap_intNorm (L := L), ← IsScalarTower.algebraMap_apply] + +end norm + +lemma Algebra.algebraMap_intNorm_of_isGalois + [IsDomain A] [IsIntegrallyClosed A] [IsDomain B] [IsIntegrallyClosed B] + [Module.Finite A B] [NoZeroSMulDivisors A B] [IsGalois (FractionRing A) (FractionRing B)] + {x : B} : + algebraMap A B (Algebra.intNorm A B x) = ∏ σ : B ≃ₐ[A] B, σ x := by + haveI : IsIntegralClosure B A (FractionRing B) := + IsIntegralClosure.of_isIntegrallyClosed _ _ _ (Algebra.IsIntegral.of_finite A B) + haveI : IsLocalization (Algebra.algebraMapSubmonoid B A⁰) (FractionRing B) := + IsIntegralClosure.isLocalization _ (FractionRing A) _ _ + (isAlgebraic_of_isFractionRing _ _ (Algebra.IsIntegral.of_finite A B)) + haveI : FiniteDimensional (FractionRing A) (FractionRing B) := + Module.Finite_of_isLocalization A B _ _ A⁰ + rw [← (galRestrict A (FractionRing A) (FractionRing B) B).toEquiv.prod_comp] + simp only [MulEquiv.toEquiv_eq_coe, EquivLike.coe_coe] + convert (prod_galRestrict_eq_norm A (FractionRing A) (FractionRing B) B x).symm diff --git a/Mathlib/RingTheory/IsTensorProduct.lean b/Mathlib/RingTheory/IsTensorProduct.lean index 3bd9937b0086d..d6b28c61ffa26 100644 --- a/Mathlib/RingTheory/IsTensorProduct.lean +++ b/Mathlib/RingTheory/IsTensorProduct.lean @@ -38,7 +38,7 @@ open TensorProduct section IsTensorProduct -variable {R : Type*} [CommRing R] +variable {R : Type*} [CommSemiring R] variable {M₁ M₂ M M' : Type*} @@ -140,9 +140,9 @@ section IsBaseChange variable {R : Type*} {M : Type v₁} {N : Type v₂} (S : Type v₃) -variable [AddCommMonoid M] [AddCommMonoid N] [CommRing R] +variable [AddCommMonoid M] [AddCommMonoid N] [CommSemiring R] -variable [CommRing S] [Algebra R S] [Module R M] [Module R N] [Module S N] [IsScalarTower R S N] +variable [CommSemiring S] [Algebra R S] [Module R M] [Module R N] [Module S N] [IsScalarTower R S N] variable (f : M →ₗ[R] N) @@ -277,7 +277,7 @@ theorem IsBaseChange.of_lift_unique TensorProduct.induction_on x _ (fun s' y => smul_assoc s s' _) fun x y hx hy => _ } · dsimp; rw [map_zero, smul_zero, map_zero, smul_zero] · dsimp at *; rw [smul_add, map_add, map_add, smul_add, hx, hy] - simp_rw [FunLike.ext_iff, LinearMap.comp_apply, LinearMap.restrictScalars_apply] at hg + simp_rw [DFunLike.ext_iff, LinearMap.comp_apply, LinearMap.restrictScalars_apply] at hg let fe : S ⊗[R] M ≃ₗ[S] N := LinearEquiv.ofLinear f'' (ULift.moduleEquiv.toLinearMap.comp g) ?_ ?_ · exact fe.bijective @@ -325,7 +325,7 @@ theorem IsBaseChange.ofEquiv (e : M ≃ₗ[R] N) : IsBaseChange R e.toLinearMap simp #align is_base_change.of_equiv IsBaseChange.ofEquiv -variable {T O : Type*} [CommRing T] [Algebra R T] [Algebra S T] [IsScalarTower R S T] +variable {T O : Type*} [CommSemiring T] [Algebra R T] [Algebra S T] [IsScalarTower R S T] variable [AddCommMonoid O] [Module R O] [Module S O] [Module T O] [IsScalarTower S T O] @@ -356,7 +356,7 @@ theorem IsBaseChange.comp {f : M →ₗ[R] N} (hf : IsBaseChange S f) {g : N → rfl #align is_base_change.comp IsBaseChange.comp -variable {R' S' : Type*} [CommRing R'] [CommRing S'] +variable {R' S' : Type*} [CommSemiring R'] [CommSemiring S'] variable [Algebra R R'] [Algebra S S'] [Algebra R' S'] [Algebra R S'] diff --git a/Mathlib/RingTheory/Kaehler.lean b/Mathlib/RingTheory/Kaehler.lean index 037effaa5c06d..58ab9918439fd 100644 --- a/Mathlib/RingTheory/Kaehler.lean +++ b/Mathlib/RingTheory/Kaehler.lean @@ -482,8 +482,8 @@ noncomputable def KaehlerDifferential.kerTotal : Submodule S (S →₀ S) := unsuppress_compilation in -- Porting note: was `local notation x "𝖣" y => (KaehlerDifferential.kerTotal R S).mkQ (single y x)` --- but not having `FunLike.coe` leads to `kerTotal_mkQ_single_smul` failing. -local notation3 x "𝖣" y => FunLike.coe (KaehlerDifferential.kerTotal R S).mkQ (single y x) +-- but not having `DFunLike.coe` leads to `kerTotal_mkQ_single_smul` failing. +local notation3 x "𝖣" y => DFunLike.coe (KaehlerDifferential.kerTotal R S).mkQ (single y x) theorem KaehlerDifferential.kerTotal_mkQ_single_add (x y z) : (z𝖣x + y) = (z𝖣x) + z𝖣y := by rw [← map_add, eq_comm, ← sub_eq_zero, ← map_sub (Submodule.mkQ (kerTotal R S)), @@ -511,6 +511,7 @@ theorem KaehlerDifferential.kerTotal_mkQ_single_algebraMap_one (x) : (x𝖣1) = #align kaehler_differential.ker_total_mkq_single_algebra_map_one KaehlerDifferential.kerTotal_mkQ_single_algebraMap_one theorem KaehlerDifferential.kerTotal_mkQ_single_smul (r : R) (x y) : (y𝖣r • x) = r • y𝖣x := by + letI : SMulZeroClass R S := inferInstance rw [Algebra.smul_def, KaehlerDifferential.kerTotal_mkQ_single_mul, KaehlerDifferential.kerTotal_mkQ_single_algebraMap, add_zero, ← LinearMap.map_smul_of_tower, Finsupp.smul_single, mul_comm, Algebra.smul_def] @@ -665,7 +666,7 @@ open IsScalarTower (toAlgHom) theorem KaehlerDifferential.map_surjective_of_surjective (h : Function.Surjective (algebraMap A B)) : Function.Surjective (KaehlerDifferential.map R S A B) := by - rw [← LinearMap.range_eq_top, _root_.eq_top_iff, ← @Submodule.restrictScalars_top B A, + rw [← LinearMap.range_eq_top, _root_.eq_top_iff, ← @Submodule.restrictScalars_top A B, ← KaehlerDifferential.span_range_derivation, Submodule.restrictScalars_span _ _ h, Submodule.span_le] rintro _ ⟨x, rfl⟩ diff --git a/Mathlib/RingTheory/LocalProperties.lean b/Mathlib/RingTheory/LocalProperties.lean index 3863cf39aa40c..5c9cb75d9b556 100644 --- a/Mathlib/RingTheory/LocalProperties.lean +++ b/Mathlib/RingTheory/LocalProperties.lean @@ -374,40 +374,53 @@ end Surjective section Finite -/-- If `S` is a finite `R`-algebra, then `S' = M⁻¹S` is a finite `R' = M⁻¹R`-algebra. -/ -theorem localization_finite : RingHom.LocalizationPreserves @RingHom.Finite := by - introv R hf - -- Setting up the `algebra` and `is_scalar_tower` instances needed - letI := f.toAlgebra - letI := ((algebraMap S S').comp f).toAlgebra - let f' : R' →+* S' := IsLocalization.map S' f (Submonoid.le_comap_map M) - letI := f'.toAlgebra - haveI : IsScalarTower R R' S' := IsScalarTower.of_algebraMap_eq' - (IsLocalization.map_comp M.le_comap_map).symm - let fₐ : S →ₐ[R] S' := AlgHom.mk' (algebraMap S S') fun c x => RingHom.map_mul _ _ _ +lemma Module.Finite_of_isLocalization (R S Rₚ Sₚ) [CommSemiring R] [CommRing S] [CommRing Rₚ] + [CommRing Sₚ] [Algebra R S] [Algebra R Rₚ] [Algebra R Sₚ] [Algebra S Sₚ] [Algebra Rₚ Sₚ] + [IsScalarTower R S Sₚ] [IsScalarTower R Rₚ Sₚ] (M : Submonoid R) [IsLocalization M Rₚ] + [IsLocalization (Algebra.algebraMapSubmonoid S M) Sₚ] [hRS : Module.Finite R S] : + Module.Finite Rₚ Sₚ := by + classical + have : algebraMap Rₚ Sₚ = IsLocalization.map (T := Algebra.algebraMapSubmonoid S M) Sₚ + (algebraMap R S) (Submonoid.le_comap_map M) + · apply IsLocalization.ringHom_ext M + simp only [IsLocalization.map_comp, ← IsScalarTower.algebraMap_eq] -- We claim that if `S` is generated by `T` as an `R`-module, -- then `S'` is generated by `T` as an `R'`-module. - obtain ⟨T, hT⟩ := hf - use T.image (algebraMap S S') + obtain ⟨T, hT⟩ := hRS + use T.image (algebraMap S Sₚ) rw [eq_top_iff] rintro x - -- By the hypotheses, for each `x : S'`, we have `x = y / (f r)` for some `y : S` and `r : M`. -- Since `S` is generated by `T`, the image of `y` should fall in the span of the image of `T`. - obtain ⟨y, ⟨_, ⟨r, hr, rfl⟩⟩, rfl⟩ := IsLocalization.mk'_surjective (M.map f) x + obtain ⟨y, ⟨_, ⟨r, hr, rfl⟩⟩, rfl⟩ := + IsLocalization.mk'_surjective (Algebra.algebraMapSubmonoid S M) x rw [IsLocalization.mk'_eq_mul_mk'_one, mul_comm, Finset.coe_image] have hy : y ∈ Submodule.span R ↑T := by rw [hT]; trivial - replace hy : algebraMap S S' y ∈ Submodule.map fₐ.toLinearMap (Submodule.span R (T : Set S)) := - Submodule.mem_map_of_mem hy - rw [Submodule.map_span fₐ.toLinearMap T] at hy - have H : Submodule.span R (algebraMap S S' '' T) ≤ - (Submodule.span R' (algebraMap S S' '' T)).restrictScalars R := by + replace hy : algebraMap S Sₚ y ∈ Submodule.map (IsScalarTower.toAlgHom R S Sₚ).toLinearMap + (Submodule.span R (T : Set S)) := Submodule.mem_map_of_mem hy + rw [Submodule.map_span (IsScalarTower.toAlgHom R S Sₚ).toLinearMap T] at hy + have H : Submodule.span R (algebraMap S Sₚ '' T) ≤ + (Submodule.span Rₚ (algebraMap S Sₚ '' T)).restrictScalars R := by rw [Submodule.span_le]; exact Submodule.subset_span -- Now, since `y ∈ span T`, and `(f r)⁻¹ ∈ R'`, `x / (f r)` is in `span T` as well. - convert (Submodule.span R' (algebraMap S S' '' T)).smul_mem - (IsLocalization.mk' R' (1 : R) ⟨r, hr⟩) (H hy) using 1 - rw [Algebra.smul_def] - erw [IsLocalization.map_mk' M.le_comap_map] - rw [map_one] + convert (Submodule.span Rₚ (algebraMap S Sₚ '' T)).smul_mem + (IsLocalization.mk' Rₚ (1 : R) ⟨r, hr⟩) (H hy) using 1 + rw [Algebra.smul_def, this, IsLocalization.map_mk', map_one] + +/-- If `S` is a finite `R`-algebra, then `S' = M⁻¹S` is a finite `R' = M⁻¹R`-algebra. -/ +theorem localization_finite : RingHom.LocalizationPreserves @RingHom.Finite := by + introv R hf + letI := f.toAlgebra + letI := ((algebraMap S S').comp f).toAlgebra + let f' : R' →+* S' := IsLocalization.map S' f (Submonoid.le_comap_map M) + letI := f'.toAlgebra + have : IsScalarTower R R' S' := IsScalarTower.of_algebraMap_eq' + (IsLocalization.map_comp M.le_comap_map).symm + have : IsScalarTower R S S' := IsScalarTower.of_algebraMap_eq' rfl + have : IsLocalization (Algebra.algebraMapSubmonoid S M) S' + · rwa [Algebra.algebraMapSubmonoid, RingHom.algebraMap_toAlgebra] + have : Module.Finite R S := hf + apply Module.Finite_of_isLocalization R S R' S' M #align localization_finite localization_finite theorem localization_away_map_finite (r : R) [IsLocalization.Away r R'] diff --git a/Mathlib/RingTheory/Localization/BaseChange.lean b/Mathlib/RingTheory/Localization/BaseChange.lean new file mode 100644 index 0000000000000..3c6078a864e9c --- /dev/null +++ b/Mathlib/RingTheory/Localization/BaseChange.lean @@ -0,0 +1,49 @@ +/- +Copyright (c) 2022 Jujian Zhang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang, Jujian Zhang +-/ +import Mathlib.RingTheory.IsTensorProduct +import Mathlib.RingTheory.Localization.Module + +/-! +# Localized Module + +Given a commutative semiring `R`, a multiplicative subset `S ⊆ R` and an `R`-module `M`, we can +localize `M` by `S`. This gives us a `Localization S`-module. + +## Main definition + +* `isLocalizedModule_iff_isBaseChange` : A localization of modules corresponds to a base change. +-/ + +variable {R : Type*} [CommSemiring R] (S : Submonoid R) + (A : Type*) [CommRing A] [Algebra R A] [IsLocalization S A] + {M : Type*} [AddCommMonoid M] [Module R M] [Module A M] [IsScalarTower R A M] + {M' : Type*} [AddCommMonoid M'] [Module R M'] [Module A M'] [IsScalarTower R A M'] + (f : M →ₗ[R] M') + +/-- The forward direction of `isLocalizedModule_iff_isBaseChange`. It is also used to prove the +other direction. -/ +theorem IsLocalizedModule.isBaseChange [IsLocalizedModule S f] : IsBaseChange A f := + .of_lift_unique _ fun Q _ _ _ _ g ↦ by + obtain ⟨ℓ, rfl, h₂⟩ := IsLocalizedModule.is_universal S f g fun s ↦ by + rw [← (Algebra.lsmul R (A := A) R Q).commutes]; exact (IsLocalization.map_units A s).map _ + refine ⟨ℓ.extendScalarsOfIsLocalization S A, by simp, fun g'' h ↦ ?_⟩ + cases h₂ (LinearMap.restrictScalars R g'') h; rfl + +/-- The map `(f : M →ₗ[R] M')` is a localization of modules iff the map +`(localization S) × M → N, (s, m) ↦ s • f m` is the tensor product (insomuch as it is the universal +bilinear map). +In particular, there is an isomorphism between `LocalizedModule S M` and `(Localization S) ⊗[R] M` +given by `m/s ↦ (1/s) ⊗ₜ m`. +-/ +theorem isLocalizedModule_iff_isBaseChange : IsLocalizedModule S f ↔ IsBaseChange A f := by + refine ⟨fun _ ↦ IsLocalizedModule.isBaseChange S A f, fun h ↦ ?_⟩ + have : IsBaseChange A (LocalizedModule.mkLinearMap S M) := IsLocalizedModule.isBaseChange S A _ + let e := (this.equiv.symm.trans h.equiv).restrictScalars R + convert IsLocalizedModule.of_linearEquiv S (LocalizedModule.mkLinearMap S M) e + ext + rw [LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply, + LinearEquiv.restrictScalars_apply, LinearEquiv.trans_apply, IsBaseChange.equiv_symm_apply, + IsBaseChange.equiv_tmul, one_smul] diff --git a/Mathlib/RingTheory/Localization/Basic.lean b/Mathlib/RingTheory/Localization/Basic.lean index 0542ec81dfa5c..a2595c80b2a00 100644 --- a/Mathlib/RingTheory/Localization/Basic.lean +++ b/Mathlib/RingTheory/Localization/Basic.lean @@ -4,11 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Mario Carneiro, Johan Commelin, Amelia Livingston, Anne Baanen -/ import Mathlib.Algebra.Algebra.Tower -import Mathlib.Algebra.Ring.Equiv +import Mathlib.Algebra.GroupWithZero.NonZeroDivisors import Mathlib.GroupTheory.MonoidLocalization import Mathlib.RingTheory.Ideal.Basic -import Mathlib.Algebra.GroupWithZero.NonZeroDivisors -import Mathlib.Tactic.Ring +import Mathlib.GroupTheory.GroupAction.Ring #align_import ring_theory.localization.basic from "leanprover-community/mathlib"@"b69c9a770ecf37eb21f7b8cf4fa00de3b62694ec" @@ -97,7 +96,7 @@ variable [Algebra R S] {P : Type*} [CommSemiring P] /-- The typeclass `IsLocalization (M : Submonoid R) S` where `S` is an `R`-algebra expresses that `S` is isomorphic to the localization of `R` at `M`. -/ -class IsLocalization : Prop where +@[mk_iff] class IsLocalization : Prop where --Porting note: add ' to fields, and made new versions of these with either `S` or `M` explicit. /-- Everything in the image of `algebraMap` is a unit -/ map_units' : ∀ y : M, IsUnit (algebraMap R S y) @@ -175,6 +174,10 @@ theorem toLocalizationMap_toMap_apply (x) : (toLocalizationMap M S).toMap x = al rfl #align is_localization.to_localization_map_to_map_apply IsLocalization.toLocalizationMap_toMap_apply +theorem surj₂ : ∀ z w : S, ∃ z' w' : R, ∃ d : M, + (z * algebraMap R S d = algebraMap R S z') ∧ (w * algebraMap R S d = algebraMap R S w') := + (toLocalizationMap M S).surj₂ + end variable (M) {S} @@ -539,12 +542,12 @@ theorem lift_eq_iff {x y : R × M} : @[simp] theorem lift_comp : (lift hg).comp (algebraMap R S) = g := - RingHom.ext <| (FunLike.ext_iff (F := MonoidHom _ _)).1 <| (toLocalizationMap M S).lift_comp _ + RingHom.ext <| (DFunLike.ext_iff (F := MonoidHom _ _)).1 <| (toLocalizationMap M S).lift_comp _ #align is_localization.lift_comp IsLocalization.lift_comp @[simp] theorem lift_of_comp (j : S →+* P) : lift (isUnit_comp M j) = j := - RingHom.ext <| (FunLike.ext_iff (F := MonoidHom _ _)).1 <| + RingHom.ext <| (DFunLike.ext_iff (F := MonoidHom _ _)).1 <| (toLocalizationMap M S).lift_of_comp j.toMonoidHom #align is_localization.lift_of_comp IsLocalization.lift_of_comp @@ -553,7 +556,7 @@ variable (M) /-- See note [partially-applied ext lemmas] -/ theorem monoidHom_ext ⦃j k : S →* P⦄ (h : j.comp (algebraMap R S : R →* S) = k.comp (algebraMap R S)) : j = k := - Submonoid.LocalizationMap.epic_of_localizationMap (toLocalizationMap M S) <| FunLike.congr_fun h + Submonoid.LocalizationMap.epic_of_localizationMap (toLocalizationMap M S) <| DFunLike.congr_fun h #align is_localization.monoid_hom_ext IsLocalization.monoidHom_ext /-- See note [partially-applied ext lemmas] -/ @@ -587,7 +590,7 @@ variable {M} theorem lift_unique {j : S →+* P} (hj : ∀ x, j ((algebraMap R S) x) = g x) : lift hg = j := RingHom.ext <| - (FunLike.ext_iff (F := MonoidHom _ _)).1 <| + (DFunLike.ext_iff (F := MonoidHom _ _)).1 <| Submonoid.LocalizationMap.lift_unique (toLocalizationMap M S) (g := g.toMonoidHom) hg (j := j.toMonoidHom) hj #align is_localization.lift_unique IsLocalization.lift_unique @@ -788,6 +791,17 @@ noncomputable def atUnits (H : M ≤ IsUnit.submonoid R) : R ≃ₐ[R] S := by end at_units +section + +variable (M S) (Q : Type*) [CommSemiring Q] [Algebra P Q] + +/-- Injectivity of a map descends to the map induced on localizations. -/ +theorem map_injective_of_injective (h : Function.Injective g) [IsLocalization (M.map g) Q] : + Function.Injective (map Q g M.le_comap_map : S → Q) := + (toLocalizationMap M S).map_injective_of_injective h (toLocalizationMap (M.map g) Q) + +end + end IsLocalization section @@ -817,8 +831,8 @@ theorem isLocalization_iff_of_algEquiv [Algebra R P] (h : S ≃ₐ[R] P) : #align is_localization.is_localization_iff_of_alg_equiv IsLocalization.isLocalization_iff_of_algEquiv theorem isLocalization_iff_of_ringEquiv (h : S ≃+* P) : - IsLocalization M S ↔ haveI := (h.toRingHom.comp <| algebraMap R S).toAlgebra; - IsLocalization M P := + IsLocalization M S ↔ + haveI := (h.toRingHom.comp <| algebraMap R S).toAlgebra; IsLocalization M P := letI := (h.toRingHom.comp <| algebraMap R S).toAlgebra isLocalization_iff_of_algEquiv M { h with commutes' := fun _ => rfl } #align is_localization.is_localization_iff_of_ring_equiv IsLocalization.isLocalization_iff_of_ringEquiv @@ -826,8 +840,8 @@ theorem isLocalization_iff_of_ringEquiv (h : S ≃+* P) : variable (S) theorem isLocalization_of_base_ringEquiv [IsLocalization M S] (h : R ≃+* P) : - haveI := ((algebraMap R S).comp h.symm.toRingHom).toAlgebra; - IsLocalization (M.map h.toMonoidHom) S := by + haveI := ((algebraMap R S).comp h.symm.toRingHom).toAlgebra + IsLocalization (M.map h.toMonoidHom) S := by letI : Algebra P S := ((algebraMap R S).comp h.symm.toRingHom).toAlgebra constructor · rintro ⟨_, ⟨y, hy, rfl⟩⟩ @@ -1249,25 +1263,7 @@ theorem sec_fst_ne_zero [Nontrivial R] [NoZeroDivisors S] (hM : M ≤ nonZeroDiv · exact IsLocalization.injective S hM #align is_localization.sec_fst_ne_zero IsLocalization.sec_fst_ne_zero -variable (S M) (Q : Type*) [CommRing Q] {g : R →+* P} [Algebra P Q] - -/-- Injectivity of a map descends to the map induced on localizations. -/ -theorem map_injective_of_injective (hg : Function.Injective g) - [i : IsLocalization (M.map g : Submonoid P) Q] : - Function.Injective (map Q g (Submonoid.le_comap_map M) : S → Q) := by - rw [injective_iff_map_eq_zero] - intro z hz - obtain ⟨a, b, rfl⟩ := mk'_surjective M z - rw [map_mk', mk'_eq_zero_iff] at hz - obtain ⟨⟨m', hm'⟩, hm⟩ := hz - rw [Submonoid.mem_map] at hm' - obtain ⟨n, hn, hnm⟩ := hm' - rw [Subtype.coe_mk, ← hnm, ← map_mul, ← map_zero g] at hm - rw [mk'_eq_zero_iff] - exact ⟨⟨n, hn⟩, hg hm⟩ -#align is_localization.map_injective_of_injective IsLocalization.map_injective_of_injective - -variable {S Q M} +variable {Q : Type*} [CommRing Q] {g : R →+* P} [Algebra P Q] variable (A : Type*) [CommRing A] [IsDomain A] @@ -1420,7 +1416,7 @@ theorem IsLocalization.algebraMap_apply_eq_map_map_submonoid (x) : algebraMap Rₘ Sₘ x = map Sₘ (algebraMap R S) (show _ ≤ (Algebra.algebraMapSubmonoid S M).comap _ from M.le_comap_map) x := - FunLike.congr_fun (IsLocalization.algebraMap_eq_map_map_submonoid _ _ _ _) x + DFunLike.congr_fun (IsLocalization.algebraMap_eq_map_map_submonoid _ _ _ _) x #align is_localization.algebra_map_apply_eq_map_map_submonoid IsLocalization.algebraMap_apply_eq_map_map_submonoid theorem IsLocalization.lift_algebraMap_eq_algebraMap : @@ -1436,7 +1432,8 @@ variable (Rₘ Sₘ) /-- Injectivity of the underlying `algebraMap` descends to the algebra induced by localization. -/ theorem localizationAlgebra_injective (hRS : Function.Injective (algebraMap R S)) : Function.Injective (@algebraMap Rₘ Sₘ _ _ (localizationAlgebra M S)) := - IsLocalization.map_injective_of_injective (M := M) _ hRS (i := i) + have : IsLocalization (M.map (algebraMap R S)) Sₘ := i + IsLocalization.map_injective_of_injective _ _ _ hRS #align localization_algebra_injective localizationAlgebra_injective end Algebra diff --git a/Mathlib/RingTheory/Localization/Integer.lean b/Mathlib/RingTheory/Localization/Integer.lean index ec4ca8ed6e21d..2076564b777ff 100644 --- a/Mathlib/RingTheory/Localization/Integer.lean +++ b/Mathlib/RingTheory/Localization/Integer.lean @@ -24,9 +24,9 @@ commutative ring, field of fractions -/ -variable {R : Type*} [CommRing R] {M : Submonoid R} {S : Type*} [CommRing S] +variable {R : Type*} [CommSemiring R] {M : Submonoid R} {S : Type*} [CommSemiring S] -variable [Algebra R S] {P : Type*} [CommRing P] +variable [Algebra R S] {P : Type*} [CommSemiring P] open Function @@ -42,25 +42,25 @@ variable (R) /-- Given `a : S`, `S` a localization of `R`, `IsInteger R a` iff `a` is in the image of the localization map from `R` to `S`. -/ def IsInteger (a : S) : Prop := - a ∈ (algebraMap R S).range + a ∈ (algebraMap R S).rangeS #align is_localization.is_integer IsLocalization.IsInteger end theorem isInteger_zero : IsInteger R (0 : S) := - Subring.zero_mem _ + Subsemiring.zero_mem _ #align is_localization.is_integer_zero IsLocalization.isInteger_zero theorem isInteger_one : IsInteger R (1 : S) := - Subring.one_mem _ + Subsemiring.one_mem _ #align is_localization.is_integer_one IsLocalization.isInteger_one theorem isInteger_add {a b : S} (ha : IsInteger R a) (hb : IsInteger R b) : IsInteger R (a + b) := - Subring.add_mem _ ha hb + Subsemiring.add_mem _ ha hb #align is_localization.is_integer_add IsLocalization.isInteger_add theorem isInteger_mul {a b : S} (ha : IsInteger R a) (hb : IsInteger R b) : IsInteger R (a * b) := - Subring.mul_mem _ ha hb + Subsemiring.mul_mem _ ha hb #align is_localization.is_integer_mul IsLocalization.isInteger_mul theorem isInteger_smul {a : R} {b : S} (hb : IsInteger R b) : IsInteger R (a • b) := by diff --git a/Mathlib/RingTheory/Localization/Integral.lean b/Mathlib/RingTheory/Localization/Integral.lean index 0e9e59a1618ac..5223d78028e4f 100644 --- a/Mathlib/RingTheory/Localization/Integral.lean +++ b/Mathlib/RingTheory/Localization/Integral.lean @@ -458,3 +458,38 @@ theorem ideal_span_singleton_map_subset {L : Type*} [IsDomain R] [IsDomain S] [F #align is_fraction_ring.ideal_span_singleton_map_subset IsFractionRing.ideal_span_singleton_map_subset end IsFractionRing + +lemma isAlgebraic_of_isLocalization {R} [CommRing R] (M : Submonoid R) (S) [CommRing S] + [Nontrivial R] [Algebra R S] [IsLocalization M S] : Algebra.IsAlgebraic R S := by + intro x + obtain ⟨x, s, rfl⟩ := IsLocalization.mk'_surjective M x + by_cases hs : (s : R) = 0 + · have := IsLocalization.mk'_spec S x s + rw [hs, map_zero, mul_zero] at this + exact ⟨X, X_ne_zero, by simp [IsLocalization.mk'_eq_mul_mk'_one x, ← this]⟩ + refine ⟨s • X - C x, ?_, ?_⟩ + · intro e; apply hs + simpa only [coeff_sub, coeff_smul, coeff_X_one, coeff_C_succ, sub_zero, coeff_zero, + ← Algebra.algebraMap_eq_smul_one, Submonoid.smul_def, + Algebra.id.map_eq_id, RingHom.id_apply] using congr_arg (Polynomial.coeff · 1) e + · simp only [map_sub, Algebra.smul_def, Submonoid.smul_def, + map_mul, AlgHom.commutes, aeval_X, IsLocalization.mk'_spec', aeval_C, sub_self] + +open nonZeroDivisors in +lemma isAlgebraic_of_isFractionRing {R S} (K L) [CommRing R] [CommRing S] [Field K] [CommRing L] + [Algebra R S] [Algebra R K] [Algebra R L] [Algebra S L] [Algebra K L] [IsScalarTower R S L] + [IsScalarTower R K L] [IsFractionRing S L] + (h : Algebra.IsIntegral R S) : Algebra.IsAlgebraic K L := by + intro x + obtain ⟨x, s, rfl⟩ := IsLocalization.mk'_surjective S⁰ x + apply IsIntegral.isAlgebraic + rw [IsLocalization.mk'_eq_mul_mk'_one] + apply RingHom.IsIntegralElem.mul + · apply IsIntegral.tower_top (R := R) + apply IsIntegral.map (IsScalarTower.toAlgHom R S L) + exact h x + · show IsIntegral _ _ + rw [← isAlgebraic_iff_isIntegral, ← IsAlgebraic.invOf_iff, isAlgebraic_iff_isIntegral] + apply IsIntegral.tower_top (R := R) + apply IsIntegral.map (IsScalarTower.toAlgHom R S L) + exact h s diff --git a/Mathlib/RingTheory/Localization/Module.lean b/Mathlib/RingTheory/Localization/Module.lean index 74847f8a73fa2..91ce0244fcd93 100644 --- a/Mathlib/RingTheory/Localization/Module.lean +++ b/Mathlib/RingTheory/Localization/Module.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Junyan Xu, Anne Baanen -/ import Mathlib.LinearAlgebra.Basis +import Mathlib.Algebra.Module.LocalizedModule import Mathlib.RingTheory.Localization.FractionRing import Mathlib.RingTheory.Localization.Integer @@ -18,8 +19,9 @@ This file contains some results about vector spaces over the field of fractions * `LinearIndependent.localization`: `b` is linear independent over a localization of `R` if it is linear independent over `R` itself - * `Basis.localizationLocalization`: promote an `R`-basis `b` of `A` to an `Rₛ`-basis of `Aₛ`, - where `Rₛ` and `Aₛ` are localizations of `R` and `A` at `s` respectively + * `Basis.ofIsLocalizedModule` / `Basis.localizationLocalization`: promote an `R`-basis `b` of `A` + to an `Rₛ`-basis of `Aₛ`, where `Rₛ` and `Aₛ` are localizations of `R` and `A` at `s` + respectively * `LinearIndependent.iff_fractionRing`: `b` is linear independent over `R` iff it is linear independent over `Frac(R)` -/ @@ -31,33 +33,102 @@ open nonZeroDivisors section Localization -variable {R : Type*} (Rₛ : Type*) [CommRing R] [CommRing Rₛ] [Algebra R Rₛ] +variable {R : Type*} (Rₛ : Type*) [CommSemiring R] (S : Submonoid R) -variable (S : Submonoid R) [hT : IsLocalization S Rₛ] - --- include hT +section IsLocalizedModule section AddCommMonoid -variable {M : Type*} [AddCommMonoid M] [Module R M] [Module Rₛ M] [IsScalarTower R Rₛ M] +open Submodule + +variable [CommSemiring Rₛ] [Algebra R Rₛ] [hT : IsLocalization S Rₛ] + +variable {M M' : Type*} [AddCommMonoid M] [Module R M] [Module Rₛ M] [IsScalarTower R Rₛ M] + [AddCommMonoid M'] [Module R M'] [Module Rₛ M'] [IsScalarTower R Rₛ M'] (f : M →ₗ[R] M') + [IsLocalizedModule S f] + +theorem span_eq_top_of_isLocalizedModule {v : Set M} (hv : span R v = ⊤) : + span Rₛ (f '' v) = ⊤ := top_unique fun x _ ↦ by + obtain ⟨⟨m, s⟩, h⟩ := IsLocalizedModule.surj S f x + rw [Submonoid.smul_def, ← algebraMap_smul Rₛ, ← Units.smul_isUnit (IsLocalization.map_units Rₛ s), + eq_comm, ← inv_smul_eq_iff] at h + refine h ▸ smul_mem _ _ (span_subset_span R Rₛ _ ?_) + rw [← LinearMap.coe_restrictScalars R, ← LinearMap.map_span, hv] + exact mem_map_of_mem mem_top + +theorem LinearIndependent.of_isLocalizedModule {ι : Type*} {v : ι → M} + (hv : LinearIndependent R v) : LinearIndependent Rₛ (f ∘ v) := by + rw [linearIndependent_iff'] at hv ⊢ + intro t g hg i hi + choose! a g' hg' using IsLocalization.exist_integer_multiples S t g + have h0 : f (∑ i in t, g' i • v i) = 0 := by + apply_fun ((a : R) • ·) at hg + rw [smul_zero, Finset.smul_sum] at hg + rw [map_sum, ← hg] + refine Finset.sum_congr rfl fun i hi => ?_ + rw [← smul_assoc, ← hg' i hi, map_smul, Function.comp_apply, algebraMap_smul] + obtain ⟨s, hs⟩ := (IsLocalizedModule.eq_zero_iff S f).mp h0 + simp_rw [Finset.smul_sum, Submonoid.smul_def, smul_smul] at hs + specialize hv t _ hs i hi + rw [← (IsLocalization.map_units Rₛ a).mul_right_eq_zero, ← Algebra.smul_def, ← hg' i hi] + exact (IsLocalization.map_eq_zero_iff S _ _).2 ⟨s, hv⟩ theorem LinearIndependent.localization {ι : Type*} {b : ι → M} (hli : LinearIndependent R b) : LinearIndependent Rₛ b := by - rw [linearIndependent_iff'] at hli ⊢ - intro s g hg i hi - choose! a g' hg' using IsLocalization.exist_integer_multiples S s g - specialize hli s g' _ i hi - · rw [← @smul_zero _ M _ _ (a : R), ← hg, Finset.smul_sum] - refine' Finset.sum_congr rfl fun i hi => _ - rw [← IsScalarTower.algebraMap_smul Rₛ, hg' i hi, smul_assoc] - refine' (IsLocalization.map_units Rₛ a).mul_right_eq_zero.mp _ - rw [← Algebra.smul_def, ← map_zero (algebraMap R Rₛ), ← hli, hg' i hi] + have := isLocalizedModule_id S M Rₛ + exact hli.of_isLocalizedModule Rₛ S .id #align linear_independent.localization LinearIndependent.localization end AddCommMonoid +section Basis + +variable [CommRing Rₛ] [Algebra R Rₛ] [hT : IsLocalization S Rₛ] + +open Submodule + +variable {M Mₛ : Type*} [AddCommGroup M] [AddCommGroup Mₛ] [Module R M] [Module R Mₛ] [Module R Mₛ] + [Module Rₛ Mₛ] (f : M →ₗ[R] Mₛ) [IsLocalizedModule S f] [IsScalarTower R Rₛ Mₛ] + {ι : Type*} (b : Basis ι R M) + +/-- If `M` has an `R`-basis, then localizing `M` at `S` has a basis over `R` localized at `S`. -/ +noncomputable def Basis.ofIsLocalizedModule : Basis ι Rₛ Mₛ := + .mk (b.linearIndependent.of_isLocalizedModule Rₛ S f) <| by + rw [Set.range_comp, span_eq_top_of_isLocalizedModule Rₛ S _ b.span_eq] + +@[simp] +theorem Basis.ofIsLocalizedModule_apply (i : ι) : b.ofIsLocalizedModule Rₛ S f i = f (b i) := by + rw [ofIsLocalizedModule, coe_mk, Function.comp_apply] + +@[simp] +theorem Basis.ofIsLocalizedModule_repr_apply (m : M) (i : ι) : + ((b.ofIsLocalizedModule Rₛ S f).repr (f m)) i = algebraMap R Rₛ (b.repr m i) := by + suffices ((b.ofIsLocalizedModule Rₛ S f).repr.toLinearMap.restrictScalars R) ∘ₗ f = + Finsupp.mapRange.linearMap (Algebra.linearMap R Rₛ) ∘ₗ b.repr.toLinearMap by + exact DFunLike.congr_fun (LinearMap.congr_fun this m) i + refine Basis.ext b fun i ↦ ?_ + rw [LinearMap.coe_comp, Function.comp_apply, LinearMap.coe_restrictScalars, + LinearEquiv.coe_coe, ← b.ofIsLocalizedModule_apply Rₛ S f, repr_self, LinearMap.coe_comp, + Function.comp_apply, LinearEquiv.coe_coe, repr_self, Finsupp.mapRange.linearMap_apply, + Finsupp.mapRange_single, Algebra.linearMap_apply, map_one] + +theorem Basis.ofIsLocalizedModule_span : + span R (Set.range (b.ofIsLocalizedModule Rₛ S f)) = LinearMap.range f := by + calc span R (Set.range (b.ofIsLocalizedModule Rₛ S f)) + _ = span R (f '' (Set.range b)) := by congr; ext; simp + _ = map f (span R (Set.range b)) := by rw [Submodule.map_span] + _ = LinearMap.range f := by rw [b.span_eq, Submodule.map_top] + +end Basis + +end IsLocalizedModule + section LocalizationLocalization +variable {R : Type*} (Rₛ : Type*) [CommSemiring R] [CommRing Rₛ] [Algebra R Rₛ] + +variable (S : Submonoid R) [hT : IsLocalization S Rₛ] + variable {A : Type*} [CommRing A] [Algebra R A] variable (Aₛ : Type*) [CommRing Aₛ] [Algebra A Aₛ] @@ -71,86 +142,41 @@ variable [hA : IsLocalization (Algebra.algebraMapSubmonoid A S) Aₛ] open Submodule theorem LinearIndependent.localization_localization {ι : Type*} {v : ι → A} - (hv : LinearIndependent R v) : LinearIndependent Rₛ (algebraMap A Aₛ ∘ v) := by - rw [linearIndependent_iff'] at hv ⊢ - intro s g hg i hi - choose! a g' hg' using IsLocalization.exist_integer_multiples S s g - have h0 : algebraMap A Aₛ (∑ i in s, g' i • v i) = 0 := by - apply_fun ((a : R) • ·) at hg - rw [smul_zero, Finset.smul_sum] at hg - rw [map_sum, ← hg] - refine' Finset.sum_congr rfl fun i hi => _ - rw [← smul_assoc, ← hg' i hi, Algebra.smul_def, map_mul, ← IsScalarTower.algebraMap_apply, ← - Algebra.smul_def, algebraMap_smul, Function.comp_apply] - obtain ⟨⟨_, r, hrS, rfl⟩, hr : algebraMap R A r * _ = 0⟩ := - (IsLocalization.map_eq_zero_iff (Algebra.algebraMapSubmonoid A S) _ _).1 h0 - simp_rw [Finset.mul_sum, ← Algebra.smul_def, smul_smul] at hr - specialize hv s _ hr i hi - rw [← (IsLocalization.map_units Rₛ a).mul_right_eq_zero, ← Algebra.smul_def, ← hg' i hi] - exact (IsLocalization.map_eq_zero_iff S _ _).2 ⟨⟨r, hrS⟩, hv⟩ + (hv : LinearIndependent R v) : LinearIndependent Rₛ ((algebraMap A Aₛ) ∘ v) := + hv.of_isLocalizedModule Rₛ S (IsScalarTower.toAlgHom R A Aₛ).toLinearMap #align linear_independent.localization_localization LinearIndependent.localization_localization -theorem SpanEqTop.localization_localization {v : Set A} (hv : span R v = ⊤) : - span Rₛ (algebraMap A Aₛ '' v) = ⊤ := by - rw [eq_top_iff] - rintro a' - - obtain ⟨a, ⟨_, s, hs, rfl⟩, rfl⟩ := - IsLocalization.mk'_surjective (Algebra.algebraMapSubmonoid A S) a' - rw [IsLocalization.mk'_eq_mul_mk'_one, mul_comm, ← map_one (algebraMap R A)] - erw [← IsLocalization.algebraMap_mk' A Rₛ Aₛ (1 : R) ⟨s, hs⟩] - -- `erw` needed to unify `⟨s, hs⟩` - rw [← Algebra.smul_def] - refine' smul_mem _ _ (span_subset_span R Rₛ _ _) - rw [← Algebra.coe_linearMap, ← LinearMap.coe_restrictScalars R, ← LinearMap.map_span] - exact mem_map_of_mem (hv.symm ▸ mem_top) -#align span_eq_top.localization_localization SpanEqTop.localization_localization +theorem span_eq_top_localization_localization {v : Set A} (hv : span R v = ⊤) : + span Rₛ (algebraMap A Aₛ '' v) = ⊤ := + span_eq_top_of_isLocalizedModule Rₛ S (IsScalarTower.toAlgHom R A Aₛ).toLinearMap hv +#align span_eq_top.localization_localization span_eq_top_localization_localization /-- If `A` has an `R`-basis, then localizing `A` at `S` has a basis over `R` localized at `S`. A suitable instance for `[Algebra A Aₛ]` is `localizationAlgebra`. -/ noncomputable def Basis.localizationLocalization {ι : Type*} (b : Basis ι R A) : Basis ι Rₛ Aₛ := - Basis.mk (b.linearIndependent.localization_localization _ S _) - (by rw [Set.range_comp, SpanEqTop.localization_localization Rₛ S Aₛ b.span_eq]) + b.ofIsLocalizedModule Rₛ S (IsScalarTower.toAlgHom R A Aₛ).toLinearMap #align basis.localization_localization Basis.localizationLocalization @[simp] theorem Basis.localizationLocalization_apply {ι : Type*} (b : Basis ι R A) (i) : b.localizationLocalization Rₛ S Aₛ i = algebraMap A Aₛ (b i) := - Basis.mk_apply _ _ _ + b.ofIsLocalizedModule_apply Rₛ S _ i #align basis.localization_localization_apply Basis.localizationLocalization_apply @[simp] theorem Basis.localizationLocalization_repr_algebraMap {ι : Type*} (b : Basis ι R A) (x i) : (b.localizationLocalization Rₛ S Aₛ).repr (algebraMap A Aₛ x) i = - algebraMap R Rₛ (b.repr x i) := - calc - (b.localizationLocalization Rₛ S Aₛ).repr (algebraMap A Aₛ x) i = - (b.localizationLocalization Rₛ S Aₛ).repr - ((b.repr x).sum fun j c => algebraMap R Rₛ c • algebraMap A Aₛ (b j)) i := by - simp_rw [IsScalarTower.algebraMap_smul, Algebra.smul_def, - IsScalarTower.algebraMap_apply R A Aₛ, ← _root_.map_mul, ← map_finsupp_sum, ← - Algebra.smul_def, ← Finsupp.total_apply, Basis.total_repr] - _ = (b.repr x).sum fun j c => algebraMap R Rₛ c • Finsupp.single j (1 : Rₛ) i := by - simp_rw [← b.localizationLocalization_apply Rₛ S Aₛ, map_finsupp_sum, LinearEquiv.map_smul, - Basis.repr_self, Finsupp.sum_apply, Finsupp.smul_apply] - _ = _ := - (Finset.sum_eq_single i (fun j _ hj => by simp [hj]) fun hi => by - simp [Finsupp.not_mem_support_iff.mp hi]) - _ = algebraMap R Rₛ (b.repr x i) := by simp [Algebra.smul_def] + algebraMap R Rₛ (b.repr x i) := b.ofIsLocalizedModule_repr_apply Rₛ S _ _ i #align basis.localization_localization_repr_algebra_map Basis.localizationLocalization_repr_algebraMap theorem Basis.localizationLocalization_span {ι : Type*} (b : Basis ι R A) : Submodule.span R (Set.range (b.localizationLocalization Rₛ S Aₛ)) = - LinearMap.range (IsScalarTower.toAlgHom R A Aₛ) := - calc span R (Set.range ↑(localizationLocalization Rₛ S Aₛ b)) - _ = span R (↑(IsScalarTower.toAlgHom R A Aₛ) '' Set.range ↑b) := by congr; ext; simp - _ = map (IsScalarTower.toAlgHom R A Aₛ) (span R (Set.range b)) := by rw [Submodule.map_span] - _ = LinearMap.range (IsScalarTower.toAlgHom R A Aₛ) := by rw [b.span_eq, Submodule.map_top] + LinearMap.range (IsScalarTower.toAlgHom R A Aₛ) := b.ofIsLocalizedModule_span Rₛ S _ end LocalizationLocalization -end Localization section FractionRing @@ -168,8 +194,8 @@ end FractionRing section -variable {R : Type*} [CommRing R] (S : Submonoid R) -variable (A : Type*) [CommRing A] [Algebra R A] [IsLocalization S A] +variable {R : Type*} [CommSemiring R] (S : Submonoid R) +variable (A : Type*) [CommSemiring A] [Algebra R A] [IsLocalization S A] variable {M N : Type*} [AddCommMonoid M] [Module R M] [Module A M] [IsScalarTower R A M] [AddCommMonoid N] [Module R N] [Module A N] [IsScalarTower R A N] diff --git a/Mathlib/RingTheory/Multiplicity.lean b/Mathlib/RingTheory/Multiplicity.lean index 132dd19448064..2dfea1218d9d1 100644 --- a/Mathlib/RingTheory/Multiplicity.lean +++ b/Mathlib/RingTheory/Multiplicity.lean @@ -511,7 +511,7 @@ theorem finite_mul_aux {p : α} (hp : Prime p) {a b : α} : ⟨s, mul_right_cancel₀ hp.1 (by rw [add_assoc, tsub_add_cancel_of_le (succ_le_of_lt hm0)] simp_all [mul_comm, mul_assoc, mul_left_comm, pow_add])⟩ -termination_by finite_mul_aux _ _ n m => n+m +termination_by n m => n + m #align multiplicity.finite_mul_aux multiplicity.finite_mul_aux theorem finite_mul {p a b : α} (hp : Prime p) : Finite p a → Finite p b → Finite p (a * b) := diff --git a/Mathlib/RingTheory/MvPolynomial/Basic.lean b/Mathlib/RingTheory/MvPolynomial/Basic.lean index 4cfef9d815be2..01fa8df188bc5 100644 --- a/Mathlib/RingTheory/MvPolynomial/Basic.lean +++ b/Mathlib/RingTheory/MvPolynomial/Basic.lean @@ -5,9 +5,9 @@ Authors: Johannes Hölzl -/ import Mathlib.Algebra.CharP.Basic import Mathlib.Data.Polynomial.AlgebraMap -import Mathlib.Data.MvPolynomial.CommRing import Mathlib.Data.MvPolynomial.Variables import Mathlib.LinearAlgebra.FinsuppVectorSpace +import Mathlib.LinearAlgebra.FreeModule.Finite.Basic #align_import ring_theory.mv_polynomial.basic from "leanprover-community/mathlib"@"2f5b500a507264de86d666a5f87ddb976e2d8de4" @@ -148,6 +148,23 @@ theorem linearIndependent_X : LinearIndependent R (X : σ → MvPolynomial σ R) set_option linter.uppercaseLean3 false in #align mv_polynomial.linear_independent_X MvPolynomial.linearIndependent_X +private lemma finite_setOf_bounded (α) [Finite α] (n : ℕ) : Finite {f : α →₀ ℕ | ∀ a, f a ≤ n} := + ((Set.Finite.pi' fun _ ↦ Set.finite_le_nat _).preimage <| + DFunLike.coe_injective.injOn _).to_subtype + +instance [Finite σ] (N : ℕ) : Module.Finite R (restrictDegree σ R N) := + have := finite_setOf_bounded σ N + Module.Finite.of_basis (basisRestrictSupport R _) + +instance [Finite σ] (N : ℕ) : Module.Finite R (restrictTotalDegree σ R N) := + have := finite_setOf_bounded σ N + have : Finite {s : σ →₀ ℕ | s.sum (fun _ e ↦ e) ≤ N} := by + rw [Set.finite_coe_iff] at this ⊢ + exact this.subset fun n hn i ↦ (eq_or_ne (n i) 0).elim + (fun h ↦ h.trans_le N.zero_le) fun h ↦ + (Finset.single_le_sum (fun _ _ ↦ Nat.zero_le _) <| Finsupp.mem_support_iff.mpr h).trans hn + Module.Finite.of_basis (basisRestrictSupport R _) + end Degree end MvPolynomial diff --git a/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean b/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean index ed0570655eda9..369691da21d7d 100644 --- a/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean +++ b/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean @@ -276,7 +276,7 @@ theorem homogeneousComponent_zero : homogeneousComponent 0 φ = C (coeff 0 φ) : · simp only [coeff_homogeneousComponent, sum_eq_zero_iff, Finsupp.zero_apply, if_true, coeff_C, eq_self_iff_true, forall_true_iff] · rw [coeff_homogeneousComponent, if_neg, coeff_C, if_neg (Ne.symm hd)] - simp only [FunLike.ext_iff, Finsupp.zero_apply] at hd + simp only [DFunLike.ext_iff, Finsupp.zero_apply] at hd simp [hd] #align mv_polynomial.homogeneous_component_zero MvPolynomial.homogeneousComponent_zero diff --git a/Mathlib/RingTheory/MvPolynomial/NewtonIdentities.lean b/Mathlib/RingTheory/MvPolynomial/NewtonIdentities.lean index f93639b52657e..82b52d0178d43 100644 --- a/Mathlib/RingTheory/MvPolynomial/NewtonIdentities.lean +++ b/Mathlib/RingTheory/MvPolynomial/NewtonIdentities.lean @@ -8,10 +8,7 @@ import Mathlib.Data.Finset.Card import Mathlib.Data.Fintype.Basic import Mathlib.Data.MvPolynomial.CommRing import Mathlib.Data.MvPolynomial.Rename -import Mathlib.Data.Nat.Parity -import Mathlib.RingTheory.MvPolynomial.Basic import Mathlib.RingTheory.MvPolynomial.Symmetric -import Mathlib.RingTheory.Polynomial.Basic /-! # Newton's Identities diff --git a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean index e8f70f29aafde..568ffe8f9fb54 100644 --- a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean +++ b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Antoine Chambert-Loir, María Inés de Frutos-Fernández -/ import Mathlib.Algebra.GradedMonoid -import Mathlib.Data.MvPolynomial.Variables +import Mathlib.Data.MvPolynomial.Basic #align_import ring_theory.mv_polynomial.weighted_homogeneous from "leanprover-community/mathlib"@"2f5b500a507264de86d666a5f87ddb976e2d8de4" @@ -458,7 +458,7 @@ theorem weightedHomogeneousComponent_zero [NoZeroSMulDivisors ℕ M] (hw : ∀ i simp only [weightedDegree', LinearMap.toAddMonoidHom_coe, Finsupp.total_apply, Finsupp.sum, sum_eq_zero_iff, Finsupp.mem_support_iff, Ne.def, smul_eq_zero, not_forall, not_or, and_self_left, exists_prop] - simp only [FunLike.ext_iff, Finsupp.coe_zero, Pi.zero_apply, not_forall] at hd + simp only [DFunLike.ext_iff, Finsupp.coe_zero, Pi.zero_apply, not_forall] at hd obtain ⟨i, hi⟩ := hd exact ⟨i, hi, hw i⟩ #align mv_polynomial.weighted_homogeneous_component_zero MvPolynomial.weightedHomogeneousComponent_zero diff --git a/Mathlib/RingTheory/Noetherian.lean b/Mathlib/RingTheory/Noetherian.lean index 610dba1027af7..79be281f08df5 100644 --- a/Mathlib/RingTheory/Noetherian.lean +++ b/Mathlib/RingTheory/Noetherian.lean @@ -157,6 +157,10 @@ instance (priority := 100) IsNoetherian.finite [IsNoetherian R M] : Finite R M : ⟨IsNoetherian.noetherian ⊤⟩ #align module.is_noetherian.finite Module.IsNoetherian.finite +instance {R₁ S : Type*} [CommSemiring R₁] [Semiring S] [Algebra R₁ S] + [IsNoetherian R₁ S] (I : Ideal S) : Finite R₁ I := + IsNoetherian.finite R₁ ((I : Submodule S S).restrictScalars R₁) + variable {R M} theorem Finite.of_injective [IsNoetherian R N] (f : M →ₗ[R] N) (hf : Function.Injective f) : @@ -589,7 +593,7 @@ instance isNoetherian_of_isNoetherianRing_of_finite (R M : Type*) [Ring R] [AddCommGroup M] [Module R M] [IsNoetherianRing R] [Module.Finite R M] : IsNoetherian R M := have : IsNoetherian R (⊤ : Submodule R M) := - isNoetherian_of_fg_of_noetherian _ $ Module.finite_def.mp inferInstance + isNoetherian_of_fg_of_noetherian _ <| Module.finite_def.mp inferInstance isNoetherian_of_linearEquiv (LinearEquiv.ofTop (⊤ : Submodule R M) rfl) #align is_noetherian_of_fg_of_noetherian' isNoetherian_of_isNoetherianRing_of_finite diff --git a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean index d25cc3befe232..fcc24cadb7a92 100644 --- a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean @@ -504,8 +504,7 @@ lemma _root_.Set.mem_center_iff_addMonoidHom (a : R) : AddMonoidHom.comp .mul (.mulRight a) = .compl₂ .mul (.mulLeft a) ∧ AddMonoidHom.compr₂ .mul (.mulRight a) = .compl₂ .mul (.mulRight a) := by rw [Set.mem_center_iff, isMulCentral_iff] - simp_rw [FunLike.ext_iff] - rfl + simp [DFunLike.ext_iff] end NonUnitalNonAssocSemiring @@ -941,7 +940,7 @@ theorem eqOn_sclosure {f g : F} {s : Set R} (h : Set.EqOn (f : R → S) (g : R theorem eq_of_eqOn_stop {f g : F} (h : Set.EqOn (f : R → S) (g : R → S) (⊤ : NonUnitalSubsemiring R)) : f = g := - FunLike.ext _ _ fun _ => h trivial + DFunLike.ext _ _ fun _ => h trivial #align non_unital_ring_hom.eq_of_eq_on_stop NonUnitalRingHom.eq_of_eqOn_stop theorem eq_of_eqOn_sdense {s : Set R} (hs : closure s = ⊤) {f g : F} diff --git a/Mathlib/RingTheory/OreLocalization/OreSet.lean b/Mathlib/RingTheory/OreLocalization/OreSet.lean index d7c90f4f2b8a7..64853a88b774a 100644 --- a/Mathlib/RingTheory/OreLocalization/OreSet.lean +++ b/Mathlib/RingTheory/OreLocalization/OreSet.lean @@ -5,6 +5,7 @@ Authors: Jakob von Raumer, Kevin Klinge -/ import Mathlib.Algebra.Ring.Regular import Mathlib.GroupTheory.Submonoid.Basic +import Mathlib.Algebra.GroupWithZero.Basic #align_import ring_theory.ore_localization.ore_set from "leanprover-community/mathlib"@"422e70f7ce183d2900c586a8cda8381e788a0c62" diff --git a/Mathlib/RingTheory/Perfection.lean b/Mathlib/RingTheory/Perfection.lean index c436dda16be99..a8e8e98ce4e09 100644 --- a/Mathlib/RingTheory/Perfection.lean +++ b/Mathlib/RingTheory/Perfection.lean @@ -177,8 +177,8 @@ variable (R p) instance perfectRing : PerfectRing (Ring.Perfection R p) p where bijective_frobenius := Function.bijective_iff_has_inverse.mpr ⟨pthRoot R p, - FunLike.congr_fun <| @frobenius_pthRoot R _ p _ _, - FunLike.congr_fun <| @pthRoot_frobenius R _ p _ _⟩ + DFunLike.congr_fun <| @frobenius_pthRoot R _ p _ _, + DFunLike.congr_fun <| @pthRoot_frobenius R _ p _ _⟩ #align perfection.perfect_ring Perfection.perfectRing /-- Given rings `R` and `S` of characteristic `p`, with `R` being perfect, diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index 1386a276f94ca..4419555f35e46 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -9,7 +9,6 @@ import Mathlib.Data.MvPolynomial.CommRing import Mathlib.Data.MvPolynomial.Equiv import Mathlib.RingTheory.Polynomial.Content import Mathlib.RingTheory.UniqueFactorizationDomain -import Mathlib.RingTheory.Ideal.QuotientOperations #align_import ring_theory.polynomial.basic from "leanprover-community/mathlib"@"da420a8c6dd5bdfb85c4ced85c34388f633bc6ff" diff --git a/Mathlib/RingTheory/Polynomial/Cyclotomic/Basic.lean b/Mathlib/RingTheory/Polynomial/Cyclotomic/Basic.lean index 3ce19acbfc083..e3ca042ec445d 100644 --- a/Mathlib/RingTheory/Polynomial/Cyclotomic/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Cyclotomic/Basic.lean @@ -8,9 +8,7 @@ import Mathlib.Algebra.Polynomial.BigOperators import Mathlib.RingTheory.RootsOfUnity.Complex import Mathlib.Data.Polynomial.Lifts import Mathlib.Data.Polynomial.Splits -import Mathlib.Data.ZMod.Algebra import Mathlib.FieldTheory.RatFunc -import Mathlib.FieldTheory.Separable import Mathlib.NumberTheory.ArithmeticFunction import Mathlib.RingTheory.RootsOfUnity.Basic diff --git a/Mathlib/RingTheory/Polynomial/Cyclotomic/Expand.lean b/Mathlib/RingTheory/Polynomial/Cyclotomic/Expand.lean index 1f76d7e29433f..e406850ac43f4 100644 --- a/Mathlib/RingTheory/Polynomial/Cyclotomic/Expand.lean +++ b/Mathlib/RingTheory/Polynomial/Cyclotomic/Expand.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Riccardo Brasca -/ import Mathlib.RingTheory.Polynomial.Cyclotomic.Roots +import Mathlib.Data.ZMod.Algebra #align_import ring_theory.polynomial.cyclotomic.expand from "leanprover-community/mathlib"@"0723536a0522d24fc2f159a096fb3304bef77472" diff --git a/Mathlib/RingTheory/Polynomial/Cyclotomic/Roots.lean b/Mathlib/RingTheory/Polynomial/Cyclotomic/Roots.lean index 1a07077def6dc..c6945a0e076d0 100644 --- a/Mathlib/RingTheory/Polynomial/Cyclotomic/Roots.lean +++ b/Mathlib/RingTheory/Polynomial/Cyclotomic/Roots.lean @@ -78,7 +78,7 @@ private theorem isRoot_cyclotomic_iff' {n : ℕ} {K : Type*} [Field K] {μ : K} rw [isRoot_of_unity_iff hnpos _] exact ⟨n, n.mem_divisors_self hnpos.ne', hμ⟩ by_contra hnμ - have ho : 0 < orderOf μ := (isOfFinOrder_iff_pow_eq_one.2 $ ⟨n, hnpos, hμn⟩).orderOf_pos + have ho : 0 < orderOf μ := (isOfFinOrder_iff_pow_eq_one.2 <| ⟨n, hnpos, hμn⟩).orderOf_pos have := pow_orderOf_eq_one μ rw [isRoot_of_unity_iff ho] at this obtain ⟨i, hio, hiμ⟩ := this diff --git a/Mathlib/RingTheory/Polynomial/GaussLemma.lean b/Mathlib/RingTheory/Polynomial/GaussLemma.lean index ad1255c106e75..1a55097cad7b0 100644 --- a/Mathlib/RingTheory/Polynomial/GaussLemma.lean +++ b/Mathlib/RingTheory/Polynomial/GaussLemma.lean @@ -153,7 +153,7 @@ open IsIntegrallyClosed theorem Monic.irreducible_iff_irreducible_map_fraction_map [IsIntegrallyClosed R] {p : R[X]} (h : p.Monic) : Irreducible p ↔ Irreducible (p.map <| algebraMap R K) := by /- The ← direction follows from `IsPrimitive.irreducible_of_irreducible_map_of_injective`. - For the → direction, it is enought to show that if `(p.map $ algebraMap R K) = a * b` and + For the → direction, it is enought to show that if `(p.map <| algebraMap R K) = a * b` and `a` is not a unit then `b` is a unit -/ refine' ⟨fun hp => diff --git a/Mathlib/RingTheory/Polynomial/Hermite/Basic.lean b/Mathlib/RingTheory/Polynomial/Hermite/Basic.lean index d21b4b7548141..525b961234471 100644 --- a/Mathlib/RingTheory/Polynomial/Hermite/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Hermite/Basic.lean @@ -172,7 +172,7 @@ theorem coeff_hermite_explicit : simp only -- Factor out (-1)'s. rw [mul_comm (↑k + _ : ℤ), sub_eq_add_neg] - nth_rw 2 [neg_eq_neg_one_mul] + nth_rw 3 [neg_eq_neg_one_mul] simp only [mul_assoc, ← mul_add, pow_succ] congr 2 -- Factor out double factorials. @@ -186,20 +186,15 @@ theorem coeff_hermite_explicit : rw [(by ring : 2 * (n + 1) + (k + 1) = 2 * n + 1 + (k + 1) + 1), (by ring : 2 * (n + 1) + k = 2 * n + 1 + (k + 1)), (by ring : 2 * n + (k + 2) = 2 * n + 1 + (k + 1))] - rw [Nat.choose, Nat.choose_succ_right_eq (2 * n + 1 + (k + 1)) (k + 1), Nat.add_sub_cancel, - Int.negSucc_eq] - -- porting note: ring could not solve the goal so the lines 195, 198-200 were added. - ring_nf - simp only [sub_eq_add_neg, ← neg_mul, ← right_distrib _ _ ((-(1 : ℤ)) ^ n), ← neg_add] - norm_cast - simp only [← add_assoc, add_comm] + rw [Nat.choose, Nat.choose_succ_right_eq (2 * n + 1 + (k + 1)) (k + 1), Nat.add_sub_cancel] + ring change _ = hermite_explicit _ _ rw [← add_assoc, coeff_hermite_succ_succ, hermite_explicit_recur] congr · rw [coeff_hermite_explicit (n + 1) k] · rw [(by ring : 2 * (n + 1) + k = 2 * n + (k + 2)), coeff_hermite_explicit n (k + 2)] -- porting note: Lean 3 worked this out automatically -termination_by _ n k => (n, k) +termination_by n k => (n, k) #align polynomial.coeff_hermite_explicit Polynomial.coeff_hermite_explicit theorem coeff_hermite_of_even_add {n k : ℕ} (hnk : Even (n + k)) : diff --git a/Mathlib/RingTheory/Polynomial/Nilpotent.lean b/Mathlib/RingTheory/Polynomial/Nilpotent.lean index 38917dbbcb84d..2b88a2427e1a0 100644 --- a/Mathlib/RingTheory/Polynomial/Nilpotent.lean +++ b/Mathlib/RingTheory/Polynomial/Nilpotent.lean @@ -3,7 +3,10 @@ Copyright (c) 2023 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Emilie Uthaiwat, Oliver Nash -/ -import Mathlib.RingTheory.Polynomial.Basic +import Mathlib.RingTheory.Nilpotent +import Mathlib.Data.Polynomial.AlgebraMap +import Mathlib.Data.Polynomial.Div +import Mathlib.RingTheory.Ideal.QuotientOperations /-! # Nilpotency in polynomial rings. @@ -86,7 +89,7 @@ protected lemma isNilpotent_iff : simp only [Polynomial.isNilpotent_iff, coeff_reverse] refine' ⟨fun h i ↦ _, fun h i ↦ _⟩ <;> rcases le_or_lt i N with hi | hi · simpa [tsub_tsub_cancel_of_le hi] using h (N - i) - · simp [coeff_eq_zero_of_natDegree_lt $ lt_of_le_of_lt hN hi] + · simp [coeff_eq_zero_of_natDegree_lt <| lt_of_le_of_lt hN hi] · simpa [hi, revAt_le] using h (N - i) · simpa [revAt_eq_self_of_lt hi] using h i @@ -140,7 +143,7 @@ theorem coeff_isUnit_isNilpotent_of_isUnit (hunit : IsUnit P) : have hcoeff : (f P).coeff n = 0 := by refine' coeff_eq_zero_of_degree_lt _ rw [hPQ.1] - exact (@WithBot.coe_pos _ _ _ n).2 (Ne.bot_lt hn) + exact WithBot.coe_pos.2 hn.bot_lt rw [coe_mapRingHom, coeff_map, ← RingHom.mem_ker, Ideal.mk_ker] at hcoeff exact hcoeff diff --git a/Mathlib/RingTheory/Polynomial/Pochhammer.lean b/Mathlib/RingTheory/Polynomial/Pochhammer.lean index 3989255b981be..8ede38f8ba446 100644 --- a/Mathlib/RingTheory/Polynomial/Pochhammer.lean +++ b/Mathlib/RingTheory/Polynomial/Pochhammer.lean @@ -151,24 +151,16 @@ theorem ascPochhammer_mul (n m : ℕ) : #align pochhammer_mul ascPochhammer_mul theorem ascPochhammer_nat_eq_ascFactorial (n : ℕ) : - ∀ k, (ascPochhammer ℕ k).eval (n + 1) = n.ascFactorial k + ∀ k, (ascPochhammer ℕ k).eval n = n.ascFactorial k | 0 => by rw [ascPochhammer_zero, eval_one, Nat.ascFactorial_zero] | t + 1 => by - rw [ascPochhammer_succ_right, eval_mul, ascPochhammer_nat_eq_ascFactorial n t] - simp only [eval_add, eval_X, eval_nat_cast, Nat.cast_id] - rw [Nat.ascFactorial_succ, add_right_comm, mul_comm] + rw [ascPochhammer_succ_right, eval_mul, ascPochhammer_nat_eq_ascFactorial n t, eval_add, eval_X, + eval_nat_cast, Nat.cast_id, Nat.ascFactorial_succ, mul_comm] #align pochhammer_nat_eq_asc_factorial ascPochhammer_nat_eq_ascFactorial theorem ascPochhammer_nat_eq_descFactorial (a b : ℕ) : (ascPochhammer ℕ b).eval a = (a + b - 1).descFactorial b := by - cases' b with b - · rw [Nat.descFactorial_zero, ascPochhammer_zero, Polynomial.eval_one] - rw [Nat.add_succ, Nat.succ_sub_succ, tsub_zero] - cases a - · simp only [Nat.zero_eq, ne_eq, Nat.succ_ne_zero, not_false_iff, ascPochhammer_ne_zero_eval_zero, - zero_add, Nat.descFactorial_succ, le_refl, tsub_eq_zero_of_le, zero_mul] - · rw [Nat.succ_add, ← Nat.add_succ, Nat.add_descFactorial_eq_ascFactorial, - ascPochhammer_nat_eq_ascFactorial] + rw [ascPochhammer_nat_eq_ascFactorial, Nat.add_descFactorial_eq_ascFactorial'] #align pochhammer_nat_eq_desc_factorial ascPochhammer_nat_eq_descFactorial @[simp] @@ -209,7 +201,7 @@ variable (S : Type*) [Semiring S] (r n : ℕ) @[simp] theorem ascPochhammer_eval_one (S : Type*) [Semiring S] (n : ℕ) : (ascPochhammer S n).eval (1 : S) = (n ! : S) := by - rw_mod_cast [ascPochhammer_nat_eq_ascFactorial, Nat.zero_ascFactorial] + rw_mod_cast [ascPochhammer_nat_eq_ascFactorial, Nat.one_ascFactorial] #align pochhammer_eval_one ascPochhammer_eval_one theorem factorial_mul_ascPochhammer (S : Type*) [Semiring S] (r n : ℕ) : @@ -343,6 +335,18 @@ theorem descPochhammer_mul (n m : ℕ) : · rw [descPochhammer_succ_right, Polynomial.mul_X_sub_int_cast_comp, ← mul_assoc, ih, Nat.succ_eq_add_one, ← add_assoc, descPochhammer_succ_right, Nat.cast_add, sub_add_eq_sub_sub] +theorem ascPochhammer_eval_neg_eq_descPochhammer (r : R) : ∀ (k : ℕ), + (ascPochhammer R k).eval (-r) = (-1)^k * (descPochhammer R k).eval r + | 0 => by + rw [ascPochhammer_zero, descPochhammer_zero] + simp only [eval_one, pow_zero, mul_one] + | (k+1) => by + rw [ascPochhammer_succ_right, mul_add, eval_add, eval_mul_X, ← Nat.cast_comm, eval_nat_cast_mul, + Nat.cast_comm, ← mul_add, ascPochhammer_eval_neg_eq_descPochhammer r k, mul_assoc, + descPochhammer_succ_right, mul_sub, eval_sub, eval_mul_X, ← Nat.cast_comm, eval_nat_cast_mul, + pow_add, pow_one, mul_assoc ((-1)^k) (-1), mul_sub, neg_one_mul, neg_mul_eq_mul_neg, + Nat.cast_comm, sub_eq_add_neg, neg_one_mul, neg_neg, ← mul_add] + theorem descPochhammer_int_eq_descFactorial (n : ℕ) : ∀ k, (descPochhammer ℤ k).eval (n : ℤ) = n.descFactorial k | 0 => by @@ -360,8 +364,8 @@ theorem descPochhammer_int_eq_descFactorial (n : ℕ) : exact (Int.ofNat_sub <| not_lt.mp h).symm theorem descPochhammer_int_eq_ascFactorial (a b : ℕ) : - (descPochhammer ℤ b).eval (a + b : ℤ) = a.ascFactorial b := by + (descPochhammer ℤ b).eval (a + b : ℤ) = (a + 1).ascFactorial b := by rw [← Nat.cast_add, descPochhammer_int_eq_descFactorial (a + b) b, - Nat.add_descFactorial_eq_ascFactorial] + Nat.add_descFactorial_eq_ascFactorial] end Ring diff --git a/Mathlib/RingTheory/Polynomial/ScaleRoots.lean b/Mathlib/RingTheory/Polynomial/ScaleRoots.lean index 43dc9e7f44e0d..48990903fe31d 100644 --- a/Mathlib/RingTheory/Polynomial/ScaleRoots.lean +++ b/Mathlib/RingTheory/Polynomial/ScaleRoots.lean @@ -144,11 +144,10 @@ theorem scaleRoots_eval₂_mul_of_commute {p : S[X]} (f : S →+* A) (a : A) (s (Finset.sum_congr rfl fun i _hi => by simp_rw [f.map_mul, f.map_pow, pow_add, hsa.mul_pow, mul_assoc]) _ = p.support.sum fun i : ℕ => f s ^ p.natDegree * (f (p.coeff i) * a ^ i) := - (Finset.sum_congr rfl fun i hi => by + Finset.sum_congr rfl fun i hi => by rw [mul_assoc, ← map_pow, (hf _ _).left_comm, map_pow, tsub_add_cancel_of_le] - exact le_natDegree_of_ne_zero (Polynomial.mem_support_iff.mp hi)) - _ = f s ^ p.natDegree * p.support.sum fun i : ℕ => f (p.coeff i) * a ^ i := Finset.mul_sum.symm - _ = f s ^ p.natDegree * eval₂ f a p := by simp [eval₂_eq_sum, sum_def] + exact le_natDegree_of_ne_zero (Polynomial.mem_support_iff.mp hi) + _ = f s ^ p.natDegree * eval₂ f a p := by simp [← Finset.mul_sum, eval₂_eq_sum, sum_def] theorem scaleRoots_eval₂_mul {p : S[X]} (f : S →+* R) (r : R) (s : S) : eval₂ f (f s * r) (scaleRoots p s) = f s ^ p.natDegree * eval₂ f r p := diff --git a/Mathlib/RingTheory/PowerSeries/Basic.lean b/Mathlib/RingTheory/PowerSeries/Basic.lean index 42b7957cbec84..67417d9f410f8 100644 --- a/Mathlib/RingTheory/PowerSeries/Basic.lean +++ b/Mathlib/RingTheory/PowerSeries/Basic.lean @@ -831,7 +831,7 @@ protected noncomputable def inv.aux (a : R) (φ : MvPowerSeries σ R) : MvPowerS else -a * ∑ x in antidiagonal n, if _ : x.2 < n then coeff R x.1 φ * inv.aux a φ x.2 else 0 -termination_by _ n => n +termination_by n => n #align mv_power_series.inv.aux MvPowerSeries.inv.aux theorem coeff_inv_aux [DecidableEq σ] (n : σ →₀ ℕ) (a : R) (φ : MvPowerSeries σ R) : diff --git a/Mathlib/RingTheory/QuotientNilpotent.lean b/Mathlib/RingTheory/QuotientNilpotent.lean index 437e6dc96931b..e31d0d72e14fc 100644 --- a/Mathlib/RingTheory/QuotientNilpotent.lean +++ b/Mathlib/RingTheory/QuotientNilpotent.lean @@ -24,7 +24,7 @@ variable {R S : Type*} [CommSemiring R] [CommRing S] [Algebra R S] (I : Ideal S) /-- Let `P` be a property on ideals. If `P` holds for square-zero ideals, and if `P I → P (J ⧸ I) → P J`, then `P` holds for all nilpotent ideals. -/ theorem Ideal.IsNilpotent.induction_on (hI : IsNilpotent I) - {P : ∀ ⦃S : Type _⦄ [CommRing S], ∀ _I : Ideal S, Prop} + {P : ∀ ⦃S : Type _⦄ [CommRing S], Ideal S → Prop} (h₁ : ∀ ⦃S : Type _⦄ [CommRing S], ∀ I : Ideal S, I ^ 2 = ⊥ → P I) (h₂ : ∀ ⦃S : Type _⦄ [CommRing S], ∀ I J : Ideal S, I ≤ J → P I → P (J.map (Ideal.Quotient.mk I)) → P J) : diff --git a/Mathlib/RingTheory/QuotientNoetherian.lean b/Mathlib/RingTheory/QuotientNoetherian.lean index b06747e21562d..4be3d2bb02efe 100644 --- a/Mathlib/RingTheory/QuotientNoetherian.lean +++ b/Mathlib/RingTheory/QuotientNoetherian.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ import Mathlib.RingTheory.Noetherian -import Mathlib.RingTheory.QuotientNilpotent +import Mathlib.RingTheory.Ideal.QuotientOperations #align_import ring_theory.quotient_noetherian from "leanprover-community/mathlib"@"da420a8c6dd5bdfb85c4ced85c34388f633bc6ff" diff --git a/Mathlib/RingTheory/RootsOfUnity/Basic.lean b/Mathlib/RingTheory/RootsOfUnity/Basic.lean index 32f9c2555c891..38793c953ce42 100644 --- a/Mathlib/RingTheory/RootsOfUnity/Basic.lean +++ b/Mathlib/RingTheory/RootsOfUnity/Basic.lean @@ -4,11 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ import Mathlib.Algebra.CharP.Two +import Mathlib.Algebra.CharP.Reduced import Mathlib.Algebra.NeZero -import Mathlib.Algebra.GCDMonoid.IntegrallyClosed import Mathlib.Data.Polynomial.RingDivision -import Mathlib.FieldTheory.Finite.Basic -import Mathlib.FieldTheory.Separable import Mathlib.GroupTheory.SpecificGroups.Cyclic import Mathlib.NumberTheory.Divisors import Mathlib.RingTheory.IntegralDomain diff --git a/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean b/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean index 72d5a359fbf3a..f041a037922e0 100644 --- a/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean +++ b/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean @@ -5,6 +5,8 @@ Authors: Riccardo Brasca, Johan Commelin -/ import Mathlib.RingTheory.RootsOfUnity.Basic import Mathlib.FieldTheory.Minpoly.IsIntegrallyClosed +import Mathlib.Algebra.GCDMonoid.IntegrallyClosed +import Mathlib.FieldTheory.Finite.Basic #align_import ring_theory.roots_of_unity.minpoly from "leanprover-community/mathlib"@"7fdeecc0d03cd40f7a165e6cf00a4d2286db599f" diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index 77eba283dbee9..6f586bfc92c65 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -70,15 +70,15 @@ theorem isSimpleModule_iff_isCoatom : IsSimpleModule R (M ⧸ m) ↔ IsCoatom m exact Submodule.comapMkQRelIso m #align is_simple_module_iff_is_coatom isSimpleModule_iff_isCoatom -theorem covby_iff_quot_is_simple {A B : Submodule R M} (hAB : A ≤ B) : +theorem covBy_iff_quot_is_simple {A B : Submodule R M} (hAB : A ≤ B) : A ⋖ B ↔ IsSimpleModule R (B ⧸ Submodule.comap B.subtype A) := by set f : Submodule R B ≃o Set.Iic B := Submodule.MapSubtype.relIso B with hf - rw [covby_iff_coatom_Iic hAB, isSimpleModule_iff_isCoatom, ← OrderIso.isCoatom_iff f, hf] + rw [covBy_iff_coatom_Iic hAB, isSimpleModule_iff_isCoatom, ← OrderIso.isCoatom_iff f, hf] -- This used to be in the next `simp`, but we need `erw` after leanprover/lean4#2644 erw [RelIso.coe_fn_mk] simp [-OrderIso.isCoatom_iff, Submodule.MapSubtype.relIso, Submodule.map_comap_subtype, inf_eq_right.2 hAB] -#align covby_iff_quot_is_simple covby_iff_quot_is_simple +#align covby_iff_quot_is_simple covBy_iff_quot_is_simple namespace IsSimpleModule @@ -222,9 +222,9 @@ theorem second_iso {X Y : Submodule R M} (_ : X ⋖ X ⊔ Y) : instance instJordanHolderLattice : JordanHolderLattice (Submodule R M) where IsMaximal := (· ⋖ ·) - lt_of_isMaximal := Covby.lt - sup_eq_of_isMaximal hxz hyz := Wcovby.sup_eq hxz.wcovby hyz.wcovby - isMaximal_inf_left_of_isMaximal_sup := inf_covby_of_covby_sup_of_covby_sup_left + lt_of_isMaximal := CovBy.lt + sup_eq_of_isMaximal hxz hyz := WCovBy.sup_eq hxz.wcovBy hyz.wcovBy + isMaximal_inf_left_of_isMaximal_sup := inf_covBy_of_covBy_sup_of_covBy_sup_left Iso := Iso iso_symm := iso_symm iso_trans := iso_trans diff --git a/Mathlib/RingTheory/Subring/Basic.lean b/Mathlib/RingTheory/Subring/Basic.lean index 2a13188dec350..e52b30855fc53 100644 --- a/Mathlib/RingTheory/Subring/Basic.lean +++ b/Mathlib/RingTheory/Subring/Basic.lean @@ -114,7 +114,6 @@ instance (priority := 75) toCommRing {R} [CommRing R] [SetLike S R] [SubringClas -- Prefer subclasses of `Ring` over subclasses of `SubringClass`. /-- A subring of a domain is a domain. -/ instance (priority := 75) {R} [Ring R] [IsDomain R] [SetLike S R] [SubringClass S R] : IsDomain s := - have := SubsemiringClass.noZeroDivisors (s := s) -- porting note: todo: fails without `have` NoZeroDivisors.to_isDomain _ -- Prefer subclasses of `Ring` over subclasses of `SubringClass`. @@ -602,7 +601,7 @@ theorem coe_map (f : R →+* S) (s : Subring R) : (s.map f : Set S) = f '' s := @[simp] theorem mem_map {f : R →+* S} {s : Subring R} {y : S} : y ∈ s.map f ↔ ∃ x ∈ s, f x = y := - Set.mem_image_iff_bex.trans $ by simp + Set.mem_image_iff_bex.trans <| by simp #align subring.mem_map Subring.mem_map @[simp] diff --git a/Mathlib/RingTheory/TensorProduct.lean b/Mathlib/RingTheory/TensorProduct.lean index 513bae32c5797..4a19481b670a6 100644 --- a/Mathlib/RingTheory/TensorProduct.lean +++ b/Mathlib/RingTheory/TensorProduct.lean @@ -322,7 +322,7 @@ protected theorem mul_assoc (x y z : A ⊗[R] B) : mul (mul x y) z = mul x (mul -- restate as an equality of morphisms so that we can use `ext` suffices LinearMap.llcomp R _ _ _ mul ∘ₗ mul = (LinearMap.llcomp R _ _ _ LinearMap.lflip <| LinearMap.llcomp R _ _ _ mul.flip ∘ₗ mul).flip by - exact FunLike.congr_fun (FunLike.congr_fun (FunLike.congr_fun this x) y) z + exact DFunLike.congr_fun (DFunLike.congr_fun (DFunLike.congr_fun this x) y) z ext xa xb ya yb za zb exact congr_arg₂ (· ⊗ₜ ·) (mul_assoc xa ya za) (mul_assoc xb yb zb) #align algebra.tensor_product.mul_assoc Algebra.TensorProduct.mul_assoc diff --git a/Mathlib/RingTheory/Trace.lean b/Mathlib/RingTheory/Trace.lean index 183407924e4e7..102562ae73030 100644 --- a/Mathlib/RingTheory/Trace.lean +++ b/Mathlib/RingTheory/Trace.lean @@ -241,7 +241,7 @@ theorem PowerBasis.trace_gen_eq_nextCoeff_minpoly [Nontrivial S] (pb : PowerBasi have d_pos' : 0 < (minpoly K pb.gen).natDegree := by simpa haveI : Nonempty (Fin pb.dim) := ⟨⟨0, d_pos⟩⟩ rw [trace_eq_matrix_trace pb.basis, trace_eq_neg_charpoly_coeff, charpoly_leftMulMatrix, ← - pb.natDegree_minpoly, Fintype.card_fin, ← nextCoeff_of_pos_natDegree _ d_pos'] + pb.natDegree_minpoly, Fintype.card_fin, ← nextCoeff_of_natDegree_pos d_pos'] #align power_basis.trace_gen_eq_next_coeff_minpoly PowerBasis.trace_gen_eq_nextCoeff_minpoly /-- Given `pb : PowerBasis K S`, then the trace of `pb.gen` is diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index 58417fafc3598..c161bc9d16a71 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -6,6 +6,7 @@ Authors: Kevin Buzzard, Johan Commelin, Patrick Massot import Mathlib.Algebra.Order.WithZero import Mathlib.RingTheory.Ideal.Operations import Mathlib.Tactic.TFAE +import Mathlib.Algebra.GroupPower.Order #align_import ring_theory.valuation.basic from "leanprover-community/mathlib"@"2196ab363eb097c008d4497125e0dde23fb36db2" @@ -55,7 +56,7 @@ In the `DiscreteValuation` locale: ## TODO -If ever someone extends `Valuation`, we should fully comply to the `FunLike` by migrating the +If ever someone extends `Valuation`, we should fully comply to the `DFunLike` by migrating the boilerplate lemmas to `ValuationClass`. -/ @@ -127,10 +128,10 @@ instance : ValuationClass (Valuation R Γ₀) R Γ₀ where map_add_le_max f := f.map_add_le_max' -- porting note: is this still helpful? Let's find out!! -/- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ -- instance : CoeFun (Valuation R Γ₀) fun _ => R → Γ₀ := - -- FunLike.hasCoeToFun + -- DFunLike.hasCoeToFun theorem toFun_eq_coe (v : Valuation R Γ₀) : v.toFun = v := rfl #align valuation.to_fun_eq_coe Valuation.toFun_eq_coe @@ -141,7 +142,7 @@ theorem toMonoidWithZeroHom_coe_eq_coe (v : Valuation R Γ₀) : @[ext] theorem ext {v₁ v₂ : Valuation R Γ₀} (h : ∀ r, v₁ r = v₂ r) : v₁ = v₂ := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align valuation.ext Valuation.ext variable (v : Valuation R Γ₀) {x y z : R} @@ -212,10 +213,10 @@ theorem map_pow : ∀ (x) (n : ℕ), v (x ^ n) = v x ^ n := v.toMonoidWithZeroHom.toMonoidHom.map_pow #align valuation.map_pow Valuation.map_pow -/-- Deprecated. Use `FunLike.ext_iff`. -/ --- @[deprecated] Porting note: using `FunLike.ext_iff` is not viable below for now +/-- Deprecated. Use `DFunLike.ext_iff`. -/ +-- @[deprecated] Porting note: using `DFunLike.ext_iff` is not viable below for now theorem ext_iff {v₁ v₂ : Valuation R Γ₀} : v₁ = v₂ ↔ ∀ r, v₁ r = v₂ r := - FunLike.ext_iff + DFunLike.ext_iff #align valuation.ext_iff Valuation.ext_iff -- The following definition is not an instance, because we have more than one `v` on a given `R`. @@ -613,7 +614,7 @@ section Monoid /-- A valuation is coerced to the underlying function `R → Γ₀`. -/ instance (R) (Γ₀) [Ring R] [LinearOrderedAddCommMonoidWithTop Γ₀] : - FunLike (AddValuation R Γ₀) R fun _ => Γ₀ where + FunLike (AddValuation R Γ₀) R Γ₀ where coe v := v.toMonoidWithZeroHom.toFun coe_injective' f g := by cases f; cases g; simp (config := {contextual := true}) diff --git a/Mathlib/RingTheory/Valuation/ValuationSubring.lean b/Mathlib/RingTheory/Valuation/ValuationSubring.lean index 7813e797b658c..0fa5c43528790 100644 --- a/Mathlib/RingTheory/Valuation/ValuationSubring.lean +++ b/Mathlib/RingTheory/Valuation/ValuationSubring.lean @@ -762,7 +762,7 @@ def unitsModPrincipalUnitsEquivResidueFieldUnits : (QuotientGroup.quotientKerEquivOfSurjective _ A.surjective_unitGroupToResidueFieldUnits) #align valuation_subring.units_mod_principal_units_equiv_residue_field_units ValuationSubring.unitsModPrincipalUnitsEquivResidueFieldUnits --- Porting note: Lean needs to be reminded of this instance +/-- Porting note: Lean needs to be reminded of this instance -/ local instance : MulOneClass ({ x // x ∈ unitGroup A } ⧸ Subgroup.comap (Subgroup.subtype (unitGroup A)) (principalUnitGroup A)) := inferInstance diff --git a/Mathlib/RingTheory/WittVector/DiscreteValuationRing.lean b/Mathlib/RingTheory/WittVector/DiscreteValuationRing.lean index 554e2051aead4..df4964efaedc9 100644 --- a/Mathlib/RingTheory/WittVector/DiscreteValuationRing.lean +++ b/Mathlib/RingTheory/WittVector/DiscreteValuationRing.lean @@ -68,7 +68,7 @@ def mkUnit {a : Units k} {A : 𝕎 k} (hA : A.coeff 0 = a) : Units (𝕎 k) := have H := Units.mul_inv (a ^ p ^ (n + 1)) linear_combination (norm := skip) -H_coeff * H have ha : (a : k) ^ p ^ (n + 1) = ↑(a ^ p ^ (n + 1)) := by norm_cast - have ha_inv : (↑a⁻¹ : k) ^ p ^ (n + 1) = ↑(a ^ p ^ (n + 1))⁻¹ := by norm_cast; norm_num + have ha_inv : (↑a⁻¹ : k) ^ p ^ (n + 1) = ↑(a ^ p ^ (n + 1))⁻¹ := by norm_cast simp only [nthRemainder_spec, inverseCoeff, succNthValUnits, hA, one_coeff_eq_of_pos, Nat.succ_pos', ha_inv, ha, inv_pow] ring!) diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index 8b58e4038d755..56a4783dc7db2 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -12,7 +12,6 @@ import Mathlib.Logic.Small.Basic import Mathlib.Order.ConditionallyCompleteLattice.Basic import Mathlib.Order.SuccPred.CompleteLinearOrder import Mathlib.SetTheory.Cardinal.SchroederBernstein -import Mathlib.Tactic.Positivity import Mathlib.Tactic.PPWithUniv #align_import set_theory.cardinal.basic from "leanprover-community/mathlib"@"3ff3f2d6a3118b8711063de7111a0d77a53219a8" @@ -926,7 +925,7 @@ theorem lift_mk_le_lift_mk_mul_of_lift_mk_preimage_le {α : Type u} {β : Type v rw [Equiv.image_eq_preimage] /- Porting note: Need to insert the following `have` b/c bad fun coercion behaviour for Equivs -/ - have : FunLike.coe (Equiv.symm (Equiv.ulift (α := α))) = ULift.up (α := α) := rfl + have : DFunLike.coe (Equiv.symm (Equiv.ulift (α := α))) = ULift.up (α := α) := rfl rw [this] simp only [preimage, mem_singleton_iff, ULift.up_inj, mem_setOf_eq, coe_setOf] exact Equiv.refl _) diff --git a/Mathlib/SetTheory/Cardinal/Cofinality.lean b/Mathlib/SetTheory/Cardinal/Cofinality.lean index b5b10eacecd20..f45a377b3ff33 100644 --- a/Mathlib/SetTheory/Cardinal/Cofinality.lean +++ b/Mathlib/SetTheory/Cardinal/Cofinality.lean @@ -90,7 +90,7 @@ theorem RelIso.cof_le_lift {α : Type u} {β : Type v} {r : α → α → Prop} (f : r ≃r s) : Cardinal.lift.{max u v} (Order.cof r) ≤ Cardinal.lift.{max u v} (Order.cof s) := by rw [Order.cof, Order.cof, lift_sInf, lift_sInf, - le_csInf_iff'' (nonempty_image_iff.2 (Order.cof_nonempty s))] + le_csInf_iff'' ((Order.cof_nonempty s).image _)] rintro - ⟨-, ⟨u, H, rfl⟩, rfl⟩ apply csInf_le' refine' diff --git a/Mathlib/SetTheory/Cardinal/ENat.lean b/Mathlib/SetTheory/Cardinal/ENat.lean new file mode 100644 index 0000000000000..25132fbf49d30 --- /dev/null +++ b/Mathlib/SetTheory/Cardinal/ENat.lean @@ -0,0 +1,282 @@ +/- +Copyright (c) 2024 Yury G. Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury G. Kudryashov +-/ +import Mathlib.SetTheory.Cardinal.Basic +import Mathlib.Algebra.Order.Hom.Ring + +/-! +# Conversion between `Cardinal` and `ℕ∞` + +In this file we define a coercion `Cardinal.ofENat : ℕ∞ → Cardinal` +and a projection `Cardinal.toENat : Cardinal →+*o ℕ∞`. +We also prove basic theorems about these definitons. + +## Implementation notes + +We define `Cardinal.ofENat` as a function instead of a bundled homomorphism +so that we can use it as a coercion and delaborate its application to `↑n`. + +We define `Cardinal.toENat` as a bundled homomorphism +so that we can use all the theorems about homomorphisms without specializing them to this function. +Since it is not registered as a coercion, the argument about delaboration does not apply. + +## Keywords + +set theory, cardinals, extended natural numbers +-/ + +open Function Set +universe u v + +namespace Cardinal + +/-- Coercion `ℕ∞ → Cardinal`. It sends natural numbers to natural numbers and `⊤` to `ℵ₀`. + +See also `Cardinal.ofENatHom` for a bundled homomorphism version. -/ +@[coe] def ofENat : ℕ∞ → Cardinal + | (n : ℕ) => n + | ⊤ => ℵ₀ + +instance : Coe ENat Cardinal := ⟨Cardinal.ofENat⟩ + +@[simp, norm_cast] lemma ofENat_top : ofENat ⊤ = ℵ₀ := rfl +@[simp, norm_cast] lemma ofENat_nat (n : ℕ) : ofENat n = n := rfl +@[simp, norm_cast] lemma ofENat_zero : ofENat 0 = 0 := rfl +@[simp, norm_cast] lemma ofENat_one : ofENat 1 = 1 := rfl + +@[simp, norm_cast] lemma ofENat_ofNat (n : ℕ) [n.AtLeastTwo] : + ((no_index (OfNat.ofNat n : ℕ∞)) : Cardinal) = OfNat.ofNat n := + rfl + +lemma ofENat_strictMono : StrictMono ofENat := + WithTop.strictMono_iff.2 ⟨Nat.strictMono_cast, nat_lt_aleph0⟩ + +@[simp, norm_cast] +lemma ofENat_lt_ofENat {m n : ℕ∞} : (m : Cardinal) < n ↔ m < n := + ofENat_strictMono.lt_iff_lt + +@[gcongr, mono] alias ⟨_, ofENat_lt_ofENat_of_lt⟩ := ofENat_lt_ofENat + +@[simp, norm_cast] +lemma ofENat_lt_aleph0 {m : ℕ∞} : (m : Cardinal) < ℵ₀ ↔ m < ⊤ := + ofENat_lt_ofENat (n := ⊤) + +@[simp] lemma ofENat_lt_nat {m : ℕ∞} {n : ℕ} : ofENat m < n ↔ m < n := by norm_cast + +@[simp] lemma ofENat_lt_ofNat {m : ℕ∞} {n : ℕ} [n.AtLeastTwo] : + ofENat m < no_index (OfNat.ofNat n) ↔ m < OfNat.ofNat n := ofENat_lt_nat + +@[simp] lemma nat_lt_ofENat {m : ℕ} {n : ℕ∞} : (m : Cardinal) < n ↔ m < n := by norm_cast +@[simp] lemma ofENat_pos {m : ℕ∞} : 0 < (m : Cardinal) ↔ 0 < m := by norm_cast +@[simp] lemma one_lt_ofENat {m : ℕ∞} : 1 < (m : Cardinal) ↔ 1 < m := by norm_cast + +@[simp, norm_cast] lemma ofNat_lt_ofENat {m : ℕ} [m.AtLeastTwo] {n : ℕ∞} : + no_index (OfNat.ofNat m : Cardinal) < n ↔ OfNat.ofNat m < n := nat_lt_ofENat + +lemma ofENat_mono : Monotone ofENat := ofENat_strictMono.monotone + +@[simp, norm_cast] +lemma ofENat_le_ofENat {m n : ℕ∞} : (m : Cardinal) ≤ n ↔ m ≤ n := ofENat_strictMono.le_iff_le + +@[gcongr, mono] alias ⟨_, ofENat_le_ofENat_of_le⟩ := ofENat_le_ofENat + +@[simp] lemma ofENat_le_aleph0 (n : ℕ∞) : ↑n ≤ ℵ₀ := ofENat_le_ofENat.2 le_top +@[simp] lemma ofENat_le_nat {m : ℕ∞} {n : ℕ} : ofENat m ≤ n ↔ m ≤ n := by norm_cast +@[simp] lemma ofENat_le_one {m : ℕ∞} : ofENat m ≤ 1 ↔ m ≤ 1 := by norm_cast + +@[simp] lemma ofENat_le_ofNat {m : ℕ∞} {n : ℕ} [n.AtLeastTwo] : + ofENat m ≤ no_index (OfNat.ofNat n) ↔ m ≤ OfNat.ofNat n := ofENat_le_nat + +@[simp] lemma nat_le_ofENat {m : ℕ} {n : ℕ∞} : (m : Cardinal) ≤ n ↔ m ≤ n := by norm_cast +@[simp] lemma one_le_ofENat {n : ℕ∞} : 1 ≤ (n : Cardinal) ↔ 1 ≤ n := by norm_cast + +@[simp] +lemma ofNat_le_ofENat {m : ℕ} [m.AtLeastTwo] {n : ℕ∞} : + no_index (OfNat.ofNat m : Cardinal) ≤ n ↔ OfNat.ofNat m ≤ n := nat_le_ofENat + +lemma ofENat_injective : Injective ofENat := ofENat_strictMono.injective + +@[simp, norm_cast] +lemma ofENat_inj {m n : ℕ∞} : (m : Cardinal) = n ↔ m = n := ofENat_injective.eq_iff + +@[simp] lemma ofENat_eq_nat {m : ℕ∞} {n : ℕ} : (m : Cardinal) = n ↔ m = n := by norm_cast +@[simp] lemma nat_eq_ofENat {m : ℕ} {n : ℕ∞} : (m : Cardinal) = n ↔ m = n := by norm_cast + +@[simp] lemma ofENat_eq_zero {m : ℕ∞} : (m : Cardinal) = 0 ↔ m = 0 := by norm_cast +@[simp] lemma zero_eq_ofENat {m : ℕ∞} : 0 = (m : Cardinal) ↔ m = 0 := by norm_cast; apply eq_comm + +@[simp] lemma ofENat_eq_one {m : ℕ∞} : (m : Cardinal) = 1 ↔ m = 1 := by norm_cast +@[simp] lemma one_eq_ofENat {m : ℕ∞} : 1 = (m : Cardinal) ↔ m = 1 := by norm_cast; apply eq_comm + +@[simp] lemma ofENat_eq_ofNat {m : ℕ∞} {n : ℕ} [n.AtLeastTwo] : + (m : Cardinal) = no_index (OfNat.ofNat n) ↔ m = OfNat.ofNat n := ofENat_eq_nat + +@[simp] lemma ofNat_eq_ofENat {m : ℕ} {n : ℕ∞} [m.AtLeastTwo] : + no_index (OfNat.ofNat m) = (n : Cardinal) ↔ OfNat.ofNat m = n := nat_eq_ofENat + +@[simp, norm_cast] lemma lift_ofENat : ∀ m : ℕ∞, lift.{u, v} m = m + | (m : ℕ) => lift_natCast m + | ⊤ => lift_aleph0 + +@[simp] lemma lift_lt_ofENat {x : Cardinal.{v}} {m : ℕ∞} : lift.{u} x < m ↔ x < m := by + rw [← lift_ofENat.{u, v}, lift_lt] + +@[simp] lemma lift_le_ofENat {x : Cardinal.{v}} {m : ℕ∞} : lift.{u} x ≤ m ↔ x ≤ m := by + rw [← lift_ofENat.{u, v}, lift_le] + +@[simp] lemma lift_eq_ofENat {x : Cardinal.{v}} {m : ℕ∞} : lift.{u} x = m ↔ x = m := by + rw [← lift_ofENat.{u, v}, lift_inj] + +@[simp] lemma ofENat_lt_lift {x : Cardinal.{v}} {m : ℕ∞} : m < lift.{u} x ↔ m < x := by + rw [← lift_ofENat.{u, v}, lift_lt] + +@[simp] lemma ofENat_le_lift {x : Cardinal.{v}} {m : ℕ∞} : m ≤ lift.{u} x ↔ m ≤ x := by + rw [← lift_ofENat.{u, v}, lift_le] + +@[simp] lemma ofENat_eq_lift {x : Cardinal.{v}} {m : ℕ∞} : m = lift.{u} x ↔ m = x := by + rw [← lift_ofENat.{u, v}, lift_inj] + +@[simp] +lemma range_ofENat : range ofENat = Iic ℵ₀ := by + refine (range_subset_iff.2 ofENat_le_aleph0).antisymm fun x (hx : x ≤ ℵ₀) ↦ ?_ + rcases hx.lt_or_eq with hlt | rfl + · lift x to ℕ using hlt + exact mem_range_self (x : ℕ∞) + · exact mem_range_self (⊤ : ℕ∞) + +instance : CanLift Cardinal ℕ∞ (↑) (· ≤ ℵ₀) where + prf x := (Set.ext_iff.1 range_ofENat x).2 + +/-- Unbundled version of `Cardinal.toENat`. -/ +noncomputable def toENatAux : Cardinal.{u} → ℕ∞ := extend Nat.cast Nat.cast fun _ ↦ ⊤ + +lemma toENatAux_nat (n : ℕ) : toENatAux n = n := Nat.cast_injective.extend_apply .. +lemma toENatAux_zero : toENatAux 0 = 0 := toENatAux_nat 0 + +lemma toENatAux_eq_top {a : Cardinal} (ha : ℵ₀ ≤ a) : toENatAux a = ⊤ := + extend_apply' _ _ _ fun ⟨n, hn⟩ ↦ ha.not_lt <| hn ▸ nat_lt_aleph0 n + +lemma toENatAux_ofENat : ∀ n : ℕ∞, toENatAux n = n + | (n : ℕ) => toENatAux_nat n + | ⊤ => toENatAux_eq_top le_rfl + +attribute [local simp] toENatAux_nat toENatAux_zero toENatAux_ofENat + +lemma toENatAux_gc : GaloisConnection (↑) toENatAux := fun n x ↦ by + cases lt_or_le x ℵ₀ with + | inl hx => lift x to ℕ using hx; simp + | inr hx => simp [toENatAux_eq_top hx, (ofENat_le_aleph0 n).trans hx] + +lemma toENatAux_eq_nat {x : Cardinal} {n : ℕ} : toENatAux x = n ↔ x = n := by + cases lt_or_le x ℵ₀ with + | inl hx => lift x to ℕ using hx; simp + | inr hx => simpa [toENatAux_eq_top hx] using ((nat_lt_aleph0 n).trans_le hx).ne' + +lemma toENatAux_eq_zero {x : Cardinal} : toENatAux x = 0 ↔ x = 0 := toENatAux_eq_nat + +/-- Projection from cardinals to `ℕ∞`. Sends all infinite cardinals to `⊤`. + +We define this function as a bundled monotone ring homomorphism. -/ +noncomputable def toENat : Cardinal.{u} →+*o ℕ∞ where + toFun := toENatAux + map_one' := toENatAux_nat 1 + map_mul' x y := by + wlog hle : x ≤ y; · rw [mul_comm, this y x (le_of_not_le hle), mul_comm] + cases lt_or_le y ℵ₀ with + | inl hy => + lift x to ℕ using hle.trans_lt hy; lift y to ℕ using hy + simp only [← Nat.cast_mul, toENatAux_nat] + | inr hy => + rcases eq_or_ne x 0 with rfl | hx + · simp + · simp only [toENatAux_eq_top hy] + rw [toENatAux_eq_top, ENat.mul_top] + · rwa [Ne.def, toENatAux_eq_zero] + · exact le_mul_of_one_le_of_le (one_le_iff_ne_zero.2 hx) hy + map_add' x y := by + wlog hle : x ≤ y; · rw [add_comm, this y x (le_of_not_le hle), add_comm] + cases lt_or_le y ℵ₀ with + | inl hy => + lift x to ℕ using hle.trans_lt hy; lift y to ℕ using hy + simp only [← Nat.cast_add, toENatAux_nat] + | inr hy => + simp only [toENatAux_eq_top hy, add_top] + exact toENatAux_eq_top <| le_add_left hy + map_zero' := toENatAux_zero + monotone' := toENatAux_gc.monotone_u + +/-- The coercion `Cardinal.ofENat` and the projection `Cardinal.toENat` form a Galois connection. +See also `Cardinal.gciENat`. -/ +lemma enat_gc : GaloisConnection (↑) toENat := toENatAux_gc + +@[simp] lemma toENat_ofENat (n : ℕ∞) : toENat n = n := toENatAux_ofENat n +@[simp] lemma toENat_comp_ofENat : toENat ∘ (↑) = id := funext toENat_ofENat + +/-- The coercion `Cardinal.ofENat` and the projection `Cardinal.toENat` +form a Galois coinsertion. -/ +noncomputable def gciENat : GaloisCoinsertion (↑) toENat := + enat_gc.toGaloisCoinsertion fun n ↦ (toENat_ofENat n).le + +lemma toENat_strictMonoOn : StrictMonoOn toENat (Iic ℵ₀) := by + simp only [← range_ofENat, StrictMonoOn, forall_range_iff, toENat_ofENat, ofENat_lt_ofENat] + exact fun _ _ ↦ id + +lemma toENat_injOn : InjOn toENat (Iic ℵ₀) := toENat_strictMonoOn.injOn + +lemma ofENat_toENat_le (a : Cardinal) : ↑(toENat a) ≤ a := enat_gc.l_u_le _ + +@[simp] +lemma ofENat_toENat_eq_self {a : Cardinal} : toENat a = a ↔ a ≤ ℵ₀ := by + rw [eq_comm, ← enat_gc.exists_eq_l] + simpa only [mem_range, eq_comm] using Set.ext_iff.1 range_ofENat a + +@[simp] alias ⟨_, ofENat_toENat⟩ := ofENat_toENat_eq_self + +lemma toENat_nat (n : ℕ) : toENat n = n := map_natCast _ n + +@[simp] lemma toENat_eq_nat {a : Cardinal} {n : ℕ} : toENat a = n ↔ a = n := toENatAux_eq_nat +@[simp] lemma toENat_eq_zero {a : Cardinal} : toENat a = 0 ↔ a = 0 := toENatAux_eq_zero +@[simp] lemma toENat_eq_one {a : Cardinal} : toENat a = 1 ↔ a = 1 := toENat_eq_nat + +@[simp] lemma toENat_eq_ofNat {a : Cardinal} {n : ℕ} [n.AtLeastTwo] : + toENat a = no_index (OfNat.ofNat n) ↔ a = OfNat.ofNat n := toENat_eq_nat + +@[simp] lemma toENat_eq_top {a : Cardinal} : toENat a = ⊤ ↔ ℵ₀ ≤ a := enat_gc.u_eq_top + +@[simp, norm_cast] +lemma ofENat_add (m n : ℕ∞) : ofENat (m + n) = m + n := by apply toENat_injOn <;> simp + +@[simp] lemma aleph0_add_ofENat (m : ℕ∞) : ℵ₀ + m = ℵ₀ := (ofENat_add ⊤ m).symm + +@[simp] lemma ofENat_add_aleph0 (m : ℕ∞) : m + ℵ₀ = ℵ₀ := by rw [add_comm, aleph0_add_ofENat] + +@[simp] lemma ofENat_mul_aleph0 {m : ℕ∞} (hm : m ≠ 0) : ↑m * ℵ₀ = ℵ₀ := by + induction m using ENat.recTopCoe with + | top => exact aleph0_mul_aleph0 + | coe m => rw [ofENat_nat, nat_mul_aleph0 (mod_cast hm)] + +@[simp] lemma aleph0_mul_ofENat {m : ℕ∞} (hm : m ≠ 0) : ℵ₀ * m = ℵ₀ := by + rw [mul_comm, ofENat_mul_aleph0 hm] + +@[simp] lemma ofENat_mul (m n : ℕ∞) : ofENat (m * n) = m * n := + toENat_injOn (by simp) + (aleph0_mul_aleph0 ▸ mul_le_mul' (ofENat_le_aleph0 _) (ofENat_le_aleph0 _)) (by simp) + +/-- The coercion `Cardinal.ofENat` as a bundled homomorphism. -/ +def ofENatHom : ℕ∞ →+*o Cardinal where + toFun := (↑) + map_one' := ofENat_one + map_mul' := ofENat_mul + map_zero' := ofENat_zero + map_add' := ofENat_add + monotone' := ofENat_mono + +@[simp] -- TODO: redefine `Cardinal.toNat` as the composition of `ENat.toNat` and `Cardinal.toENat` +lemma toNat_toENat (a : Cardinal) : ENat.toNat (toENat a) = toNat a := + match lt_or_le a ℵ₀ with + | .inl h => by lift a to ℕ using h; simp + | .inr h => by rw [toENat_eq_top.2 h, ENat.toNat_top, toNat_apply_of_aleph0_le h] + +end Cardinal diff --git a/Mathlib/SetTheory/Cardinal/Finite.lean b/Mathlib/SetTheory/Cardinal/Finite.lean index 9c7c41fae7c48..3fc89a8384088 100644 --- a/Mathlib/SetTheory/Cardinal/Finite.lean +++ b/Mathlib/SetTheory/Cardinal/Finite.lean @@ -79,13 +79,13 @@ theorem card_congr (f : α ≃ β) : Nat.card α = Nat.card β := lemma card_le_card_of_injective {α : Type u} {β : Type v} [Finite β] (f : α → β) (hf : Injective f) : Nat.card α ≤ Nat.card β := by - simpa using toNat_le_of_le_of_lt_aleph0 (by simp [lt_aleph0_of_finite]) $ - mk_le_of_injective (α := ULift.{max u v} α) (β := ULift.{max u v} β) $ ULift.map_injective.2 hf + simpa using toNat_le_of_le_of_lt_aleph0 (by simp [lt_aleph0_of_finite]) <| + mk_le_of_injective (α := ULift.{max u v} α) (β := ULift.{max u v} β) <| ULift.map_injective.2 hf lemma card_le_card_of_surjective {α : Type u} {β : Type v} [Finite α] (f : α → β) (hf : Surjective f) : Nat.card β ≤ Nat.card α := by - simpa using toNat_le_of_le_of_lt_aleph0 (by simp [lt_aleph0_of_finite]) $ mk_le_of_surjective - (α := ULift.{max u v} α) (β := ULift.{max u v} β) $ ULift.map_surjective.2 hf + simpa using toNat_le_of_le_of_lt_aleph0 (by simp [lt_aleph0_of_finite]) <| mk_le_of_surjective + (α := ULift.{max u v} α) (β := ULift.{max u v} β) <| ULift.map_surjective.2 hf theorem card_eq_of_bijective (f : α → β) (hf : Function.Bijective f) : Nat.card α = Nat.card β := card_congr (Equiv.ofBijective f hf) @@ -116,7 +116,7 @@ lemma card_image_of_injOn (hf : s.InjOn f) : Nat.card (f '' s) = Nat.card s := b simp [Nat.card_eq_zero_of_infinite] lemma card_image_of_injective (hf : Injective f) (s : Set α) : - Nat.card (f '' s) = Nat.card s := card_image_of_injOn $ hf.injOn _ + Nat.card (f '' s) = Nat.card s := card_image_of_injOn <| hf.injOn _ lemma card_image_equiv (e : α ≃ β) : Nat.card (e '' s) = Nat.card s := Nat.card_congr (e.image s).symm diff --git a/Mathlib/SetTheory/Cardinal/Ordinal.lean b/Mathlib/SetTheory/Cardinal/Ordinal.lean index ffb4c5924fa85..03ea9884381f1 100644 --- a/Mathlib/SetTheory/Cardinal/Ordinal.lean +++ b/Mathlib/SetTheory/Cardinal/Ordinal.lean @@ -1042,6 +1042,108 @@ theorem powerlt_aleph0_le (c : Cardinal) : c ^< ℵ₀ ≤ max c ℵ₀ := by /-! ### Computing cardinality of various types -/ +section Function + +variable {α β : Type u} {β' : Type v} + +theorem mk_equiv_eq_zero_iff_lift_ne : #(α ≃ β') = 0 ↔ lift.{v} #α ≠ lift.{u} #β' := by + rw [mk_eq_zero_iff, ← not_nonempty_iff, ← lift_mk_eq'] + +theorem mk_equiv_eq_zero_iff_ne : #(α ≃ β) = 0 ↔ #α ≠ #β := by + rw [mk_equiv_eq_zero_iff_lift_ne, lift_id, lift_id] + +/-- This lemma makes lemmas assuming `Infinite α` applicable to the situation where we have + `Infinite β` instead. -/ +theorem mk_equiv_comm : #(α ≃ β') = #(β' ≃ α) := + (ofBijective _ symm_bijective).cardinal_eq + +theorem mk_embedding_eq_zero_iff_lift_lt : #(α ↪ β') = 0 ↔ lift.{u} #β' < lift.{v} #α := by + rw [mk_eq_zero_iff, ← not_nonempty_iff, ← lift_mk_le', not_le] + +theorem mk_embedding_eq_zero_iff_lt : #(α ↪ β) = 0 ↔ #β < #α := by + rw [mk_embedding_eq_zero_iff_lift_lt, lift_lt] + +theorem mk_arrow_eq_zero_iff : #(α → β') = 0 ↔ #α ≠ 0 ∧ #β' = 0 := by + simp_rw [mk_eq_zero_iff, mk_ne_zero_iff, isEmpty_fun] + +theorem mk_surjective_eq_zero_iff_lift : + #{f : α → β' | Surjective f} = 0 ↔ lift.{v} #α < lift.{u} #β' ∨ (#α ≠ 0 ∧ #β' = 0) := by + rw [← not_iff_not, not_or, not_lt, lift_mk_le', ← Ne, not_and_or, not_ne_iff, and_comm] + simp_rw [mk_ne_zero_iff, mk_eq_zero_iff, nonempty_coe_sort, + Set.Nonempty, mem_setOf, exists_surjective_iff, nonempty_fun] + +theorem mk_surjective_eq_zero_iff : + #{f : α → β | Surjective f} = 0 ↔ #α < #β ∨ (#α ≠ 0 ∧ #β = 0) := by + rw [mk_surjective_eq_zero_iff_lift, lift_lt] + +variable (α β') + +theorem mk_equiv_le_embedding : #(α ≃ β') ≤ #(α ↪ β') := ⟨⟨_, Equiv.toEmbedding_injective⟩⟩ + +theorem mk_embedding_le_arrow : #(α ↪ β') ≤ #(α → β') := ⟨⟨_, DFunLike.coe_injective⟩⟩ + +variable [Infinite α] {α β'} + +theorem mk_perm_eq_self_power : #(Equiv.Perm α) = #α ^ #α := + ((mk_equiv_le_embedding α α).trans (mk_embedding_le_arrow α α)).antisymm <| by + suffices : Nonempty ((α → Bool) ↪ Equiv.Perm (α × Bool)) + · obtain ⟨e⟩ : Nonempty (α ≃ α × Bool) + · erw [← Cardinal.eq, mk_prod, lift_uzero, mk_bool, + lift_natCast, mul_two, add_eq_self (aleph0_le_mk α)] + erw [← le_def, mk_arrow, lift_uzero, mk_bool, lift_natCast 2] at this + rwa [← power_def, power_self_eq (aleph0_le_mk α), e.permCongr.cardinal_eq] + refine ⟨⟨fun f ↦ Involutive.toPerm (fun x ↦ ⟨x.1, xor (f x.1) x.2⟩) fun x ↦ ?_, fun f g h ↦ ?_⟩⟩ + · simp_rw [← Bool.xor_assoc, Bool.xor_self, Bool.false_xor] + · ext a; rw [← (f a).xor_false, ← (g a).xor_false]; exact congr(($h ⟨a, false⟩).2) + +theorem mk_perm_eq_two_power : #(Equiv.Perm α) = 2 ^ #α := by + rw [mk_perm_eq_self_power, power_self_eq (aleph0_le_mk α)] + +variable (leq : lift.{v} #α = lift.{u} #β') (eq : #α = #β) + +theorem mk_equiv_eq_arrow_of_lift_eq : #(α ≃ β') = #(α → β') := by + obtain ⟨e⟩ := lift_mk_eq'.mp leq + have e₁ := lift_mk_eq'.mpr ⟨.equivCongr (.refl α) e⟩ + have e₂ := lift_mk_eq'.mpr ⟨.arrowCongr (.refl α) e⟩ + rw [lift_id'.{u,v}] at e₁ e₂ + rw [← e₁, ← e₂, lift_inj, mk_perm_eq_self_power, power_def] + +theorem mk_equiv_eq_arrow_of_eq : #(α ≃ β) = #(α → β) := + mk_equiv_eq_arrow_of_lift_eq congr(lift $eq) + +theorem mk_equiv_of_lift_eq : #(α ≃ β') = 2 ^ lift.{v} #α := by + erw [← (lift_mk_eq'.2 ⟨.equivCongr (.refl α) (lift_mk_eq'.1 leq).some⟩).trans (lift_id'.{u,v} _), + lift_umax.{u,v}, mk_perm_eq_two_power, lift_power, lift_natCast]; rfl + +theorem mk_equiv_of_eq : #(α ≃ β) = 2 ^ #α := by rw [mk_equiv_of_lift_eq (lift_inj.mpr eq), lift_id] + +variable (lle : lift.{u} #β' ≤ lift.{v} #α) (le : #β ≤ #α) + +theorem mk_embedding_eq_arrow_of_lift_le : #(β' ↪ α) = #(β' → α) := + (mk_embedding_le_arrow _ _).antisymm <| by + conv_rhs => rw [← (Equiv.embeddingCongr (.refl _) + (Cardinal.eq.mp <| mul_eq_self <| aleph0_le_mk α).some).cardinal_eq] + obtain ⟨e⟩ := lift_mk_le'.mp lle + exact ⟨⟨fun f ↦ ⟨fun b ↦ ⟨e b, f b⟩, fun _ _ h ↦ e.injective congr(Prod.fst $h)⟩, + fun f g h ↦ funext fun b ↦ congr(Prod.snd <| $h b)⟩⟩ + +theorem mk_embedding_eq_arrow_of_le : #(β ↪ α) = #(β → α) := + mk_embedding_eq_arrow_of_lift_le (lift_le.mpr le) + +theorem mk_surjective_eq_arrow_of_lift_le : #{f : α → β' | Surjective f} = #(α → β') := + (mk_set_le _).antisymm <| + have ⟨e⟩ : Nonempty (α ≃ α ⊕ β') := by + simp_rw [← lift_mk_eq', mk_sum, lift_add, lift_lift]; rw [lift_umax.{u,v}, eq_comm] + exact add_eq_left (aleph0_le_lift.mpr <| aleph0_le_mk α) lle + ⟨⟨fun f ↦ ⟨fun a ↦ (e a).elim f id, fun b ↦ ⟨e.symm (.inr b), congr_arg _ (e.right_inv _)⟩⟩, + fun f g h ↦ funext fun a ↦ by + simpa only [e.apply_symm_apply] using congr_fun (Subtype.ext_iff.mp h) (e.symm <| .inl a)⟩⟩ + +theorem mk_surjective_eq_arrow_of_le : #{f : α → β | Surjective f} = #(α → β) := + mk_surjective_eq_arrow_of_lift_le (lift_le.mpr le) + +end Function + @[simp] theorem mk_list_eq_mk (α : Type u) [Infinite α] : #(List α) = #α := have H1 : ℵ₀ ≤ #α := aleph0_le_mk α diff --git a/Mathlib/SetTheory/Cardinal/SchroederBernstein.lean b/Mathlib/SetTheory/Cardinal/SchroederBernstein.lean index 3de06308776b3..4331f80ea69f5 100644 --- a/Mathlib/SetTheory/Cardinal/SchroederBernstein.lean +++ b/Mathlib/SetTheory/Cardinal/SchroederBernstein.lean @@ -3,6 +3,7 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ +import Mathlib.Init.Classical import Mathlib.Order.FixedPoints import Mathlib.Order.Zorn diff --git a/Mathlib/SetTheory/Game/Basic.lean b/Mathlib/SetTheory/Game/Basic.lean index 7df6126811ac3..1c9a9cccab594 100644 --- a/Mathlib/SetTheory/Game/Basic.lean +++ b/Mathlib/SetTheory/Game/Basic.lean @@ -396,8 +396,8 @@ def mulCommRelabelling (x y : PGame.{u}) : x * y ≡r y * x := exact ((addCommRelabelling _ _).trans <| (mulCommRelabelling _ _).addCongr (mulCommRelabelling _ _)).subCongr (mulCommRelabelling _ _) } - termination_by _ => (x, y) - decreasing_by pgame_wf_tac + termination_by (x, y) + decreasing_by all_goals pgame_wf_tac #align pgame.mul_comm_relabelling SetTheory.PGame.mulCommRelabelling theorem quot_mul_comm (x y : PGame.{u}) : (⟦x * y⟧ : Game) = ⟦y * x⟧ := @@ -476,8 +476,8 @@ def negMulRelabelling (x y : PGame.{u}) : -x * y ≡r -(x * y) := -- but if we just `change` it to look like the mathlib3 goal then we're fine!? change -(mk xl xr xL xR * _) ≡r _ exact (negMulRelabelling _ _).symm - termination_by _ => (x, y) - decreasing_by pgame_wf_tac + termination_by (x, y) + decreasing_by all_goals pgame_wf_tac #align pgame.neg_mul_relabelling SetTheory.PGame.negMulRelabelling @[simp] @@ -590,8 +590,8 @@ theorem quot_left_distrib (x y z : PGame) : (⟦x * (y + z)⟧ : Game) = ⟦x * rw [quot_left_distrib (mk xl xr xL xR) (mk yl yr yL yR) (zL k)] rw [quot_left_distrib (xR i) (mk yl yr yL yR) (zL k)] abel - termination_by _ => (x, y, z) - decreasing_by pgame_wf_tac + termination_by (x, y, z) + decreasing_by all_goals pgame_wf_tac #align pgame.quot_left_distrib SetTheory.PGame.quot_left_distrib /-- `x * (y + z)` is equivalent to `x * y + x * z.`-/ @@ -815,8 +815,8 @@ theorem quot_mul_assoc (x y z : PGame) : (⟦x * y * z⟧ : Game) = ⟦x * (y * rw [quot_mul_assoc (mk xl xr xL xR) (yL j) (zL k)] rw [quot_mul_assoc (xR i) (yL j) (zL k)] abel - termination_by _ => (x, y, z) - decreasing_by pgame_wf_tac + termination_by (x, y, z) + decreasing_by all_goals pgame_wf_tac #align pgame.quot_mul_assoc SetTheory.PGame.quot_mul_assoc /-- `x * y * z` is equivalent to `x * (y * z).`-/ diff --git a/Mathlib/SetTheory/Game/Birthday.lean b/Mathlib/SetTheory/Game/Birthday.lean index 0a99c7c87dca6..81c1de5e1fd26 100644 --- a/Mathlib/SetTheory/Game/Birthday.lean +++ b/Mathlib/SetTheory/Game/Birthday.lean @@ -89,7 +89,7 @@ theorem Relabelling.birthday_congr : ∀ {x y : PGame.{u}}, x ≡r y → birthda · exact ⟨_, (r.moveLeftSymm j).birthday_congr⟩ · exact ⟨_, (r.moveRight j).birthday_congr.symm⟩ · exact ⟨_, (r.moveRightSymm j).birthday_congr⟩ -termination_by birthday_congr x y _ => (x, y) +termination_by x y => (x, y) #align pgame.relabelling.birthday_congr SetTheory.PGame.Relabelling.birthday_congr @[simp] @@ -170,7 +170,7 @@ theorem birthday_add : ∀ x y : PGame.{u}, (x + y).birthday = x.birthday ♯ y. · exact lt_max_of_lt_right ((nadd_le_nadd_right hj _).trans_lt (lt_lsub _ _)) · exact lt_max_of_lt_left ((nadd_le_nadd_left hj _).trans_lt (lt_lsub _ _)) · exact lt_max_of_lt_right ((nadd_le_nadd_left hj _).trans_lt (lt_lsub _ _)) -termination_by birthday_add a b => (a, b) +termination_by a b => (a, b) #align pgame.birthday_add SetTheory.PGame.birthday_add theorem birthday_add_zero : (a + 0).birthday = a.birthday := by simp diff --git a/Mathlib/SetTheory/Game/Impartial.lean b/Mathlib/SetTheory/Game/Impartial.lean index 897054dc1185a..af1907e2b0280 100644 --- a/Mathlib/SetTheory/Game/Impartial.lean +++ b/Mathlib/SetTheory/Game/Impartial.lean @@ -29,8 +29,8 @@ namespace PGame /-- The definition for an impartial game, defined using Conway induction. -/ def ImpartialAux : PGame → Prop | G => (G ≈ -G) ∧ (∀ i, ImpartialAux (G.moveLeft i)) ∧ ∀ j, ImpartialAux (G.moveRight j) -termination_by _ G => G -- Porting note: Added `termination_by` -decreasing_by pgame_wf_tac +termination_by G => G -- Porting note: Added `termination_by` +decreasing_by all_goals pgame_wf_tac #align pgame.impartial_aux SetTheory.PGame.ImpartialAux theorem impartialAux_def {G : PGame} : @@ -88,8 +88,8 @@ theorem impartial_congr : ∀ {G H : PGame} (_ : G ≡r H) [G.Impartial], H.Impa exact impartial_def.2 ⟨Equiv.trans e.symm.equiv (Equiv.trans (neg_equiv_self G) (neg_equiv_neg_iff.2 e.equiv)), fun i => impartial_congr (e.moveLeftSymm i), fun j => impartial_congr (e.moveRightSymm j)⟩ -termination_by _ G H => (G, H) -decreasing_by pgame_wf_tac +termination_by G H => (G, H) +decreasing_by all_goals pgame_wf_tac #align pgame.impartial.impartial_congr SetTheory.PGame.Impartial.impartial_congr instance impartial_add : ∀ (G H : PGame) [G.Impartial] [H.Impartial], (G + H).Impartial @@ -105,8 +105,8 @@ instance impartial_add : ∀ (G H : PGame) [G.Impartial] [H.Impartial], (G + H). all_goals intro i; simp only [add_moveRight_inl, add_moveRight_inr] apply impartial_add -termination_by _ G H _ _ => (G, H) -decreasing_by pgame_wf_tac +termination_by G H => (G, H) +decreasing_by all_goals pgame_wf_tac #align pgame.impartial.impartial_add SetTheory.PGame.Impartial.impartial_add instance impartial_neg : ∀ (G : PGame) [G.Impartial], (-G).Impartial @@ -119,8 +119,8 @@ instance impartial_neg : ∀ (G : PGame) [G.Impartial], (-G).Impartial apply impartial_neg · rw [moveRight_neg'] apply impartial_neg -termination_by _ G _ => G -decreasing_by pgame_wf_tac +termination_by G => G +decreasing_by all_goals pgame_wf_tac #align pgame.impartial.impartial_neg SetTheory.PGame.Impartial.impartial_neg variable (G : PGame) [Impartial G] diff --git a/Mathlib/SetTheory/Game/Nim.lean b/Mathlib/SetTheory/Game/Nim.lean index c9039d211c125..b9735a7e2554b 100644 --- a/Mathlib/SetTheory/Game/Nim.lean +++ b/Mathlib/SetTheory/Game/Nim.lean @@ -51,7 +51,7 @@ noncomputable def nim : Ordinal.{u} → PGame.{u} have _ : Ordinal.typein o₁.out.r o₂ < o₁ := Ordinal.typein_lt_self o₂ nim (Ordinal.typein o₁.out.r o₂) ⟨o₁.out.α, o₁.out.α, f, f⟩ -termination_by nim o => o +termination_by o => o #align pgame.nim SetTheory.PGame.nim open Ordinal @@ -258,9 +258,9 @@ theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o /-- The Grundy value of an impartial game, the ordinal which corresponds to the game of nim that the game is equivalent to -/ -noncomputable def grundyValue : ∀ _ : PGame.{u}, Ordinal.{u} +noncomputable def grundyValue : PGame.{u} → Ordinal.{u} | G => Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i) -termination_by grundyValue G => G +termination_by G => G decreasing_by pgame_wf_tac #align pgame.grundy_value SetTheory.PGame.grundyValue @@ -305,8 +305,8 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr rw [add_moveLeft_inl, moveLeft_mk] apply Equiv.trans (add_congr_left (equiv_nim_grundyValue (G.moveLeft i))) simpa only [hi] using Impartial.add_self (nim (grundyValue (G.moveLeft i))) -termination_by equiv_nim_grundyValue G _ => G -decreasing_by pgame_wf_tac +termination_by G => G +decreasing_by all_goals pgame_wf_tac #align pgame.equiv_nim_grundy_value SetTheory.PGame.equiv_nim_grundyValue theorem grundyValue_eq_iff_equiv_nim {G : PGame} [G.Impartial] {o : Ordinal} : diff --git a/Mathlib/SetTheory/Game/Ordinal.lean b/Mathlib/SetTheory/Game/Ordinal.lean index 1db93a0ebf662..956e49cb8b623 100644 --- a/Mathlib/SetTheory/Game/Ordinal.lean +++ b/Mathlib/SetTheory/Game/Ordinal.lean @@ -39,7 +39,7 @@ noncomputable def toPGame : Ordinal.{u} → PGame.{u} have := Ordinal.typein_lt_self x (typein (· < ·) x).toPGame, PEmpty.elim⟩ -termination_by toPGame x => x +termination_by x => x #align ordinal.to_pgame Ordinal.toPGame @[nolint unusedHavesSuffices] @@ -204,7 +204,7 @@ theorem toPGame_add : ∀ a b : Ordinal.{u}, a.toPGame + b.toPGame ≈ (a ♯ b) rwa [toPGame_lf_iff] · apply add_lf_add_left rwa [toPGame_lf_iff] -termination_by toPGame_add a b => (a, b) +termination_by a b => (a, b) #align ordinal.to_pgame_add Ordinal.toPGame_add @[simp] diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index 03db93db84227..d4910aeefdfe5 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -1066,7 +1066,7 @@ def mk' (L : y.LeftMoves ≃ x.LeftMoves) (R : y.RightMoves ≃ x.RightMoves) #align pgame.relabelling.mk' SetTheory.PGame.Relabelling.mk' /-- The equivalence between left moves of `x` and `y` given by the relabelling. -/ -def leftMovesEquiv : ∀ _ : x ≡r y, x.LeftMoves ≃ y.LeftMoves +def leftMovesEquiv : x ≡r y → x.LeftMoves ≃ y.LeftMoves | ⟨L,_, _,_⟩ => L #align pgame.relabelling.left_moves_equiv SetTheory.PGame.Relabelling.leftMovesEquiv @@ -1082,7 +1082,7 @@ theorem mk'_leftMovesEquiv {x y L R hL hR} : #align pgame.relabelling.mk'_left_moves_equiv SetTheory.PGame.Relabelling.mk'_leftMovesEquiv /-- The equivalence between right moves of `x` and `y` given by the relabelling. -/ -def rightMovesEquiv : ∀ _ : x ≡r y, x.RightMoves ≃ y.RightMoves +def rightMovesEquiv : x ≡r y → x.RightMoves ≃ y.RightMoves | ⟨_, R, _, _⟩ => R #align pgame.relabelling.right_moves_equiv SetTheory.PGame.Relabelling.rightMovesEquiv @@ -1124,7 +1124,7 @@ def moveRightSymm : @[refl] def refl (x : PGame) : x ≡r x := ⟨Equiv.refl _, Equiv.refl _, fun i => refl _, fun j => refl _⟩ -termination_by _ => x +termination_by x #align pgame.relabelling.refl SetTheory.PGame.Relabelling.refl instance (x : PGame) : Inhabited (x ≡r x) := @@ -1140,7 +1140,7 @@ theorem le {x y : PGame} (r : x ≡r y) : x ≤ y := le_def.2 ⟨fun i => Or.inl ⟨_, (r.moveLeft i).le⟩, fun j => Or.inr ⟨_, (r.moveRightSymm j).le⟩⟩ -termination_by _ => x +termination_by x #align pgame.relabelling.le SetTheory.PGame.Relabelling.le theorem ge {x y : PGame} (r : x ≡r y) : y ≤ x := @@ -1347,7 +1347,7 @@ private theorem neg_le_lf_neg_iff : ∀ {x y : PGame.{u}}, (-y ≤ -x ↔ x ≤ apply and_congr <;> exact forall_congr' fun _ => neg_le_lf_neg_iff.2 · rw [or_comm] apply or_congr <;> exact exists_congr fun _ => neg_le_lf_neg_iff.1 -termination_by _ x y => (x, y) +termination_by x y => (x, y) @[simp] theorem neg_le_neg_iff {x y : PGame} : -y ≤ -x ↔ x ≤ y := @@ -1485,7 +1485,7 @@ def addZeroRelabelling : ∀ x : PGame.{u}, x + 0 ≡r x | ⟨xl, xr, xL, xR⟩ => by refine' ⟨Equiv.sumEmpty xl PEmpty, Equiv.sumEmpty xr PEmpty, _, _⟩ <;> rintro (⟨i⟩ | ⟨⟨⟩⟩) <;> apply addZeroRelabelling -termination_by _ x => x +termination_by x => x #align pgame.add_zero_relabelling SetTheory.PGame.addZeroRelabelling /-- `x + 0` is equivalent to `x`. -/ @@ -1627,7 +1627,7 @@ def Relabelling.addCongr : ∀ {w x y z : PGame.{u}}, w ≡r x → y ≡r z → · exact Hwx.addCongr (hL₂ j) · exact (hR₁ i).addCongr Hyz · exact Hwx.addCongr (hR₂ j) -termination_by _ w x y z _ _ => (x, z) +termination_by w x y z => (x, z) #align pgame.relabelling.add_congr SetTheory.PGame.Relabelling.addCongr instance : Sub PGame := @@ -1652,7 +1652,7 @@ def negAddRelabelling : ∀ x y : PGame, -(x + y) ≡r -x + -y exact fun j => Sum.casesOn j (fun j => negAddRelabelling _ _) fun j => negAddRelabelling ⟨xl, xr, xL, xR⟩ _ -termination_by _ x y => (x, y) +termination_by x y => (x, y) #align pgame.neg_add_relabelling SetTheory.PGame.negAddRelabelling theorem neg_add_le {x y : PGame} : -(x + y) ≤ -x + -y := @@ -1663,9 +1663,9 @@ theorem neg_add_le {x y : PGame} : -(x + y) ≤ -x + -y := def addCommRelabelling : ∀ x y : PGame.{u}, x + y ≡r y + x | mk xl xr xL xR, mk yl yr yL yR => by refine' ⟨Equiv.sumComm _ _, Equiv.sumComm _ _, _, _⟩ <;> rintro (_ | _) <;> - · dsimp [leftMoves_add, rightMoves_add] + · dsimp apply addCommRelabelling -termination_by _ x y => (x, y) +termination_by x y => (x, y) #align pgame.add_comm_relabelling SetTheory.PGame.addCommRelabelling theorem add_comm_le {x y : PGame} : x + y ≤ y + x := @@ -1688,7 +1688,7 @@ def addAssocRelabelling : ∀ x y z : PGame.{u}, x + y + z ≡r x + (y + z) · apply addAssocRelabelling · apply addAssocRelabelling ⟨xl, xr, xL, xR⟩ (yR i) · apply addAssocRelabelling ⟨xl, xr, xL, xR⟩ ⟨yl, yr, yL, yR⟩ (zR i) -termination_by _ x y z => (x, y, z) +termination_by x y z => (x, y, z) #align pgame.add_assoc_relabelling SetTheory.PGame.addAssocRelabelling theorem add_assoc_equiv {x y z : PGame} : x + y + z ≈ x + (y + z) := @@ -1754,7 +1754,7 @@ private theorem add_le_add_right' : ∀ {x y z : PGame}, x ≤ y → x + z ≤ y · exact Or.inr ⟨toRightMovesAdd (Sum.inl j'), add_le_add_right' jh⟩ · exact Or.inr ⟨@toRightMovesAdd _ ⟨_, _, _, _⟩ (Sum.inr i), add_le_add_right' h⟩ -termination_by _ x y z => (x, y, z) +termination_by x y z => (x, y, z) instance covariantClass_swap_add_le : CovariantClass PGame PGame (swap (· + ·)) (· ≤ ·) := ⟨fun _ _ _ => add_le_add_right'⟩ diff --git a/Mathlib/SetTheory/Game/Short.lean b/Mathlib/SetTheory/Game/Short.lean index b44cac9bc0f95..f7e1be3f87d51 100644 --- a/Mathlib/SetTheory/Game/Short.lean +++ b/Mathlib/SetTheory/Game/Short.lean @@ -72,9 +72,9 @@ theorem subsingleton_short_example : ∀ x : PGame, Subsingleton (Short x) -- (In Lean 3 it was `(mk xl xr xL xR)` instead.) · funext x apply @Subsingleton.elim _ (subsingleton_short_example (xR x))⟩ -termination_by subsingleton_short_example x => x +termination_by x => x -- We need to unify a bunch of hypotheses before `pgame_wf_tac` can work. -decreasing_by { +decreasing_by all_goals { subst_vars simp only [mk.injEq, heq_eq_eq, true_and] at * casesm* _ ∧ _ @@ -252,7 +252,7 @@ instance shortAdd : ∀ (x y : PGame.{u}) [Short x] [Short y], Short (x + y) · apply shortAdd · change Short (mk xl xr xL xR + _); apply shortAdd -- Porting note: In Lean 3 `using_well_founded` didn't need this to be explicit. -termination_by shortAdd x y _ _ => Prod.mk x y +termination_by x y => (x, y) -- Porting note: `decreasing_by pgame_wf_tac` is no longer needed. #align pgame.short_add SetTheory.PGame.shortAdd @@ -296,7 +296,7 @@ def leLFDecidable : ∀ (x y : PGame.{u}) [Short x] [Short y], Decidable (x ≤ intro i apply (leLFDecidable _ _).1 -- Porting note: In Lean 3 `using_well_founded` didn't need this to be explicit. -termination_by leLFDecidable x y _ _ => Prod.mk x y +termination_by x y => (x, y) -- Porting note: `decreasing_by pgame_wf_tac` is no longer needed. #align pgame.le_lf_decidable SetTheory.PGame.leLFDecidable diff --git a/Mathlib/SetTheory/Lists.lean b/Mathlib/SetTheory/Lists.lean index 3b811c7d62078..10d851bee247f 100644 --- a/Mathlib/SetTheory/Lists.lean +++ b/Mathlib/SetTheory/Lists.lean @@ -3,7 +3,8 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.List.Basic +import Mathlib.Data.Sigma.Basic +import Mathlib.Data.Nat.Order.Basic #align_import set_theory.lists from "leanprover-community/mathlib"@"497d1e06409995dd8ec95301fa8d8f3480187f4c" @@ -402,6 +403,7 @@ mutual by decreasing_tactic Subset.decidable l₂ l₁ exact decidable_of_iff' _ Equiv.antisymm_iff + termination_by x y => sizeOf x + sizeOf y instance Subset.decidable : ∀ l₁ l₂ : Lists' α true, Decidable (l₁ ⊆ l₂) | Lists'.nil, l₂ => isTrue Lists'.Subset.nil | @Lists'.cons' _ b a l₁, l₂ => by @@ -414,6 +416,7 @@ mutual by decreasing_tactic Subset.decidable l₁ l₂ exact decidable_of_iff' _ (@Lists'.cons_subset _ ⟨_, _⟩ _ _) + termination_by x y => sizeOf x + sizeOf y instance mem.decidable : ∀ (a : Lists α) (l : Lists' α true), Decidable (a ∈ l) | a, Lists'.nil => isFalse <| by rintro ⟨_, ⟨⟩, _⟩ | a, Lists'.cons' b l₂ => by @@ -428,11 +431,8 @@ mutual mem.decidable a l₂ refine' decidable_of_iff' (a ~ ⟨_, b⟩ ∨ a ∈ l₂) _ rw [← Lists'.mem_cons]; rfl + termination_by x y => sizeOf x + sizeOf y end -termination_by - Subset.decidable x y => sizeOf x + sizeOf y - Equiv.decidable x y => sizeOf x + sizeOf y - mem.decidable x y => sizeOf x + sizeOf y #align lists.equiv.decidable Lists.Equiv.decidable #align lists.subset.decidable Lists.Subset.decidable #align lists.mem.decidable Lists.mem.decidable diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 10446df87444a..ea0a7500f2ec4 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -1057,7 +1057,7 @@ theorem succ_zero : succ (0 : Ordinal) = 1 := -- Porting note: Proof used to be rfl @[simp] theorem succ_one : succ (1 : Ordinal) = 2 := by - unfold instOfNat OfNat.ofNat + unfold instOfNatAtLeastTwo OfNat.ofNat simpa using by rfl #align ordinal.succ_one Ordinal.succ_one diff --git a/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean b/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean index c22ce85dd8cb5..c767d58053185 100644 --- a/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean +++ b/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean @@ -46,7 +46,7 @@ noncomputable def CNFRec (b : Ordinal) {C : Ordinal → Sort*} (H0 : C 0) by_cases h : o = 0 · rw [h]; exact H0 · exact H o h (CNFRec _ H0 H (o % b ^ log b o)) - termination_by CNFRec b H0 H o => o + termination_by o => o decreasing_by exact mod_opow_log_lt_self b h set_option linter.uppercaseLean3 false in #align ordinal.CNF_rec Ordinal.CNFRec diff --git a/Mathlib/SetTheory/Ordinal/NaturalOps.lean b/Mathlib/SetTheory/Ordinal/NaturalOps.lean index 06f8498b63d63..e15374737c27d 100644 --- a/Mathlib/SetTheory/Ordinal/NaturalOps.lean +++ b/Mathlib/SetTheory/Ordinal/NaturalOps.lean @@ -203,7 +203,7 @@ corresponding coefficients in the Cantor normal forms of `a` and `b`. -/ noncomputable def nadd : Ordinal → Ordinal → Ordinal | a, b => max (blsub.{u, u} a fun a' _ => nadd a' b) (blsub.{u, u} b fun b' _ => nadd a b') - termination_by nadd o₁ o₂ => (o₁, o₂) + termination_by o₁ o₂ => (o₁, o₂) #align ordinal.nadd Ordinal.nadd @[inherit_doc] @@ -221,7 +221,7 @@ the Cantor normal forms of `a` and `b` as if they were polynomials in `ω`. Addi done via natural addition. -/ noncomputable def nmul : Ordinal.{u} → Ordinal.{u} → Ordinal.{u} | a, b => sInf {c | ∀ a' < a, ∀ b' < b, nmul a' b ♯ nmul a b' < c ♯ nmul a' b'} -termination_by nmul a b => (a, b) +termination_by a b => (a, b) #align ordinal.nmul Ordinal.nmul @[inherit_doc] @@ -271,7 +271,7 @@ theorem nadd_comm : ∀ a b, a ♯ b = b ♯ a rw [nadd_def, nadd_def, max_comm] congr <;> ext <;> apply nadd_comm -- porting note: below was decreasing_by solve_by_elim [PSigma.Lex.left, PSigma.Lex.right] - termination_by nadd_comm a b => (a,b) + termination_by a b => (a,b) #align ordinal.nadd_comm Ordinal.nadd_comm theorem blsub_nadd_of_mono {f : ∀ c < a ♯ b, Ordinal.{max u v}} @@ -296,7 +296,7 @@ theorem nadd_assoc (a b c) : a ♯ b ♯ c = a ♯ (b ♯ c) := by · congr <;> ext (d hd) <;> apply nadd_assoc · exact fun _ _ h => nadd_le_nadd_left h a · exact fun _ _ h => nadd_le_nadd_right h c -termination_by _ => (a, b, c) +termination_by (a, b, c) -- Porting note: above lines replaces -- decreasing_by solve_by_elim [PSigma.Lex.left, PSigma.Lex.right] #align ordinal.nadd_assoc Ordinal.nadd_assoc @@ -560,7 +560,7 @@ theorem nmul_comm : ∀ a b, a ⨳ b = b ⨳ a exact H _ hd _ hc · rw [nadd_comm, nmul_comm a d, nmul_comm c, nmul_comm c] exact H _ hd _ hc -termination_by nmul_comm a b => (a, b) +termination_by a b => (a, b) #align ordinal.nmul_comm Ordinal.nmul_comm @[simp] @@ -587,7 +587,7 @@ theorem nmul_one (a : Ordinal) : a ⨳ 1 = a := by -- for the termination checker. · simpa only [nmul_one c] using H c hc · simpa only [nmul_one c] using hc.trans_le ha -termination_by nmul_one a => a +termination_by a #align ordinal.nmul_one Ordinal.nmul_one @[simp] @@ -653,7 +653,7 @@ theorem nmul_nadd : ∀ a b c, a ⨳ (b ♯ c) = a ⨳ b ♯ a ⨳ c nadd_left_comm _ (a' ⨳ c), nadd_lt_nadd_iff_left, nadd_left_comm, nadd_comm (a' ⨳ c'), nadd_left_comm _ (a ⨳ c'), nadd_lt_nadd_iff_left, nadd_comm _ (a' ⨳ c'), nadd_comm _ (a' ⨳ c'), nadd_left_comm, nadd_lt_nadd_iff_left] at this -termination_by nmul_nadd a b c => (a, b, c) +termination_by a b c => (a, b, c) #align ordinal.nmul_nadd Ordinal.nmul_nadd theorem nadd_nmul (a b c) : (a ♯ b) ⨳ c = a ⨳ c ♯ b ⨳ c := by @@ -757,7 +757,7 @@ theorem nmul_assoc : ∀ a b c, a ⨳ b ⨳ c = a ⨳ (b ⨳ c) rw [← nmul_assoc a' b c, ← nmul_assoc a b' c, ← nmul_assoc a b c', ← nmul_assoc a' b' c', ← nmul_assoc a' b' c, ← nmul_assoc a' b c', ← nmul_assoc a b' c'] exact nmul_nadd_lt₃ ha hb hc -termination_by nmul_assoc a b c => (a, b, c) +termination_by a b c => (a, b, c) #align ordinal.nmul_assoc Ordinal.nmul_assoc end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/Notation.lean b/Mathlib/SetTheory/Ordinal/Notation.lean index 4247cccfcd67b..c7c9b84390a88 100644 --- a/Mathlib/SetTheory/Ordinal/Notation.lean +++ b/Mathlib/SetTheory/Ordinal/Notation.lean @@ -1161,7 +1161,7 @@ def fastGrowing : ONote → ℕ → ℕ | Sum.inr f, h => fun i => have : f i < o := (h.2.1 i).2.1 fastGrowing (f i) i - termination_by fastGrowing o => o + termination_by o => o #align onote.fast_growing ONote.fastGrowing -- Porting note: the bug of the linter, should be fixed. diff --git a/Mathlib/SetTheory/Ordinal/Topology.lean b/Mathlib/SetTheory/Ordinal/Topology.lean index e23eae9da1d32..863f9c240874c 100644 --- a/Mathlib/SetTheory/Ordinal/Topology.lean +++ b/Mathlib/SetTheory/Ordinal/Topology.lean @@ -54,7 +54,7 @@ theorem isOpen_singleton_iff : IsOpen ({a} : Set Ordinal) ↔ ¬IsLimit a := by #align ordinal.is_open_singleton_iff Ordinal.isOpen_singleton_iff -- porting note: todo: generalize to a `SuccOrder` -theorem nhds_right' (a : Ordinal) : 𝓝[>] a = ⊥ := (covby_succ a).nhdsWithin_Ioi +theorem nhds_right' (a : Ordinal) : 𝓝[>] a = ⊥ := (covBy_succ a).nhdsWithin_Ioi -- todo: generalize to a `SuccOrder` theorem nhds_left'_eq_nhds_ne (a : Ordinal) : 𝓝[<] a = 𝓝[≠] a := by diff --git a/Mathlib/SetTheory/Surreal/Basic.lean b/Mathlib/SetTheory/Surreal/Basic.lean index 007650831d182..53b923048670b 100644 --- a/Mathlib/SetTheory/Surreal/Basic.lean +++ b/Mathlib/SetTheory/Surreal/Basic.lean @@ -250,8 +250,8 @@ theorem add : ∀ {x y : PGame} (_ : Numeric x) (_ : Numeric y), Numeric (x + y) · rintro (jx | jy) · apply (ox.moveRight jx).add oy · apply ox.add (oy.moveRight jy)⟩ -termination_by _ x y _ _ => (x, y) -- Porting note: Added `termination_by` -decreasing_by pgame_wf_tac +termination_by x y => (x, y) -- Porting note: Added `termination_by` +decreasing_by all_goals pgame_wf_tac #align pgame.numeric.add SetTheory.PGame.Numeric.add theorem sub {x y : PGame} (ox : Numeric x) (oy : Numeric y) : Numeric (x - y) := diff --git a/Mathlib/SetTheory/ZFC/Basic.lean b/Mathlib/SetTheory/ZFC/Basic.lean index 8bfc3b9f71fad..f7cc70de08549 100644 --- a/Mathlib/SetTheory/ZFC/Basic.lean +++ b/Mathlib/SetTheory/ZFC/Basic.lean @@ -1370,7 +1370,7 @@ theorem map_isFunc {f : ZFSet → ZFSet} [Definable 1 f] {x y : ZFSet} : members of `x` are all `Hereditarily p`. -/ def Hereditarily (p : ZFSet → Prop) (x : ZFSet) : Prop := p x ∧ ∀ y ∈ x, Hereditarily p y -termination_by _ => x +termination_by x #align Set.hereditarily ZFSet.Hereditarily section Hereditarily @@ -1784,7 +1784,7 @@ theorem choice_mem (y : ZFSet.{u}) (yx : y ∈ x) : (choice x ′ y : Class.{u}) #align Set.choice_mem ZFSet.choice_mem private lemma toSet_equiv_aux {s : Set ZFSet.{u}} (hs : Small.{u} s) : - (mk $ PSet.mk (Shrink s) fun x ↦ ((equivShrink s).symm x).1.out).toSet = s := by + (mk <| PSet.mk (Shrink s) fun x ↦ ((equivShrink s).symm x).1.out).toSet = s := by ext x rw [mem_toSet, ← mk_out x, mk_mem_iff, mk_out] refine' ⟨_, λ xs ↦ ⟨equivShrink s (Subtype.mk x xs), _⟩⟩ @@ -1797,9 +1797,9 @@ private lemma toSet_equiv_aux {s : Set ZFSet.{u}} (hs : Small.{u} s) : @[simps apply_coe] noncomputable def toSet_equiv : ZFSet.{u} ≃ {s : Set ZFSet.{u} // Small.{u, u+1} s} where toFun x := ⟨x.toSet, x.small_toSet⟩ - invFun := λ ⟨s, h⟩ ↦ mk $ PSet.mk (Shrink s) fun x ↦ ((equivShrink.{u, u+1} s).symm x).1.out + invFun := λ ⟨s, h⟩ ↦ mk <| PSet.mk (Shrink s) fun x ↦ ((equivShrink.{u, u+1} s).symm x).1.out left_inv := Function.rightInverse_of_injective_of_leftInverse (by intros x y; simp) - λ s ↦ Subtype.coe_injective $ toSet_equiv_aux s.2 - right_inv s := Subtype.coe_injective $ toSet_equiv_aux s.2 + λ s ↦ Subtype.coe_injective <| toSet_equiv_aux s.2 + right_inv s := Subtype.coe_injective <| toSet_equiv_aux s.2 end ZFSet diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index 19af921d915fd..9e17126b806c1 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -68,6 +68,7 @@ import Mathlib.Tactic.InferParam import Mathlib.Tactic.Inhabit import Mathlib.Tactic.IntervalCases import Mathlib.Tactic.IrreducibleDef +import Mathlib.Tactic.Lemma import Mathlib.Tactic.LibrarySearch import Mathlib.Tactic.Lift import Mathlib.Tactic.LiftLets @@ -169,6 +170,7 @@ import Mathlib.Tactic.ToLevel import Mathlib.Tactic.Trace import Mathlib.Tactic.TryThis import Mathlib.Tactic.TypeCheck +import Mathlib.Tactic.TypeStar import Mathlib.Tactic.UnsetOption import Mathlib.Tactic.Use import Mathlib.Tactic.Variable diff --git a/Mathlib/Tactic/Abel.lean b/Mathlib/Tactic/Abel.lean index 294f48725777e..55b6a8b9e6fb1 100644 --- a/Mathlib/Tactic/Abel.lean +++ b/Mathlib/Tactic/Abel.lean @@ -442,7 +442,7 @@ partial def abelNFCore let thms := [``term_eq, ``termg_eq, ``add_zero, ``one_nsmul, ``one_zsmul, ``zsmul_zero] let ctx' := { ctx with simpTheorems := #[← thms.foldlM (·.addConst ·) {:_}] } pure fun r' : Simp.Result ↦ do - Simp.mkEqTrans r' (← Simp.main r'.expr ctx' (methods := Simp.DefaultMethods.methods)).1 + Simp.mkEqTrans r' (← Simp.main r'.expr ctx' (methods := ← Lean.Meta.Simp.mkDefaultMethods)).1 let rec /-- The recursive case of `abelNF`. * `root`: true when the function is called directly from `abelNFCore` diff --git a/Mathlib/Tactic/ApplyAt.lean b/Mathlib/Tactic/ApplyAt.lean index 9c7971582cd01..4f3e2750087e7 100644 --- a/Mathlib/Tactic/ApplyAt.lean +++ b/Mathlib/Tactic/ApplyAt.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Adam Topaz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Adam Topaz -/ -import Lean.Elab.Tactic +import Lean.Elab.Tactic.ElabTerm import Mathlib.Lean.Meta.Basic /-! @@ -23,7 +23,7 @@ metavariables/goals for any terms of `αⱼ` for `j = 1, …, i-1`, then replace the type of `i` with `αᵢ₊₁ → ⋯ → αₙ` by applying those metavariables and the original `i`. -/ -elab "apply" t:term "at" i:ident : tactic => withMainContext do +elab "apply" t:term "at" i:ident : tactic => withSynthesize <| withMainContext do let f ← elabTermForApply t let some ldecl := (← getLCtx).findFromUserName? i.getId | throwErrorAt i m!"Identifier {i} not found" diff --git a/Mathlib/Tactic/ApplyWith.lean b/Mathlib/Tactic/ApplyWith.lean index 5968537a9085e..f06d4c9e7e323 100644 --- a/Mathlib/Tactic/ApplyWith.lean +++ b/Mathlib/Tactic/ApplyWith.lean @@ -1,4 +1,5 @@ -import Lean +import Lean.Elab.Eval +import Lean.Elab.Tactic.ElabTerm import Std.Util.TermUnsafe namespace Mathlib.Tactic diff --git a/Mathlib/Tactic/Attr/Register.lean b/Mathlib/Tactic/Attr/Register.lean index 53f85a8483cc7..4a0b6d92f0b28 100644 --- a/Mathlib/Tactic/Attr/Register.lean +++ b/Mathlib/Tactic/Attr/Register.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Lean.Meta.Tactic.Simp +import Lean.Meta.Tactic.Simp.SimpTheorems import Std.Tactic.LabelAttr /-! diff --git a/Mathlib/Tactic/Basic.lean b/Mathlib/Tactic/Basic.lean index 5a1a3f5a3ff74..5773d41dcf83b 100644 --- a/Mathlib/Tactic/Basic.lean +++ b/Mathlib/Tactic/Basic.lean @@ -7,6 +7,8 @@ import Lean import Std import Mathlib.Tactic.PPWithUniv import Mathlib.Tactic.ExtendDoc +import Mathlib.Tactic.Lemma +import Mathlib.Tactic.TypeStar set_option autoImplicit true @@ -21,31 +23,6 @@ syntax (name := «variables») "variables" (ppSpace bracketedBinder)* : command elabVariable (← `(variable%$pos $binders*)) | _ => throwUnsupportedSyntax -/-- `lemma` means the same as `theorem`. It is used to denote "less important" theorems -/ -syntax (name := lemma) declModifiers - group("lemma " declId ppIndent(declSig) declVal Parser.Command.terminationSuffix) : command - -/-- Implementation of the `lemma` command, by macro expansion to `theorem`. -/ -@[macro «lemma»] def expandLemma : Macro := fun stx => - -- FIXME: this should be a macro match, but terminationSuffix is not easy to bind correctly. - -- This implementation ensures that any future changes to `theorem` are reflected in `lemma` - let stx := stx.modifyArg 1 fun stx => - let stx := stx.modifyArg 0 (mkAtomFrom · "theorem" (canonical := true)) - stx.setKind ``Parser.Command.theorem - pure <| stx.setKind ``Parser.Command.declaration - -/-- The syntax `variable (X Y ... Z : Sort*)` creates a new distinct implicit universe variable -for each variable in the sequence. -/ -elab "Sort*" : term => do - let u ← Lean.Meta.mkFreshLevelMVar - Elab.Term.levelMVarToParam (.sort u) - -/-- The syntax `variable (X Y ... Z : Type*)` creates a new distinct implicit universe variable -`> 0` for each variable in the sequence. -/ -elab "Type*" : term => do - let u ← Lean.Meta.mkFreshLevelMVar - Elab.Term.levelMVarToParam (.sort (.succ u)) - /-- Given two arrays of `FVarId`s, one from an old local context and the other from a new local context, pushes `FVarAliasInfo`s into the info tree for corresponding pairs of `FVarId`s. Recall that variables linked this way should be considered to be semantically identical. diff --git a/Mathlib/Tactic/ByContra.lean b/Mathlib/Tactic/ByContra.lean index ec7bc62e4cbd9..88ad506536c1e 100644 --- a/Mathlib/Tactic/ByContra.lean +++ b/Mathlib/Tactic/ByContra.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Kevin Buzzard. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Kevin Buzzard -/ -import Lean import Mathlib.Tactic.PushNeg open Lean Lean.Parser Parser.Tactic Elab Command Elab.Tactic Meta diff --git a/Mathlib/Tactic/CancelDenoms/Core.lean b/Mathlib/Tactic/CancelDenoms/Core.lean index 5d56764a986e7..1affc7c689e32 100644 --- a/Mathlib/Tactic/CancelDenoms/Core.lean +++ b/Mathlib/Tactic/CancelDenoms/Core.lean @@ -3,10 +3,11 @@ Copyright (c) 2020 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis -/ -import Mathlib.Tactic.NormNum.Core import Mathlib.Algebra.Order.Field.Basic -import Mathlib.Util.SynthesizeUsing import Mathlib.Data.Tree +import Mathlib.Logic.Basic +import Mathlib.Tactic.NormNum.Core +import Mathlib.Util.SynthesizeUsing import Mathlib.Util.Qq /-! diff --git a/Mathlib/Tactic/Cases.lean b/Mathlib/Tactic/Cases.lean index 5f423d3e1d625..a24d483eeaf0b 100644 --- a/Mathlib/Tactic/Cases.lean +++ b/Mathlib/Tactic/Cases.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Lean +import Lean.Elab.Tactic.Induction import Std.Tactic.OpenPrivate import Std.Data.List.Basic import Mathlib.Lean.Expr.Basic diff --git a/Mathlib/Tactic/CasesM.lean b/Mathlib/Tactic/CasesM.lean index 64723bf62db1b..4ea17a6d60288 100644 --- a/Mathlib/Tactic/CasesM.lean +++ b/Mathlib/Tactic/CasesM.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Lean +import Lean.Elab.Tactic.Conv.Pattern /-! # `casesm`, `cases_type`, `constructorm` tactics diff --git a/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean b/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean index 625ff62312235..12775bef2b95a 100644 --- a/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean +++ b/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yuma Mizuno. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yuma Mizuno -/ -import Mathlib.CategoryTheory.Bicategory.Coherence +import Mathlib.CategoryTheory.Bicategory.Free #align_import category_theory.bicategory.coherence_tactic from "leanprover-community/mathlib"@"3d7987cda72abc473c7cdbbb075170e9ac620042" diff --git a/Mathlib/Tactic/CategoryTheory/Coherence.lean b/Mathlib/Tactic/CategoryTheory/Coherence.lean index ffa3d3e9dea24..e20cfd503f257 100644 --- a/Mathlib/Tactic/CategoryTheory/Coherence.lean +++ b/Mathlib/Tactic/CategoryTheory/Coherence.lean @@ -3,7 +3,8 @@ Copyright (c) 2022. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Yuma Mizuno, Oleksandr Manzyuk -/ -import Mathlib.CategoryTheory.Monoidal.Free.Coherence +import Mathlib.CategoryTheory.Monoidal.Free.Basic +import Mathlib.Lean.Meta import Mathlib.Tactic.CategoryTheory.BicategoryCoherence #align_import category_theory.monoidal.coherence from "leanprover-community/mathlib"@"f187f1074fa1857c94589cc653c786cadc4c35ff" diff --git a/Mathlib/Tactic/CategoryTheory/Elementwise.lean b/Mathlib/Tactic/CategoryTheory/Elementwise.lean index e9920aa866288..ea89b5018467b 100644 --- a/Mathlib/Tactic/CategoryTheory/Elementwise.lean +++ b/Mathlib/Tactic/CategoryTheory/Elementwise.lean @@ -45,9 +45,9 @@ section theorems theorem forall_congr_forget_Type (α : Type u) (p : α → Prop) : (∀ (x : (forget (Type u)).obj α), p x) ↔ ∀ (x : α), p x := Iff.rfl -attribute [local instance] ConcreteCategory.funLike ConcreteCategory.hasCoeToSort +attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort -theorem forget_hom_Type (α β : Type u) (f : α ⟶ β) : FunLike.coe f = f := rfl +theorem forget_hom_Type (α β : Type u) (f : α ⟶ β) : DFunLike.coe f = f := rfl theorem hom_elementwise [Category C] [ConcreteCategory C] {X Y : C} {f g : X ⟶ Y} (h : f = g) (x : X) : f x = g x := by rw [h] diff --git a/Mathlib/Tactic/Choose.lean b/Mathlib/Tactic/Choose.lean index 4f04db360628d..8e5fd8cbf8861 100644 --- a/Mathlib/Tactic/Choose.lean +++ b/Mathlib/Tactic/Choose.lean @@ -130,8 +130,8 @@ def choose1 (g : MVarId) (nondep : Bool) (h : Option Expr) (data : Name) : return (neFail, fvar, g) | .const ``And _, #[p, q] => do let data ← mkFreshNameFrom data `h - let e1 ← mkLambdaFVars ctx $ mkApp3 (.const ``And.left []) p q (mkAppN h ctx) - let e2 ← mkLambdaFVars ctx $ mkApp3 (.const ``And.right []) p q (mkAppN h ctx) + let e1 ← mkLambdaFVars ctx <| mkApp3 (.const ``And.left []) p q (mkAppN h ctx) + let e2 ← mkLambdaFVars ctx <| mkApp3 (.const ``And.right []) p q (mkAppN h ctx) let t1 ← inferType e1 let t2 ← inferType e2 let (fvar, g) ← (← (← g.assert .anonymous t2 e2).assert data t1 e1).intro1P diff --git a/Mathlib/Tactic/Clean.lean b/Mathlib/Tactic/Clean.lean index d1c1bb02bc2d4..3c27d21b3c97e 100644 --- a/Mathlib/Tactic/Clean.lean +++ b/Mathlib/Tactic/Clean.lean @@ -3,8 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Michail Karatarakis, Kyle Miller -/ - -import Lean +import Lean.Elab.SyntheticMVars /-! # `clean%` term elaborator diff --git a/Mathlib/Tactic/Clear!.lean b/Mathlib/Tactic/Clear!.lean index ae06fdf66a186..f15744e865792 100644 --- a/Mathlib/Tactic/Clear!.lean +++ b/Mathlib/Tactic/Clear!.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Joshua Clune. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joshua Clune -/ -import Lean +import Lean.Elab.Tactic.ElabTerm /-! # `clear!` tactic -/ diff --git a/Mathlib/Tactic/ClearExcept.lean b/Mathlib/Tactic/ClearExcept.lean index 06204633292d5..3939f201134e2 100644 --- a/Mathlib/Tactic/ClearExcept.lean +++ b/Mathlib/Tactic/ClearExcept.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Joshua Clune. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joshua Clune -/ -import Lean +import Lean.Elab.Tactic.ElabTerm open Lean.Meta diff --git a/Mathlib/Tactic/Clear_.lean b/Mathlib/Tactic/Clear_.lean index 014ec5dd9a42a..d1be75bb99ce9 100644 --- a/Mathlib/Tactic/Clear_.lean +++ b/Mathlib/Tactic/Clear_.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Joshua Clune. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joshua Clune -/ -import Lean +import Lean.Meta.Tactic.Clear +import Lean.Elab.Tactic.Basic /-! # `clear_` tactic -/ diff --git a/Mathlib/Tactic/Coe.lean b/Mathlib/Tactic/Coe.lean index 40cd99a2f7192..7c0b12f3914f1 100644 --- a/Mathlib/Tactic/Coe.lean +++ b/Mathlib/Tactic/Coe.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Gabriel Ebner. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Gabriel Ebner -/ -import Lean +import Lean.Elab.ElabRules open Lean Elab Term Meta diff --git a/Mathlib/Tactic/Common.lean b/Mathlib/Tactic/Common.lean index ab30a2a40e83e..8bd06a6a6a34e 100644 --- a/Mathlib/Tactic/Common.lean +++ b/Mathlib/Tactic/Common.lean @@ -8,6 +8,9 @@ Authors: Scott Morrison import Aesop import Qq +-- Tools for analysing imports, like `#find_home`, `#minimize_imports`, ... +import ImportGraph.Imports + -- Now import all tactics defined in Mathlib that do not require theory files. import Mathlib.Mathport.Rename import Mathlib.Tactic.ApplyCongr @@ -108,7 +111,6 @@ import Mathlib.Tactic.Widget.Conv import Mathlib.Tactic.WLOG import Mathlib.Util.AssertExists import Mathlib.Util.CountHeartbeats -import Mathlib.Util.Imports import Mathlib.Util.WhatsNew /-! diff --git a/Mathlib/Tactic/ComputeDegree.lean b/Mathlib/Tactic/ComputeDegree.lean index a731eec11f844..eed0600a827be 100644 --- a/Mathlib/Tactic/ComputeDegree.lean +++ b/Mathlib/Tactic/ComputeDegree.lean @@ -221,7 +221,7 @@ def twoHeadsArgs (e : Expr) : Name × Name × Sum Name Name × List Bool := Id.r | some 1 => .inl `one | some _ => .inl `many | none => match pol.getAppFnArgs with - | (``FunLike.coe, #[_, _, _, _, polFun, _]) => + | (``DFunLike.coe, #[_, _, _, _, polFun, _]) => let na := polFun.getAppFn.constName if na ∈ [``Polynomial.monomial, ``Polynomial.C] then .inr na diff --git a/Mathlib/Tactic/Congr!.lean b/Mathlib/Tactic/Congr!.lean index 89ffe382d0a04..28b29a939c715 100644 --- a/Mathlib/Tactic/Congr!.lean +++ b/Mathlib/Tactic/Congr!.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Lean import Mathlib.Lean.Meta.CongrTheorems import Mathlib.Tactic.Relation.Rfl import Std.Logic diff --git a/Mathlib/Tactic/Constructor.lean b/Mathlib/Tactic/Constructor.lean index d86d74a2c8131..718dccf4276fc 100644 --- a/Mathlib/Tactic/Constructor.lean +++ b/Mathlib/Tactic/Constructor.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Newell Jensen -/ -import Lean.Elab.Command +import Lean.Elab.SyntheticMVars import Lean.Meta.Tactic.Constructor open Lean Meta Elab Tactic diff --git a/Mathlib/Tactic/Continuity.lean b/Mathlib/Tactic/Continuity.lean index 7d824fd5a841c..983151140dfe3 100644 --- a/Mathlib/Tactic/Continuity.lean +++ b/Mathlib/Tactic/Continuity.lean @@ -5,7 +5,6 @@ Authors: Moritz Doll -/ import Mathlib.Tactic.Continuity.Init -import Mathlib.Algebra.Group.Defs /-! # Continuity @@ -23,13 +22,14 @@ macro "continuity" : attr => The tactic `continuity` solves goals of the form `Continuous f` by applying lemmas tagged with the `continuity` user attribute. -/ macro "continuity" : tactic => - `(tactic| aesop (options := { terminal := true }) (rule_sets [$(Lean.mkIdent `Continuous):ident])) + `(tactic| aesop (config := { terminal := true }) + (rule_sets [$(Lean.mkIdent `Continuous):ident])) /-- The tactic `continuity` solves goals of the form `Continuous f` by applying lemmas tagged with the `continuity` user attribute. -/ macro "continuity?" : tactic => - `(tactic| aesop? (options := { terminal := true }) + `(tactic| aesop? (config := { terminal := true }) (rule_sets [$(Lean.mkIdent `Continuous):ident])) -- Todo: implement `continuity!` and `continuity!?` and add configuration, original diff --git a/Mathlib/Tactic/Convert.lean b/Mathlib/Tactic/Convert.lean index a16d50fbadf6f..fd8c95044ae83 100644 --- a/Mathlib/Tactic/Convert.lean +++ b/Mathlib/Tactic/Convert.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Lean import Mathlib.Tactic.Congr! /-! diff --git a/Mathlib/Tactic/Core.lean b/Mathlib/Tactic/Core.lean index 79d349fad19e7..e11b16551d73a 100644 --- a/Mathlib/Tactic/Core.lean +++ b/Mathlib/Tactic/Core.lean @@ -3,8 +3,10 @@ Copyright (c) 2021 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino, Aurélien Saue, Mario Carneiro -/ +import Lean.Elab.PreDefinition.Basic +import Lean.Util.Paths import Std.Tactic.Simpa -import Mathlib.Lean.Expr +import Mathlib.Lean.Expr.Basic /-! # @@ -38,7 +40,7 @@ def toModifiers (nm : Name) (newDoc : Option String := none) : Visibility.regular else Visibility.protected - isNoncomputable := if (env.find? $ nm.mkStr "_cstage1").isSome then false else true + isNoncomputable := if (env.find? <| nm.mkStr "_cstage1").isSome then false else true recKind := RecKind.default -- nonrec only matters for name resolution, so is irrelevant (?) isUnsafe := d.isUnsafe attrs := #[] } @@ -61,7 +63,8 @@ def toPreDefinition (nm newNm : Name) (newType newValue : Expr) (newDoc : Option modifiers := mods declName := newNm type := newType - value := newValue } + value := newValue + termination := .none } return predef /-- Make `nm` protected. -/ diff --git a/Mathlib/Tactic/DeriveToExpr.lean b/Mathlib/Tactic/DeriveToExpr.lean index db39232bce65c..7dccf4d691c16 100644 --- a/Mathlib/Tactic/DeriveToExpr.lean +++ b/Mathlib/Tactic/DeriveToExpr.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Lean import Mathlib.Tactic.ToLevel /-! diff --git a/Mathlib/Tactic/DeriveTraversable.lean b/Mathlib/Tactic/DeriveTraversable.lean index 2bd7d81ad59f3..f29102a366d73 100644 --- a/Mathlib/Tactic/DeriveTraversable.lean +++ b/Mathlib/Tactic/DeriveTraversable.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ -import Mathlib.Tactic.Basic import Mathlib.Control.Traversable.Lemmas #align_import control.traversable.derive from "leanprover-community/mathlib"@"b01d6eb9d0a308807af54319b264d0994b91774b" @@ -179,7 +178,8 @@ def deriveFunctor (m : MVarId) : TermElabM Unit := do stx := ← `(attr| specialize) }] } declName := n' type := t' - value := e' }] {} + value := e' + termination := .none }] {} m.assign (mkAppN (mkConst n' (levels.map Level.param)) vars.toArray) /-- Similar to `mkInstanceName`, but for a `Expr` type. -/ @@ -244,7 +244,8 @@ def mkOneInstance (n cls : Name) (tac : MVarId → TermElabM Unit) stx := ← `(attr| instance) }] } declName := instN type := tgt - value := val }] {} + value := val + termination := .none }] {} /-- Make the new deriving handler depends on other deriving handlers. -/ def higherOrderDeriveHandler (cls : Name) (tac : MVarId → TermElabM Unit) @@ -415,7 +416,8 @@ def deriveTraversable (m : MVarId) : TermElabM Unit := do visibility := .protected } declName := n' type := t' - value := e' }] {} + value := e' + termination := .none }] {} m.assign (mkAppN (mkConst n' (levels.map Level.param)) vars.toArray) /-- The deriving handler for `Traversable`. -/ @@ -425,13 +427,14 @@ def traversableDeriveHandler : DerivingHandlerNoArgs := initialize registerDerivingHandler ``Traversable traversableDeriveHandler /-- Simplify the goal `m` using `functor_norm`. -/ -def simpFunctorGoal (m : MVarId) (s : Simp.Context) (discharge? : Option Simp.Discharge := none) +def simpFunctorGoal (m : MVarId) (s : Simp.Context) (simprocs : Simprocs := {}) + (discharge? : Option Simp.Discharge := none) (simplifyTarget : Bool := true) (fvarIdsToSimp : Array FVarId := #[]) (usedSimps : Simp.UsedSimps := {}) : MetaM (Option (Array FVarId × MVarId) × Simp.UsedSimps) := do let some e ← getSimpExtension? `functor_norm | failure let s' ← e.getTheorems - simpGoal m { s with simpTheorems := s.simpTheorems.push s' } discharge? simplifyTarget + simpGoal m { s with simpTheorems := s.simpTheorems.push s' } simprocs discharge? simplifyTarget fvarIdsToSimp usedSimps /-- Run the following tactic: diff --git a/Mathlib/Tactic/Eqns.lean b/Mathlib/Tactic/Eqns.lean index e8ea5e7a6dc19..7118d31444e08 100644 --- a/Mathlib/Tactic/Eqns.lean +++ b/Mathlib/Tactic/Eqns.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Lean.Meta.Eqns -import Mathlib.Lean.Expr import Std.Lean.NameMapAttribute +import Std.CodeAction.Attr +import Std.Tactic.Lint.Basic /-! # The `@[eqns]` attribute diff --git a/Mathlib/Tactic/Existsi.lean b/Mathlib/Tactic/Existsi.lean index 544e1285bb2cf..f14ce250511c4 100644 --- a/Mathlib/Tactic/Existsi.lean +++ b/Mathlib/Tactic/Existsi.lean @@ -4,8 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino, Gabriel Ebner, Moritz Doll -/ -import Mathlib.Tactic.Basic - namespace Mathlib.Tactic /-- diff --git a/Mathlib/Tactic/Explode.lean b/Mathlib/Tactic/Explode.lean index 0730a283e6ddb..70e52d35d6ab1 100644 --- a/Mathlib/Tactic/Explode.lean +++ b/Mathlib/Tactic/Explode.lean @@ -3,7 +3,8 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Evgenia Karunus, Kyle Miller -/ -import Lean +import Lean.Elab.Command +import Lean.PrettyPrinter import Mathlib.Tactic.Explode.Datatypes import Mathlib.Tactic.Explode.Pretty diff --git a/Mathlib/Tactic/Explode/Datatypes.lean b/Mathlib/Tactic/Explode/Datatypes.lean index 0bc264b81d460..0ce6999aa004c 100644 --- a/Mathlib/Tactic/Explode/Datatypes.lean +++ b/Mathlib/Tactic/Explode/Datatypes.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Evgenia Karunus, Kyle Miller -/ -import Lean +import Lean.Util.Trace /-! # Explode command: datatypes diff --git a/Mathlib/Tactic/Explode/Pretty.lean b/Mathlib/Tactic/Explode/Pretty.lean index 44f15e7531e3d..cb2b463d13943 100644 --- a/Mathlib/Tactic/Explode/Pretty.lean +++ b/Mathlib/Tactic/Explode/Pretty.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Evgenia Karunus, Kyle Miller -/ -import Lean +import Lean.Meta.Basic import Mathlib.Tactic.Explode.Datatypes /-! diff --git a/Mathlib/Tactic/ExtractGoal.lean b/Mathlib/Tactic/ExtractGoal.lean index 510d6c201bc39..f2672712927bb 100644 --- a/Mathlib/Tactic/ExtractGoal.lean +++ b/Mathlib/Tactic/ExtractGoal.lean @@ -3,6 +3,9 @@ Copyright (c) 2017 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon, Kyle Miller, Damiano Testa -/ +import Lean.Elab.Tactic.ElabTerm +import Lean.Meta.Tactic.Cleanup +import Lean.PrettyPrinter import Std.Lean.Meta.Inaccessible /-! diff --git a/Mathlib/Tactic/FailIfNoProgress.lean b/Mathlib/Tactic/FailIfNoProgress.lean index 04e85daed6574..7510cb693be57 100644 --- a/Mathlib/Tactic/FailIfNoProgress.lean +++ b/Mathlib/Tactic/FailIfNoProgress.lean @@ -3,7 +3,8 @@ Copyright (c) 2023 Thomas Murrills. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Murrills -/ -import Lean +import Lean.Elab.Tactic.Basic +import Lean.Meta.Tactic.Util /-! # Fail if no progress @@ -57,7 +58,7 @@ def lctxIsDefEq : (l₁ l₂ : List (Option LocalDecl)) → MetaM Bool lctxIsDefEq l₁ l₂ | [], [] => return true | _, _ => return false -termination_by _ l₁ l₂ => l₁.length + l₂.length +termination_by l₁ l₂ => l₁.length + l₂.length /-- Run `tacs : TacticM Unit` on `goal`, and fail if no progress is made. -/ def runAndFailIfNoProgress (goal : MVarId) (tacs : TacticM Unit) : TacticM (List MVarId) := do diff --git a/Mathlib/Tactic/FieldSimp.lean b/Mathlib/Tactic/FieldSimp.lean index cf7853643b95e..bc804f070ce37 100644 --- a/Mathlib/Tactic/FieldSimp.lean +++ b/Mathlib/Tactic/FieldSimp.lean @@ -61,7 +61,7 @@ partial def discharge (prop : Expr) : SimpM (Option Expr) := if let some pf := pf? then return some pf -- Discharge strategy 4: Use the simplifier - let ctx ← read + let ctx ← readThe Simp.Context let usedTheorems := (← get).usedTheorems -- Port note: mathlib3's analogous field_simp discharger `field_simp.ne_zero` @@ -71,7 +71,8 @@ partial def discharge (prop : Expr) : SimpM (Option Expr) := -- 2) mathlib3 norm_num1 is able to handle any needed discharging, or -- 3) some other reason? let ⟨simpResult, usedTheorems'⟩ ← - simp prop { ctx with dischargeDepth := ctx.dischargeDepth + 1} discharge usedTheorems + simp prop { ctx with dischargeDepth := ctx.dischargeDepth + 1 } (← Simp.getSimprocs) discharge + usedTheorems set {(← get) with usedTheorems := usedTheorems'} if simpResult.expr.isConstOf ``True then try @@ -175,7 +176,7 @@ elab_rules : tactic congrTheorems := (← getSimpCongrTheorems) config := cfg } - let mut r ← elabSimpArgs (sa.getD ⟨.missing⟩) ctx (eraseLocal := false) .simp + let mut r ← elabSimpArgs (sa.getD ⟨.missing⟩) ctx (simprocs := {}) (eraseLocal := false) .simp if r.starArg then r ← do let ctx := r.ctx @@ -185,6 +186,6 @@ elab_rules : tactic unless simpTheorems.isErased (.fvar h) do simpTheorems ← simpTheorems.addTheorem (.fvar h) (← h.getDecl).toExpr let ctx := { ctx with simpTheorems } - pure { ctx } + pure { ctx, simprocs := {} } - _ ← simpLocation r.ctx dis loc + _ ← simpLocation r.ctx {} dis loc diff --git a/Mathlib/Tactic/Find.lean b/Mathlib/Tactic/Find.lean index 14effbeab0dd2..2f68e9be0c092 100644 --- a/Mathlib/Tactic/Find.lean +++ b/Mathlib/Tactic/Find.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Sebastian Ullrich. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sebastian Ullrich -/ -import Lean import Std.Util.Cache /-! @@ -43,7 +42,7 @@ private partial def matchHyps : List Expr → List Expr → List Expr → MetaM -- from Lean.Server.Completion private def isBlackListed (declName : Name) : MetaM Bool := do let env ← getEnv - pure $ declName.isInternal + pure <| declName.isInternal || isAuxRecursor env declName || isNoConfusion env declName <||> isRec declName @@ -57,7 +56,7 @@ initialize findDeclsPerHead : DeclCache (Lean.HashMap HeadIndex (Array Name)) -- to avoid leaking metavariables. let (_, _, ty) ← forallMetaTelescopeReducing c.type let head := ty.toHeadIndex - pure $ headMap.insert head (headMap.findD head #[] |>.push c.name) + pure <| headMap.insert head (headMap.findD head #[] |>.push c.name) def findType (t : Expr) : TermElabM Unit := withReducible do let t ← instantiateMVars t diff --git a/Mathlib/Tactic/GeneralizeProofs.lean b/Mathlib/Tactic/GeneralizeProofs.lean index 2c737f1c3963a..0a17dd68d5a3b 100644 --- a/Mathlib/Tactic/GeneralizeProofs.lean +++ b/Mathlib/Tactic/GeneralizeProofs.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Alex J. Best. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Alex J. Best -/ -import Lean +import Lean.Meta.AbstractNestedProofs import Mathlib.Lean.Expr.Basic /-! @@ -39,7 +39,7 @@ structure State where /-- Monad used by the `generalizeProofs` tactic, carries an expr cache and state with names to use and previous generalizations -/ -abbrev M := MonadCacheT ExprStructEq Expr $ StateRefT State MetaM +abbrev M := MonadCacheT ExprStructEq Expr <| StateRefT State MetaM /-- generalize the given e -/ private def mkGen (e : Expr) : M Unit := do diff --git a/Mathlib/Tactic/GuardGoalNums.lean b/Mathlib/Tactic/GuardGoalNums.lean index 3239eeb64efdb..882cb6b7bf060 100644 --- a/Mathlib/Tactic/GuardGoalNums.lean +++ b/Mathlib/Tactic/GuardGoalNums.lean @@ -3,8 +3,7 @@ Copyright (c) 2022 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis -/ - -import Lean +import Lean.Elab.Tactic.Basic /-! diff --git a/Mathlib/Tactic/GuardHypNums.lean b/Mathlib/Tactic/GuardHypNums.lean index 33116c380a75d..60a0cf119966a 100644 --- a/Mathlib/Tactic/GuardHypNums.lean +++ b/Mathlib/Tactic/GuardHypNums.lean @@ -3,8 +3,7 @@ Copyright (c) 2022 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis -/ - -import Lean +import Lean.Elab.Tactic.Basic /-! A tactic stub file for the `guard_hyp_nums` tactic. diff --git a/Mathlib/Tactic/Have.lean b/Mathlib/Tactic/Have.lean index 49a534d80ff3d..26bd141416d87 100644 --- a/Mathlib/Tactic/Have.lean +++ b/Mathlib/Tactic/Have.lean @@ -3,8 +3,9 @@ Copyright (c) 2022 Arthur Paulino. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino, Edward Ayers, Mario Carneiro -/ -import Lean -import Mathlib.Data.Array.Defs +import Lean.Elab.Binders +import Lean.Elab.SyntheticMVars +import Lean.Meta.Tactic.Assert /-! # Extending `have`, `let` and `suffices` diff --git a/Mathlib/Tactic/HelpCmd.lean b/Mathlib/Tactic/HelpCmd.lean index 11a979baf8953..bf9e4f6e6c890 100644 --- a/Mathlib/Tactic/HelpCmd.lean +++ b/Mathlib/Tactic/HelpCmd.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Lean.Expr.Basic +import Lean.Elab.Syntax +import Std.Lean.Expr /-! diff --git a/Mathlib/Tactic/HigherOrder.lean b/Mathlib/Tactic/HigherOrder.lean index 4573db5a8169d..b6744d6df3759 100644 --- a/Mathlib/Tactic/HigherOrder.lean +++ b/Mathlib/Tactic/HigherOrder.lean @@ -6,6 +6,8 @@ Authors: Simon Hudon import Lean.Elab.Term import Lean.Meta.Tactic.Apply import Lean.Meta.Tactic.Assumption +import Lean.Meta.MatchUtil +import Lean.Meta.Tactic.Intro import Lean.Elab.DeclarationRange import Mathlib.Tactic.Attr.Register diff --git a/Mathlib/Tactic/InferParam.lean b/Mathlib/Tactic/InferParam.lean index 0fd9486acae8b..e649d5b1f7f72 100644 --- a/Mathlib/Tactic/InferParam.lean +++ b/Mathlib/Tactic/InferParam.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Mario Carneiro -/ -import Lean +import Lean.Elab.Tactic.Basic +import Lean.Meta.Tactic.Replace /-! # Infer an optional parameter diff --git a/Mathlib/Tactic/Inhabit.lean b/Mathlib/Tactic/Inhabit.lean index b4a2a6fd08b5a..daa5b484d6c1e 100644 --- a/Mathlib/Tactic/Inhabit.lean +++ b/Mathlib/Tactic/Inhabit.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joshua Clune -/ import Lean -import Mathlib.Tactic.Basic +import Mathlib.Tactic.TypeStar /-! Defines the `inhabit α` tactic, which tries to construct an `Inhabited α` instance, diff --git a/Mathlib/Tactic/IntervalCases.lean b/Mathlib/Tactic/IntervalCases.lean index 0c4ffc599cecf..3b7437e51cab3 100644 --- a/Mathlib/Tactic/IntervalCases.lean +++ b/Mathlib/Tactic/IntervalCases.lean @@ -5,7 +5,6 @@ Authors: Scott Morrison, Mario Carneiro -/ import Mathlib.Tactic.NormNum import Mathlib.Tactic.FinCases -import Mathlib.Data.Set.Intervals.Basic /-! # Case bash on variables in finite intervals diff --git a/Mathlib/Tactic/Lemma.lean b/Mathlib/Tactic/Lemma.lean new file mode 100644 index 0000000000000..4412258b0c428 --- /dev/null +++ b/Mathlib/Tactic/Lemma.lean @@ -0,0 +1,25 @@ +/- +Copyright (c) 2021 Mario Carneiro. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro, Kyle Miller +-/ +import Lean.Parser.Command + +/-! +# Support for `lemma` as a synonym for `theorem`. +-/ + +open Lean + +/-- `lemma` means the same as `theorem`. It is used to denote "less important" theorems -/ +syntax (name := lemma) declModifiers + group("lemma " declId ppIndent(declSig) declVal) : command + +/-- Implementation of the `lemma` command, by macro expansion to `theorem`. -/ +@[macro «lemma»] def expandLemma : Macro := fun stx => + -- Not using a macro match, to be more resilient against changes to `lemma`. + -- This implementation ensures that any future changes to `theorem` are reflected in `lemma` + let stx := stx.modifyArg 1 fun stx => + let stx := stx.modifyArg 0 (mkAtomFrom · "theorem" (canonical := true)) + stx.setKind ``Parser.Command.theorem + pure <| stx.setKind ``Parser.Command.declaration diff --git a/Mathlib/Tactic/LibrarySearch.lean b/Mathlib/Tactic/LibrarySearch.lean index e149c32a3a862..5855a99fd8aa4 100644 --- a/Mathlib/Tactic/LibrarySearch.lean +++ b/Mathlib/Tactic/LibrarySearch.lean @@ -7,9 +7,9 @@ import Std.Util.Pickle import Std.Util.Cache import Std.Tactic.SolveByElim import Std.Data.MLList.Heartbeats -import Mathlib.Lean.Name import Mathlib.Lean.Meta import Mathlib.Lean.Meta.DiscrTree +import Mathlib.Lean.Expr.Basic /-! # Library search diff --git a/Mathlib/Tactic/Lift.lean b/Mathlib/Tactic/Lift.lean index 3fb71eeb4a499..52af933587cca 100644 --- a/Mathlib/Tactic/Lift.lean +++ b/Mathlib/Tactic/Lift.lean @@ -3,8 +3,8 @@ Copyright (c) 2019 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ -import Mathlib.Tactic.Cases -import Mathlib.Init.Data.Int.Order +import Mathlib.Tactic.Basic +import Mathlib.Init.Data.Int.Basic /-! # lift tactic @@ -106,8 +106,8 @@ syntax (name := lift) "lift " term " to " term (" using " term)? /-- Generate instance for the `lift` tactic. -/ def Lift.getInst (old_tp new_tp : Expr) : MetaM (Expr × Expr × Expr) := do - let coe ← mkFreshExprMVar (some $ .forallE `a new_tp old_tp .default) - let p ← mkFreshExprMVar (some $ .forallE `a old_tp (.sort .zero) .default) + let coe ← mkFreshExprMVar (some <| .forallE `a new_tp old_tp .default) + let p ← mkFreshExprMVar (some <| .forallE `a old_tp (.sort .zero) .default) let inst_type ← mkAppM ``CanLift #[old_tp, new_tp, coe, p] let inst ← synthInstance inst_type -- TODO: catch error return (← instantiateMVars p, ← instantiateMVars coe, ← instantiateMVars inst) diff --git a/Mathlib/Tactic/Linarith/Lemmas.lean b/Mathlib/Tactic/Linarith/Lemmas.lean index f6555a602a111..45520dd96e6e3 100644 --- a/Mathlib/Tactic/Linarith/Lemmas.lean +++ b/Mathlib/Tactic/Linarith/Lemmas.lean @@ -9,7 +9,6 @@ import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Order.Monoid.Lemmas import Mathlib.Init.Data.Int.Order import Mathlib.Algebra.Order.ZeroLEOne -import Mathlib.Algebra.GroupPower.Order import Mathlib.Data.Nat.Cast.Order /-! diff --git a/Mathlib/Tactic/Linarith/Preprocessing.lean b/Mathlib/Tactic/Linarith/Preprocessing.lean index a4e9dae56b87a..585a7d4dbc8b6 100644 --- a/Mathlib/Tactic/Linarith/Preprocessing.lean +++ b/Mathlib/Tactic/Linarith/Preprocessing.lean @@ -6,7 +6,6 @@ Authors: Robert Y. Lewis import Mathlib.Tactic.Linarith.Datatypes import Mathlib.Tactic.Zify import Mathlib.Tactic.CancelDenoms.Core -import Mathlib.Lean.Exception import Std.Data.RBMap.Basic import Mathlib.Data.HashMap import Mathlib.Control.Basic @@ -299,7 +298,7 @@ def cancelDenoms : Preprocessor where name := "cancel denominators" transform := fun pf => (do let (_, lhs) ← parseCompAndExpr (← inferType pf) - guard $ lhs.containsConst (fun n => n = ``HDiv.hDiv || n = ``Div.div) + guard <| lhs.containsConst (fun n => n = ``HDiv.hDiv || n = ``Div.div) pure [← normalizeDenominatorsLHS pf lhs]) <|> return [pf] end cancelDenoms @@ -341,7 +340,7 @@ def nlinarithExtras : GlobalPreprocessor where let new_es ← s.foldM (fun new_es (⟨e, is_sq⟩ : Expr × Bool) => ((do let p ← mkAppM (if is_sq then ``sq_nonneg else ``mul_self_nonneg) #[e] - pure $ p::new_es) <|> pure new_es)) ([] : List Expr) + pure <| p::new_es) <|> pure new_es)) ([] : List Expr) let new_es ← compWithZero.globalize.transform new_es trace[linarith] "nlinarith preprocessing found squares" trace[linarith] "{s.toList}" @@ -386,7 +385,7 @@ partial def removeNe_aux : MVarId → List Expr → MetaM (List Branch) := fun g let do_goal : MVarId → MetaM (List Branch) := fun g => do let (f, h) ← g.intro1 h.withContext do - let ls ← removeNe_aux h $ hs.removeAll [e] + let ls ← removeNe_aux h <| hs.removeAll [e] return ls.map (fun b : Branch => (b.1, (.fvar f)::b.2)) return ((← do_goal ng1) ++ (← do_goal ng2)) diff --git a/Mathlib/Tactic/Measurability.lean b/Mathlib/Tactic/Measurability.lean index 8cc7bbf740ff3..1b3788e84a120 100644 --- a/Mathlib/Tactic/Measurability.lean +++ b/Mathlib/Tactic/Measurability.lean @@ -30,7 +30,8 @@ The tactic `measurability` solves goals of the form `Measurable f`, `AEMeasurabl `StronglyMeasurable f`, `AEStronglyMeasurable f μ`, or `MeasurableSet s` by applying lemmas tagged with the `measurability` user attribute. -/ macro "measurability" (config)? : tactic => - `(tactic| aesop (options := { terminal := true }) (rule_sets [$(Lean.mkIdent `Measurable):ident])) + `(tactic| aesop (config := { terminal := true }) + (rule_sets [$(Lean.mkIdent `Measurable):ident])) /-- The tactic `measurability?` solves goals of the form `Measurable f`, `AEMeasurable f`, @@ -38,7 +39,7 @@ The tactic `measurability?` solves goals of the form `Measurable f`, `AEMeasurab with the `measurability` user attribute, and suggests a faster proof script that can be substituted for the tactic call in case of success. -/ macro "measurability?" (config)? : tactic => - `(tactic| aesop? (options := { terminal := true }) + `(tactic| aesop? (config := { terminal := true }) (rule_sets [$(Lean.mkIdent `Measurable):ident])) -- Todo: implement `measurability!` and `measurability!?` and add configuration, diff --git a/Mathlib/Tactic/MkIffOfInductiveProp.lean b/Mathlib/Tactic/MkIffOfInductiveProp.lean index 6efae87acb7bc..94caf2862cb03 100644 --- a/Mathlib/Tactic/MkIffOfInductiveProp.lean +++ b/Mathlib/Tactic/MkIffOfInductiveProp.lean @@ -7,7 +7,7 @@ import Lean import Std.Tactic.LeftRight import Mathlib.Lean.Meta import Mathlib.Lean.Name -import Mathlib.Tactic.Basic +import Mathlib.Tactic.TypeStar /-! # mk_iff_of_inductive_prop diff --git a/Mathlib/Tactic/ModCases.lean b/Mathlib/Tactic/ModCases.lean index 97e2c05360ae9..1b4375e46c05d 100644 --- a/Mathlib/Tactic/ModCases.lean +++ b/Mathlib/Tactic/ModCases.lean @@ -26,7 +26,7 @@ It asserts that if `∃ z, lb ≤ z < n ∧ a ≡ z (mod n)` holds, then `p` (where `p` is the current goal). -/ def OnModCases (n : ℕ) (a : ℤ) (lb : ℕ) (p : Sort*) := -∀ z, lb ≤ z ∧ z < n ∧ a ≡ ↑z [ZMOD ↑n] → p + ∀ z, lb ≤ z ∧ z < n ∧ a ≡ ↑z [ZMOD ↑n] → p /-- The first theorem we apply says that `∃ z, 0 ≤ z < n ∧ a ≡ z (mod n)`. @@ -103,7 +103,7 @@ It asserts that if `∃ m, lb ≤ m < n ∧ a ≡ m (mod n)` holds, then `p` (where `p` is the current goal). -/ def OnModCases (n : ℕ) (a : ℕ) (lb : ℕ) (p : Sort _) := -∀ m, lb ≤ m ∧ m < n ∧ a ≡ m [MOD n] → p + ∀ m, lb ≤ m ∧ m < n ∧ a ≡ m [MOD n] → p /-- The first theorem we apply says that `∃ m, 0 ≤ m < n ∧ a ≡ m (mod n)`. diff --git a/Mathlib/Tactic/Monotonicity/Lemmas.lean b/Mathlib/Tactic/Monotonicity/Lemmas.lean index 50d39ac7fccf1..3ad48a50d8db3 100644 --- a/Mathlib/Tactic/Monotonicity/Lemmas.lean +++ b/Mathlib/Tactic/Monotonicity/Lemmas.lean @@ -20,7 +20,7 @@ open Set attribute [mono] le_refl -- added for Lean 4 version -attribute [mono] inter_subset_inter union_subset_union +attribute [mono] subset_refl inter_subset_inter union_subset_union sUnion_mono iUnion₂_mono sInter_subset_sInter iInter₂_mono image_subset preimage_mono prod_mono Monotone.set_prod seq_mono image2_subset OrderEmbedding.monotone diff --git a/Mathlib/Tactic/MoveAdd.lean b/Mathlib/Tactic/MoveAdd.lean index b160937169965..987a6d7fddde0 100644 --- a/Mathlib/Tactic/MoveAdd.lean +++ b/Mathlib/Tactic/MoveAdd.lean @@ -81,10 +81,12 @@ associative, commutative operation and a list of "operand atoms" and rearranges To work with a general associative, commutative binary operation, `move_oper` needs to have inbuilt the lemmas asserting the analogues of `add_comm, add_assoc, add_left_comm` for the new operation. -Currently, `move_oper` supports `HAdd.hAdd`, `HAdd.hAdd`, `and`, `or`, `max`, `min`. +Currently, `move_oper` supports `HAdd.hAdd`, `HMul.hMul`, `And`, `Or`, `Max.max`, `Min.min`. These lemmas should be added to `Mathlib.MoveAdd.move_oper_simpCtx`. +See `test/MoveAdd.lean` for sample usage of `move_oper`. + ## Implementation notes The main driver behind the tactic is `Mathlib.MoveAdd.reorderAndSimp`. diff --git a/Mathlib/Tactic/NormNum/Basic.lean b/Mathlib/Tactic/NormNum/Basic.lean index d3ddb5388d29c..a99d0fdc956ed 100644 --- a/Mathlib/Tactic/NormNum/Basic.lean +++ b/Mathlib/Tactic/NormNum/Basic.lean @@ -9,6 +9,7 @@ import Mathlib.Data.Int.Basic import Mathlib.Algebra.Invertible.Basic import Mathlib.Tactic.HaveI import Mathlib.Tactic.Clear! +import Mathlib.Data.Nat.Cast.Basic /-! ## `norm_num` basic plugins diff --git a/Mathlib/Tactic/NormNum/Core.lean b/Mathlib/Tactic/NormNum/Core.lean index d3450da515eb2..15536d94cd581 100644 --- a/Mathlib/Tactic/NormNum/Core.lean +++ b/Mathlib/Tactic/NormNum/Core.lean @@ -273,7 +273,8 @@ def getSimpContext (args : Syntax) (simpOnly := false) : TacticM Simp.Context := do let simpTheorems ← if simpOnly then simpOnlyBuiltins.foldlM (·.addConst ·) {} else getSimpTheorems - let mut { ctx, starArg } ← elabSimpArgs args[0] (eraseLocal := false) (kind := .simp) + let mut { ctx, simprocs := _, starArg } ← + elabSimpArgs args[0] (eraseLocal := false) (kind := .simp) (simprocs := {}) { simpTheorems := #[simpTheorems], congrTheorems := ← getSimpCongrTheorems } unless starArg do return ctx let mut simpTheorems := ctx.simpTheorems diff --git a/Mathlib/Tactic/NormNum/Eq.lean b/Mathlib/Tactic/NormNum/Eq.lean index 811ead10c38fd..266a35a08eb16 100644 --- a/Mathlib/Tactic/NormNum/Eq.lean +++ b/Mathlib/Tactic/NormNum/Eq.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Tactic.NormNum.Inv -import Mathlib.Algebra.Order.Invertible /-! # `norm_num` extension for equalities diff --git a/Mathlib/Tactic/NormNum/GCD.lean b/Mathlib/Tactic/NormNum/GCD.lean index 8c0d258f0732c..5aad293a3de72 100644 --- a/Mathlib/Tactic/NormNum/GCD.lean +++ b/Mathlib/Tactic/NormNum/GCD.lean @@ -24,8 +24,8 @@ theorem int_gcd_helper' {d : ℕ} {x y : ℤ} (a b : ℤ) (h₁ : (d : ℤ) ∣ refine Nat.dvd_antisymm ?_ (Int.coe_nat_dvd.1 (Int.dvd_gcd h₁ h₂)) rw [← Int.coe_nat_dvd, ← h₃] apply dvd_add - · exact (Int.gcd_dvd_left _ _).mul_right _ - · exact (Int.gcd_dvd_right _ _).mul_right _ + · exact Int.gcd_dvd_left.mul_right _ + · exact Int.gcd_dvd_right.mul_right _ theorem nat_gcd_helper_dvd_left (x y : ℕ) (h : y % x = 0) : Nat.gcd x y = x := Nat.gcd_eq_left (Nat.dvd_of_mod_eq_zero h) diff --git a/Mathlib/Tactic/NormNum/Ineq.lean b/Mathlib/Tactic/NormNum/Ineq.lean index ef1d6a60653f2..e721ea956a395 100644 --- a/Mathlib/Tactic/NormNum/Ineq.lean +++ b/Mathlib/Tactic/NormNum/Ineq.lean @@ -6,6 +6,7 @@ Authors: Mario Carneiro import Mathlib.Tactic.NormNum.Eq import Mathlib.Algebra.Order.Field.Defs import Mathlib.Algebra.Order.Monoid.WithTop +import Mathlib.Algebra.Order.Invertible /-! # `norm_num` extensions for inequalities. diff --git a/Mathlib/Tactic/NormNum/LegendreSymbol.lean b/Mathlib/Tactic/NormNum/LegendreSymbol.lean index 8417a02e44a34..730f2de9e9aba 100644 --- a/Mathlib/Tactic/NormNum/LegendreSymbol.lean +++ b/Mathlib/Tactic/NormNum/LegendreSymbol.lean @@ -78,8 +78,7 @@ theorem jacobiSymNat.zero_left (b : ℕ) (hb : Nat.beq (b / 2) 0 = false) : jaco · calc 1 < 2 * 1 := by decide _ ≤ 2 * (b / 2) := - Nat.mul_le_mul_of_nonneg_left - (Nat.succ_le.mpr (Nat.pos_of_ne_zero (Nat.ne_of_beq_eq_false hb))) + Nat.mul_le_mul_left _ (Nat.succ_le.mpr (Nat.pos_of_ne_zero (Nat.ne_of_beq_eq_false hb))) _ ≤ b := Nat.mul_div_le b 2 #align norm_num.jacobi_sym_nat.zero_left_even Mathlib.Meta.NormNum.jacobiSymNat.zero_left #align norm_num.jacobi_sym_nat.zero_left_odd Mathlib.Meta.NormNum.jacobiSymNat.zero_left diff --git a/Mathlib/Tactic/NormNum/Pow.lean b/Mathlib/Tactic/NormNum/Pow.lean index 29f9033f43e2b..b413507cca0e8 100644 --- a/Mathlib/Tactic/NormNum/Pow.lean +++ b/Mathlib/Tactic/NormNum/Pow.lean @@ -3,8 +3,9 @@ Copyright (c) 2021 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Thomas Murrills -/ +import Mathlib.Algebra.GroupPower.Ring +import Mathlib.Data.Int.Cast.Lemmas import Mathlib.Tactic.NormNum.Basic -import Mathlib.Algebra.GroupPower.Lemmas /-! ## `norm_num` plugin for `^`. @@ -105,13 +106,14 @@ theorem intPow_ofNat (h1 : Nat.pow a b = c) : theorem intPow_negOfNat_bit0 (h1 : Nat.pow a b' = c') (hb : nat_lit 2 * b' = b) (hc : c' * c' = c) : Int.pow (Int.negOfNat a) b = Int.ofNat c := by - rw [← hb, Int.negOfNat_eq, pow_eq, pow_mul, neg_pow_two, ← pow_mul, two_mul, pow_add, ← hc, ← h1] + rw [← hb, Int.negOfNat_eq, Int.pow_eq, pow_mul, neg_pow_two, ← pow_mul, two_mul, pow_add, ← hc, + ← h1] simp theorem intPow_negOfNat_bit1 (h1 : Nat.pow a b' = c') (hb : nat_lit 2 * b' + nat_lit 1 = b) (hc : c' * (c' * a) = c) : Int.pow (Int.negOfNat a) b = Int.negOfNat c := by - rw [← hb, Int.negOfNat_eq, Int.negOfNat_eq, pow_eq, pow_succ, pow_mul, neg_pow_two, ← pow_mul, + rw [← hb, Int.negOfNat_eq, Int.negOfNat_eq, Int.pow_eq, pow_succ, pow_mul, neg_pow_two, ← pow_mul, two_mul, pow_add, ← hc, ← h1] simp [mul_assoc, mul_comm, mul_left_comm] @@ -191,3 +193,73 @@ def evalPow : NormNumExt where eval {u α} e := do let qc := mkRat zc dc.natLit! return .isRat' dα qc nc dc q(isRat_pow (f := $f) (.refl $f) $pa $pb $r1 $r2) core + +theorem isNat_zpow_pos {α : Type*} [DivisionSemiring α] {a : α} {b : ℤ} {nb ne : ℕ} + (pb : IsNat b nb) (pe' : IsNat (a ^ nb) ne) : + IsNat (a ^ b) ne := by + rwa [pb.out, zpow_coe_nat] + +theorem isNat_zpow_neg {α : Type*} [DivisionSemiring α] {a : α} {b : ℤ} {nb ne : ℕ} + (pb : IsInt b (Int.negOfNat nb)) (pe' : IsNat (a ^ nb)⁻¹ ne) : + IsNat (a ^ b) ne := by + rwa [pb.out, Int.cast_negOfNat, zpow_neg, zpow_coe_nat] + +theorem isInt_zpow_pos {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb ne : ℕ} + (pb : IsNat b nb) (pe' : IsInt (a ^ nb) (Int.negOfNat ne)) : + IsInt (a ^ b) (Int.negOfNat ne) := by + rwa [pb.out, zpow_coe_nat] + +theorem isInt_zpow_neg {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb ne : ℕ} + (pb : IsInt b (Int.negOfNat nb)) (pe' : IsInt (a ^ nb)⁻¹ (Int.negOfNat ne)) : + IsInt (a ^ b) (Int.negOfNat ne) := by + rwa [pb.out, Int.cast_negOfNat, zpow_neg, zpow_coe_nat] + +theorem isRat_zpow_pos {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb : ℕ} + {num : ℤ} {den : ℕ} + (pb : IsNat b nb) (pe' : IsRat (a^nb) num den) : + IsRat (a^b) num den := by + rwa [pb.out, zpow_coe_nat] + +theorem isRat_zpow_neg {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb : ℕ} + {num : ℤ} {den : ℕ} + (pb : IsInt b (Int.negOfNat nb)) (pe' : IsRat ((a^nb)⁻¹) num den) : + IsRat (a^b) num den := by + rwa [pb.out, Int.cast_negOfNat, zpow_neg, zpow_coe_nat] + +/-- The `norm_num` extension which identifies expressions of the form `a ^ b`, +such that `norm_num` successfully recognises both `a` and `b`, with `b : ℤ`. -/ +@[norm_num (_ : α) ^ (_ : ℤ)] +def evalZPow : NormNumExt where eval {u α} e := do + let .app (.app (f : Q($α → ℤ → $α)) (a : Q($α))) (b : Q(ℤ)) ← whnfR e | failure + let _c ← synthInstanceQ q(DivisionSemiring $α) + let rb ← derive (α := q(ℤ)) b + have h : $e =Q $a ^ $b := ⟨⟩ + h.check + match rb with + | .isBool .. | .isRat _ .. => failure + | .isNat sβ nb pb => + match ← derive q($a ^ $nb) with + | .isBool .. => failure + | .isNat sα' ne' pe' => + assumeInstancesCommute + return .isNat sα' ne' q(isNat_zpow_pos $pb $pe') + | .isNegNat sα' ne' pe' => + let _c ← synthInstanceQ q(DivisionRing $α) + assumeInstancesCommute + return .isNegNat sα' ne' q(isInt_zpow_pos $pb $pe') + | .isRat sα' qe' nume' dene' pe' => + assumeInstancesCommute + return .isRat sα' qe' nume' dene' q(isRat_zpow_pos $pb $pe') + | .isNegNat sβ nb pb => + match ← derive q(($a ^ $nb)⁻¹) with + | .isBool .. => failure + | .isNat sα' ne' pe' => + assumeInstancesCommute + return .isNat sα' ne' q(isNat_zpow_neg $pb $pe') + | .isNegNat sα' ne' pe' => + let _c ← synthInstanceQ q(DivisionRing $α) + assumeInstancesCommute + return .isNegNat sα' ne' q(isInt_zpow_neg $pb $pe') + | .isRat sα' qe' nume' dene' pe' => + assumeInstancesCommute + return .isRat sα' qe' nume' dene' q(isRat_zpow_neg $pb $pe') diff --git a/Mathlib/Tactic/NormNum/Prime.lean b/Mathlib/Tactic/NormNum/Prime.lean index 76556d646e710..9c411cb1193bf 100644 --- a/Mathlib/Tactic/NormNum/Prime.lean +++ b/Mathlib/Tactic/NormNum/Prime.lean @@ -3,7 +3,6 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Data.Nat.Factors import Mathlib.Data.Nat.Prime import Mathlib.Tactic.NormNum.Basic @@ -33,7 +32,7 @@ namespace Mathlib.Meta.NormNum theorem not_prime_mul_of_ble (a b n : ℕ) (h : a * b = n) (h₁ : a.ble 1 = false) (h₂ : b.ble 1 = false) : ¬ n.Prime := - not_prime_mul' h (ble_eq_false.mp h₁) (ble_eq_false.mp h₂) + not_prime_mul' h (ble_eq_false.mp h₁).ne' (ble_eq_false.mp h₂).ne' /-- Produce a proof that `n` is not prime from a factor `1 < d < n`. `en` should be the expression that is the natural number literal `n`. -/ diff --git a/Mathlib/Tactic/NthRewrite.lean b/Mathlib/Tactic/NthRewrite.lean index 840b98377dd0b..2a64b121d3dfd 100644 --- a/Mathlib/Tactic/NthRewrite.lean +++ b/Mathlib/Tactic/NthRewrite.lean @@ -5,7 +5,6 @@ Authors: Moritz Doll -/ import Lean.Elab.Tactic.Rewrite -import Lean.Elab.BuiltinTerm /-! # `nth_rewrite` tactic diff --git a/Mathlib/Tactic/Observe.lean b/Mathlib/Tactic/Observe.lean index 8b167536f51f4..abd45fc70c103 100644 --- a/Mathlib/Tactic/Observe.lean +++ b/Mathlib/Tactic/Observe.lean @@ -41,8 +41,7 @@ elab_rules : tactic | else let v := (← instantiateMVars (mkMVar goal)).headBeta if trace.isSome then - -- TODO: we should be allowed to pass an identifier to `addHaveSuggestion`. - addHaveSuggestion tk type v + addHaveSuggestion tk (some name) type v let (_, newGoal) ← (← getMainGoal).note name v replaceMainGoal [newGoal] diff --git a/Mathlib/Tactic/PPWithUniv.lean b/Mathlib/Tactic/PPWithUniv.lean index 1831940ec6917..b13db774ec90c 100644 --- a/Mathlib/Tactic/PPWithUniv.lean +++ b/Mathlib/Tactic/PPWithUniv.lean @@ -28,8 +28,7 @@ def delabWithUniv : Delab := let expr := subExpr.expr let expr := mkAppN (expr.getAppFn.setOption pp.universes.name true) expr.getAppArgs { subExpr with expr } - withTheReader SubExpr enablePPUnivOnHead <| - delabAppImplicit <|> delabAppExplicit + withTheReader SubExpr enablePPUnivOnHead delabApp /-- `attribute [pp_with_univ] Ordinal` instructs the pretty-printer to diff --git a/Mathlib/Tactic/Peel.lean b/Mathlib/Tactic/Peel.lean index 717fa7fcb05cc..6f5034b706e6f 100644 --- a/Mathlib/Tactic/Peel.lean +++ b/Mathlib/Tactic/Peel.lean @@ -32,17 +32,17 @@ Peels matching quantifiers off of a given term and the goal and introduces the r - `peel e with h` is `peel e` but names the peeled hypothesis `h`. If `h` is `_` then uses `this` for the name of the peeled hypothesis. - `peel n e` peels `n` quantifiers (at default transparency). -- `peel n e with h x y z ...` peels `n` quantifiers, names the peeled hypothesis `h`, +- `peel n e with x y z ... h` peels `n` quantifiers, names the peeled hypothesis `h`, and uses `x`, `y`, `z`, and so on to name the introduced variables; these names may be `_`. If `h` is `_` then uses `this` for the name of the peeled hypothesis. The length of the list of variables does not need to equal `n`. -- `peel e with h x₁ ... xₙ` is `peel n e with h x₁ ... xₙ`. +- `peel e with x₁ ... xₙ h` is `peel n e with x₁ ... xₙ h`. There are also variants that apply to an iff in the goal: - `peel n` peels `n` quantifiers in an iff. - `peel with x₁ ... xₙ` peels `n` quantifiers in an iff and names them. -Given `p q : ℕ → Prop`, `h : ∀ x, p x`, and a goal `⊢ : ∀ x, q x`, the tactic `peel h with h' x` +Given `p q : ℕ → Prop`, `h : ∀ x, p x`, and a goal `⊢ : ∀ x, q x`, the tactic `peel h with x h'` will introduce `x : ℕ`, `h' : p x` into the context and the new goal will be `⊢ q x`. This works with `∃`, as well as `∀ᶠ` and `∃ᶠ`, and it can even be applied to a sequence of quantifiers. Note that this is a logically weaker setup, so using this tactic is not always feasible. @@ -52,7 +52,7 @@ For a more complex example, given a hypothesis and a goal: h : ∀ ε > (0 : ℝ), ∃ N : ℕ, ∀ n ≥ N, 1 / (n + 1 : ℝ) < ε ⊢ ∀ ε > (0 : ℝ), ∃ N : ℕ, ∀ n ≥ N, 1 / (n + 1 : ℝ) ≤ ε ``` -(which differ only in `<`/`≤`), applying `peel h with h_peel ε hε N n hn` will yield a tactic state: +(which differ only in `<`/`≤`), applying `peel h with ε hε N n hn h_peel` will yield a tactic state: ``` h : ∀ ε > (0 : ℝ), ∃ N : ℕ, ∀ n ≥ N, 1 / (n + 1 : ℝ) < ε ε : ℝ @@ -223,7 +223,7 @@ def peelArgsIff (l : List Name) : TacticM Unit := withMainContext do peelArgsIff hs elab_rules : tactic - | `(tactic| peel $[$num?:num]? $e:term $[with $n? $l?*]?) => withMainContext do + | `(tactic| peel $[$num?:num]? $e:term $[with $l?* $n?]?) => withMainContext do /- we use `elabTermForApply` instead of `elabTerm` so that terms passed to `peel` can contain quantifiers with implicit bound variables without causing errors or requiring `@`. -/ let e ← elabTermForApply e false diff --git a/Mathlib/Tactic/Positivity/Basic.lean b/Mathlib/Tactic/Positivity/Basic.lean index 7ef1b4b58a3f0..8728e9deaf008 100644 --- a/Mathlib/Tactic/Positivity/Basic.lean +++ b/Mathlib/Tactic/Positivity/Basic.lean @@ -5,10 +5,7 @@ Authors: Mario Carneiro, Heather Macbeth, Yaël Dillies -/ import Std.Lean.Parser import Mathlib.Data.Int.Order.Basic -import Mathlib.Data.Int.CharZero import Mathlib.Data.Nat.Factorial.Basic -import Mathlib.Data.Rat.Order -import Mathlib.Data.Rat.Cast.CharZero import Mathlib.Data.Rat.Cast.Order import Mathlib.Tactic.Positivity.Core import Mathlib.Tactic.HaveI @@ -426,7 +423,7 @@ private theorem abs_pos_of_ne_zero {α : Type*} [AddGroup α] [LinearOrder α] /-- The `positivity` extension which identifies expressions of the form `|a|`. -/ @[positivity |(_ : α)|] def evalAbs : PositivityExt where eval {u} (α : Q(Type u)) zα pα (e : Q($α)) := do - let ~q(@Abs.abs _ (_) $a) := e | throwError "not |·|" + let ~q(@abs _ (_) (_) $a) := e | throwError "not |·|" try match ← core zα pα a with | .positive pa => @@ -540,5 +537,5 @@ def evalFactorial : PositivityExt where eval {_ _} _ _ (e : Q(ℕ)) := do /-- Extension for Nat.ascFactorial. -/ @[positivity Nat.ascFactorial _ _] def evalAscFactorial : PositivityExt where eval {_ _} _ _ (e : Q(ℕ)) := do - let ~q(Nat.ascFactorial $n $k) := e | throwError "failed to match Nat.ascFactorial" + let ~q(Nat.ascFactorial ($n + 1) $k) := e | throwError "failed to match Nat.ascFactorial" pure (.positive (q(Nat.ascFactorial_pos $n $k) : Expr)) diff --git a/Mathlib/Tactic/ProdAssoc.lean b/Mathlib/Tactic/ProdAssoc.lean index ced3c7610defb..3c1f7e87755fc 100644 --- a/Mathlib/Tactic/ProdAssoc.lean +++ b/Mathlib/Tactic/ProdAssoc.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Adam Topaz -/ import Mathlib.Lean.Expr.Basic -import Mathlib.Logic.Equiv.Basic +import Mathlib.Logic.Equiv.Defs /-! # Associativity of products diff --git a/Mathlib/Tactic/ProjectionNotation.lean b/Mathlib/Tactic/ProjectionNotation.lean index d28554f9aa773..095984731365c 100644 --- a/Mathlib/Tactic/ProjectionNotation.lean +++ b/Mathlib/Tactic/ProjectionNotation.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ import Lean -import Lean.Elab.AuxDef import Std.Lean.Command /-! @@ -39,7 +38,7 @@ structures into a single projection. The only functional difference from `Lean.PrettyPrinter.Delaborator.delabProjectionApp` is the `walkUp` function. -/ @[delab app] -partial def delabProjectionApp' : Delab := whenPPOption getPPCollapseStructureProjections $ do +partial def delabProjectionApp' : Delab := whenPPOption getPPCollapseStructureProjections <| do let e@(Expr.app fn _) ← getExpr | failure let .const c@(.str _ f) _ := fn.getAppFn | failure let env ← getEnv diff --git a/Mathlib/Tactic/Propose.lean b/Mathlib/Tactic/Propose.lean index 6be87a6f874ed..50eadc21e5f62 100644 --- a/Mathlib/Tactic/Propose.lean +++ b/Mathlib/Tactic/Propose.lean @@ -6,7 +6,6 @@ Authors: Scott Morrison import Mathlib.Lean.Expr.Basic import Mathlib.Lean.Meta import Mathlib.Lean.Meta.Basic -import Mathlib.Lean.Meta.DiscrTree import Std.Util.Cache import Mathlib.Tactic.Core import Std.Tactic.SolveByElim @@ -113,11 +112,11 @@ only the types of the lemmas in the `using` clause. Suggestions are printed as `have := f a b c`. -/ -syntax (name := propose') "have?" "!"? (" : " term)? " using " (colGt term),+ : tactic +syntax (name := propose') "have?" "!"? (ident)? (" : " term)? " using " (colGt term),+ : tactic open Elab.Tactic Elab Tactic in elab_rules : tactic - | `(tactic| have?%$tk $[!%$lucky]? $[ : $type:term]? using $[$terms:term],*) => do + | `(tactic| have?%$tk $[!%$lucky]? $[$h:ident]? $[ : $type:term]? using $[$terms:term],*) => do let stx ← getRef let goal ← getMainGoal goal.withContext do @@ -130,7 +129,7 @@ elab_rules : tactic throwError "propose could not find any lemmas using the given hypotheses" -- TODO we should have `proposals` return a lazy list, to avoid unnecessary computation here. for p in proposals.toList.take 10 do - addHaveSuggestion tk (← inferType p.2) p.2 stx + addHaveSuggestion tk (h.map (·.getId)) (← inferType p.2) p.2 stx if lucky.isSome then let mut g := goal for p in proposals.toList.take 10 do diff --git a/Mathlib/Tactic/ProxyType.lean b/Mathlib/Tactic/ProxyType.lean index 5aca18d189eee..8efed5ca6ab68 100644 --- a/Mathlib/Tactic/ProxyType.lean +++ b/Mathlib/Tactic/ProxyType.lean @@ -5,7 +5,7 @@ Authors: Kyle Miller -/ import Lean import Mathlib.Tactic.Core -import Mathlib.Logic.Equiv.Basic +import Mathlib.Logic.Equiv.Defs /-! # Generating "proxy types" diff --git a/Mathlib/Tactic/PushNeg.lean b/Mathlib/Tactic/PushNeg.lean index fb21cadfd33da..e302bc85e74c3 100644 --- a/Mathlib/Tactic/PushNeg.lean +++ b/Mathlib/Tactic/PushNeg.lean @@ -5,7 +5,6 @@ Authors: Patrick Massot, Simon Hudon, Alice Laroche, Frédéric Dupuis, Jireh Lo -/ import Lean -import Mathlib.Lean.Expr import Mathlib.Logic.Basic import Mathlib.Init.Order.Defs import Mathlib.Tactic.Conv diff --git a/Mathlib/Tactic/Qify.lean b/Mathlib/Tactic/Qify.lean index 844537299c096..b118a179bf5ca 100644 --- a/Mathlib/Tactic/Qify.lean +++ b/Mathlib/Tactic/Qify.lean @@ -5,7 +5,8 @@ Authors: Moritz Doll, Mario Carneiro, Robert Y. Lewis -/ import Mathlib.Tactic.Basic import Mathlib.Tactic.Zify -import Mathlib.Data.Rat.Cast.Order +import Mathlib.Data.Int.CharZero +import Mathlib.Data.Rat.Order /-! # `qify` tactic diff --git a/Mathlib/Tactic/RSuffices.lean b/Mathlib/Tactic/RSuffices.lean index 5a530bb8acf6c..feae1fcd134b1 100644 --- a/Mathlib/Tactic/RSuffices.lean +++ b/Mathlib/Tactic/RSuffices.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Moritz Doll -/ import Mathlib.Tactic.Basic + /-! # `rsuffices` tactic @@ -23,4 +24,3 @@ syntax (name := rsuffices) "rsuffices" macro_rules | `(tactic| rsuffices $[$pred]? $[: $foo]? $[:= $bar]?) => `(tactic | (obtain $[$pred]? $[: $foo]? $[:= $bar]?; rotate_left)) - diff --git a/Mathlib/Tactic/ReduceModChar/Ext.lean b/Mathlib/Tactic/ReduceModChar/Ext.lean index 87688f630040a..a62a8d645c9c3 100644 --- a/Mathlib/Tactic/ReduceModChar/Ext.lean +++ b/Mathlib/Tactic/ReduceModChar/Ext.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Anne Baanen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ -import Lean.Meta.Tactic.Simp +import Lean.Meta.Tactic.Simp.SimpTheorems /-! # `@[reduce_mod_char]` attribute diff --git a/Mathlib/Tactic/Relation/Rfl.lean b/Mathlib/Tactic/Relation/Rfl.lean index 97d8c07069e1b..c979157d45cc6 100644 --- a/Mathlib/Tactic/Relation/Rfl.lean +++ b/Mathlib/Tactic/Relation/Rfl.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Newell Jensen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Newell Jensen -/ -import Mathlib.Lean.Meta +import Lean.Meta.Tactic.Subst import Std.Tactic.Relation.Rfl /-! diff --git a/Mathlib/Tactic/Relation/Symm.lean b/Mathlib/Tactic/Relation/Symm.lean index 239d92ca4f703..747846300cb6d 100644 --- a/Mathlib/Tactic/Relation/Symm.lean +++ b/Mathlib/Tactic/Relation/Symm.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.Lean.Meta import Std.Tactic.Relation.Symm import Lean.Elab.Tactic.Location diff --git a/Mathlib/Tactic/RenameBVar.lean b/Mathlib/Tactic/RenameBVar.lean index 14770ecae204f..0e1f7e5464e9d 100644 --- a/Mathlib/Tactic/RenameBVar.lean +++ b/Mathlib/Tactic/RenameBVar.lean @@ -6,6 +6,7 @@ Authors: Arthur Paulino, Patrick Massot import Lean import Mathlib.Util.Tactic +import Mathlib.Lean.Expr.Basic namespace Mathlib.Tactic @@ -15,7 +16,7 @@ open Lean Meta Parser Elab Tactic def renameBVarHyp (mvarId : MVarId) (fvarId : FVarId) (old new : Name) : MetaM Unit := modifyLocalDecl mvarId fvarId fun ldecl ↦ - ldecl.setType $ ldecl.type.renameBVar old new + ldecl.setType <| ldecl.type.renameBVar old new /-- Renames a bound variable in the target. -/ def renameBVarTarget (mvarId : MVarId) (old new : Name) : MetaM Unit := diff --git a/Mathlib/Tactic/RewriteSearch.lean b/Mathlib/Tactic/RewriteSearch.lean index 10774fbe1fda8..b7a1afb6c54a3 100644 --- a/Mathlib/Tactic/RewriteSearch.lean +++ b/Mathlib/Tactic/RewriteSearch.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Lean FRO, LLC. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ +import Mathlib.Init.Core import Mathlib.Data.List.EditDistance.Estimator import Mathlib.Data.MLList.BestFirst import Mathlib.Data.Nat.Interval diff --git a/Mathlib/Tactic/Rewrites.lean b/Mathlib/Tactic/Rewrites.lean index 53e2b90786cfc..9f3730cacc194 100644 --- a/Mathlib/Tactic/Rewrites.lean +++ b/Mathlib/Tactic/Rewrites.lean @@ -3,16 +3,17 @@ Copyright (c) 2023 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Std.Util.Pickle import Std.Data.MLList.Heartbeats import Std.Tactic.Relation.Rfl +import Std.Tactic.SolveByElim +import Std.Util.Pickle +import Std.Util.Cache +import Mathlib.Init.Core +import Mathlib.Control.Basic import Mathlib.Data.MLList.Dedup +import Mathlib.Lean.Expr.Basic import Mathlib.Lean.Meta.DiscrTree -import Std.Util.Cache -import Mathlib.Lean.Meta import Mathlib.Tactic.TryThis -import Mathlib.Control.Basic -import Std.Tactic.SolveByElim /-! # The `rewrites` tactic. @@ -31,10 +32,10 @@ namespace Lean.Meta /-- Extract the lemma, with arguments, that was used to produce a `RewriteResult`. -/ -- This assumes that `r.eqProof` was constructed as: --- `mkAppN (mkConst ``Eq.ndrec [u1, u2]) #[α, a, motive, h₁, b, h₂]` --- and we want `h₂`. +-- `mkApp6 (.const ``congrArg _) α eType lhs rhs motive heq` +-- in `Lean.Meta.Tactic.Rewrite` and we want `heq`. def RewriteResult.by? (r : RewriteResult) : Option Expr := - if r.eqProof.isAppOfArity ``Eq.ndrec 6 then + if r.eqProof.isAppOfArity ``congrArg 6 then r.eqProof.getArg! 5 else none diff --git a/Mathlib/Tactic/Ring/Basic.lean b/Mathlib/Tactic/Ring/Basic.lean index fc46d76e953e7..c8667a64ccb49 100644 --- a/Mathlib/Tactic/Ring/Basic.lean +++ b/Mathlib/Tactic/Ring/Basic.lean @@ -390,7 +390,7 @@ partial def evalMulProd (va : ExProd sα a) (vb : ExProd sα b) : Result (ExProd let rc := (NormNum.evalMul.core q($a * $b) q(HMul.hMul) _ _ q(CommSemiring.toSemiring) ra rb).get! let ⟨zc, hc⟩ := rc.toRatNZ.get! - let ⟨c, pc⟩ := rc.toRawEq + let ⟨c, pc⟩ := rc.toRawEq ⟨c, .const zc hc, pc⟩ | .mul (x := a₁) (e := a₂) va₁ va₂ va₃, .const _ _ => let ⟨_, vc, pc⟩ := evalMulProd va₃ vb diff --git a/Mathlib/Tactic/Ring/RingNF.lean b/Mathlib/Tactic/Ring/RingNF.lean index fab03e31671c0..9f9c4ffdc2866 100644 --- a/Mathlib/Tactic/Ring/RingNF.lean +++ b/Mathlib/Tactic/Ring/RingNF.lean @@ -149,7 +149,7 @@ partial def M.run ``rat_rawCast_neg, ``rat_rawCast_pos].foldlM (·.addConst · (post := false)) thms let ctx' := { ctx with simpTheorems := #[thms] } pure fun r' : Simp.Result ↦ do - Simp.mkEqTrans r' (← Simp.main r'.expr ctx' (methods := Simp.DefaultMethods.methods)).1 + Simp.mkEqTrans r' (← Simp.main r'.expr ctx' (methods := ← Lean.Meta.Simp.mkDefaultMethods)).1 let nctx := { ctx, simp } let rec /-- The recursive context. -/ @@ -164,7 +164,8 @@ partial def M.run /-- Overrides the default error message in `ring1` to use a prettified version of the goal. -/ initialize ringCleanupRef.set fun e => do M.run (← IO.mkRef {}) { recursive := false } fun nctx _ _ => - return (← nctx.simp { expr := e } nctx.ctx |>.run {}).1.expr + return (← nctx.simp { expr := e } ({} : Lean.Meta.Simp.Methods).toMethodsRef nctx.ctx + |>.run {}).1.expr open Elab.Tactic Parser.Tactic /-- Use `ring_nf` to rewrite the main goal. -/ diff --git a/Mathlib/Tactic/Sat/FromLRAT.lean b/Mathlib/Tactic/Sat/FromLRAT.lean index 4805d8e0ebe9a..f20193ee4d36f 100644 --- a/Mathlib/Tactic/Sat/FromLRAT.lean +++ b/Mathlib/Tactic/Sat/FromLRAT.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.List.Basic +import Mathlib.Data.Nat.Basic +import Mathlib.Init.Data.List.Instances /-! # `lrat_proof` command @@ -90,9 +91,9 @@ structure Fmla.subsumes (f f' : Fmla) : Prop where theorem Fmla.subsumes_self (f : Fmla) : f.subsumes f := ⟨fun _ h ↦ h⟩ theorem Fmla.subsumes_left (f f₁ f₂ : Fmla) (H : f.subsumes (f₁.and f₂)) : f.subsumes f₁ := - ⟨fun _ h ↦ H.1 _ $ List.mem_append.2 $ Or.inl h⟩ + ⟨fun _ h ↦ H.1 _ <| List.mem_append.2 <| Or.inl h⟩ theorem Fmla.subsumes_right (f f₁ f₂ : Fmla) (H : f.subsumes (f₁.and f₂)) : f.subsumes f₂ := - ⟨fun _ h ↦ H.1 _ $ List.mem_append.2 $ Or.inr h⟩ + ⟨fun _ h ↦ H.1 _ <| List.mem_append.2 <| Or.inr h⟩ /-- A valuation is an assignment of values to all the propositional variables. -/ def Valuation := Nat → Prop @@ -121,7 +122,7 @@ def Fmla.proof (f : Fmla) (c : Clause) : Prop := /-- If `f` subsumes `c` (i.e. `c ∈ f`), then `f.proof c`. -/ theorem Fmla.proof_of_subsumes (H : Fmla.subsumes f (Fmla.one c)) : f.proof c := - fun _ h ↦ h.1 _ $ H.1 _ $ List.Mem.head .. + fun _ h ↦ h.1 _ <| H.1 _ <| List.Mem.head .. /-- The core unit-propagation step. @@ -181,8 +182,8 @@ theorem Fmla.reify_or (h₁ : Fmla.reify v f₁ a) (h₂ : Fmla.reify v f₂ b) Fmla.reify v (f₁.and f₂) (a ∨ b) := by refine ⟨fun H ↦ by_contra fun hn ↦ H ⟨fun c h ↦ by_contra fun hn' ↦ ?_⟩⟩ rcases List.mem_append.1 h with h | h - · exact hn $ Or.inl $ h₁.1 fun Hc ↦ hn' $ Hc.1 _ h - · exact hn $ Or.inr $ h₂.1 fun Hc ↦ hn' $ Hc.1 _ h + · exact hn <| Or.inl <| h₁.1 fun Hc ↦ hn' <| Hc.1 _ h + · exact hn <| Or.inr <| h₂.1 fun Hc ↦ hn' <| Hc.1 _ h /-- Asserts that `¬⟦c⟧_v` implies `p`. -/ structure Clause.reify (v : Valuation) (c : Clause) (p : Prop) : Prop where @@ -236,7 +237,7 @@ structure Clause where def buildClause (arr : Array Int) : Expr := let nil := mkConst ``Sat.Clause.nil let cons := mkConst ``Sat.Clause.cons - arr.foldr (fun i e ↦ mkApp2 cons (toExpr $ Sat.Literal.ofInt i) e) nil + arr.foldr (fun i e ↦ mkApp2 cons (toExpr <| Sat.Literal.ofInt i) e) nil /-- Constructs the formula expression from the input CNF, as a balanced tree of `Fmla.and` nodes. -/ partial def buildConj (arr : Array (Array Int)) (start stop : Nat) : Expr := @@ -360,8 +361,8 @@ partial def buildProofStep (db : HashMap Nat Clause) for i in cl.lits do pr := mkApp pr <| mkBVar (match lctx.find? i with | some k => depth - k | _ => 0) let some u := unit | return Except.ok <| f pr - let lit := toExpr $ Sat.Literal.ofInt u - let nlit := toExpr $ Sat.Literal.ofInt (-u) + let lit := toExpr <| Sat.Literal.ofInt u + let nlit := toExpr <| Sat.Literal.ofInt (-u) let d1 := depth-1 let app := mkApp3 (mkConst ``Sat.Valuation.by_cases) (v d1) nlit <| mkLambda `h default (mkApp2 (mkConst ``Sat.Valuation.neg) (v d1) lit) pr @@ -496,7 +497,7 @@ def parseNat : Parsec Nat := Json.Parser.natMaybeZero /-- Parse an integer -/ def parseInt : Parsec Int := do - if (← peek!) = '-' then skip; pure $ -(← parseNat) else parseNat + if (← peek!) = '-' then skip; pure <| -(← parseNat) else parseNat /-- Parse a list of integers terminated by 0 -/ partial def parseInts (arr : Array Int := #[]) : Parsec (Array Int) := do @@ -524,8 +525,8 @@ def parseDimacs : Parsec (Nat × Array (Array Int)) := do /-- Parse an LRAT file into a list of steps. -/ def parseLRAT : Parsec (Array LRATStep) := many do let step ← parseNat <* ws - if (← peek!) = 'd' then skip <* ws; pure $ LRATStep.del (← parseNats) - else ws; pure $ LRATStep.add step (← parseInts) (← parseInts) + if (← peek!) = 'd' then skip <* ws; pure <| LRATStep.del (← parseNats) + else ws; pure <| LRATStep.add step (← parseInts) (← parseInts) end Parser @@ -543,7 +544,7 @@ def fromLRATAux (cnf lrat : String) (name : Name) : MetaM (Nat × Expr × Expr if arr.isEmpty then throwError "empty CNF" let ctx' := buildConj arr 0 arr.size let ctxName ← mkAuxName (name ++ `ctx) 1 - addDecl $ Declaration.defnDecl { + addDecl <| Declaration.defnDecl { name := ctxName levelParams := [] type := mkConst ``Sat.Fmla @@ -556,7 +557,7 @@ def fromLRATAux (cnf lrat : String) (name : Name) : MetaM (Nat × Expr × Expr | throwError "parse LRAT failed" let proof ← buildProof arr ctx ctx' steps let declName ← mkAuxName (name ++ `proof) 1 - addDecl $ Declaration.thmDecl { + addDecl <| Declaration.thmDecl { name := declName levelParams := [] type := mkApp2 (mkConst ``Sat.Fmla.proof) ctx (buildClause #[]) @@ -573,7 +574,7 @@ and `name.proof_1` (for the LRAT proof), with `name` itself containing the reifi def fromLRAT (cnf lrat : String) (name : Name) : MetaM Unit := do let (nvars, ctx, ctx', proof) ← fromLRATAux cnf lrat name let (type, value) := buildReify ctx ctx' proof nvars - addDecl $ Declaration.thmDecl { name, levelParams := [], type, value } + addDecl <| Declaration.thmDecl { name, levelParams := [], type, value } open Elab Term diff --git a/Mathlib/Tactic/SimpIntro.lean b/Mathlib/Tactic/SimpIntro.lean index 176d246f39b7f..c71aa344bdaa3 100644 --- a/Mathlib/Tactic/SimpIntro.lean +++ b/Mathlib/Tactic/SimpIntro.lean @@ -19,9 +19,10 @@ Main loop of the `simp_intro` tactic. * `more`: if true, we will keep introducing binders as long as we can * `ids`: the list of binder identifiers -/ -partial def simpIntroCore (g : MVarId) (ctx : Simp.Context) (discharge? : Option Simp.Discharge) - (more : Bool) (ids : List (TSyntax ``binderIdent)) : TermElabM (Option MVarId) := do - let done := return (← simpTargetCore g ctx discharge?).1 +partial def simpIntroCore (g : MVarId) (ctx : Simp.Context) (simprocs : Simprocs := {}) + (discharge? : Option Simp.Discharge) (more : Bool) (ids : List (TSyntax ``binderIdent)) : + TermElabM (Option MVarId) := do + let done := return (← simpTargetCore g ctx simprocs discharge?).1 let (transp, var, ids') ← match ids with | [] => if more then pure (.reducible, mkHole (← getRef), []) else return ← done | v::ids => pure (.default, v.raw[0], ids) @@ -30,13 +31,13 @@ partial def simpIntroCore (g : MVarId) (ctx : Simp.Context) (discharge? : Option let withFVar := fun (fvar, g) ↦ g.withContext do Term.addLocalVarInfo var (mkFVar fvar) let simpTheorems ← ctx.simpTheorems.addTheorem (.fvar fvar) (.fvar fvar) - simpIntroCore g { ctx with simpTheorems } discharge? more ids' + simpIntroCore g { ctx with simpTheorems } simprocs discharge? more ids' match t with | .letE .. => withFVar (← g.intro n) | .forallE (body := body) .. => let (fvar, g) ← g.intro n if body.hasLooseBVars then withFVar (fvar, g) else - match (← simpLocalDecl g fvar ctx discharge?).1 with + match (← simpLocalDecl g fvar ctx simprocs discharge?).1 with | none => g.withContext <| Term.addLocalVarInfo var (mkFVar fvar) return none @@ -65,10 +66,11 @@ elab "simp_intro" cfg:(config)? disch:(discharger)? ids:(ppSpace colGt binderIdent)* more:" .."? only:(&" only")? args:(simpArgs)? : tactic => do let args := args.map fun args ↦ ⟨args.raw[1].getArgs⟩ let stx ← `(tactic| simp $(cfg)? $(disch)? $[only%$only]? $[[$args,*]]?) - let { ctx, dischargeWrapper } ← withMainContext <| mkSimpContext stx (eraseLocal := false) + let { ctx, simprocs, dischargeWrapper } ← + withMainContext <| mkSimpContext stx (eraseLocal := false) dischargeWrapper.with fun discharge? ↦ do let g ← getMainGoal g.checkNotAssigned `simp_intro g.withContext do - let g? ← simpIntroCore g ctx discharge? more.isSome ids.toList + let g? ← simpIntroCore g ctx simprocs discharge? more.isSome ids.toList replaceMainGoal <| if let some g := g? then [g] else [] diff --git a/Mathlib/Tactic/Simps/Basic.lean b/Mathlib/Tactic/Simps/Basic.lean index 1e8297e6b47d7..242d6124f818d 100644 --- a/Mathlib/Tactic/Simps/Basic.lean +++ b/Mathlib/Tactic/Simps/Basic.lean @@ -8,7 +8,6 @@ import Mathlib.Tactic.Simps.NotationClass import Std.Classes.Dvd import Std.Data.String.Basic import Std.Util.LibraryNote -import Std.Data.List.Count import Mathlib.Lean.Expr.Basic /-! @@ -83,13 +82,14 @@ def mkSimpContextResult (cfg : Meta.Simp.Config := {}) (simpOnly := false) (kind simpOnlyBuiltins.foldlM (·.addConst ·) ({} : SimpTheorems) else getSimpTheorems + let simprocs ← if simpOnly then pure {} else Simp.getSimprocs let congrTheorems ← getSimpCongrTheorems let ctx : Simp.Context := { config := cfg simpTheorems := #[simpTheorems], congrTheorems } if !hasStar then - return { ctx, dischargeWrapper } + return { ctx, simprocs, dischargeWrapper } else let mut simpTheorems := ctx.simpTheorems let hs ← getPropHyps @@ -97,7 +97,7 @@ def mkSimpContextResult (cfg : Meta.Simp.Config := {}) (simpOnly := false) (kind unless simpTheorems.isErased (.fvar h) do simpTheorems ← simpTheorems.addTheorem (.fvar h) (← h.getDecl).toExpr let ctx := { ctx with simpTheorems } - return { ctx, dischargeWrapper } + return { ctx, simprocs, dischargeWrapper } /-- Make `Simp.Context` giving data instead of Syntax. Doesn't support arguments. Intended to be very similar to `Lean.Elab.Tactic.mkSimpContext` @@ -302,10 +302,10 @@ This command specifies custom names and custom projections for the simp attribut Some common uses: * If you define a new homomorphism-like structure (like `MulHom`) you can just run - `initialize_simps_projections` after defining the `FunLike` instance (or instance that implies - a `FunLike` instance). + `initialize_simps_projections` after defining the `DFunLike` instance (or instance that implies + a `DFunLike` instance). ``` - instance {mM : Mul M} {mN : Mul N} : FunLike (MulHom M N) M N := ... + instance {mM : Mul M} {mN : Mul N} : DFunLike (MulHom M N) M N := ... initialize_simps_projections MulHom (toFun → apply) ``` This will generate `foo_apply` lemmas for each declaration `foo`. @@ -322,7 +322,7 @@ Some common uses: In the first case, you can get both lemmas using `@[simps, simps (config := .asFn) coe]` and in the second case you can get both lemmas using `@[simps (config := .asFn), simps apply]`. * If you declare a new homomorphism-like structure (like `RelEmbedding`), - then `initialize_simps_projections` will automatically find any `FunLike` coercions + then `initialize_simps_projections` will automatically find any `DFunLike` coercions that will be used as the default projection for the `toFun` field. ``` initialize_simps_projections relEmbedding (toFun → apply) @@ -680,7 +680,7 @@ def findAutomaticProjectionsAux (str : Name) (proj : ParsedProjectionData) (args /-- Auxiliary function for `getRawProjections`. Find custom projections, automatically found by simps. -These come from `FunLike` and `SetLike` instances. -/ +These come from `DFunLike` and `SetLike` instances. -/ def findAutomaticProjections (str : Name) (projs : Array ParsedProjectionData) : CoreM (Array ParsedProjectionData) := do let strDecl ← getConstInfo str diff --git a/Mathlib/Tactic/Simps/NotationClass.lean b/Mathlib/Tactic/Simps/NotationClass.lean index c86ffb059e124..fb87f282321d8 100644 --- a/Mathlib/Tactic/Simps/NotationClass.lean +++ b/Mathlib/Tactic/Simps/NotationClass.lean @@ -26,7 +26,7 @@ in the file where we declare `@[simps]`. For further documentation, see `Tactic. We also add it to non-heterogenous notation classes, like `Neg`, but it doesn't do much for any class that extends `Neg`. * `@[notation_class * Simps.findCoercionArgs]` is used to configure the - `SetLike` and `FunLike` coercions. + `SetLike` and `DFunLike` coercions. * The first name argument is the projection name we use as the key to search for this class (default: name of first projection of the class). * The second argument is the name of a declaration that has type @@ -78,7 +78,7 @@ def findZeroArgs : findArgType := λ _ _ args => def findOneArgs : findArgType := λ _ _ args => return #[some <| args[0]?.getD default, some <| mkRawNatLit 1] -/-- Find arguments of a coercion class (`FunLike` or `SetLike`) -/ +/-- Find arguments of a coercion class (`DFunLike` or `SetLike`) -/ def findCoercionArgs : findArgType := λ str className args => do let some classExpr := (← getEnv).find? className | throwError "no such class {className}" let arity := classExpr.type.forallArity @@ -92,7 +92,7 @@ structure AutomaticProjectionData where /-- `className` is the name of the class we are looking for. -/ className : Name /-- `isNotation` is a boolean that specifies whether this is notation - (false for the coercions `FunLike` and `SetLike`). If this is set to true, we add the current + (false for the coercions `DFunLike` and `SetLike`). If this is set to true, we add the current class as hypothesis during type-class synthesis. -/ isNotation := true /-- The method to find the arguments of the class. -/ diff --git a/Mathlib/Tactic/SlimCheck.lean b/Mathlib/Tactic/SlimCheck.lean index ecdda1de64057..ef50c7cff96b4 100644 --- a/Mathlib/Tactic/SlimCheck.lean +++ b/Mathlib/Tactic/SlimCheck.lean @@ -5,7 +5,6 @@ Authors: Simon Hudon, Scott Morrison -/ import Mathlib.Testing.SlimCheck.Testable -import Mathlib.Data.List.Sort import Qq /-! @@ -197,7 +196,7 @@ set_option trace.Meta.synthInstance true trace[slim_check.decoration] "[testable decoration]\n {tgt'}" -- Porting note: I have not ported support for `trace.slim_check.instance`. -- See the commented out code below from mathlib3 if you would like to implement this. - -- when_tracing `slim_check.instance $ do + -- when_tracing `slim_check.instance <| do -- { inst ← summarize_instance inst >>= pp, -- trace!"\n[testable instance]{format.indent inst 2}" }, let code ← unsafe evalExpr (IO PUnit) q(IO PUnit) e @@ -223,18 +222,18 @@ set_option trace.Meta.synthInstance true -- meta def summarize_instance : expr → tactic instance_tree -- | (lam n bi d b) := do -- v ← mk_local' n bi d, --- summarize_instance $ b.instantiate_var v +-- summarize_instance <| b.instantiate_var v -- | e@(app f x) := do -- `(testable %%p) ← infer_type e, -- xs ← e.get_app_args.mmap_filter (try_core ∘ summarize_instance), --- pure $ instance_tree.node e.get_app_fn.const_name p xs +-- pure <| instance_tree.node e.get_app_fn.const_name p xs -- | e := do -- failed -- /-- format an `instance_tree` -/ -- meta def instance_tree.to_format : instance_tree → tactic format -- | (instance_tree.node n p xs) := do --- xs ← format.join <$> (xs.mmap $ λ t, flip format.indent 2 <$> instance_tree.to_format t), +-- xs ← format.join <$> (xs.mmap <| λ t, flip format.indent 2 <$> instance_tree.to_format t), -- ys ← pformat!"testable ({p})", -- pformat!"+ {n} :{format.indent ys 2}\n{xs}" diff --git a/Mathlib/Tactic/SplitIfs.lean b/Mathlib/Tactic/SplitIfs.lean index a721fbcc8773a..da45993b4e96d 100644 --- a/Mathlib/Tactic/SplitIfs.lean +++ b/Mathlib/Tactic/SplitIfs.lean @@ -64,7 +64,7 @@ private def discharge? (e : Expr) : SimpM (Option Expr) := do private def reduceIfsAt (loc : Location) : TacticM Unit := do let ctx ← SplitIf.getSimpContext let ctx := { ctx with config := { ctx.config with failIfUnchanged := false } } - let _ ← simpLocation ctx discharge? loc + let _ ← simpLocation ctx {} discharge? loc pure () /-- Splits a single if-then-else expression and then reduces the resulting goals. diff --git a/Mathlib/Tactic/SudoSetOption.lean b/Mathlib/Tactic/SudoSetOption.lean index 44d548f4752ca..dbbc47f542621 100644 --- a/Mathlib/Tactic/SudoSetOption.lean +++ b/Mathlib/Tactic/SudoSetOption.lean @@ -3,8 +3,7 @@ Copyright (c) 2021 Gabriel Ebner. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Gabriel Ebner -/ - -import Lean +import Lean.Elab.ElabRules /-! # Defines the `sudo set_option` command. @@ -19,14 +18,14 @@ open Lean Elab private def setOption [Monad m] [MonadError m] (name val : Syntax) (opts : Options) : m Options := do let val ← match val with - | Syntax.ident _ _ `true _ => pure $ DataValue.ofBool true - | Syntax.ident _ _ `false _ => pure $ DataValue.ofBool false + | Syntax.ident _ _ `true _ => pure <| DataValue.ofBool true + | Syntax.ident _ _ `false _ => pure <| DataValue.ofBool false | _ => match val.isNatLit? with - | some num => pure $ DataValue.ofNat num + | some num => pure <| DataValue.ofNat num | none => match val.isStrLit? with - | some str => pure $ DataValue.ofString str + | some str => pure <| DataValue.ofString str | none => throwError "unsupported option value {val}" - pure $ opts.insert name.getId val + pure <| opts.insert name.getId val open Elab.Command in /-- diff --git a/Mathlib/Tactic/SuppressCompilation.lean b/Mathlib/Tactic/SuppressCompilation.lean index b98e2101ea461..945340816281a 100644 --- a/Mathlib/Tactic/SuppressCompilation.lean +++ b/Mathlib/Tactic/SuppressCompilation.lean @@ -3,7 +3,8 @@ Copyright (c) 2023 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Alex J. Best, Mac Malone -/ -import Lean +import Lean.Elab.Declaration +import Lean.Elab.Notation /-! # Supressing compilation to executable code in a file or in a section @@ -28,25 +29,25 @@ to disable the compiler in a given file or a given section. This is a hack to work around mathlib4#7103. -/ def elabSuppressCompilationDecl : CommandElab := fun | `($[$doc?:docComment]? $(attrs?)? $(vis?)? $[noncomputable]? $(unsafe?)? - $(recKind?)? def $id $sig:optDeclSig $val:declVal $(term?)? $(decr?)?) => do + $(recKind?)? def $id $sig:optDeclSig $val:declVal) => do elabDeclaration <| ← `($[$doc?:docComment]? $(attrs?)? $(vis?)? noncomputable $(unsafe?)? - $(recKind?)? def $id $sig:optDeclSig $val:declVal $(term?)? $(decr?)?) + $(recKind?)? def $id $sig:optDeclSig $val:declVal) | `($[$doc?:docComment]? $(attrs?)? $(vis?)? $[noncomputable]? $(unsafe?)? - $(recKind?)? def $id $sig:optDeclSig $val:declVal deriving $derivs,* $(term?)? $(decr?)?) => do + $(recKind?)? def $id $sig:optDeclSig $val:declVal deriving $derivs,*) => do elabDeclaration <| ← `($[$doc?:docComment]? $(attrs?)? $(vis?)? noncomputable $(unsafe?)? - $(recKind?)? def $id $sig:optDeclSig $val:declVal deriving $derivs,* $(term?)? $(decr?)?) + $(recKind?)? def $id $sig:optDeclSig $val:declVal deriving $derivs,*) | `($[$doc?:docComment]? $(attrs?)? $(vis?)? $[noncomputable]? $(unsafe?)? - $(recKind?)? $(attrKind?)? instance $(prio?)? $(id?)? $sig:declSig $val:declVal $(term?)?) => do + $(recKind?)? $(attrKind?)? instance $(prio?)? $(id?)? $sig:declSig $val:declVal) => do elabDeclaration <| ← `($[$doc?:docComment]? $(attrs?)? $(vis?)? noncomputable $(unsafe?)? - $(recKind?)? $(attrKind?)? instance $(prio?)? $(id?)? $sig:declSig $val:declVal $(term?)?) + $(recKind?)? $(attrKind?)? instance $(prio?)? $(id?)? $sig:declSig $val:declVal) | `($[$doc?:docComment]? $(attrs?)? $(vis?)? $[noncomputable]? $(unsafe?)? $(recKind?)? example $sig:optDeclSig $val:declVal) => do elabDeclaration <| ← `($[$doc?:docComment]? $(attrs?)? $(vis?)? noncomputable $(unsafe?)? $(recKind?)? example $sig:optDeclSig $val:declVal) | `($[$doc?:docComment]? $(attrs?)? $(vis?)? $[noncomputable]? $(unsafe?)? - $(recKind?)? abbrev $id $sig:optDeclSig $val:declVal $(term?)? $(decr?)?) => do + $(recKind?)? abbrev $id $sig:optDeclSig $val:declVal) => do elabDeclaration <| ← `($[$doc?:docComment]? $(attrs?)? $(vis?)? noncomputable $(unsafe?)? - $(recKind?)? abbrev $id $sig:optDeclSig $val:declVal $(term?)? $(decr?)?) + $(recKind?)? abbrev $id $sig:optDeclSig $val:declVal) | _ => throwUnsupportedSyntax /-- The command `unsuppress_compilation in def foo : ...` makes sure that the definition is diff --git a/Mathlib/Tactic/SwapVar.lean b/Mathlib/Tactic/SwapVar.lean index be13d2e4ace3e..7bc39caecd595 100644 --- a/Mathlib/Tactic/SwapVar.lean +++ b/Mathlib/Tactic/SwapVar.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Arthur Paulino. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino -/ - +import Lean.Elab.ElabRules import Mathlib.Util.Tactic /-! diff --git a/Mathlib/Tactic/TFAE.lean b/Mathlib/Tactic/TFAE.lean index a5cf5f4b84a54..4594db66cf4d4 100644 --- a/Mathlib/Tactic/TFAE.lean +++ b/Mathlib/Tactic/TFAE.lean @@ -3,6 +3,8 @@ Copyright (c) 2018 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Reid Barton, Simon Hudon, Thomas Murrills, Mario Carneiro -/ +import Qq +import Mathlib.Init.Data.Nat.Notation import Mathlib.Util.AtomM import Mathlib.Data.List.TFAE @@ -126,19 +128,21 @@ partial def proveChain (i : ℕ) (is : List ℕ) (P : Q(Prop)) (l : Q(List Prop) match l with | ~q([]) => return q(Chain.nil) | ~q($P' :: $l') => - let i' :: is' := is | unreachable! + -- `id` is a workaround for https://github.com/leanprover-community/quote4/issues/30 + let i' :: is' := id is | unreachable! have cl' : Q(Chain (· → ·) $P' $l') := ← proveChain i' is' q($P') q($l') let p ← proveImpl hyps atoms i i' P P' return q(Chain.cons $p $cl') -/-- Attempt to prove `ilast' P' l → P` given an explicit list `l`. -/ -partial def proveILast'Impl (i i' : ℕ) (is : List ℕ) (P P' : Q(Prop)) (l : Q(List Prop)) : - MetaM Q(ilast' $P' $l → $P) := do +/-- Attempt to prove `getLastD l P' → P` given an explicit list `l`. -/ +partial def proveGetLastDImpl (i i' : ℕ) (is : List ℕ) (P P' : Q(Prop)) (l : Q(List Prop)) : + MetaM Q(getLastD $l $P' → $P) := do match l with | ~q([]) => proveImpl hyps atoms i' i P' P | ~q($P'' :: $l') => - let i'' :: is' := is | unreachable! - proveILast'Impl i i'' is' P P'' l' + -- `id` is a workaround for https://github.com/leanprover-community/quote4/issues/30 + let i'' :: is' := id is | unreachable! + proveGetLastDImpl i i'' is' P P'' l' /-- Attempt to prove a statement of the form `TFAE [P₁, P₂, ...]`. -/ def proveTFAE (is : List ℕ) (l : Q(List Prop)) : MetaM Q(TFAE $l) := do @@ -146,9 +150,10 @@ def proveTFAE (is : List ℕ) (l : Q(List Prop)) : MetaM Q(TFAE $l) := do | ~q([]) => return q(tfae_nil) | ~q([$P]) => return q(tfae_singleton $P) | ~q($P :: $P' :: $l') => - let i :: i' :: is' := is | unreachable! + -- `id` is a workaround for https://github.com/leanprover-community/quote4/issues/30 + let i :: i' :: is' := id is | unreachable! let c ← proveChain hyps atoms i (i'::is') P q($P' :: $l') - let il ← proveILast'Impl hyps atoms i i' is' P P' l' + let il ← proveGetLastDImpl hyps atoms i i' is' P P' l' return q(tfae_of_cycle $c $il) /-! # `tfae_have` components -/ diff --git a/Mathlib/Tactic/Tauto.lean b/Mathlib/Tactic/Tauto.lean index e1bfd66bcd776..0794af1cec67c 100644 --- a/Mathlib/Tactic/Tauto.lean +++ b/Mathlib/Tactic/Tauto.lean @@ -3,8 +3,6 @@ Copyright (c) 2018 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon, David Renshaw -/ - -import Lean import Mathlib.Tactic.CasesM import Mathlib.Tactic.Classical import Mathlib.Tactic.Core diff --git a/Mathlib/Tactic/ToAdditive.lean b/Mathlib/Tactic/ToAdditive.lean index 83bb87dd8afea..e2b1b92339779 100644 --- a/Mathlib/Tactic/ToAdditive.lean +++ b/Mathlib/Tactic/ToAdditive.lean @@ -26,6 +26,213 @@ import Mathlib.Tactic.Simps.Basic The attribute `to_additive` can be used to automatically transport theorems and definitions (but not inductive types and structures) from a multiplicative theory to an additive theory. + +To use this attribute, just write: + +``` +@[to_additive] +theorem mul_comm' {α} [CommSemigroup α] (x y : α) : x * y = y * x := mul_comm x y +``` + +This code will generate a theorem named `add_comm'`. It is also +possible to manually specify the name of the new declaration: + +``` +@[to_additive add_foo] +theorem foo := sorry +``` + +An existing documentation string will _not_ be automatically used, so if the theorem or definition +has a doc string, a doc string for the additive version should be passed explicitly to +`to_additive`. + +``` +/-- Multiplication is commutative -/ +@[to_additive "Addition is commutative"] +theorem mul_comm' {α} [comm_semigroup α] (x y : α) : x * y = y * x := comm_semigroup.mul_comm +``` + +The transport tries to do the right thing in most cases using several +heuristics described below. However, in some cases it fails, and +requires manual intervention. + +Use the `(reorder := ...)` syntax to reorder the arguments in the generated additive declaration. +This is specified using cycle notation. For example `(reorder := 1 2, 5 6)` swaps the first two +arguments with each other and the fifth and the sixth argument and `(reorder := 3 4 5)` will move +the fifth argument before the third argument. This is mostly useful to translate declarations using +`Pow` to those using `SMul`. + +Use the `(attr := ...)` syntax to apply attributes to both the multiplicative and the additive +version: + +``` +@[to_additive (attr := simp)] lemma mul_one' {G : Type*} [group G] (x : G) : x * 1 = x := mul_one x +``` + +For `simp` and `simps` this also ensures that some generated lemmas are added to the additive +dictionary. +`@[to_additive (attr := to_additive)]` is a special case, where the `to_additive` +attribute is added to the generated lemma only, to additivize it again. +This is useful for lemmas about `Pow` to generate both lemmas about `SMul` and `VAdd`. Example: +``` +@[to_additive (attr := to_additive VAdd_lemma, simp) SMul_lemma] +lemma Pow_lemma ... := +``` +In the above example, the `simp` is added to all 3 lemmas. All other options to `to_additive` +(like the generated name or `(reorder := ...)`) are not passed down, +and can be given manually to each individual `to_additive` call. + +## Implementation notes + +The transport process generally works by taking all the names of +identifiers appearing in the name, type, and body of a declaration and +creating a new declaration by mapping those names to additive versions +using a simple string-based dictionary and also using all declarations +that have previously been labeled with `to_additive`. + +In the `mul_comm'` example above, `to_additive` maps: +* `mul_comm'` to `add_comm'`, +* `comm_semigroup` to `add_comm_semigroup`, +* `x * y` to `x + y` and `y * x` to `y + x`, and +* `comm_semigroup.mul_comm'` to `add_comm_semigroup.add_comm'`. + +### Heuristics + +`to_additive` uses heuristics to determine whether a particular identifier has to be +mapped to its additive version. The basic heuristic is + +* Only map an identifier to its additive version if its first argument doesn't + contain any unapplied identifiers. + +Examples: +* `@Mul.mul Nat n m` (i.e. `(n * m : Nat)`) will not change to `+`, since its + first argument is `Nat`, an identifier not applied to any arguments. +* `@Mul.mul (α × β) x y` will change to `+`. It's first argument contains only the identifier + `prod`, but this is applied to arguments, `α` and `β`. +* `@Mul.mul (α × Int) x y` will not change to `+`, since its first argument contains `Int`. + +The reasoning behind the heuristic is that the first argument is the type which is "additivized", +and this usually doesn't make sense if this is on a fixed type. + +There are some exceptions to this heuristic: + +* Identifiers that have the `@[to_additive]` attribute are ignored. + For example, multiplication in `↥Semigroup` is replaced by addition in `↥AddSemigroup`. +* If an identifier `d` has attribute `@[to_additive_relevant_arg n]` then the argument + in position `n` is checked for a fixed type, instead of checking the first argument. + `@[to_additive]` will automatically add the attribute `@[to_additive_relevant_arg n]` to a + declaration when the first argument has no multiplicative type-class, but argument `n` does. +* If an identifier has attribute `@[to_additive_ignore_args n1 n2 ...]` then all the arguments in + positions `n1`, `n2`, ... will not be checked for unapplied identifiers (start counting from 1). + For example, `ContMDiffMap` has attribute `@[to_additive_ignore_args 21]`, which means + that its 21st argument `(n : WithTop ℕ)` can contain `ℕ` + (usually in the form `Top.top ℕ ...`) and still be additivized. + So `@Mul.mul (C^∞⟮I, N; I', G⟯) _ f g` will be additivized. + +### Troubleshooting + +If `@[to_additive]` fails because the additive declaration raises a type mismatch, there are +various things you can try. +The first thing to do is to figure out what `@[to_additive]` did wrong by looking at the type +mismatch error. + +* Option 1: The most common case is that it didn't additivize a declaration that should be + additivized. This happened because the heuristic applied, and the first argument contains a + fixed type, like `ℕ` or `ℝ`. However, the heuristic misfires on some other declarations. + Solutions: + * First figure out what the fixed type is in the first argument of the declaration that didn't + get additivized. Note that this fixed type can occur in implicit arguments. If manually finding + it is hard, you can run `set_option trace.to_additive_detail true` and search the output for the + fragment "contains the fixed type" to find what the fixed type is. + * If the fixed type has an additive counterpart (like `↥Semigroup`), give it the `@[to_additive]` + attribute. + * If the fixed type has nothing to do with algebraic operations (like `TopCat`), add the attribute + `@[to_additive existing Foo]` to the fixed type `Foo`. + * If the fixed type occurs inside the `k`-th argument of a declaration `d`, and the + `k`-th argument is not connected to the multiplicative structure on `d`, consider adding + attribute `[to_additive_ignore_args k]` to `d`. + Example: `ContMDiffMap` ignores the argument `(n : WithTop ℕ)` +* Option 2: It additivized a declaration `d` that should remain multiplicative. Solution: + * Make sure the first argument of `d` is a type with a multiplicative structure. If not, can you + reorder the (implicit) arguments of `d` so that the first argument becomes a type with a + multiplicative structure (and not some indexing type)? + The reason is that `@[to_additive]` doesn't additivize declarations if their first argument + contains fixed types like `ℕ` or `ℝ`. See section Heuristics. + If the first argument is not the argument with a multiplicative type-class, `@[to_additive]` + should have automatically added the attribute `@[to_additive_relevant_arg]` to the declaration. + You can test this by running the following (where `d` is the full name of the declaration): + ``` + open Lean in run_cmd logInfo m!"{ToAdditive.relevantArgAttr.find? (← getEnv) `d}" + ``` + The expected output is `n` where the `n`-th (0-indexed) argument of `d` is a type (family) + with a multiplicative structure on it. `none` means `0`. + If you get a different output (or a failure), you could add the attribute + `@[to_additive_relevant_arg n]` manually, where `n` is an (1-indexed) argument with a + multiplicative structure. +* Option 3: Arguments / universe levels are incorrectly ordered in the additive version. + This likely only happens when the multiplicative declaration involves `pow`/`^`. Solutions: + * Ensure that the order of arguments of all relevant declarations are the same for the + multiplicative and additive version. This might mean that arguments have an "unnatural" order + (e.g. `Monoid.npow n x` corresponds to `x ^ n`, but it is convenient that `Monoid.npow` has this + argument order, since it matches `AddMonoid.nsmul n x`. + * If this is not possible, add `(reorder := ...)` argument to `to_additive`. + +If neither of these solutions work, and `to_additive` is unable to automatically generate the +additive version of a declaration, manually write and prove the additive version. +Often the proof of a lemma/theorem can just be the multiplicative version of the lemma applied to +`multiplicative G`. +Afterwards, apply the attribute manually: + +``` +attribute [to_additive foo_add_bar] foo_bar +``` + +This will allow future uses of `to_additive` to recognize that +`foo_bar` should be replaced with `foo_add_bar`. + +### Handling of hidden definitions + +Before transporting the “main” declaration `src`, `to_additive` first +scans its type and value for names starting with `src`, and transports +them. This includes auxiliary definitions like `src._match_1`, +`src._proof_1`. + +In addition to transporting the “main” declaration, `to_additive` transports +its equational lemmas and tags them as equational lemmas for the new declaration. + +### Structure fields and constructors + +If `src` is a structure, then the additive version has to be already written manually. +In this case `to_additive` adds all structure fields to its mapping. + +### Name generation + +* If `@[to_additive]` is called without a `name` argument, then the + new name is autogenerated. First, it takes the longest prefix of + the source name that is already known to `to_additive`, and replaces + this prefix with its additive counterpart. Second, it takes the last + part of the name (i.e., after the last dot), and replaces common + name parts (“mul”, “one”, “inv”, “prod”) with their additive versions. + +* [todo] Namespaces can be transformed using `map_namespace`. For example: + ``` + run_cmd to_additive.map_namespace `quotient_group `quotient_add_group + ``` + + Later uses of `to_additive` on declarations in the `quotient_group` + namespace will be created in the `quotient_add_group` namespaces. + +* If `@[to_additive]` is called with a `name` argument `new_name` + /without a dot/, then `to_additive` updates the prefix as described + above, then replaces the last part of the name with `new_name`. + +* If `@[to_additive]` is called with a `name` argument + `new_namespace.new_name` /with a dot/, then `to_additive` uses this + new name as is. + +As a safety check, in the first case `to_additive` double checks +that the new name differs from the original one. + -/ set_option autoImplicit true @@ -154,7 +361,7 @@ An attribute that stores all the declarations that needs their arguments reorder applying `@[to_additive]`. It is applied automatically by the `(reorder := ...)` syntax of `to_additive`, and should not usually be added manually. -/ -initialize reorderAttr : NameMapExtension (List $ List Nat) ← +initialize reorderAttr : NameMapExtension (List <| List Nat) ← registerNameMapAttribute { name := `to_additive_reorder descr := "\ @@ -591,7 +798,7 @@ partial def transformDeclAux | _ => panic! "unreachable" if isNoncomputable env src then addDecl trgDecl.toDeclaration! - setEnv $ addNoncomputable (← getEnv) tgt + setEnv <| addNoncomputable (← getEnv) tgt else addAndCompile trgDecl.toDeclaration! -- now add declaration ranges so jump-to-definition works @@ -601,7 +808,7 @@ partial def transformDeclAux range := ← getDeclarationRange (← getRef) selectionRange := ← getDeclarationRange cfg.ref } if isProtected (← getEnv) src then - setEnv $ addProtected (← getEnv) tgt + setEnv <| addProtected (← getEnv) tgt /-- Copy the instance attribute in a `to_additive` @@ -723,6 +930,7 @@ def nameDict : String → List String | "pow" => ["nsmul"] | "npow" => ["nsmul"] | "zpow" => ["zsmul"] + | "mabs" => ["abs"] | "monoid" => ["add", "Monoid"] | "submonoid" => ["add", "Submonoid"] | "group" => ["add", "Group"] @@ -815,6 +1023,8 @@ def fixAbbreviation : List String → List String => "function" :: "_" :: "semiconj" :: fixAbbreviation s | "function" :: "_" :: "add" :: "Commute" :: s => "function" :: "_" :: "commute" :: fixAbbreviation s + | "zero" :: "Le" :: "Part" :: s => "posPart" :: fixAbbreviation s + | "le" :: "Zero" :: "Part" :: s => "negPart" :: fixAbbreviation s | x :: s => x :: fixAbbreviation s | [] => [] diff --git a/Mathlib/Tactic/ToLevel.lean b/Mathlib/Tactic/ToLevel.lean index 5ab8b90e41870..13e69a2f8d30e 100644 --- a/Mathlib/Tactic/ToLevel.lean +++ b/Mathlib/Tactic/ToLevel.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Lean import Mathlib.Mathport.Rename import Mathlib.Tactic.PPWithUniv diff --git a/Mathlib/Tactic/TryThis.lean b/Mathlib/Tactic/TryThis.lean index b97d93020af1e..dc205622463a6 100644 --- a/Mathlib/Tactic/TryThis.lean +++ b/Mathlib/Tactic/TryThis.lean @@ -15,21 +15,25 @@ This file could be upstreamed to `Std`. open Lean Elab Elab.Tactic PrettyPrinter Meta Std.Tactic.TryThis /-- Add a suggestion for `have : t := e`. -/ -def addHaveSuggestion (ref : Syntax) (t? : Option Expr) (e : Expr) +def addHaveSuggestion (ref : Syntax) (h? : Option Name) (t? : Option Expr) (e : Expr) (origSpan? : Option Syntax := none) : TermElabM Unit := do let estx ← delabToRefinableSyntax e let prop ← isProp (← inferType e) let tac ← if let some t := t? then let tstx ← delabToRefinableSyntax t if prop then - `(tactic| have : $tstx := $estx) + match h? with + | some h => `(tactic| have $(mkIdent h) : $tstx := $estx) + | none => `(tactic| have : $tstx := $estx) else - `(tactic| let this : $tstx := $estx) + `(tactic| let $(mkIdent (h?.getD `_)) : $tstx := $estx) else if prop then - `(tactic| have := $estx) + match h? with + | some h => `(tactic| have $(mkIdent h) := $estx) + | none => `(tactic| have := $estx) else - `(tactic| let this := $estx) + `(tactic| let $(mkIdent (h?.getD `_)) := $estx) addSuggestion ref tac origSpan? open Lean.Parser.Tactic diff --git a/Mathlib/Tactic/TypeStar.lean b/Mathlib/Tactic/TypeStar.lean new file mode 100644 index 0000000000000..50dc1a4f01c46 --- /dev/null +++ b/Mathlib/Tactic/TypeStar.lean @@ -0,0 +1,29 @@ +/- +Copyright (c) 2023 Matthew Ballard. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Matthew Ballard +-/ +import Lean +import Std +import Mathlib.Tactic.PPWithUniv +import Mathlib.Tactic.ExtendDoc + +/-! +# Support for `Sort*` and `Type*`. + +These elaborate as `Sort u` and `Type u` with a fresh implicit universe variable `u`. +-/ + +open Lean + +/-- The syntax `variable (X Y ... Z : Sort*)` creates a new distinct implicit universe variable +for each variable in the sequence. -/ +elab "Sort*" : term => do + let u ← Lean.Meta.mkFreshLevelMVar + Elab.Term.levelMVarToParam (.sort u) + +/-- The syntax `variable (X Y ... Z : Type*)` creates a new distinct implicit universe variable +`> 0` for each variable in the sequence. -/ +elab "Type*" : term => do + let u ← Lean.Meta.mkFreshLevelMVar + Elab.Term.levelMVarToParam (.sort (.succ u)) diff --git a/Mathlib/Tactic/Use.lean b/Mathlib/Tactic/Use.lean index 950f60793c1ae..a7cb5e12c2ca3 100644 --- a/Mathlib/Tactic/Use.lean +++ b/Mathlib/Tactic/Use.lean @@ -3,8 +3,6 @@ Copyright (c) 2022 Arthur Paulino. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino, Gabriel Ebner, Kyle Miller -/ - -import Lean import Std.Logic /-! diff --git a/Mathlib/Tactic/Variable.lean b/Mathlib/Tactic/Variable.lean index 492733e07cb7f..10fec753055c3 100644 --- a/Mathlib/Tactic/Variable.lean +++ b/Mathlib/Tactic/Variable.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Lean import Std.Tactic.TryThis /-! diff --git a/Mathlib/Tactic/WLOG.lean b/Mathlib/Tactic/WLOG.lean index 395b0d729f8ad..5f2974426cc5e 100644 --- a/Mathlib/Tactic/WLOG.lean +++ b/Mathlib/Tactic/WLOG.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Johan Commelin, Reid Barton, Thomas Murrills -/ -import Lean import Mathlib.Tactic.Core /-! diff --git a/Mathlib/Tactic/Widget/Calc.lean b/Mathlib/Tactic/Widget/Calc.lean index abc5859ec2dbf..8a49dff8b6310 100644 --- a/Mathlib/Tactic/Widget/Calc.lean +++ b/Mathlib/Tactic/Widget/Calc.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot -/ - +import Lean.Elab.Tactic.Calc import Std.CodeAction import Mathlib.Data.String.Defs diff --git a/Mathlib/Tactic/Widget/CommDiag.lean b/Mathlib/Tactic/Widget/CommDiag.lean index 4f33aa5db6408..83973e04de8c2 100644 --- a/Mathlib/Tactic/Widget/CommDiag.lean +++ b/Mathlib/Tactic/Widget/CommDiag.lean @@ -3,12 +3,9 @@ Copyright (c) 2022 Wojciech Nawrocki. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Wojciech Nawrocki -/ - -import Mathlib.CategoryTheory.Category.Basic - import ProofWidgets.Component.PenroseDiagram import ProofWidgets.Presentation.Expr -import ProofWidgets.Component.Panel.SelectionPanel +import Mathlib.CategoryTheory.Category.Basic /-! This module defines tactic/meta infrastructure for displaying commutative diagrams in the infoview. -/ diff --git a/Mathlib/Tactic/Widget/Congrm.lean b/Mathlib/Tactic/Widget/Congrm.lean index 9095c828b36ae..a1da2f20d52a5 100644 --- a/Mathlib/Tactic/Widget/Congrm.lean +++ b/Mathlib/Tactic/Widget/Congrm.lean @@ -52,4 +52,4 @@ subexpressions in the goal.-/ elab stx:"congrm?" : tactic => do let some replaceRange := (← getFileMap).rangeOfStx? stx | return Widget.savePanelWidgetInfo CongrmSelectionPanel.javascriptHash - (pure $ json% { replaceRange: $(replaceRange) }) stx + (pure <| json% { replaceRange: $(replaceRange) }) stx diff --git a/Mathlib/Tactic/Widget/Conv.lean b/Mathlib/Tactic/Widget/Conv.lean index aabc847b6ac06..a23c91199ace2 100644 --- a/Mathlib/Tactic/Widget/Conv.lean +++ b/Mathlib/Tactic/Widget/Conv.lean @@ -134,4 +134,4 @@ in the goal.-/ elab stx:"conv?" : tactic => do let some replaceRange := (← getFileMap).rangeOfStx? stx | return Widget.savePanelWidgetInfo ConvSelectionPanel.javascriptHash - (pure $ json% { replaceRange: $(replaceRange) }) stx + (pure <| json% { replaceRange: $(replaceRange) }) stx diff --git a/Mathlib/Tactic/Widget/Gcongr.lean b/Mathlib/Tactic/Widget/Gcongr.lean index f4fb3cc4788f6..abb5e3e3bbb23 100644 --- a/Mathlib/Tactic/Widget/Gcongr.lean +++ b/Mathlib/Tactic/Widget/Gcongr.lean @@ -50,4 +50,4 @@ subexpressions in the goal.-/ elab stx:"gcongr?" : tactic => do let some replaceRange := (← getFileMap).rangeOfStx? stx | return Widget.savePanelWidgetInfo GCongrSelectionPanel.javascriptHash - (pure $ json% { replaceRange: $(replaceRange) }) stx + (pure <| json% { replaceRange: $(replaceRange) }) stx diff --git a/Mathlib/Tactic/Widget/SelectPanelUtils.lean b/Mathlib/Tactic/Widget/SelectPanelUtils.lean index 2f7ab8b8e12a2..d833afa7b2f50 100644 --- a/Mathlib/Tactic/Widget/SelectPanelUtils.lean +++ b/Mathlib/Tactic/Widget/SelectPanelUtils.lean @@ -4,12 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot -/ import Lean.Meta.ExprLens - -import Std.Data.Nat.Init.Lemmas - import ProofWidgets.Component.MakeEditLink import ProofWidgets.Component.OfRpcMethod -- needed in all files using this one. - import Mathlib.Tactic.Widget.SelectInsertParamsClass /-! # Selection panel utilities diff --git a/Mathlib/Testing/SlimCheck/Gen.lean b/Mathlib/Testing/SlimCheck/Gen.lean index 1992a955a8455..58a9a9dbec5cd 100644 --- a/Mathlib/Testing/SlimCheck/Gen.lean +++ b/Mathlib/Testing/SlimCheck/Gen.lean @@ -4,10 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Henrik Böving, Simon Hudon -/ import Mathlib.Control.Random -import Mathlib.Control.ULiftable -import Mathlib.Data.List.Perm -import Mathlib.Data.Subtype -import Mathlib.Data.Nat.Basic #align_import testing.slim_check.gen from "leanprover-community/mathlib"@"fdc286cc6967a012f41b87f76dcd2797b53152af" @@ -97,7 +93,7 @@ def oneOf (xs : Array (Gen α)) (pos : 0 < xs.size := by decide) : Gen α := do /-- Given a list of examples, choose one to create an example. -/ def elements (xs : List α) (pos : 0 < xs.length) : Gen α := do let ⟨x, _, h2⟩ ← ULiftable.up <| chooseNatLt 0 xs.length pos - pure $ xs.get ⟨x, h2⟩ + pure <| xs.get ⟨x, h2⟩ open List in /-- Generate a random permutation of a given list. -/ diff --git a/Mathlib/Testing/SlimCheck/Sampleable.lean b/Mathlib/Testing/SlimCheck/Sampleable.lean index 97b2fb3892a85..db22c2fa135a1 100644 --- a/Mathlib/Testing/SlimCheck/Sampleable.lean +++ b/Mathlib/Testing/SlimCheck/Sampleable.lean @@ -3,8 +3,9 @@ Copyright (c) 2022 Henrik Böving. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Henrik Böving, Simon Hudon -/ +import Mathlib.Data.Int.Order.Basic +import Mathlib.Init.Data.List.Instances import Mathlib.Testing.SlimCheck.Gen -import Qq #align_import testing.slim_check.sampleable from "leanprover-community/mathlib"@"fdc286cc6967a012f41b87f76dcd2797b53152af" @@ -200,7 +201,7 @@ instance Nat.sampleableExt : SampleableExt Nat := instance Fin.sampleableExt {n : Nat} : SampleableExt (Fin (n.succ)) := mkSelfContained (do choose (Fin n.succ) (Fin.ofNat 0) (Fin.ofNat (← getSize)) (by - simp only [LE.le, Fin.ofNat, Nat.zero_mod, Fin.zero_eta, Fin.val_zero, Nat.le_eq] + simp only [Fin.ofNat, Fin.val_zero] exact Nat.zero_le _)) instance Int.sampleableExt : SampleableExt Int := @@ -216,7 +217,7 @@ instance Rat.sampleableExt : SampleableExt Rat := return Rat.divInt d n) instance Bool.sampleableExt : SampleableExt Bool := - mkSelfContained $ chooseAny Bool + mkSelfContained <| chooseAny Bool /-- This can be specialized into customized `SampleableExt Char` instances. The resulting instance has `1 / length` chances of making an unrestricted choice of characters @@ -227,7 +228,7 @@ def Char.sampleable (length : Nat) (chars : List Char) (pos : 0 < chars.length) let x ← choose Nat 0 length (Nat.zero_le _) if x.val == 0 then let n ← interpSample Nat - pure $ Char.ofNat n + pure <| Char.ofNat n else elements chars pos @@ -271,7 +272,7 @@ instance shrinkable : Shrinkable (NoShrink α) where shrink := λ _ => [] instance sampleableExt [SampleableExt α] [Repr α] : SampleableExt (NoShrink α) := - SampleableExt.mkSelfContained $ (NoShrink.mk ∘ SampleableExt.interp) <$> SampleableExt.sample + SampleableExt.mkSelfContained <| (NoShrink.mk ∘ SampleableExt.interp) <$> SampleableExt.sample end NoShrink diff --git a/Mathlib/Testing/SlimCheck/Testable.lean b/Mathlib/Testing/SlimCheck/Testable.lean index a4b45386c1182..1275079fb21db 100644 --- a/Mathlib/Testing/SlimCheck/Testable.lean +++ b/Mathlib/Testing/SlimCheck/Testable.lean @@ -41,7 +41,7 @@ structure MyType where ``` How do we test a property about `MyType`? For instance, let us consider -`Testable.check $ ∀ a b : MyType, a.y ≤ b.x → a.x ≤ b.y`. Writing this +`Testable.check <| ∀ a b : MyType, a.y ≤ b.x → a.x ≤ b.y`. Writing this property as is will give us an error because we do not have an instance of `Shrinkable MyType` and `SampleableExt MyType`. We can define one as follows: @@ -55,7 +55,7 @@ instance : SampleableExt MyType := SampleableExt.mkSelfContained do let x ← SampleableExt.interpSample Nat let xyDiff ← SampleableExt.interpSample Nat - pure $ ⟨x, x + xyDiff, sorry⟩ + pure <| ⟨x, x + xyDiff, sorry⟩ ``` Again, we take advantage of the fact that other types have useful @@ -166,15 +166,15 @@ instance : ToString (TestResult p) := ⟨toString⟩ /-- Applicative combinator proof carrying test results. -/ def combine {p q : Prop} : PSum Unit (p → q) → PSum Unit p → PSum Unit q - | PSum.inr f, PSum.inr proof => PSum.inr $ f proof + | PSum.inr f, PSum.inr proof => PSum.inr <| f proof | _, _ => PSum.inl () /-- Combine the test result for properties `p` and `q` to create a test for their conjunction. -/ def and : TestResult p → TestResult q → TestResult (p ∧ q) | failure h xs n, _ => failure (λ h2 => h h2.left) xs n | _, failure h xs n => failure (λ h2 => h h2.right) xs n - | success h1, success h2 => success $ combine (combine (PSum.inr And.intro) h1) h2 - | gaveUp n, gaveUp m => gaveUp $ n + m + | success h1, success h2 => success <| combine (combine (PSum.inr And.intro) h1) h2 + | gaveUp n, gaveUp m => gaveUp <| n + m | gaveUp n, _ => gaveUp n | _, gaveUp n => gaveUp n @@ -186,9 +186,9 @@ def or : TestResult p → TestResult q → TestResult (p ∨ q) | Or.inl h3 => h1 h3 | Or.inr h3 => h2 h3 failure h3 (xs ++ ys) (n + m) - | success h, _ => success $ combine (PSum.inr Or.inl) h - | _, success h => success $ combine (PSum.inr Or.inr) h - | gaveUp n, gaveUp m => gaveUp $ n + m + | success h, _ => success <| combine (PSum.inr Or.inl) h + | _, success h => success <| combine (PSum.inr Or.inr) h + | gaveUp n, gaveUp m => gaveUp <| n + m | gaveUp n, _ => gaveUp n | _, gaveUp n => gaveUp n @@ -198,7 +198,7 @@ def imp (h : q → p) (r : TestResult p) (p : PSum Unit (p → q) := PSum.inl ()) : TestResult q := match r with | failure h2 xs n => failure (mt h h2) xs n - | success h2 => success $ combine p h2 + | success h2 => success <| combine p h2 | gaveUp n => gaveUp n /-- Test `q` by testing `p` and proving the equivalence between the two. -/ @@ -250,7 +250,7 @@ instance andTestable [Testable p] [Testable q] : Testable (p ∧ q) where run := λ cfg min => do let xp ← runProp p cfg min let xq ← runProp q cfg min - pure $ and xp xq + pure <| and xp xq instance orTestable [Testable p] [Testable q] : Testable (p ∨ q) where run := λ cfg min => do @@ -258,38 +258,38 @@ instance orTestable [Testable p] [Testable q] : Testable (p ∨ q) where -- As a little performance optimization we can just not run the second -- test if the first succeeds match xp with - | success (PSum.inl h) => pure $ success (PSum.inl h) - | success (PSum.inr h) => pure $ success (PSum.inr $ Or.inl h) + | success (PSum.inl h) => pure <| success (PSum.inl h) + | success (PSum.inr h) => pure <| success (PSum.inr <| Or.inl h) | _ => let xq ← runProp q cfg min - pure $ or xp xq + pure <| or xp xq instance iffTestable [Testable ((p ∧ q) ∨ (¬ p ∧ ¬ q))] : Testable (p ↔ q) where run := λ cfg min => do let h ← runProp ((p ∧ q) ∨ (¬ p ∧ ¬ q)) cfg min - pure $ iff iff_iff_and_or_not_and_not h + pure <| iff iff_iff_and_or_not_and_not h variable {var : String} instance decGuardTestable [PrintableProp p] [Decidable p] {β : p → Prop} [∀ h, Testable (β h)] : - Testable (NamedBinder var $ ∀ h, β h) where + Testable (NamedBinder var <| ∀ h, β h) where run := λ cfg min => do if h : p then let res := (runProp (β h) cfg min) let s := printProp p - (λ r => addInfo s!"guard: {s}" (· $ h) r (PSum.inr $ λ q _ => q)) <$> res + (λ r => addInfo s!"guard: {s}" (· <| h) r (PSum.inr <| λ q _ => q)) <$> res else if cfg.traceDiscarded || cfg.traceSuccesses then - let res := (λ _ => pure $ gaveUp 1) + let res := (λ _ => pure <| gaveUp 1) let s := printProp p slimTrace s!"discard: Guard {s} does not hold"; res else - pure $ gaveUp 1 + pure <| gaveUp 1 instance forallTypesTestable {f : Type → Prop} [Testable (f Int)] : - Testable (NamedBinder var $ ∀ x, f x) where + Testable (NamedBinder var <| ∀ x, f x) where run := λ cfg min => do let r ← runProp (f Int) cfg min - pure $ addVarInfo var "ℤ" (· $ Int) r + pure <| addVarInfo var "ℤ" (· <| Int) r /-- Format the counter-examples found in a test failure. @@ -328,11 +328,11 @@ partial def minimizeAux [SampleableExt α] {β : α → Prop} [∀ x, Testable ( for candidate in candidates do if cfg.traceShrinkCandidates then slimTrace s!"Trying {var} := {repr candidate}" - let res ← OptionT.lift $ Testable.runProp (β (SampleableExt.interp candidate)) cfg true + let res ← OptionT.lift <| Testable.runProp (β (SampleableExt.interp candidate)) cfg true if res.isFailure then if cfg.traceShrink then slimTrace s!"{var} shrunk to {repr candidate} from {repr x}" - let currentStep := OptionT.lift $ pure $ Sigma.mk candidate (addShrinks (n + 1) res) + let currentStep := OptionT.lift <| pure <| Sigma.mk candidate (addShrinks (n + 1) res) let nextStep := minimizeAux cfg var candidate (n + 1) return ← (nextStep <|> currentStep) if cfg.traceShrink then @@ -342,23 +342,23 @@ partial def minimizeAux [SampleableExt α] {β : α → Prop} [∀ x, Testable ( /-- Once a property fails to hold on an example, look for smaller counter-examples to show the user. -/ def minimize [SampleableExt α] {β : α → Prop} [∀ x, Testable (β x)] (cfg : Configuration) - (var : String) (x : SampleableExt.proxy α) (r : TestResult (β $ SampleableExt.interp x)) : - Gen (Σ x, TestResult (β $ SampleableExt.interp x)) := do + (var : String) (x : SampleableExt.proxy α) (r : TestResult (β <| SampleableExt.interp x)) : + Gen (Σ x, TestResult (β <| SampleableExt.interp x)) := do if cfg.traceShrink then slimTrace "Shrink" slimTrace s!"Attempting to shrink {var} := {repr x}" - let res ← OptionT.run $ minimizeAux cfg var x 0 - pure $ res.getD ⟨x, r⟩ + let res ← OptionT.run <| minimizeAux cfg var x 0 + pure <| res.getD ⟨x, r⟩ /-- Test a universal property by creating a sample of the right type and instantiating the bound variable with it. -/ instance varTestable [SampleableExt α] {β : α → Prop} [∀ x, Testable (β x)] : - Testable (NamedBinder var $ ∀ x : α, β x) where + Testable (NamedBinder var <| ∀ x : α, β x) where run := λ cfg min => do let x ← SampleableExt.sample if cfg.traceSuccesses || cfg.traceDiscarded then slimTrace s!"{var} := {repr x}" - let r ← Testable.runProp (β $ SampleableExt.interp x) cfg false + let r ← Testable.runProp (β <| SampleableExt.interp x) cfg false let ⟨finalX, finalR⟩ ← if isFailure r then if cfg.traceSuccesses then @@ -366,50 +366,50 @@ instance varTestable [SampleableExt α] {β : α → Prop} [∀ x, Testable (β if min then minimize cfg var x r else - pure $ ⟨x, r⟩ + pure <| ⟨x, r⟩ else - pure $ ⟨x, r⟩ - pure $ addVarInfo var finalX (· $ SampleableExt.interp finalX) finalR + pure <| ⟨x, r⟩ + pure <| addVarInfo var finalX (· <| SampleableExt.interp finalX) finalR /-- Test a universal property about propositions -/ instance propVarTestable {β : Prop → Prop} [∀ b : Bool, Testable (β b)] : - Testable (NamedBinder var $ ∀ p : Prop, β p) + Testable (NamedBinder var <| ∀ p : Prop, β p) where run := λ cfg min => - imp (λ h (b : Bool) => h b) <$> Testable.runProp (NamedBinder var $ ∀ b : Bool, β b) cfg min + imp (λ h (b : Bool) => h b) <$> Testable.runProp (NamedBinder var <| ∀ b : Bool, β b) cfg min instance (priority := high) unusedVarTestable [Nonempty α] [Testable β] : - Testable (NamedBinder var $ ∀ _x : α, β) + Testable (NamedBinder var (α → β)) where run := λ cfg min => do if cfg.traceDiscarded || cfg.traceSuccesses then slimTrace s!"{var} is unused" let r ← Testable.runProp β cfg min let finalR := addInfo s!"{var} is irrelevant (unused)" id r - pure $ imp (· $ Classical.ofNonempty) finalR (PSum.inr $ λ x _ => x) + pure <| imp (· <| Classical.ofNonempty) finalR (PSum.inr <| λ x _ => x) instance (priority := 2000) subtypeVarTestable {p : α → Prop} {β : α → Prop} [∀ x, PrintableProp (p x)] [∀ x, Testable (β x)] [SampleableExt (Subtype p)] {var'} : - Testable (NamedBinder var $ Π x : α, NamedBinder var' $ p x → β x) where + Testable (NamedBinder var <| Π x : α, NamedBinder var' <| p x → β x) where run cfg min := letI (x : Subtype p) : Testable (β x) := { run := fun cfg min => do let r ← Testable.runProp (β x.val) cfg min - pure $ addInfo s!"guard: {printProp (p x)} (by construction)" id r (PSum.inr id) } + pure <| addInfo s!"guard: {printProp (p x)} (by construction)" id r (PSum.inr id) } do let r ← @Testable.run (∀ x : Subtype p, β x.val) (@varTestable var _ _ _ _) cfg min - pure $ iff Subtype.forall' r + pure <| iff Subtype.forall' r instance (priority := low) decidableTestable {p : Prop} [PrintableProp p] [Decidable p] : Testable p where run := λ _ _ => if h : p then - pure $ success (PSum.inr h) + pure <| success (PSum.inr h) else let s := printProp p - pure $ failure h [s!"issue: {s} does not hold"] 0 + pure <| failure h [s!"issue: {s} does not hold"] 0 end Testable @@ -458,19 +458,19 @@ open TestResult /-- Execute `cmd` and repeat every time the result is `gave_up` (at most `n` times). -/ def retry (cmd : Rand (TestResult p)) : Nat → Rand (TestResult p) - | 0 => pure $ TestResult.gaveUp 1 + | 0 => pure <| TestResult.gaveUp 1 | n+1 => do let r ← cmd match r with - | success hp => pure $ success hp - | TestResult.failure h xs n => pure $ failure h xs n + | success hp => pure <| success hp + | TestResult.failure h xs n => pure <| failure h xs n | gaveUp _ => retry cmd n /-- Count the number of times the test procedure gave up. -/ def giveUp (x : Nat) : TestResult p → TestResult p | success (PSum.inl ()) => gaveUp x - | success (PSum.inr p) => success $ (PSum.inr p) - | gaveUp n => gaveUp $ n + x + | success (PSum.inr p) => success <| (PSum.inr p) + | gaveUp n => gaveUp <| n + x | TestResult.failure h xs n => failure h xs n /-- Try `n` times to find a counter-example for `p`. -/ @@ -486,11 +486,11 @@ def Testable.runSuiteAux (p : Prop) [Testable p] (cfg : Configuration) : match x with | (success (PSum.inl ())) => runSuiteAux p cfg r n | (gaveUp g) => runSuiteAux p cfg (giveUp g r) n - | _ => pure $ x + | _ => pure <| x /-- Try to find a counter-example of `p`. -/ def Testable.runSuite (p : Prop) [Testable p] (cfg : Configuration := {}) : Rand (TestResult p) := - Testable.runSuiteAux p cfg (success $ PSum.inl ()) cfg.numInst + Testable.runSuiteAux p cfg (success <| PSum.inl ()) cfg.numInst /-- Run a test suite for `p` in `BaseIO` using the global RNG in `stdGenRef`. -/ def Testable.checkIO (p : Prop) [Testable p] (cfg : Configuration := {}) : BaseIO (TestResult p) := @@ -516,7 +516,7 @@ partial def addDecorations (e : Expr) : MetaM Expr := let newType ← addDecorations type let newBody ← addDecorations body let rest := Expr.forallE name newType newBody data - return .done $ (← Meta.mkAppM `SlimCheck.NamedBinder #[mkStrLit n, rest]) + return .done <| (← Meta.mkAppM `SlimCheck.NamedBinder #[mkStrLit n, rest]) else return .continue @@ -554,7 +554,7 @@ def Testable.check (p : Prop) (cfg : Configuration := {}) match ← Testable.checkIO p' cfg with | TestResult.success _ => if !cfg.quiet then IO.println "Success" | TestResult.gaveUp n => if !cfg.quiet then IO.println s!"Gave up {n} times" - | TestResult.failure _ xs n => throw (IO.userError $ formatFailure "Found problems!" xs n) + | TestResult.failure _ xs n => throw (IO.userError <| formatFailure "Found problems!" xs n) -- #eval Testable.check (∀ (x y z a : Nat) (h1 : 3 < x) (h2 : 3 < y), x - y = y - x) -- Configuration.verbose diff --git a/Mathlib/Topology/AlexandrovDiscrete.lean b/Mathlib/Topology/AlexandrovDiscrete.lean index ea22c32a414a5..e4dc0a9f35bf7 100644 --- a/Mathlib/Topology/AlexandrovDiscrete.lean +++ b/Mathlib/Topology/AlexandrovDiscrete.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ +import Mathlib.Data.Set.Image import Mathlib.Topology.Bases import Mathlib.Topology.Inseparable import Mathlib.Topology.Compactness.LocallyCompact @@ -62,21 +63,21 @@ variable [AlexandrovDiscrete α] {S : Set (Set α)} {f : ι → Set α} lemma isOpen_sInter : (∀ s ∈ S, IsOpen s) → IsOpen (⋂₀ S) := AlexandrovDiscrete.isOpen_sInter _ lemma isOpen_iInter (hf : ∀ i, IsOpen (f i)) : IsOpen (⋂ i, f i) := - isOpen_sInter $ forall_range_iff.2 hf + isOpen_sInter <| forall_range_iff.2 hf lemma isOpen_iInter₂ {f : ∀ i, κ i → Set α} (hf : ∀ i j, IsOpen (f i j)) : IsOpen (⋂ i, ⋂ j, f i j) := - isOpen_iInter fun _ ↦ isOpen_iInter $ hf _ + isOpen_iInter fun _ ↦ isOpen_iInter <| hf _ lemma isClosed_sUnion (hS : ∀ s ∈ S, IsClosed s) : IsClosed (⋃₀ S) := by - simp only [← isOpen_compl_iff, compl_sUnion] at hS ⊢; exact isOpen_sInter $ ball_image_iff.2 hS + simp only [← isOpen_compl_iff, compl_sUnion] at hS ⊢; exact isOpen_sInter <| ball_image_iff.2 hS lemma isClosed_iUnion (hf : ∀ i, IsClosed (f i)) : IsClosed (⋃ i, f i) := - isClosed_sUnion $ forall_range_iff.2 hf + isClosed_sUnion <| forall_range_iff.2 hf lemma isClosed_iUnion₂ {f : ∀ i, κ i → Set α} (hf : ∀ i j, IsClosed (f i j)) : IsClosed (⋃ i, ⋃ j, f i j) := - isClosed_iUnion fun _ ↦ isClosed_iUnion $ hf _ + isClosed_iUnion fun _ ↦ isClosed_iUnion <| hf _ lemma isClopen_sInter (hS : ∀ s ∈ S, IsClopen s) : IsClopen (⋂₀ S) := ⟨isOpen_sInter fun s hs ↦ (hS s hs).1, isClosed_sInter fun s hs ↦ (hS s hs).2⟩ @@ -86,7 +87,7 @@ lemma isClopen_iInter (hf : ∀ i, IsClopen (f i)) : IsClopen (⋂ i, f i) := lemma isClopen_iInter₂ {f : ∀ i, κ i → Set α} (hf : ∀ i j, IsClopen (f i j)) : IsClopen (⋂ i, ⋂ j, f i j) := - isClopen_iInter fun _ ↦ isClopen_iInter $ hf _ + isClopen_iInter fun _ ↦ isClopen_iInter <| hf _ lemma isClopen_sUnion (hS : ∀ s ∈ S, IsClopen s) : IsClopen (⋃₀ S) := ⟨isOpen_sUnion fun s hs ↦ (hS s hs).1, isClosed_sUnion fun s hs ↦ (hS s hs).2⟩ @@ -96,11 +97,11 @@ lemma isClopen_iUnion (hf : ∀ i, IsClopen (f i)) : IsClopen (⋃ i, f i) := lemma isClopen_iUnion₂ {f : ∀ i, κ i → Set α} (hf : ∀ i j, IsClopen (f i j)) : IsClopen (⋃ i, ⋃ j, f i j) := - isClopen_iUnion fun _ ↦ isClopen_iUnion $ hf _ + isClopen_iUnion fun _ ↦ isClopen_iUnion <| hf _ lemma interior_iInter (f : ι → Set α) : interior (⋂ i, f i) = ⋂ i, interior (f i) := - (interior_maximal (iInter_mono fun _ ↦ interior_subset) $ isOpen_iInter fun _ ↦ - isOpen_interior).antisymm' $ subset_iInter fun _ ↦ interior_mono $ iInter_subset _ _ + (interior_maximal (iInter_mono fun _ ↦ interior_subset) <| isOpen_iInter fun _ ↦ + isOpen_interior).antisymm' <| subset_iInter fun _ ↦ interior_mono <| iInter_subset _ _ lemma interior_sInter (S : Set (Set α)) : interior (⋂₀ S) = ⋂ s ∈ S, interior s := by simp_rw [sInter_eq_biInter, interior_iInter] @@ -145,7 +146,7 @@ lemma IsOpen.exterior_subset_iff (ht : IsOpen t) : exterior s ⊆ t ↔ s ⊆ t ⟨subset_exterior.trans, fun h ↦ exterior_minimal h ht⟩ @[mono] lemma exterior_mono : Monotone (exterior : Set α → Set α) := - fun _s _t h ↦ ker_mono $ nhdsSet_mono h + fun _s _t h ↦ ker_mono <| nhdsSet_mono h @[simp] lemma exterior_empty : exterior (∅ : Set α) = ∅ := isOpen_empty.exterior_eq @[simp] lemma exterior_univ : exterior (univ : Set α) = univ := isOpen_univ.exterior_eq @@ -207,17 +208,18 @@ lemma isOpen_iff_forall_specializes : IsOpen s ↔ ∀ x y, x ⤳ y → y ∈ s simp_rw [specializes_iff_exterior_subset] at hs simp_rw [isOpen_iff_mem_nhds, mem_nhds_iff] rintro a ha - refine ⟨_, fun b hb ↦ hs _ _ ?_ ha, isOpen_exterior, subset_exterior $ mem_singleton _⟩ + refine ⟨_, fun b hb ↦ hs _ _ ?_ ha, isOpen_exterior, subset_exterior <| mem_singleton _⟩ rwa [isOpen_exterior.exterior_subset, singleton_subset_iff] lemma Set.Finite.isCompact_exterior (hs : s.Finite) : IsCompact (exterior s) := by classical refine isCompact_of_finite_subcover fun f hf hsf ↦ ?_ choose g hg using fun a (ha : a ∈ exterior s) ↦ mem_iUnion.1 (hsf ha) - refine ⟨hs.toFinset.attach.image fun a ↦ g a.1 $ subset_exterior $ (Finite.mem_toFinset _).1 a.2, + refine ⟨hs.toFinset.attach.image fun a ↦ + g a.1 <| subset_exterior <| (Finite.mem_toFinset _).1 a.2, (isOpen_iUnion fun i ↦ isOpen_iUnion ?_).exterior_subset.2 ?_⟩ exact fun _ ↦ hf _ - refine fun a ha ↦ mem_iUnion₂.2 ⟨_, ?_, hg _ $ subset_exterior ha⟩ + refine fun a ha ↦ mem_iUnion₂.2 ⟨_, ?_, hg _ <| subset_exterior ha⟩ simp only [Finset.mem_image, Finset.mem_attach, true_and, Subtype.exists, Finite.mem_toFinset] exact ⟨a, ha, rfl⟩ @@ -251,7 +253,7 @@ instance AlexandrovDiscrete.toFirstCountable : FirstCountableTopology α where instance AlexandrovDiscrete.toLocallyCompactSpace : LocallyCompactSpace α where local_compact_nhds a _U hU := ⟨exterior {a}, - isOpen_exterior.mem_nhds $ subset_exterior $ mem_singleton _, + isOpen_exterior.mem_nhds <| subset_exterior <| mem_singleton _, exterior_singleton_subset_iff_mem_nhds.2 hU, (finite_singleton _).isCompact_exterior⟩ instance Subtype.instAlexandrovDiscrete {p : α → Prop} : AlexandrovDiscrete {a // p a} := diff --git a/Mathlib/Topology/Algebra/Algebra.lean b/Mathlib/Topology/Algebra/Algebra.lean index 0ec8a5012ed0d..1badcc6a5d39c 100644 --- a/Mathlib/Topology/Algebra/Algebra.lean +++ b/Mathlib/Topology/Algebra/Algebra.lean @@ -85,17 +85,13 @@ variable {A : Type u} [TopologicalSpace A] variable [Semiring A] [Algebra R A] -instance Subalgebra.continuousSMul [TopologicalSpace R] [ContinuousSMul R A] (s : Subalgebra R A) : - ContinuousSMul R s := - s.toSubmodule.continuousSMul -#align subalgebra.has_continuous_smul Subalgebra.continuousSMul +#align subalgebra.has_continuous_smul SMulMemClass.continuousSMul variable [TopologicalSemiring A] /-- The closure of a subalgebra in a topological algebra as a subalgebra. -/ def Subalgebra.topologicalClosure (s : Subalgebra R A) : Subalgebra R A := - { - s.toSubsemiring.topologicalClosure with + { s.toSubsemiring.topologicalClosure with carrier := closure (s : Set A) algebraMap_mem' := fun r => s.toSubsemiring.le_topologicalClosure (s.algebraMap_mem r) } #align subalgebra.topological_closure Subalgebra.topologicalClosure diff --git a/Mathlib/Topology/Algebra/ContinuousAffineMap.lean b/Mathlib/Topology/Algebra/ContinuousAffineMap.lean index 2a3ec5062b95d..a6cef4e20568d 100644 --- a/Mathlib/Topology/Algebra/ContinuousAffineMap.lean +++ b/Mathlib/Topology/Algebra/ContinuousAffineMap.lean @@ -61,32 +61,32 @@ theorem to_affineMap_injective {f g : P →A[R] Q} (h : (f : P →ᵃ[R] Q) = (g instance : ContinuousMapClass (P →A[R] Q) P Q where coe f := f.toAffineMap - coe_injective' _ _ h := to_affineMap_injective <| FunLike.coe_injective h + coe_injective' _ _ h := to_affineMap_injective <| DFunLike.coe_injective h map_continuous := cont /-- Helper instance for when there's too many metavariables to apply -`FunLike.hasCoeToFun` directly. -/ +`DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (P →A[R] Q) fun _ ↦ P → Q := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun theorem toFun_eq_coe (f : P →A[R] Q) : f.toFun = ⇑f := rfl #align continuous_affine_map.to_fun_eq_coe ContinuousAffineMap.toFun_eq_coe theorem coe_injective : @Function.Injective (P →A[R] Q) (P → Q) (⇑) := - FunLike.coe_injective + DFunLike.coe_injective #align continuous_affine_map.coe_injective ContinuousAffineMap.coe_injective @[ext] theorem ext {f g : P →A[R] Q} (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align continuous_affine_map.ext ContinuousAffineMap.ext theorem ext_iff {f g : P →A[R] Q} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align continuous_affine_map.ext_iff ContinuousAffineMap.ext_iff theorem congr_fun {f g : P →A[R] Q} (h : f = g) (x : P) : f x = g x := - FunLike.congr_fun h _ + DFunLike.congr_fun h _ #align continuous_affine_map.congr_fun ContinuousAffineMap.congr_fun /-- Forgetting its algebraic properties, a continuous affine map is a continuous map. -/ diff --git a/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean b/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean index e77d882d98db8..af0ccef565aa6 100644 --- a/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean +++ b/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean @@ -109,16 +109,16 @@ instance ContinuousMonoidHom.ContinuousMonoidHomClass : map_one f := f.map_one' map_continuous f := f.continuous_toFun -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ @[to_additive - "Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun`."] + "Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun`."] instance : CoeFun (ContinuousMonoidHom A B) fun _ => A → B := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[to_additive (attr := ext)] theorem ext {f g : ContinuousMonoidHom A B} (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align continuous_monoid_hom.ext ContinuousMonoidHom.ext #align continuous_add_monoid_hom.ext ContinuousAddMonoidHom.ext @@ -131,7 +131,7 @@ def toContinuousMap (f : ContinuousMonoidHom A B) : C(A, B) := @[to_additive] theorem toContinuousMap_injective : Injective (toContinuousMap : _ → C(A, B)) := fun f g h => - ext <| by convert FunLike.ext_iff.1 h + ext <| by convert DFunLike.ext_iff.1 h #align continuous_monoid_hom.to_continuous_map_injective ContinuousMonoidHom.toContinuousMap_injective #align continuous_add_monoid_hom.to_continuous_map_injective ContinuousAddMonoidHom.toContinuousMap_injective diff --git a/Mathlib/Topology/Algebra/Group/Basic.lean b/Mathlib/Topology/Algebra/Group/Basic.lean index 0e5ea0011fc86..d41a1fac3218d 100644 --- a/Mathlib/Topology/Algebra/Group/Basic.lean +++ b/Mathlib/Topology/Algebra/Group/Basic.lean @@ -334,6 +334,10 @@ protected def Homeomorph.inv (G : Type*) [TopologicalSpace G] [InvolutiveInv G] #align homeomorph.inv Homeomorph.inv #align homeomorph.neg Homeomorph.neg +@[to_additive (attr := simp)] +lemma Homeomorph.coe_inv {G : Type*} [TopologicalSpace G] [InvolutiveInv G] [ContinuousInv G] : + ⇑(Homeomorph.inv G) = Inv.inv := rfl + @[to_additive] theorem isOpenMap_inv : IsOpenMap (Inv.inv : G → G) := (Homeomorph.inv _).isOpenMap diff --git a/Mathlib/Topology/Algebra/Group/Compact.lean b/Mathlib/Topology/Algebra/Group/Compact.lean index b12882c376510..fdcf07932650e 100644 --- a/Mathlib/Topology/Algebra/Group/Compact.lean +++ b/Mathlib/Topology/Algebra/Group/Compact.lean @@ -31,26 +31,20 @@ section variable [TopologicalSpace G] [Group G] [TopologicalGroup G] /-- Every topological group in which there exists a compact set with nonempty interior -is weakly locally compact. -/ -@[to_additive - "Every separated topological additive group - in which there exists a compact set with nonempty interior is weakly locally compact."] -theorem TopologicalSpace.PositiveCompacts.weaklyLocallyCompactSpace_of_group - (K : PositiveCompacts G) : WeaklyLocallyCompactSpace G where - exists_compact_mem_nhds x := by - obtain ⟨y, hy⟩ := K.interior_nonempty - refine ⟨(x * y⁻¹) • (K : Set G), K.isCompact.smul _, ?_⟩ - rw [mem_interior_iff_mem_nhds] at hy - simpa using smul_mem_nhds (x * y⁻¹) hy - -/-- Every separated topological group in which there exists a compact set with nonempty interior is locally compact. -/ @[to_additive - "Every separated topological additive group + "Every topological additive group in which there exists a compact set with nonempty interior is locally compact."] -theorem TopologicalSpace.PositiveCompacts.locallyCompactSpace_of_group [T2Space G] - (K : PositiveCompacts G) : LocallyCompactSpace G := - have := K.weaklyLocallyCompactSpace_of_group; inferInstance +theorem TopologicalSpace.PositiveCompacts.locallyCompactSpace_of_group + (K : PositiveCompacts G) : LocallyCompactSpace G := by + have A : WeaklyLocallyCompactSpace G := + { exists_compact_mem_nhds := by + intro x + obtain ⟨y, hy⟩ := K.interior_nonempty + refine ⟨(x * y⁻¹) • (K : Set G), K.isCompact.smul _, ?_⟩ + rw [mem_interior_iff_mem_nhds] at hy + simpa using smul_mem_nhds (x * y⁻¹) hy } + infer_instance #align topological_space.positive_compacts.locally_compact_space_of_group TopologicalSpace.PositiveCompacts.locallyCompactSpace_of_group #align topological_space.positive_compacts.locally_compact_space_of_add_group TopologicalSpace.PositiveCompacts.locallyCompactSpace_of_addGroup diff --git a/Mathlib/Topology/Algebra/GroupCompletion.lean b/Mathlib/Topology/Algebra/GroupCompletion.lean index dca1fed29af1b..55fde2bf1b273 100644 --- a/Mathlib/Topology/Algebra/GroupCompletion.lean +++ b/Mathlib/Topology/Algebra/GroupCompletion.lean @@ -68,7 +68,7 @@ section Zero instance [UniformSpace α] [MonoidWithZero M] [Zero α] [MulActionWithZero M α] [UniformContinuousConstSMul M α] : MulActionWithZero M (Completion α) := - { (inferInstance : MulAction M $ Completion α) with + { (inferInstance : MulAction M <| Completion α) with smul_zero := fun r ↦ by rw [← coe_zero, ← coe_smul, MulActionWithZero.smul_zero r] zero_smul := ext' (continuous_const_smul _) continuous_const fun a ↦ by @@ -96,8 +96,8 @@ theorem coe_add (a b : α) : ((a + b : α) : Completion α) = a + b := #align uniform_space.completion.coe_add UniformSpace.Completion.coe_add instance : AddMonoid (Completion α) := - { (inferInstance : Zero $ Completion α), - (inferInstance : Add $ Completion α) with + { (inferInstance : Zero <| Completion α), + (inferInstance : Add <| Completion α) with zero_add := fun a ↦ Completion.induction_on a (isClosed_eq (continuous_map₂ continuous_const continuous_id) continuous_id) fun a ↦ @@ -127,9 +127,9 @@ instance : AddMonoid (Completion α) := rw [← coe_smul, succ_nsmul, coe_add, coe_smul] } instance : SubNegMonoid (Completion α) := - { (inferInstance : AddMonoid $ Completion α), - (inferInstance : Neg $ Completion α), - (inferInstance : Sub $ Completion α) with + { (inferInstance : AddMonoid <| Completion α), + (inferInstance : Neg <| Completion α), + (inferInstance : Sub <| Completion α) with sub_eq_add_neg := fun a b ↦ Completion.induction_on₂ a b (isClosed_eq (continuous_map₂ continuous_fst continuous_snd) @@ -153,7 +153,7 @@ instance : SubNegMonoid (Completion α) := SubNegMonoid.zsmul_neg' n a, coe_neg, coe_smul] } instance addGroup : AddGroup (Completion α) := - { (inferInstance : SubNegMonoid $ Completion α) with + { (inferInstance : SubNegMonoid <| Completion α) with add_left_neg := fun a ↦ Completion.induction_on a (isClosed_eq (continuous_map₂ Completion.continuous_map continuous_id) continuous_const) @@ -167,7 +167,7 @@ instance uniformAddGroup : UniformAddGroup (Completion α) := instance {M} [Monoid M] [DistribMulAction M α] [UniformContinuousConstSMul M α] : DistribMulAction M (Completion α) := - { (inferInstance : MulAction M $ Completion α) with + { (inferInstance : MulAction M <| Completion α) with smul_add := fun r x y ↦ induction_on₂ x y (isClosed_eq ((continuous_fst.add continuous_snd).const_smul _) @@ -202,7 +202,7 @@ section UniformAddCommGroup variable [UniformSpace α] [AddCommGroup α] [UniformAddGroup α] instance : AddCommGroup (Completion α) := - { (inferInstance : AddGroup $ Completion α) with + { (inferInstance : AddGroup <| Completion α) with add_comm := fun a b ↦ Completion.induction_on₂ a b (isClosed_eq (continuous_map₂ continuous_fst continuous_snd) @@ -213,8 +213,8 @@ instance : AddCommGroup (Completion α) := instance instModule [Semiring R] [Module R α] [UniformContinuousConstSMul R α] : Module R (Completion α) := - { (inferInstance : DistribMulAction R $ Completion α), - (inferInstance : MulActionWithZero R $ Completion α) with + { (inferInstance : DistribMulAction R <| Completion α), + (inferInstance : MulActionWithZero R <| Completion α) with add_smul := fun a b ↦ ext' (continuous_const_smul _) ((continuous_const_smul _).add (continuous_const_smul _)) fun x ↦ by diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean b/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean index 23a6b5c68250c..e8f00715ed372 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean @@ -1028,10 +1028,8 @@ theorem tendsto_sum_nat_add [T2Space α] (f : ℕ → α) : rw [sub_eq_iff_eq_add, add_comm, sum_add_tsum_nat_add i hf] have h₁ : Tendsto (fun _ : ℕ => ∑' i, f i) atTop (𝓝 (∑' i, f i)) := tendsto_const_nhds simpa only [h₀, sub_self] using Tendsto.sub h₁ hf.hasSum.tendsto_sum_nat - · convert tendsto_const_nhds (α := α) (β := ℕ) (a := 0) (f := atTop) - rename_i i - rw [← summable_nat_add_iff i] at hf - exact tsum_eq_zero_of_not_summable hf + · refine tendsto_const_nhds.congr fun n ↦ (tsum_eq_zero_of_not_summable ?_).symm + rwa [summable_nat_add_iff n] #align tendsto_sum_nat_add tendsto_sum_nat_add /-- If `f₀, f₁, f₂, ...` and `g₀, g₁, g₂, ...` are both convergent then so is the `ℤ`-indexed @@ -1317,8 +1315,7 @@ theorem tendsto_tsum_compl_atTop_zero (f : α → G) : obtain ⟨s, hs⟩ := H.tsum_vanishing he rw [Filter.mem_map, mem_atTop_sets] exact ⟨s, fun t hts ↦ hs _ <| Set.disjoint_left.mpr fun a ha has ↦ ha (hts has)⟩ - · convert tendsto_const_nhds (α := G) (β := Finset α) (f := atTop) (a := 0) - apply tsum_eq_zero_of_not_summable + · refine tendsto_const_nhds.congr fun _ ↦ (tsum_eq_zero_of_not_summable ?_).symm rwa [Finset.summable_compl_iff] #align tendsto_tsum_compl_at_top_zero tendsto_tsum_compl_atTop_zero diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Module.lean b/Mathlib/Topology/Algebra/InfiniteSum/Module.lean index 3a16ad2044367..22ff0e53c8859 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Module.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Module.lean @@ -11,7 +11,7 @@ import Mathlib.Topology.Algebra.Module.Basic /-! # Infinite sums in topological vector spaces -/ -variable {ι R R₂ M M₂ : Type*} +variable {ι κ R R₂ M M₂ : Type*} section SMulConst @@ -32,6 +32,38 @@ theorem tsum_smul_const [T2Space M] (hf : Summable f) (a : M) : ∑' z, f z • end SMulConst +/-! +Note we cannot derive the `mul` lemmas from these `smul` lemmas, as the `mul` versions do not +require associativity, but `Module` does. +-/ +section tsum_smul_tsum + +variable [Semiring R] [AddCommMonoid M] [Module R M] +variable [TopologicalSpace R] [TopologicalSpace M] [T3Space M] +variable [ContinuousAdd M] [ContinuousSMul R M] +variable {f : ι → R} {g : κ → M} {s : R} {t u : M} + +theorem HasSum.smul_eq (hf : HasSum f s) (hg : HasSum g t) + (hfg : HasSum (fun x : ι × κ => f x.1 • g x.2) u) : s • t = u := + have key₁ : HasSum (fun i => f i • t) (s • t) := hf.smul_const t + have this : ∀ i : ι, HasSum (fun c : κ => f i • g c) (f i • t) := fun i => hg.const_smul (f i) + have key₂ : HasSum (fun i => f i • t) u := HasSum.prod_fiberwise hfg this + key₁.unique key₂ + +theorem HasSum.smul (hf : HasSum f s) (hg : HasSum g t) + (hfg : Summable fun x : ι × κ => f x.1 • g x.2) : + HasSum (fun x : ι × κ => f x.1 • g x.2) (s • t) := + let ⟨_u, hu⟩ := hfg + (hf.smul_eq hg hu).symm ▸ hu + +/-- Scalar product of two infinites sums indexed by arbitrary types. -/ +theorem tsum_smul_tsum (hf : Summable f) (hg : Summable g) + (hfg : Summable fun x : ι × κ => f x.1 • g x.2) : + ((∑' x, f x) • ∑' y, g y) = ∑' z : ι × κ, f z.1 • g z.2 := + hf.hasSum.smul_eq hg.hasSum hfg.hasSum + +end tsum_smul_tsum + section HasSum -- Results in this section hold for continuous additive monoid homomorphisms or equivalences but we diff --git a/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean b/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean index 81d5de2693ade..edefab4231e47 100644 --- a/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean +++ b/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean @@ -68,7 +68,7 @@ theorem range_toContinuousMultilinearMap : instance continuousMapClass : ContinuousMapClass (M [Λ^ι]→L[R] N) (ι → M) N where coe f := f.toFun - coe_injective' _ _ h := toContinuousMultilinearMap_injective <| FunLike.ext' h + coe_injective' _ _ h := toContinuousMultilinearMap_injective <| DFunLike.ext' h map_continuous f := f.cont initialize_simps_projections ContinuousAlternatingMap (toFun → apply) @@ -90,20 +90,20 @@ theorem coe_toAlternatingMap : ⇑f.toAlternatingMap = f := rfl @[ext] theorem ext {f g : M [Λ^ι]→L[R] N} (H : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ H + DFunLike.ext _ _ H theorem ext_iff {f g : M [Λ^ι]→L[R] N} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff theorem toAlternatingMap_injective : Injective (toAlternatingMap : (M [Λ^ι]→L[R] N) → (M [Λ^ι]→ₗ[R] N)) := fun f g h => - FunLike.ext' <| by convert FunLike.ext'_iff.1 h + DFunLike.ext' <| by convert DFunLike.ext'_iff.1 h @[simp] theorem range_toAlternatingMap : Set.range (toAlternatingMap : M [Λ^ι]→L[R] N → (M [Λ^ι]→ₗ[R] N)) = {f : M [Λ^ι]→ₗ[R] N | Continuous f} := - Set.ext fun f => ⟨fun ⟨g, hg⟩ => hg ▸ g.cont, fun h => ⟨{ f with cont := h }, FunLike.ext' rfl⟩⟩ + Set.ext fun f => ⟨fun ⟨g, hg⟩ => hg ▸ g.cont, fun h => ⟨{ f with cont := h }, DFunLike.ext' rfl⟩⟩ @[simp] theorem map_add [DecidableEq ι] (m : ι → M) (i : ι) (x y : M) : diff --git a/Mathlib/Topology/Algebra/Module/Basic.lean b/Mathlib/Topology/Algebra/Module/Basic.lean index 6d5ac30602e06..f4d17818f3cb6 100644 --- a/Mathlib/Topology/Algebra/Module/Basic.lean +++ b/Mathlib/Topology/Algebra/Module/Basic.lean @@ -102,11 +102,9 @@ variable {ι R M₁ M₂ : Type*} [Semiring R] [AddCommMonoid M₁] [AddCommMono [Module R M₂] [u : TopologicalSpace R] {t : TopologicalSpace M₂} [ContinuousSMul R M₂] (f : M₁ →ₗ[R] M₂) -theorem continuousSMul_induced : @ContinuousSMul R M₁ _ u (t.induced f) := by +theorem continuousSMul_induced : @ContinuousSMul R M₁ _ u (t.induced f) := let _ : TopologicalSpace M₁ := t.induced f - refine' ⟨continuous_induced_rng.2 _⟩ - simp_rw [Function.comp, f.map_smul] - exact continuous_fst.smul (continuous_induced_dom.comp continuous_snd) + Inducing.continuousSMul ⟨rfl⟩ continuous_id (map_smul f _ _) #align has_continuous_smul_induced continuousSMul_induced end LatticeOps @@ -130,10 +128,7 @@ namespace Submodule variable {α β : Type*} [TopologicalSpace β] -instance continuousSMul [TopologicalSpace α] [Semiring α] [AddCommMonoid β] [Module α β] - [ContinuousSMul α β] (S : Submodule α β) : ContinuousSMul α S := - continuousSMul_induced S.subtype -#align submodule.has_continuous_smul Submodule.continuousSMul +#align submodule.has_continuous_smul SMulMemClass.continuousSMul instance topologicalAddGroup [Ring α] [AddCommGroup β] [Module α β] [TopologicalAddGroup β] (S : Submodule α β) : TopologicalAddGroup S := @@ -351,7 +346,7 @@ instance (priority := 100) continuousSemilinearMapClass [s : ContinuousSemilinearEquivClass F σ M M₂] : ContinuousSemilinearMapClass F σ M M₂ := { s with coe := ((↑) : F → M → M₂) - coe_injective' := @FunLike.coe_injective F _ _ _ } + coe_injective' := @DFunLike.coe_injective F _ _ _ } #align continuous_semilinear_equiv_class.continuous_semilinear_map_class ContinuousSemilinearEquivClass.continuousSemilinearMapClass end ContinuousSemilinearEquivClass @@ -424,7 +419,7 @@ theorem coe_injective : Function.Injective ((↑) : (M₁ →SL[σ₁₂] M₂) instance continuousSemilinearMapClass : ContinuousSemilinearMapClass (M₁ →SL[σ₁₂] M₂) σ₁₂ M₁ M₂ where coe f := f.toLinearMap - coe_injective' _ _ h := coe_injective (FunLike.coe_injective h) + coe_injective' _ _ h := coe_injective (DFunLike.coe_injective h) map_add f := map_add f.toLinearMap map_continuous f := f.2 map_smulₛₗ f := f.toLinearMap.map_smul' @@ -432,7 +427,7 @@ instance continuousSemilinearMapClass : -- see Note [function coercion] /-- Coerce continuous linear maps to functions. -/ ---instance toFun' : CoeFun (M₁ →SL[σ₁₂] M₂) fun _ => M₁ → M₂ := ⟨FunLike.coe⟩ +--instance toFun' : CoeFun (M₁ →SL[σ₁₂] M₂) fun _ => M₁ → M₂ := ⟨DFunLike.coe⟩ -- porting note: was `simp`, now `simp only` proves it theorem coe_mk (f : M₁ →ₛₗ[σ₁₂] M₂) (h) : (mk f h : M₁ →ₛₗ[σ₁₂] M₂) = f := @@ -461,7 +456,7 @@ theorem coe_inj {f g : M₁ →SL[σ₁₂] M₂} : (f : M₁ →ₛₗ[σ₁₂ #align continuous_linear_map.coe_inj ContinuousLinearMap.coe_inj theorem coeFn_injective : @Function.Injective (M₁ →SL[σ₁₂] M₂) (M₁ → M₂) (↑) := - FunLike.coe_injective + DFunLike.coe_injective #align continuous_linear_map.coe_fn_injective ContinuousLinearMap.coeFn_injective /-- See Note [custom simps projection]. We need to specify this projection explicitly in this case, @@ -479,11 +474,11 @@ initialize_simps_projections ContinuousLinearMap (toLinearMap_toFun → apply, t @[ext] theorem ext {f g : M₁ →SL[σ₁₂] M₂} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align continuous_linear_map.ext ContinuousLinearMap.ext theorem ext_iff {f g : M₁ →SL[σ₁₂] M₂} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align continuous_linear_map.ext_iff ContinuousLinearMap.ext_iff /-- Copy of a `ContinuousLinearMap` with a new `toFun` equal to the old one. Useful to fix @@ -499,7 +494,7 @@ theorem coe_copy (f : M₁ →SL[σ₁₂] M₂) (f' : M₁ → M₂) (h : f' = #align continuous_linear_map.coe_copy ContinuousLinearMap.coe_copy theorem copy_eq (f : M₁ →SL[σ₁₂] M₂) (f' : M₁ → M₂) (h : f' = ⇑f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align continuous_linear_map.copy_eq ContinuousLinearMap.copy_eq -- make some straightforward lemmas available to `simp`. @@ -715,7 +710,8 @@ theorem one_apply (x : M₁) : (1 : M₁ →L[R₁] M₁) x = x := #align continuous_linear_map.one_apply ContinuousLinearMap.one_apply instance [Nontrivial M₁] : Nontrivial (M₁ →L[R₁] M₁) := - ⟨0, 1, fun e ↦ have ⟨x, hx⟩ := exists_ne (0 : M₁); hx (by simpa using FunLike.congr_fun e.symm x)⟩ + ⟨0, 1, fun e ↦ + have ⟨x, hx⟩ := exists_ne (0 : M₁); hx (by simpa using DFunLike.congr_fun e.symm x)⟩ section Add @@ -1060,6 +1056,16 @@ theorem ker_codRestrict (f : M₁ →SL[σ₁₂] M₂) (p : Submodule R₂ M₂ (f : M₁ →ₛₗ[σ₁₂] M₂).ker_codRestrict p h #align continuous_linear_map.ker_cod_restrict ContinuousLinearMap.ker_codRestrict +/-- Restrict the codomain of a continuous linear map `f` to `f.range`. -/ +@[reducible] +def rangeRestrict [RingHomSurjective σ₁₂] (f : M₁ →SL[σ₁₂] M₂) := + f.codRestrict (LinearMap.range f) (LinearMap.mem_range_self f) + +@[simp] +theorem coe_rangeRestrict [RingHomSurjective σ₁₂] (f : M₁ →SL[σ₁₂] M₂) : + (f.rangeRestrict : M₁ →ₛₗ[σ₁₂] LinearMap.range f) = (f : M₁ →ₛₗ[σ₁₂] M₂).rangeRestrict := + rfl + /-- `Submodule.subtype` as a `ContinuousLinearMap`. -/ def _root_.Submodule.subtypeL (p : Submodule R₁ M₁) : p →L[R₁] M₁ where cont := continuous_subtype_val diff --git a/Mathlib/Topology/Algebra/Module/Cardinality.lean b/Mathlib/Topology/Algebra/Module/Cardinality.lean index d87a1032f5c94..6302451696e07 100644 --- a/Mathlib/Topology/Algebra/Module/Cardinality.lean +++ b/Mathlib/Topology/Algebra/Module/Cardinality.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.SetTheory.Cardinal.CountableCover -import Mathlib.Data.Real.Cardinality +import Mathlib.SetTheory.Cardinal.Continuum import Mathlib.Analysis.SpecificLimits.Normed import Mathlib.Topology.Perfect diff --git a/Mathlib/Topology/Algebra/Module/CharacterSpace.lean b/Mathlib/Topology/Algebra/Module/CharacterSpace.lean index 5657965d5b749..02a3acd91a2cd 100644 --- a/Mathlib/Topology/Algebra/Module/CharacterSpace.lean +++ b/Mathlib/Topology/Algebra/Module/CharacterSpace.lean @@ -57,12 +57,12 @@ variable [CommSemiring 𝕜] [TopologicalSpace 𝕜] [ContinuousAdd 𝕜] [Conti /-- Elements of the character space are continuous linear maps. -/ instance instContinuousLinearMapClass : ContinuousLinearMapClass (characterSpace 𝕜 A) 𝕜 A 𝕜 where coe φ := ((φ : WeakDual 𝕜 A) : A → 𝕜) - coe_injective' φ ψ h := by ext1; apply FunLike.ext; exact congr_fun h + coe_injective' φ ψ h := by ext1; apply DFunLike.ext; exact congr_fun h map_smulₛₗ φ := (φ : WeakDual 𝕜 A).map_smul map_add φ := (φ : WeakDual 𝕜 A).map_add map_continuous φ := (φ : WeakDual 𝕜 A).cont --- porting note: moved because Lean 4 doesn't see the `FunLike` instance on `characterSpace 𝕜 A` +-- porting note: moved because Lean 4 doesn't see the `DFunLike` instance on `characterSpace 𝕜 A` -- until the `ContinuousLinearMapClass` instance is declared @[simp, norm_cast] protected theorem coe_coe (φ : characterSpace 𝕜 A) : ⇑(φ : WeakDual 𝕜 A) = (φ : A → 𝕜) := @@ -71,7 +71,7 @@ protected theorem coe_coe (φ : characterSpace 𝕜 A) : ⇑(φ : WeakDual 𝕜 @[ext] theorem ext {φ ψ : characterSpace 𝕜 A} (h : ∀ x, φ x = ψ x) : φ = ψ := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align weak_dual.character_space.ext WeakDual.CharacterSpace.ext /-- An element of the character space, as a continuous linear map. -/ diff --git a/Mathlib/Topology/Algebra/Module/FiniteDimension.lean b/Mathlib/Topology/Algebra/Module/FiniteDimension.lean index fda352aed6b75..e8d1aafc21d81 100644 --- a/Mathlib/Topology/Algebra/Module/FiniteDimension.lean +++ b/Mathlib/Topology/Algebra/Module/FiniteDimension.lean @@ -158,9 +158,8 @@ theorem LinearMap.continuous_of_isClosed_ker (l : E →ₗ[𝕜] 𝕜) -- is injective. Since `φ.symm` is linear, it is also a vector space topology. -- Hence, we know that it is equal to the topology induced by the norm. have : induced φ.toEquiv.symm inferInstance = hnorm.toUniformSpace.toTopologicalSpace := by - refine' - unique_topology_of_t2 (topologicalAddGroup_induced φ.symm.toLinearMap) - (continuousSMul_induced φ.symm.toLinearMap) _ + refine' unique_topology_of_t2 (topologicalAddGroup_induced φ.symm.toLinearMap) + (continuousSMul_induced φ.symm.toLinearMap) _ -- Porting note: was `rw [t2Space_iff]` refine (@t2Space_iff 𝕜 (induced (↑(LinearEquiv.toEquiv φ).symm) inferInstance)).mpr ?_ exact fun x y hxy => diff --git a/Mathlib/Topology/Algebra/Module/Multilinear/Basic.lean b/Mathlib/Topology/Algebra/Module/Multilinear/Basic.lean index 15a4f8d9217dd..abd41c2d9cb99 100644 --- a/Mathlib/Topology/Algebra/Module/Multilinear/Basic.lean +++ b/Mathlib/Topology/Algebra/Module/Multilinear/Basic.lean @@ -107,7 +107,7 @@ theorem coe_coe : (f.toMultilinearMap : (∀ i, M₁ i) → M₂) = f := @[ext] theorem ext {f f' : ContinuousMultilinearMap R M₁ M₂} (H : ∀ x, f x = f' x) : f = f' := - FunLike.ext _ _ H + DFunLike.ext _ _ H #align continuous_multilinear_map.ext ContinuousMultilinearMap.ext theorem ext_iff {f f' : ContinuousMultilinearMap R M₁ M₂} : f = f' ↔ ∀ x, f x = f' x := by diff --git a/Mathlib/Topology/Algebra/Module/StrongTopology.lean b/Mathlib/Topology/Algebra/Module/StrongTopology.lean index 1df4d1594db1d..92cf9839c5b29 100644 --- a/Mathlib/Topology/Algebra/Module/StrongTopology.lean +++ b/Mathlib/Topology/Algebra/Module/StrongTopology.lean @@ -75,7 +75,7 @@ topological vector space. -/ def strongTopology [TopologicalSpace F] [TopologicalAddGroup F] (𝔖 : Set (Set E)) : TopologicalSpace (E →SL[σ] F) := (@UniformOnFun.topologicalSpace E F (TopologicalAddGroup.toUniformSpace F) 𝔖).induced - (FunLike.coe : (E →SL[σ] F) → (E →ᵤ[𝔖] F)) + (DFunLike.coe : (E →SL[σ] F) → (E →ᵤ[𝔖] F)) #align continuous_linear_map.strong_topology ContinuousLinearMap.strongTopology /-- The uniform structure associated with `ContinuousLinearMap.strongTopology`. We make sure @@ -83,7 +83,7 @@ that this has nice definitional properties. -/ def strongUniformity [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : UniformSpace (E →SL[σ] F) := @UniformSpace.replaceTopology _ (strongTopology σ F 𝔖) - ((UniformOnFun.uniformSpace E F 𝔖).comap (FunLike.coe : (E →SL[σ] F) → (E →ᵤ[𝔖] F))) + ((UniformOnFun.uniformSpace E F 𝔖).comap (DFunLike.coe : (E →SL[σ] F) → (E →ᵤ[𝔖] F))) (by rw [strongTopology, UniformAddGroup.toUniformSpace_eq]; rfl) #align continuous_linear_map.strong_uniformity ContinuousLinearMap.strongUniformity @@ -96,14 +96,14 @@ theorem strongUniformity_topology_eq [UniformSpace F] [UniformAddGroup F] (𝔖 theorem strongUniformity.uniformEmbedding_coeFn [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : @UniformEmbedding (E →SL[σ] F) (E →ᵤ[𝔖] F) (strongUniformity σ F 𝔖) - (UniformOnFun.uniformSpace E F 𝔖) FunLike.coe := + (UniformOnFun.uniformSpace E F 𝔖) DFunLike.coe := letI : UniformSpace (E →SL[σ] F) := strongUniformity σ F 𝔖 - ⟨⟨rfl⟩, FunLike.coe_injective⟩ + ⟨⟨rfl⟩, DFunLike.coe_injective⟩ #align continuous_linear_map.strong_uniformity.uniform_embedding_coe_fn ContinuousLinearMap.strongUniformity.uniformEmbedding_coeFn theorem strongTopology.embedding_coeFn [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : @Embedding (E →SL[σ] F) (E →ᵤ[𝔖] F) (strongTopology σ F 𝔖) - (UniformOnFun.topologicalSpace E F 𝔖) (UniformOnFun.ofFun 𝔖 ∘ FunLike.coe) := + (UniformOnFun.topologicalSpace E F 𝔖) (UniformOnFun.ofFun 𝔖 ∘ DFunLike.coe) := @UniformEmbedding.embedding _ _ (_root_.id _) _ _ (strongUniformity.uniformEmbedding_coeFn _ _ _) #align continuous_linear_map.strong_topology.embedding_coe_fn ContinuousLinearMap.strongTopology.embedding_coeFn @@ -111,7 +111,7 @@ theorem strongUniformity.uniformAddGroup [UniformSpace F] [UniformAddGroup F] ( @UniformAddGroup (E →SL[σ] F) (strongUniformity σ F 𝔖) _ := by letI : UniformSpace (E →SL[σ] F) := strongUniformity σ F 𝔖 let φ : (E →SL[σ] F) →+ E →ᵤ[𝔖] F := - ⟨⟨(FunLike.coe : (E →SL[σ] F) → E →ᵤ[𝔖] F), rfl⟩, fun _ _ => rfl⟩ + ⟨⟨(DFunLike.coe : (E →SL[σ] F) → E →ᵤ[𝔖] F), rfl⟩, fun _ _ => rfl⟩ exact (strongUniformity.uniformEmbedding_coeFn _ _ _).uniformAddGroup φ #align continuous_linear_map.strong_uniformity.uniform_add_group ContinuousLinearMap.strongUniformity.uniformAddGroup @@ -142,7 +142,7 @@ theorem strongTopology.continuousSMul [RingHomSurjective σ] [RingHomIsometric haveI : UniformAddGroup F := comm_topologicalAddGroup_is_uniform letI : TopologicalSpace (E →SL[σ] F) := strongTopology σ F 𝔖 let φ : (E →SL[σ] F) →ₗ[𝕜₂] E →ᵤ[𝔖] F := - ⟨⟨(FunLike.coe : (E →SL[σ] F) → E → F), fun _ _ => rfl⟩, fun _ _ => rfl⟩ + ⟨⟨(DFunLike.coe : (E →SL[σ] F) → E → F), fun _ _ => rfl⟩, fun _ _ => rfl⟩ exact UniformOnFun.continuousSMul_induced_of_image_bounded 𝕜₂ E F (E →SL[σ] F) h𝔖₁ h𝔖₂ φ ⟨rfl⟩ fun u s hs => (h𝔖₃ s hs).image u @@ -160,7 +160,7 @@ theorem strongTopology.hasBasis_nhds_zero_of_basis [TopologicalSpace F] [Topolog -- `letI`) so that Lean doesn't try to use the product topology letI : TopologicalSpace (E →SL[σ] F) := strongTopology σ F 𝔖 rw [(strongTopology.embedding_coeFn σ F 𝔖).toInducing.nhds_eq_comap] - exact (UniformOnFun.hasBasis_nhds_zero_of_basis 𝔖 h𝔖₁ h𝔖₂ h).comap FunLike.coe + exact (UniformOnFun.hasBasis_nhds_zero_of_basis 𝔖 h𝔖₁ h𝔖₂ h).comap DFunLike.coe #align continuous_linear_map.strong_topology.has_basis_nhds_zero_of_basis ContinuousLinearMap.strongTopology.hasBasis_nhds_zero_of_basis theorem strongTopology.hasBasis_nhds_zero [TopologicalSpace F] [TopologicalAddGroup F] @@ -171,20 +171,24 @@ theorem strongTopology.hasBasis_nhds_zero [TopologicalSpace F] [TopologicalAddGr strongTopology.hasBasis_nhds_zero_of_basis σ F 𝔖 h𝔖₁ h𝔖₂ (𝓝 0).basis_sets #align continuous_linear_map.strong_topology.has_basis_nhds_zero ContinuousLinearMap.strongTopology.hasBasis_nhds_zero -theorem strongTopology.continuousConstSMul {M : Type*} +theorem strongTopology.uniformContinuousConstSMul (M : Type*) [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜₂ M F] - [TopologicalSpace F] [TopologicalAddGroup F] [ContinuousConstSMul M F] (𝔖 : Set (Set E)) - (h𝔖₁ : 𝔖.Nonempty) (h𝔖₂ : DirectedOn (· ⊆ ·) 𝔖) : - @ContinuousConstSMul M (E →SL[σ] F) (strongTopology σ F 𝔖) _ := by - letI := strongTopology σ F 𝔖 - haveI : TopologicalAddGroup (E →SL[σ] F) := strongTopology.topologicalAddGroup σ F 𝔖 - refine ⟨fun c ↦ continuous_of_continuousAt_zero (DistribSMul.toAddMonoidHom _ c) ?_⟩ - have H₁ := strongTopology.hasBasis_nhds_zero σ F _ h𝔖₁ h𝔖₂ - have H₂ : Filter.Tendsto (c • ·) (𝓝 0 : Filter F) (𝓝 0) := - (continuous_const_smul c).tendsto' 0 _ (smul_zero _) - rw [ContinuousAt, map_zero, H₁.tendsto_iff H₁] - rintro ⟨s, t⟩ ⟨hs : s ∈ 𝔖, ht : t ∈ 𝓝 0⟩ - exact ⟨(s, (c • ·) ⁻¹' t), ⟨hs, H₂ ht⟩, fun f ↦ _root_.id⟩ + [UniformSpace F] [UniformAddGroup F] [UniformContinuousConstSMul M F] (𝔖 : Set (Set E)) : + @UniformContinuousConstSMul M (E →SL[σ] F) (strongUniformity σ F 𝔖) _ := + let _ := strongUniformity σ F 𝔖 + (strongUniformity.uniformEmbedding_coeFn σ F 𝔖).toUniformInducing.uniformContinuousConstSMul + fun _ _ ↦ rfl + +theorem strongTopology.continuousConstSMul (M : Type*) + [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜₂ M F] + [TopologicalSpace F] [TopologicalAddGroup F] [ContinuousConstSMul M F] (𝔖 : Set (Set E)) : + @ContinuousConstSMul M (E →SL[σ] F) (strongTopology σ F 𝔖) _ := + let _ := TopologicalAddGroup.toUniformSpace F + have _ : UniformAddGroup F := comm_topologicalAddGroup_is_uniform + let _ := strongUniformity σ F 𝔖 + have _ := uniformContinuousConstSMul_of_continuousConstSMul M F + have _ := strongTopology.uniformContinuousConstSMul σ F M 𝔖 + inferInstance end General @@ -239,12 +243,16 @@ protected theorem hasBasis_nhds_zero [TopologicalSpace F] [TopologicalAddGroup F ContinuousLinearMap.hasBasis_nhds_zero_of_basis (𝓝 0).basis_sets #align continuous_linear_map.has_basis_nhds_zero ContinuousLinearMap.hasBasis_nhds_zero +instance uniformContinuousConstSMul + {M : Type*} [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜₂ M F] + [UniformSpace F] [UniformAddGroup F] [UniformContinuousConstSMul M F] : + UniformContinuousConstSMul M (E →SL[σ] F) := + strongTopology.uniformContinuousConstSMul σ F _ _ + instance continuousConstSMul {M : Type*} [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜₂ M F] [TopologicalSpace F] [TopologicalAddGroup F] [ContinuousConstSMul M F] : ContinuousConstSMul M (E →SL[σ] F) := - strongTopology.continuousConstSMul σ F {S | Bornology.IsVonNBounded 𝕜₁ S} - ⟨∅, Bornology.isVonNBounded_empty 𝕜₁ E⟩ - (directedOn_of_sup_mem fun _ _ => Bornology.IsVonNBounded.union) + strongTopology.continuousConstSMul σ F _ _ variable (G) [TopologicalSpace F] [TopologicalSpace G] @@ -263,7 +271,7 @@ def precomp [TopologicalAddGroup G] [ContinuousConstSMul 𝕜₃ G] [RingHomSurj haveI : UniformAddGroup G := comm_topologicalAddGroup_is_uniform rw [(strongTopology.embedding_coeFn _ _ _).continuous_iff] -- Porting note: without this, the following doesn't work - change Continuous ((λ f ↦ UniformOnFun.ofFun _ (f ∘ L)) ∘ FunLike.coe) + change Continuous ((λ f ↦ UniformOnFun.ofFun _ (f ∘ L)) ∘ DFunLike.coe) exact (UniformOnFun.precomp_uniformContinuous fun S hS => hS.image L).continuous.comp (strongTopology.embedding_coeFn _ _ _).continuous #align continuous_linear_map.precomp ContinuousLinearMap.precomp diff --git a/Mathlib/Topology/Algebra/Module/WeakDual.lean b/Mathlib/Topology/Algebra/Module/WeakDual.lean index 4c85b71e622e3..7e74efc02a9eb 100644 --- a/Mathlib/Topology/Algebra/Module/WeakDual.lean +++ b/Mathlib/Topology/Algebra/Module/WeakDual.lean @@ -237,10 +237,10 @@ instance instContinuousLinearMapClass : ContinuousLinearMapClass (WeakDual 𝕜 ContinuousLinearMap.continuousSemilinearMapClass #align weak_dual.weak_dual.continuous_linear_map_class WeakDual.instContinuousLinearMapClass -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (WeakDual 𝕜 E) fun _ => E → 𝕜 := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun /-- If a monoid `M` distributively continuously acts on `𝕜` and this action commutes with multiplication on `𝕜`, then it acts on `WeakDual 𝕜 E`. -/ diff --git a/Mathlib/Topology/Algebra/Monoid.lean b/Mathlib/Topology/Algebra/Monoid.lean index be51f141e72fd..fba3a3904bbd1 100644 --- a/Mathlib/Topology/Algebra/Monoid.lean +++ b/Mathlib/Topology/Algebra/Monoid.lean @@ -376,8 +376,7 @@ end PointwiseLimits theorem Inducing.continuousMul {M N F : Type*} [Mul M] [Mul N] [MulHomClass F M N] [TopologicalSpace M] [TopologicalSpace N] [ContinuousMul N] (f : F) (hf : Inducing f) : ContinuousMul M := - ⟨hf.continuous_iff.2 <| by - simpa only [(· ∘ ·), map_mul f] using hf.continuous.fst'.mul hf.continuous.snd'⟩ + ⟨(hf.continuousSMul hf.continuous (map_mul f _ _)).1⟩ #align inducing.has_continuous_mul Inducing.continuousMul #align inducing.has_continuous_add Inducing.continuousAdd diff --git a/Mathlib/Topology/Algebra/MulAction.lean b/Mathlib/Topology/Algebra/MulAction.lean index bf4a50f84f0d5..9ff57d21e14ab 100644 --- a/Mathlib/Topology/Algebra/MulAction.lean +++ b/Mathlib/Topology/Algebra/MulAction.lean @@ -5,7 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Algebra.AddTorsor import Mathlib.Topology.Algebra.Constructions -import Mathlib.GroupTheory.GroupAction.Prod +import Mathlib.GroupTheory.GroupAction.SubMulAction import Mathlib.Topology.Algebra.ConstMulAction #align_import topology.algebra.mul_action from "leanprover-community/mathlib"@"d90e4e186f1d18e375dcd4e5b5f6364b01cb3e46" @@ -152,6 +152,33 @@ lemma smul_set_closure_subset (K : Set M) (L : Set X) : Set.smul_subset_iff.2 fun _x hx _y hy ↦ map_mem_closure₂ continuous_smul hx hy fun _a ha _b hb ↦ Set.smul_mem_smul ha hb +/-- Suppose that `N` acts on `X` and `M` continuously acts on `Y`. +Suppose that `g : Y → X` is an action homomorphism in the following sense: +there exists a continuous function `f : N → M` such that `g (c • x) = f c • g x`. +Then the action of `N` on `X` is continuous as well. + +In many cases, `f = id` so that `g` is an action homomorphism in the sense of `MulActionHom`. +However, this version also works for semilinear maps and `f = Units.val`. -/ +@[to_additive + "Suppose that `N` additively acts on `X` and `M` continuously additively acts on `Y`. +Suppose that `g : Y → X` is an additive action homomorphism in the following sense: +there exists a continuous function `f : N → M` such that `g (c +ᵥ x) = f c +ᵥ g x`. +Then the action of `N` on `X` is continuous as well. + +In many cases, `f = id` so that `g` is an action homomorphism in the sense of `AddActionHom`. +However, this version also works for `f = AddUnits.val`."] +lemma Inducing.continuousSMul {N : Type*} [SMul N Y] [TopologicalSpace N] {f : N → M} + (hg : Inducing g) (hf : Continuous f) (hsmul : ∀ {c x}, g (c • x) = f c • g x) : + ContinuousSMul N Y where + continuous_smul := by + simpa only [hg.continuous_iff, Function.comp_def, hsmul] + using (hf.comp continuous_fst).smul <| hg.continuous.comp continuous_snd + +@[to_additive] +instance SMulMemClass.continuousSMul {S : Type*} [SetLike S X] [SMulMemClass S M X] (s : S) : + ContinuousSMul M s := + inducing_subtype_val.continuousSMul continuous_id rfl + end SMul section Monoid @@ -159,10 +186,8 @@ section Monoid variable [Monoid M] [MulAction M X] [ContinuousSMul M X] @[to_additive] -instance Units.continuousSMul : ContinuousSMul Mˣ X where - continuous_smul := - show Continuous ((fun p : M × X => p.fst • p.snd) ∘ fun p : Mˣ × X => (p.1, p.2)) from - continuous_smul.comp ((Units.continuous_val.comp continuous_fst).prod_mk continuous_snd) +instance Units.continuousSMul : ContinuousSMul Mˣ X := + inducing_id.continuousSMul Units.continuous_val rfl #align units.has_continuous_smul Units.continuousSMul #align add_units.has_continuous_vadd AddUnits.continuousVAdd @@ -176,6 +201,10 @@ theorem MulAction.continuousSMul_compHom let _ : MulAction N X := MulAction.compHom _ f exact ⟨(hf.comp continuous_fst).smul continuous_snd⟩ +@[to_additive] +instance Submonoid.continuousSMul {S : Submonoid M} : ContinuousSMul S X := + inducing_id.continuousSMul continuous_subtype_val rfl + end Monoid section Group @@ -183,12 +212,8 @@ section Group variable [Group M] [MulAction M X] [ContinuousSMul M X] @[to_additive] -instance Submonoid.continuousSMul {S : Submonoid M} : ContinuousSMul S X where - continuous_smul := (continuous_subtype_val.comp continuous_fst).smul continuous_snd - -@[to_additive] -instance Subgroup.continuousSMul {S : Subgroup M} : ContinuousSMul S X where - continuous_smul := (continuous_subtype_val.comp continuous_fst).smul continuous_snd +instance Subgroup.continuousSMul {S : Subgroup M} : ContinuousSMul S X := + S.toSubmonoid.continuousSMul end Group diff --git a/Mathlib/Topology/Algebra/MvPolynomial.lean b/Mathlib/Topology/Algebra/MvPolynomial.lean new file mode 100644 index 0000000000000..739b1104f6c1b --- /dev/null +++ b/Mathlib/Topology/Algebra/MvPolynomial.lean @@ -0,0 +1,26 @@ +/- +Copyright (c) 2023 Ruben Van de Velde. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Ruben Van de Velde +-/ + +import Mathlib.Data.MvPolynomial.Basic +import Mathlib.Topology.Algebra.Ring.Basic + +/-! +# Multivariate polynomials and continuity + +In this file we prove the following lemma: + +* `MvPolynomial.continuous_eval`: `MvPolynomial.eval` is continuous + +## Tags + +multivariate polynomial, continuity +-/ + +variable {X σ : Type*} [TopologicalSpace X] [CommSemiring X] [TopologicalSemiring X] + (p : MvPolynomial σ X) + +theorem MvPolynomial.continuous_eval : Continuous fun x ↦ eval x p := by + continuity diff --git a/Mathlib/Topology/Algebra/Nonarchimedean/AdicTopology.lean b/Mathlib/Topology/Algebra/Nonarchimedean/AdicTopology.lean index 2d2ef70c73ba3..efa4dcb5aa199 100644 --- a/Mathlib/Topology/Algebra/Nonarchimedean/AdicTopology.lean +++ b/Mathlib/Topology/Algebra/Nonarchimedean/AdicTopology.lean @@ -5,7 +5,6 @@ Authors: Patrick Massot -/ import Mathlib.RingTheory.Ideal.Operations import Mathlib.Topology.Algebra.Nonarchimedean.Bases -import Mathlib.Topology.UniformSpace.Completion import Mathlib.Topology.Algebra.UniformRing #align_import topology.algebra.nonarchimedean.adic_topology from "leanprover-community/mathlib"@"f0c8bf9245297a541f468be517f1bde6195105e9" diff --git a/Mathlib/Topology/Algebra/Order/Compact.lean b/Mathlib/Topology/Algebra/Order/Compact.lean index 1eb7f6d3e01e0..6d8b28edceeca 100644 --- a/Mathlib/Topology/Algebra/Order/Compact.lean +++ b/Mathlib/Topology/Algebra/Order/Compact.lean @@ -5,6 +5,7 @@ Authors: Patrick Massot, Yury Kudryashov -/ import Mathlib.Topology.Algebra.Order.IntermediateValue import Mathlib.Topology.LocalExtr +import Mathlib.Topology.Support #align_import topology.algebra.order.compact from "leanprover-community/mathlib"@"3efd324a3a31eaa40c9d5bfc669c4fafee5f9423" diff --git a/Mathlib/Topology/Algebra/Order/Field.lean b/Mathlib/Topology/Algebra/Order/Field.lean index 51466057f890e..e0b37af82ed7e 100644 --- a/Mathlib/Topology/Algebra/Order/Field.lean +++ b/Mathlib/Topology/Algebra/Order/Field.lean @@ -3,9 +3,9 @@ Copyright (c) 2022 Benjamin Davidson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Benjamin Davidson, Devon Tuma, Eric Rodriguez, Oliver Nash -/ -import Mathlib.Tactic.Positivity import Mathlib.Topology.Algebra.Order.Group import Mathlib.Topology.Algebra.Field +import Mathlib.Data.Set.Pointwise.Interval #align_import topology.algebra.order.field from "leanprover-community/mathlib"@"9a59dcb7a2d06bf55da57b9030169219980660cd" diff --git a/Mathlib/Topology/Algebra/Order/Group.lean b/Mathlib/Topology/Algebra/Order/Group.lean index 587b1ca86ef54..1ebf239c88d0b 100644 --- a/Mathlib/Topology/Algebra/Order/Group.lean +++ b/Mathlib/Topology/Algebra/Order/Group.lean @@ -70,7 +70,7 @@ theorem tendsto_zero_iff_abs_tendsto_zero (f : α → G) : refine' ⟨fun h => (abs_zero : |(0 : G)| = 0) ▸ h.abs, fun h => _⟩ have : Tendsto (fun a => -|f a|) l (𝓝 0) := (neg_zero : -(0 : G) = 0) ▸ h.neg exact - tendsto_of_tendsto_of_tendsto_of_le_of_le this h (fun x => neg_abs_le_self <| f x) fun x => + tendsto_of_tendsto_of_tendsto_of_le_of_le this h (fun x => neg_abs_le <| f x) fun x => le_abs_self <| f x #align tendsto_zero_iff_abs_tendsto_zero tendsto_zero_iff_abs_tendsto_zero diff --git a/Mathlib/Topology/Algebra/Order/LeftRightLim.lean b/Mathlib/Topology/Algebra/Order/LeftRightLim.lean index 89df76adc880a..0e716dbf5f976 100644 --- a/Mathlib/Topology/Algebra/Order/LeftRightLim.lean +++ b/Mathlib/Topology/Algebra/Order/LeftRightLim.lean @@ -115,7 +115,7 @@ theorem leftLim_le (h : x ≤ y) : leftLim f x ≤ f y := by haveI A : NeBot (𝓝[<] x) := neBot_iff.2 h' rw [leftLim_eq_sSup hf h'] refine' csSup_le _ _ - · simp only [nonempty_image_iff] + · simp only [image_nonempty] exact (forall_mem_nonempty_iff_neBot.2 A) _ self_mem_nhdsWithin · simp only [mem_image, mem_Iio, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] intro z hz diff --git a/Mathlib/Topology/Algebra/Order/Rolle.lean b/Mathlib/Topology/Algebra/Order/Rolle.lean index 7ccd3d7523cf3..1a3f8967c5489 100644 --- a/Mathlib/Topology/Algebra/Order/Rolle.lean +++ b/Mathlib/Topology/Algebra/Order/Rolle.lean @@ -83,4 +83,4 @@ lemma exists_isLocalExtr_Ioo_of_tendsto (hab : a < b) (hfc : ContinuousOn f (Ioo (ha : Tendsto f (𝓝[>] a) (𝓝 l)) (hb : Tendsto f (𝓝[<] b) (𝓝 l)) : ∃ c ∈ Ioo a b, IsLocalExtr f c := let ⟨c, cmem, hc⟩ := exists_isExtrOn_Ioo_of_tendsto hab hfc ha hb - ⟨c, cmem, hc.isLocalExtr $ Ioo_mem_nhds cmem.1 cmem.2⟩ + ⟨c, cmem, hc.isLocalExtr <| Ioo_mem_nhds cmem.1 cmem.2⟩ diff --git a/Mathlib/Topology/Algebra/Semigroup.lean b/Mathlib/Topology/Algebra/Semigroup.lean index e09e5b0da4d25..76c2ee0712669 100644 --- a/Mathlib/Topology/Algebra/Semigroup.lean +++ b/Mathlib/Topology/Algebra/Semigroup.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: David Wärn -/ import Mathlib.Topology.Separation +import Mathlib.Algebra.Group.Defs #align_import topology.algebra.semigroup from "leanprover-community/mathlib"@"4c19a16e4b705bf135cf9a80ac18fcc99c438514" diff --git a/Mathlib/Topology/Algebra/StarSubalgebra.lean b/Mathlib/Topology/Algebra/StarSubalgebra.lean index a0673a707e56e..bd1d5c9d771e4 100644 --- a/Mathlib/Topology/Algebra/StarSubalgebra.lean +++ b/Mathlib/Topology/Algebra/StarSubalgebra.lean @@ -37,9 +37,6 @@ variable {R A B : Type*} [CommSemiring R] [StarRing R] variable [TopologicalSpace A] [Semiring A] [Algebra R A] [StarRing A] [StarModule R A] -instance [TopologicalSpace R] [ContinuousSMul R A] (s : StarSubalgebra R A) : ContinuousSMul R s := - s.toSubalgebra.continuousSMul - instance [TopologicalSemiring A] (s : StarSubalgebra R A) : TopologicalSemiring s := s.toSubalgebra.topologicalSemiring @@ -154,7 +151,7 @@ theorem _root_.StarAlgHom.ext_topologicalClosure [T2Space B] {S : StarSubalgebra (h : φ.comp (inclusion (le_topologicalClosure S)) = ψ.comp (inclusion (le_topologicalClosure S))) : φ = ψ := by - rw [FunLike.ext'_iff] + rw [DFunLike.ext'_iff] have : Dense (Set.range <| inclusion (le_topologicalClosure S)) := by refine' embedding_subtype_val.toInducing.dense_iff.2 fun x => _ convert show ↑x ∈ closure (S : Set A) from x.prop @@ -166,7 +163,7 @@ theorem _root_.StarAlgHom.ext_topologicalClosure [T2Space B] {S : StarSubalgebra exact y.prop, fun hy => ⟨⟨y, hy⟩, rfl⟩⟩ refine' Continuous.ext_on this hφ hψ _ rintro _ ⟨x, rfl⟩ - simpa only using FunLike.congr_fun h x + simpa only using DFunLike.congr_fun h x #align star_alg_hom.ext_topological_closure StarAlgHom.ext_topologicalClosure theorem _root_.StarAlgHomClass.ext_topologicalClosure [T2Space B] {F : Type*} @@ -178,7 +175,7 @@ theorem _root_.StarAlgHomClass.ext_topologicalClosure [T2Space B] {F : Type*} have : (φ : S.topologicalClosure →⋆ₐ[R] B) = (ψ : S.topologicalClosure →⋆ₐ[R] B) := by refine StarAlgHom.ext_topologicalClosure (R := R) (A := A) (B := B) hφ hψ (StarAlgHom.ext ?_) simpa only [StarAlgHom.coe_comp, StarAlgHom.coe_coe] using h - rw [FunLike.ext'_iff, ← StarAlgHom.coe_coe] + rw [DFunLike.ext'_iff, ← StarAlgHom.coe_coe] apply congrArg _ this #align star_alg_hom_class.ext_topological_closure StarAlgHomClass.ext_topologicalClosure diff --git a/Mathlib/Topology/Algebra/UniformConvergence.lean b/Mathlib/Topology/Algebra/UniformConvergence.lean index 5e927c0ac278e..8ff74e57fe68f 100644 --- a/Mathlib/Topology/Algebra/UniformConvergence.lean +++ b/Mathlib/Topology/Algebra/UniformConvergence.lean @@ -292,6 +292,22 @@ protected theorem UniformOnFun.hasBasis_nhds_one (𝔖 : Set <| Set α) (h𝔖 end Group +section ConstSMul + +variable (M α X : Type*) [SMul M X] [UniformSpace X] [UniformContinuousConstSMul M X] + +instance UniformFun.uniformContinuousConstSMul : + UniformContinuousConstSMul M (α →ᵤ X) where + uniformContinuous_const_smul c := UniformFun.postcomp_uniformContinuous <| + uniformContinuous_const_smul c + +instance UniformFunOn.uniformContinuousConstSMul {𝔖 : Set (Set α)} : + UniformContinuousConstSMul M (α →ᵤ[𝔖] X) where + uniformContinuous_const_smul c := UniformOnFun.postcomp_uniformContinuous <| + uniformContinuous_const_smul c + +end ConstSMul + section Module variable (𝕜 α E H : Type*) {hom : Type*} [NormedField 𝕜] [AddCommGroup H] [Module 𝕜 H] @@ -336,7 +352,7 @@ theorem UniformOnFun.continuousSMul_induced_of_image_bounded (h𝔖₁ : 𝔖.No rw [map_smul] exact hf x hx · rintro u ⟨S, V⟩ ⟨hS, hV⟩ - rcases h u S hS hV with ⟨r, hrpos, hr⟩ + rcases (h u S hS hV).exists_pos with ⟨r, hrpos, hr⟩ rw [Metric.eventually_nhds_iff_ball] refine' ⟨r⁻¹, inv_pos.mpr hrpos, fun a ha x hx => _⟩ by_cases ha0 : a = 0 diff --git a/Mathlib/Topology/Algebra/UniformGroup.lean b/Mathlib/Topology/Algebra/UniformGroup.lean index 894aff5665a65..8bd4adb46527d 100644 --- a/Mathlib/Topology/Algebra/UniformGroup.lean +++ b/Mathlib/Topology/Algebra/UniformGroup.lean @@ -162,6 +162,13 @@ instance [UniformSpace β] [Group β] [UniformGroup β] : UniformGroup (α × β ((uniformContinuous_snd.comp uniformContinuous_fst).div (uniformContinuous_snd.comp uniformContinuous_snd))⟩ +@[to_additive] +instance Pi.instUniformGroup {ι : Type*} {G : ι → Type*} [∀ i, UniformSpace (G i)] + [∀ i, Group (G i)] [∀ i, UniformGroup (G i)] : UniformGroup (∀ i, G i) where + uniformContinuous_div := uniformContinuous_pi.mpr fun i ↦ + (uniformContinuous_proj G i).comp uniformContinuous_fst |>.div <| + (uniformContinuous_proj G i).comp uniformContinuous_snd + @[to_additive] theorem uniformity_translate_mul (a : α) : ((𝓤 α).map fun x : α × α => (x.1 * a, x.2 * a)) = 𝓤 α := le_antisymm (uniformContinuous_id.mul uniformContinuous_const) diff --git a/Mathlib/Topology/Algebra/UniformMulAction.lean b/Mathlib/Topology/Algebra/UniformMulAction.lean index 1870fbca4ff42..0589b6053b916 100644 --- a/Mathlib/Topology/Algebra/UniformMulAction.lean +++ b/Mathlib/Topology/Algebra/UniformMulAction.lean @@ -99,6 +99,14 @@ theorem UniformContinuous.const_smul [UniformContinuousConstSMul M X] {f : Y → #align uniform_continuous.const_smul UniformContinuous.const_smul #align uniform_continuous.const_vadd UniformContinuous.const_vadd +@[to_additive] +lemma UniformInducing.uniformContinuousConstSMul [SMul M Y] [UniformContinuousConstSMul M Y] + {f : X → Y} (hf : UniformInducing f) (hsmul : ∀ (c : M) x, f (c • x) = c • f x) : + UniformContinuousConstSMul M X where + uniformContinuous_const_smul c := by + simpa only [hf.uniformContinuous_iff, Function.comp_def, hsmul] + using hf.uniformContinuous.const_smul c + /-- 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 diff --git a/Mathlib/Topology/Bases.lean b/Mathlib/Topology/Bases.lean index 552be4211a378..4d64a0a400e79 100644 --- a/Mathlib/Topology/Bases.lean +++ b/Mathlib/Topology/Bases.lean @@ -52,9 +52,6 @@ More fine grained instances for `FirstCountableTopology`, `TopologicalSpace.SeparableSpace`, and more. -/ -set_option autoImplicit true - - open Set Filter Function Topology noncomputable section @@ -63,7 +60,7 @@ namespace TopologicalSpace universe u -variable {α : Type u} [t : TopologicalSpace α] {B : Set (Set α)} {s : Set α} +variable {α : Type u} {β : Type*} [t : TopologicalSpace α] {B : Set (Set α)} {s : Set α} /-- A topological basis is one that satisfies the necessary conditions so that it suffices to take unions of the basis sets to get a topology (without taking @@ -117,7 +114,7 @@ theorem isTopologicalBasis_of_subbasis {s : Set (Set α)} (hs : t = generateFrom · rw [sUnion_image, iUnion₂_eq_univ_iff] exact fun x => ⟨∅, ⟨finite_empty, empty_subset _⟩, sInter_empty.substr <| mem_univ x⟩ · rintro _ ⟨t, ⟨hft, htb⟩, rfl⟩ - exact hft.isOpen_sInter fun s hs ↦ GenerateOpen.basic _ $ htb hs + exact hft.isOpen_sInter fun s hs ↦ GenerateOpen.basic _ <| htb hs · rw [← sInter_singleton t] exact ⟨{t}, ⟨finite_singleton t, singleton_subset_iff.2 ht⟩, rfl⟩ #align topological_space.is_topological_basis_of_subbasis TopologicalSpace.isTopologicalBasis_of_subbasis @@ -215,7 +212,7 @@ lemma IsTopologicalBasis.subset_of_forall_subset {t : Set α} (hB : IsTopologica lemma IsTopologicalBasis.eq_of_forall_subset_iff {t : Set α} (hB : IsTopologicalBasis B) (hs : IsOpen s) (ht : IsOpen t) (h : ∀ U ∈ B, U ⊆ s ↔ U ⊆ t) : s = t := by rw [hB.open_eq_sUnion' hs, hB.open_eq_sUnion' ht] - exact congr_arg _ (Set.ext λ U ↦ and_congr_right $ h _) + exact congr_arg _ (Set.ext λ U ↦ and_congr_right <| h _) /-- A point `a` is in the closure of `s` iff all basis sets containing `a` intersect `s`. -/ theorem IsTopologicalBasis.mem_closure_iff {b : Set (Set α)} (hb : IsTopologicalBasis b) {s : Set α} diff --git a/Mathlib/Topology/Basic.lean b/Mathlib/Topology/Basic.lean index 1fe9cac449c45..9b702e014ce5f 100644 --- a/Mathlib/Topology/Basic.lean +++ b/Mathlib/Topology/Basic.lean @@ -13,14 +13,14 @@ import Mathlib.Tactic.Continuity /-! # Basic theory of topological spaces. -The main definition is the type class `TopologicalSpace α` which endows a type `α` with a topology. -Then `Set α` gets predicates `IsOpen`, `IsClosed` and functions `interior`, `closure` and -`frontier`. Each point `x` of `α` gets a neighborhood filter `𝓝 x`. A filter `F` on `α` has -`x` as a cluster point if `ClusterPt x F : 𝓝 x ⊓ F ≠ ⊥`. A map `f : ι → α` clusters at `x` -along `F : Filter ι` if `MapClusterPt x F f : ClusterPt x (map f F)`. In particular +The main definition is the type class `TopologicalSpace X` which endows a type `X` with a topology. +Then `Set X` gets predicates `IsOpen`, `IsClosed` and functions `interior`, `closure` and +`frontier`. Each point `x` of `X` gets a neighborhood filter `𝓝 x`. A filter `F` on `X` has +`x` as a cluster point if `ClusterPt x F : 𝓝 x ⊓ F ≠ ⊥`. A map `f : α → X` clusters at `x` +along `F : Filter α` if `MapClusterPt x F f : ClusterPt x (map f F)`. In particular the notion of cluster point of a sequence `u` is `MapClusterPt x atTop u`. -For topological spaces `α` and `β`, a function `f : α → β` and a point `a : α`, +For topological spaces `X` and `Y`, a function `f : X → Y` and a point `a : X`, `ContinuousAt f a` means `f` is continuous at `a`, and global continuity is `Continuous f`. There is also a version of continuity `PContinuous` for partially defined functions. @@ -51,25 +51,22 @@ Topology in mathlib heavily uses filters (even more than in Bourbaki). See expla topological space, interior, closure, frontier, neighborhood, continuity, continuous function -/ -set_option autoImplicit true - - noncomputable section open Set Filter -universe u v w +universe u v w x /-! ### Topological spaces -/ -/-- A topology on `α`. -/ +/-- A topology on `X`. -/ @[to_additive existing TopologicalSpace] -class TopologicalSpace (α : Type u) where +class TopologicalSpace (X : Type u) where /-- A predicate saying that a set is an open set. Use `IsOpen` in the root namespace instead. -/ - protected IsOpen : Set α → Prop + protected IsOpen : Set X → Prop /-- The set representing the whole space is an open set. Use `isOpen_univ` in the root namespace instead. -/ protected isOpen_univ : IsOpen univ @@ -82,9 +79,9 @@ class TopologicalSpace (α : Type u) where /-- A constructor for topologies by specifying the closed sets, and showing that they satisfy the appropriate conditions. -/ -def TopologicalSpace.ofClosed {α : Type u} (T : Set (Set α)) (empty_mem : ∅ ∈ T) +def TopologicalSpace.ofClosed {X : Type u} (T : Set (Set X)) (empty_mem : ∅ ∈ T) (sInter_mem : ∀ A, A ⊆ T → ⋂₀ A ∈ T) - (union_mem : ∀ A, A ∈ T → ∀ B, B ∈ T → A ∪ B ∈ T) : TopologicalSpace α where + (union_mem : ∀ A, A ∈ T → ∀ B, B ∈ T → A ∪ B ∈ T) : TopologicalSpace X where IsOpen X := Xᶜ ∈ T isOpen_univ := by simp [empty_mem] isOpen_inter s t hs ht := by simpa only [compl_inter] using union_mem sᶜ hs tᶜ ht @@ -95,10 +92,11 @@ def TopologicalSpace.ofClosed {α : Type u} (T : Set (Set α)) (empty_mem : ∅ section TopologicalSpace -variable {α : Type u} {β : Type v} {ι : Sort w} {a : α} {s s₁ s₂ t : Set α} {p p₁ p₂ : α → Prop} +variable {X : Type u} {Y : Type v} {ι : Sort w} {α β : Type*} + {a : X} {s s₁ s₂ t : Set X} {p p₁ p₂ : X → Prop} -/-- `IsOpen s` means that `s` is open in the ambient topological space on `α` -/ -def IsOpen [TopologicalSpace α] : Set α → Prop := TopologicalSpace.IsOpen +/-- `IsOpen s` means that `s` is open in the ambient topological space on `X` -/ +def IsOpen [TopologicalSpace X] : Set X → Prop := TopologicalSpace.IsOpen #align is_open IsOpen set_option quotPrecheck false in @@ -107,48 +105,48 @@ scoped[Topology] notation (name := IsOpen_of) "IsOpen[" t "]" => @IsOpen _ t open Topology -lemma isOpen_mk {p h₁ h₂ h₃} {s : Set α} : IsOpen[⟨p, h₁, h₂, h₃⟩] s ↔ p s := Iff.rfl +lemma isOpen_mk {p h₁ h₂ h₃} {s : Set X} : IsOpen[⟨p, h₁, h₂, h₃⟩] s ↔ p s := Iff.rfl #align is_open_mk isOpen_mk @[ext] protected theorem TopologicalSpace.ext : - ∀ {f g : TopologicalSpace α}, IsOpen[f] = IsOpen[g] → f = g + ∀ {f g : TopologicalSpace X}, IsOpen[f] = IsOpen[g] → f = g | ⟨_, _, _, _⟩, ⟨_, _, _, _⟩, rfl => rfl #align topological_space_eq TopologicalSpace.ext section -variable [TopologicalSpace α] +variable [TopologicalSpace X] -@[simp] theorem isOpen_univ : IsOpen (univ : Set α) := TopologicalSpace.isOpen_univ +@[simp] theorem isOpen_univ : IsOpen (univ : Set X) := TopologicalSpace.isOpen_univ #align is_open_univ isOpen_univ theorem IsOpen.inter (h₁ : IsOpen s₁) (h₂ : IsOpen s₂) : IsOpen (s₁ ∩ s₂) := TopologicalSpace.isOpen_inter s₁ s₂ h₁ h₂ #align is_open.inter IsOpen.inter -theorem isOpen_sUnion {s : Set (Set α)} (h : ∀ t ∈ s, IsOpen t) : IsOpen (⋃₀ s) := +theorem isOpen_sUnion {s : Set (Set X)} (h : ∀ t ∈ s, IsOpen t) : IsOpen (⋃₀ s) := TopologicalSpace.isOpen_sUnion s h #align is_open_sUnion isOpen_sUnion end -protected theorem TopologicalSpace.ext_iff {t t' : TopologicalSpace α} : +protected theorem TopologicalSpace.ext_iff {t t' : TopologicalSpace X} : t = t' ↔ ∀ s, IsOpen[t] s ↔ IsOpen[t'] s := ⟨fun h s => h ▸ Iff.rfl, fun h => by ext; exact h _⟩ #align topological_space_eq_iff TopologicalSpace.ext_iff -theorem isOpen_fold {s : Set α} {t : TopologicalSpace α} : t.IsOpen s = IsOpen[t] s := +theorem isOpen_fold {s : Set X} {t : TopologicalSpace X} : t.IsOpen s = IsOpen[t] s := rfl #align is_open_fold isOpen_fold -variable [TopologicalSpace α] +variable [TopologicalSpace X] -theorem isOpen_iUnion {f : ι → Set α} (h : ∀ i, IsOpen (f i)) : IsOpen (⋃ i, f i) := +theorem isOpen_iUnion {f : ι → Set X} (h : ∀ i, IsOpen (f i)) : IsOpen (⋃ i, f i) := isOpen_sUnion (forall_range_iff.2 h) #align is_open_Union isOpen_iUnion -theorem isOpen_biUnion {s : Set β} {f : β → Set α} (h : ∀ i ∈ s, IsOpen (f i)) : +theorem isOpen_biUnion {s : Set α} {f : α → Set X} (h : ∀ i ∈ s, IsOpen (f i)) : IsOpen (⋃ i ∈ s, f i) := isOpen_iUnion fun i => isOpen_iUnion fun hi => h i hi #align is_open_bUnion isOpen_biUnion @@ -157,35 +155,41 @@ theorem IsOpen.union (h₁ : IsOpen s₁) (h₂ : IsOpen s₂) : IsOpen (s₁ rw [union_eq_iUnion]; exact isOpen_iUnion (Bool.forall_bool.2 ⟨h₂, h₁⟩) #align is_open.union IsOpen.union -@[simp] theorem isOpen_empty : IsOpen (∅ : Set α) := by +lemma isOpen_iff_of_cover {f : α → Set X} (ho : ∀ i, IsOpen (f i)) (hU : (⋃ i, f i) = univ) : + IsOpen s ↔ ∀ i, IsOpen (f i ∩ s) := by + refine ⟨fun h i ↦ (ho i).inter h, fun h ↦ ?_⟩ + rw [← s.inter_univ, inter_comm, ← hU, iUnion_inter] + exact isOpen_iUnion fun i ↦ h i + +@[simp] theorem isOpen_empty : IsOpen (∅ : Set X) := by rw [← sUnion_empty]; exact isOpen_sUnion fun a => False.elim #align is_open_empty isOpen_empty -theorem Set.Finite.isOpen_sInter {s : Set (Set α)} (hs : s.Finite) : +theorem Set.Finite.isOpen_sInter {s : Set (Set X)} (hs : s.Finite) : (∀ t ∈ s, IsOpen t) → IsOpen (⋂₀ s) := Finite.induction_on hs (fun _ => by rw [sInter_empty]; exact isOpen_univ) fun _ _ ih h => by simp only [sInter_insert, ball_insert_iff] at h ⊢ exact h.1.inter (ih h.2) #align is_open_sInter Set.Finite.isOpen_sInter -theorem Set.Finite.isOpen_biInter {s : Set β} {f : β → Set α} (hs : s.Finite) +theorem Set.Finite.isOpen_biInter {s : Set α} {f : α → Set X} (hs : s.Finite) (h : ∀ i ∈ s, IsOpen (f i)) : IsOpen (⋂ i ∈ s, f i) := sInter_image f s ▸ (hs.image _).isOpen_sInter (ball_image_iff.2 h) #align is_open_bInter Set.Finite.isOpen_biInter -theorem isOpen_iInter_of_finite [Finite ι] {s : ι → Set α} (h : ∀ i, IsOpen (s i)) : +theorem isOpen_iInter_of_finite [Finite ι] {s : ι → Set X} (h : ∀ i, IsOpen (s i)) : IsOpen (⋂ i, s i) := (finite_range _).isOpen_sInter (forall_range_iff.2 h) #align is_open_Inter isOpen_iInter_of_finite -theorem isOpen_biInter_finset {s : Finset β} {f : β → Set α} (h : ∀ i ∈ s, IsOpen (f i)) : +theorem isOpen_biInter_finset {s : Finset α} {f : α → Set X} (h : ∀ i ∈ s, IsOpen (f i)) : IsOpen (⋂ i ∈ s, f i) := s.finite_toSet.isOpen_biInter h #align is_open_bInter_finset isOpen_biInter_finset @[simp] -- porting note: added `simp` -theorem isOpen_const {p : Prop} : IsOpen { _a : α | p } := by by_cases p <;> simp [*] +theorem isOpen_const {p : Prop} : IsOpen { _a : X | p } := by by_cases p <;> simp [*] #align is_open_const isOpen_const theorem IsOpen.and : IsOpen { a | p₁ a } → IsOpen { a | p₂ a } → IsOpen { a | p₁ a ∧ p₂ a } := @@ -193,7 +197,7 @@ theorem IsOpen.and : IsOpen { a | p₁ a } → IsOpen { a | p₂ a } → IsOpen #align is_open.and IsOpen.and /-- A set is closed if its complement is open -/ -class IsClosed (s : Set α) : Prop where +class IsClosed (s : Set X) : Prop where /-- The complement of a closed set is an open set. -/ isOpen_compl : IsOpen sᶜ #align is_closed IsClosed @@ -202,45 +206,45 @@ set_option quotPrecheck false in /-- Notation for `IsClosed` with respect to a non-standard topology. -/ scoped[Topology] notation (name := IsClosed_of) "IsClosed[" t "]" => @IsClosed _ t -@[simp] theorem isOpen_compl_iff {s : Set α} : IsOpen sᶜ ↔ IsClosed s := +@[simp] theorem isOpen_compl_iff {s : Set X} : IsOpen sᶜ ↔ IsClosed s := ⟨fun h => ⟨h⟩, fun h => h.isOpen_compl⟩ #align is_open_compl_iff isOpen_compl_iff -- porting note: new lemma -theorem isClosed_const {p : Prop} : IsClosed { _a : α | p } := ⟨isOpen_const (p := ¬p)⟩ +theorem isClosed_const {p : Prop} : IsClosed { _a : X | p } := ⟨isOpen_const (p := ¬p)⟩ -@[simp] theorem isClosed_empty : IsClosed (∅ : Set α) := isClosed_const +@[simp] theorem isClosed_empty : IsClosed (∅ : Set X) := isClosed_const #align is_closed_empty isClosed_empty -@[simp] theorem isClosed_univ : IsClosed (univ : Set α) := isClosed_const +@[simp] theorem isClosed_univ : IsClosed (univ : Set X) := isClosed_const #align is_closed_univ isClosed_univ theorem IsClosed.union : IsClosed s₁ → IsClosed s₂ → IsClosed (s₁ ∪ s₂) := by simpa only [← isOpen_compl_iff, compl_union] using IsOpen.inter #align is_closed.union IsClosed.union -theorem isClosed_sInter {s : Set (Set α)} : (∀ t ∈ s, IsClosed t) → IsClosed (⋂₀ s) := by +theorem isClosed_sInter {s : Set (Set X)} : (∀ t ∈ s, IsClosed t) → IsClosed (⋂₀ s) := by simpa only [← isOpen_compl_iff, compl_sInter, sUnion_image] using isOpen_biUnion #align is_closed_sInter isClosed_sInter -theorem isClosed_iInter {f : ι → Set α} (h : ∀ i, IsClosed (f i)) : IsClosed (⋂ i, f i) := +theorem isClosed_iInter {f : ι → Set X} (h : ∀ i, IsClosed (f i)) : IsClosed (⋂ i, f i) := isClosed_sInter <| forall_range_iff.2 h #align is_closed_Inter isClosed_iInter -theorem isClosed_biInter {s : Set β} {f : β → Set α} (h : ∀ i ∈ s, IsClosed (f i)) : +theorem isClosed_biInter {s : Set α} {f : α → Set X} (h : ∀ i ∈ s, IsClosed (f i)) : IsClosed (⋂ i ∈ s, f i) := isClosed_iInter fun i => isClosed_iInter <| h i #align is_closed_bInter isClosed_biInter @[simp] -theorem isClosed_compl_iff {s : Set α} : IsClosed sᶜ ↔ IsOpen s := by +theorem isClosed_compl_iff {s : Set X} : IsClosed sᶜ ↔ IsOpen s := by rw [← isOpen_compl_iff, compl_compl] #align is_closed_compl_iff isClosed_compl_iff alias ⟨_, IsOpen.isClosed_compl⟩ := isClosed_compl_iff #align is_open.is_closed_compl IsOpen.isClosed_compl -theorem IsOpen.sdiff {s t : Set α} (h₁ : IsOpen s) (h₂ : IsClosed t) : IsOpen (s \ t) := +theorem IsOpen.sdiff {s t : Set X} (h₁ : IsOpen s) (h₂ : IsClosed t) : IsOpen (s \ t) := IsOpen.inter h₁ h₂.isOpen_compl #align is_open.sdiff IsOpen.sdiff @@ -250,28 +254,28 @@ theorem IsClosed.inter (h₁ : IsClosed s₁) (h₂ : IsClosed s₂) : IsClosed exact IsOpen.union h₁ h₂ #align is_closed.inter IsClosed.inter -theorem IsClosed.sdiff {s t : Set α} (h₁ : IsClosed s) (h₂ : IsOpen t) : IsClosed (s \ t) := +theorem IsClosed.sdiff {s t : Set X} (h₁ : IsClosed s) (h₂ : IsOpen t) : IsClosed (s \ t) := IsClosed.inter h₁ (isClosed_compl_iff.mpr h₂) #align is_closed.sdiff IsClosed.sdiff -theorem Set.Finite.isClosed_biUnion {s : Set β} {f : β → Set α} (hs : s.Finite) +theorem Set.Finite.isClosed_biUnion {s : Set α} {f : α → Set X} (hs : s.Finite) (h : ∀ i ∈ s, IsClosed (f i)) : IsClosed (⋃ i ∈ s, f i) := by simp only [← isOpen_compl_iff, compl_iUnion] at * exact hs.isOpen_biInter h #align is_closed_bUnion Set.Finite.isClosed_biUnion -lemma isClosed_biUnion_finset {s : Finset β} {f : β → Set α} (h : ∀ i ∈ s, IsClosed (f i)) : +lemma isClosed_biUnion_finset {s : Finset α} {f : α → Set X} (h : ∀ i ∈ s, IsClosed (f i)) : IsClosed (⋃ i ∈ s, f i) := s.finite_toSet.isClosed_biUnion h -theorem isClosed_iUnion_of_finite [Finite ι] {s : ι → Set α} (h : ∀ i, IsClosed (s i)) : +theorem isClosed_iUnion_of_finite [Finite ι] {s : ι → Set X} (h : ∀ i, IsClosed (s i)) : IsClosed (⋃ i, s i) := by simp only [← isOpen_compl_iff, compl_iUnion] at * exact isOpen_iInter_of_finite h #align is_closed_Union isClosed_iUnion_of_finite -theorem isClosed_imp {p q : α → Prop} (hp : IsOpen { x | p x }) (hq : IsClosed { x | q x }) : +theorem isClosed_imp {p q : X → Prop} (hp : IsOpen { x | p x }) (hq : IsClosed { x | q x }) : IsClosed { x | p x → q x } := by simpa only [imp_iff_not_or] using hp.isClosed_compl.union hq #align is_closed_imp isClosed_imp @@ -285,45 +289,45 @@ theorem IsClosed.not : IsClosed { a | p a } → IsOpen { a | ¬p a } := -/ /-- The interior of a set `s` is the largest open subset of `s`. -/ -def interior (s : Set α) : Set α := +def interior (s : Set X) : Set X := ⋃₀ { t | IsOpen t ∧ t ⊆ s } #align interior interior -- porting note: use `∃ t, t ⊆ s ∧ _` instead of `∃ t ⊆ s, _` -theorem mem_interior {s : Set α} {x : α} : x ∈ interior s ↔ ∃ t, t ⊆ s ∧ IsOpen t ∧ x ∈ t := by +theorem mem_interior {s : Set X} {x : X} : x ∈ interior s ↔ ∃ t, t ⊆ s ∧ IsOpen t ∧ x ∈ t := by simp only [interior, mem_sUnion, mem_setOf_eq, and_assoc, and_left_comm] #align mem_interior mem_interiorₓ @[simp] -theorem isOpen_interior {s : Set α} : IsOpen (interior s) := +theorem isOpen_interior {s : Set X} : IsOpen (interior s) := isOpen_sUnion fun _ => And.left #align is_open_interior isOpen_interior -theorem interior_subset {s : Set α} : interior s ⊆ s := +theorem interior_subset {s : Set X} : interior s ⊆ s := sUnion_subset fun _ => And.right #align interior_subset interior_subset -theorem interior_maximal {s t : Set α} (h₁ : t ⊆ s) (h₂ : IsOpen t) : t ⊆ interior s := +theorem interior_maximal {s t : Set X} (h₁ : t ⊆ s) (h₂ : IsOpen t) : t ⊆ interior s := subset_sUnion_of_mem ⟨h₂, h₁⟩ #align interior_maximal interior_maximal -theorem IsOpen.interior_eq {s : Set α} (h : IsOpen s) : interior s = s := +theorem IsOpen.interior_eq {s : Set X} (h : IsOpen s) : interior s = s := interior_subset.antisymm (interior_maximal (Subset.refl s) h) #align is_open.interior_eq IsOpen.interior_eq -theorem interior_eq_iff_isOpen {s : Set α} : interior s = s ↔ IsOpen s := +theorem interior_eq_iff_isOpen {s : Set X} : interior s = s ↔ IsOpen s := ⟨fun h => h ▸ isOpen_interior, IsOpen.interior_eq⟩ #align interior_eq_iff_is_open interior_eq_iff_isOpen -theorem subset_interior_iff_isOpen {s : Set α} : s ⊆ interior s ↔ IsOpen s := by +theorem subset_interior_iff_isOpen {s : Set X} : s ⊆ interior s ↔ IsOpen s := by simp only [interior_eq_iff_isOpen.symm, Subset.antisymm_iff, interior_subset, true_and] #align subset_interior_iff_is_open subset_interior_iff_isOpen -theorem IsOpen.subset_interior_iff {s t : Set α} (h₁ : IsOpen s) : s ⊆ interior t ↔ s ⊆ t := +theorem IsOpen.subset_interior_iff {s t : Set X} (h₁ : IsOpen s) : s ⊆ interior t ↔ s ⊆ t := ⟨fun h => Subset.trans h interior_subset, fun h₂ => interior_maximal h₂ h₁⟩ #align is_open.subset_interior_iff IsOpen.subset_interior_iff -theorem subset_interior_iff {s t : Set α} : t ⊆ interior s ↔ ∃ U, IsOpen U ∧ t ⊆ U ∧ U ⊆ s := +theorem subset_interior_iff {s t : Set X} : t ⊆ interior s ↔ ∃ U, IsOpen U ∧ t ⊆ U ∧ U ⊆ s := ⟨fun h => ⟨interior s, isOpen_interior, h, interior_subset⟩, fun ⟨_U, hU, htU, hUs⟩ => htU.trans (interior_maximal hUs hU)⟩ #align subset_interior_iff subset_interior_iff @@ -332,57 +336,58 @@ lemma interior_subset_iff : interior s ⊆ t ↔ ∀ U, IsOpen U → U ⊆ s → simp [interior] @[mono] -theorem interior_mono {s t : Set α} (h : s ⊆ t) : interior s ⊆ interior t := +theorem interior_mono {s t : Set X} (h : s ⊆ t) : interior s ⊆ interior t := interior_maximal (Subset.trans interior_subset h) isOpen_interior #align interior_mono interior_mono @[simp] -theorem interior_empty : interior (∅ : Set α) = ∅ := +theorem interior_empty : interior (∅ : Set X) = ∅ := isOpen_empty.interior_eq #align interior_empty interior_empty @[simp] -theorem interior_univ : interior (univ : Set α) = univ := +theorem interior_univ : interior (univ : Set X) = univ := isOpen_univ.interior_eq #align interior_univ interior_univ @[simp] -theorem interior_eq_univ {s : Set α} : interior s = univ ↔ s = univ := +theorem interior_eq_univ {s : Set X} : interior s = univ ↔ s = univ := ⟨fun h => univ_subset_iff.mp <| h.symm.trans_le interior_subset, fun h => h.symm ▸ interior_univ⟩ #align interior_eq_univ interior_eq_univ @[simp] -theorem interior_interior {s : Set α} : interior (interior s) = interior s := +theorem interior_interior {s : Set X} : interior (interior s) = interior s := isOpen_interior.interior_eq #align interior_interior interior_interior @[simp] -theorem interior_inter {s t : Set α} : interior (s ∩ t) = interior s ∩ interior t := - Subset.antisymm - (subset_inter (interior_mono <| inter_subset_left s t) - (interior_mono <| inter_subset_right s t)) - (interior_maximal (inter_subset_inter interior_subset interior_subset) <| - IsOpen.inter isOpen_interior isOpen_interior) +theorem interior_inter {s t : Set X} : interior (s ∩ t) = interior s ∩ interior t := + (Monotone.map_inf_le (fun _ _ ↦ interior_mono) s t).antisymm <| + interior_maximal (inter_subset_inter interior_subset interior_subset) <| + isOpen_interior.inter isOpen_interior #align interior_inter interior_inter +theorem Set.Finite.interior_biInter {ι : Type*} {s : Set ι} (hs : s.Finite) (f : ι → Set X) : + interior (⋂ i ∈ s, f i) = ⋂ i ∈ s, interior (f i) := + hs.induction_on (by simp) <| by intros; simp [*] + +theorem Set.Finite.interior_sInter {S : Set (Set X)} (hS : S.Finite) : + interior (⋂₀ S) = ⋂ s ∈ S, interior s := by + rw [sInter_eq_biInter, hS.interior_biInter] + @[simp] -theorem Finset.interior_iInter {ι : Type*} (s : Finset ι) (f : ι → Set α) : - interior (⋂ i ∈ s, f i) = ⋂ i ∈ s, interior (f i) := by - classical - refine' s.induction_on (by simp) _ - intro i s _ h₂ - simp [h₂] +theorem Finset.interior_iInter {ι : Type*} (s : Finset ι) (f : ι → Set X) : + interior (⋂ i ∈ s, f i) = ⋂ i ∈ s, interior (f i) := + s.finite_toSet.interior_biInter f #align finset.interior_Inter Finset.interior_iInter --- todo: generalize to `ι : Sort*` @[simp] -theorem interior_iInter_of_finite {ι : Type*} [Finite ι] (f : ι → Set α) : +theorem interior_iInter_of_finite [Finite ι] (f : ι → Set X) : interior (⋂ i, f i) = ⋂ i, interior (f i) := by - cases nonempty_fintype ι - convert Finset.univ.interior_iInter f <;> simp + rw [← sInter_range, (finite_range f).interior_sInter, biInter_range] #align interior_Inter interior_iInter_of_finite -theorem interior_union_isClosed_of_interior_empty {s t : Set α} (h₁ : IsClosed s) +theorem interior_union_isClosed_of_interior_empty {s t : Set X} (h₁ : IsClosed s) (h₂ : interior t = ∅) : interior (s ∪ t) = interior s := have : interior (s ∪ t) ⊆ s := fun x ⟨u, ⟨(hu₁ : IsOpen u), (hu₂ : u ⊆ s ∪ t)⟩, (hx₁ : x ∈ u)⟩ => by_contradiction fun hx₂ : x ∉ s => @@ -398,16 +403,16 @@ theorem isOpen_iff_forall_mem_open : IsOpen s ↔ ∀ x ∈ s, ∃ t, t ⊆ s simp only [subset_def, mem_interior] #align is_open_iff_forall_mem_open isOpen_iff_forall_mem_open -theorem interior_iInter_subset (s : ι → Set α) : interior (⋂ i, s i) ⊆ ⋂ i, interior (s i) := +theorem interior_iInter_subset (s : ι → Set X) : interior (⋂ i, s i) ⊆ ⋂ i, interior (s i) := subset_iInter fun _ => interior_mono <| iInter_subset _ _ #align interior_Inter_subset interior_iInter_subset -theorem interior_iInter₂_subset (p : ι → Sort*) (s : ∀ i, p i → Set α) : +theorem interior_iInter₂_subset (p : ι → Sort*) (s : ∀ i, p i → Set X) : interior (⋂ (i) (j), s i j) ⊆ ⋂ (i) (j), interior (s i j) := (interior_iInter_subset _).trans <| iInter_mono fun _ => interior_iInter_subset _ #align interior_Inter₂_subset interior_iInter₂_subset -theorem interior_sInter_subset (S : Set (Set α)) : interior (⋂₀ S) ⊆ ⋂ s ∈ S, interior s := +theorem interior_sInter_subset (S : Set (Set X)) : interior (⋂₀ S) ⊆ ⋂ s ∈ S, interior s := calc interior (⋂₀ S) = interior (⋂ s ∈ S, s) := by rw [sInter_eq_biInter] _ ⊆ ⋂ s ∈ S, interior s := interior_iInter₂_subset _ _ @@ -419,7 +424,7 @@ theorem interior_sInter_subset (S : Set (Set α)) : interior (⋂₀ S) ⊆ ⋂ /-- The closure of `s` is the smallest closed set containing `s`. -/ -def closure (s : Set α) : Set α := +def closure (s : Set X) : Set X := ⋂₀ { t | IsClosed t ∧ s ⊆ t } #align closure closure @@ -428,91 +433,91 @@ set_option quotPrecheck false in scoped[Topology] notation (name := closure_of) "closure[" t "]" => @closure _ t @[simp] -theorem isClosed_closure {s : Set α} : IsClosed (closure s) := +theorem isClosed_closure {s : Set X} : IsClosed (closure s) := isClosed_sInter fun _ => And.left #align is_closed_closure isClosed_closure -theorem subset_closure {s : Set α} : s ⊆ closure s := +theorem subset_closure {s : Set X} : s ⊆ closure s := subset_sInter fun _ => And.right #align subset_closure subset_closure -theorem not_mem_of_not_mem_closure {s : Set α} {P : α} (hP : P ∉ closure s) : P ∉ s := fun h => +theorem not_mem_of_not_mem_closure {s : Set X} {P : X} (hP : P ∉ closure s) : P ∉ s := fun h => hP (subset_closure h) #align not_mem_of_not_mem_closure not_mem_of_not_mem_closure -theorem closure_minimal {s t : Set α} (h₁ : s ⊆ t) (h₂ : IsClosed t) : closure s ⊆ t := +theorem closure_minimal {s t : Set X} (h₁ : s ⊆ t) (h₂ : IsClosed t) : closure s ⊆ t := sInter_subset_of_mem ⟨h₂, h₁⟩ #align closure_minimal closure_minimal -theorem Disjoint.closure_left {s t : Set α} (hd : Disjoint s t) (ht : IsOpen t) : +theorem Disjoint.closure_left {s t : Set X} (hd : Disjoint s t) (ht : IsOpen t) : Disjoint (closure s) t := disjoint_compl_left.mono_left <| closure_minimal hd.subset_compl_right ht.isClosed_compl #align disjoint.closure_left Disjoint.closure_left -theorem Disjoint.closure_right {s t : Set α} (hd : Disjoint s t) (hs : IsOpen s) : +theorem Disjoint.closure_right {s t : Set X} (hd : Disjoint s t) (hs : IsOpen s) : Disjoint s (closure t) := (hd.symm.closure_left hs).symm #align disjoint.closure_right Disjoint.closure_right -theorem IsClosed.closure_eq {s : Set α} (h : IsClosed s) : closure s = s := +theorem IsClosed.closure_eq {s : Set X} (h : IsClosed s) : closure s = s := Subset.antisymm (closure_minimal (Subset.refl s) h) subset_closure #align is_closed.closure_eq IsClosed.closure_eq -theorem IsClosed.closure_subset {s : Set α} (hs : IsClosed s) : closure s ⊆ s := +theorem IsClosed.closure_subset {s : Set X} (hs : IsClosed s) : closure s ⊆ s := closure_minimal (Subset.refl _) hs #align is_closed.closure_subset IsClosed.closure_subset -theorem IsClosed.closure_subset_iff {s t : Set α} (h₁ : IsClosed t) : closure s ⊆ t ↔ s ⊆ t := +theorem IsClosed.closure_subset_iff {s t : Set X} (h₁ : IsClosed t) : closure s ⊆ t ↔ s ⊆ t := ⟨Subset.trans subset_closure, fun h => closure_minimal h h₁⟩ #align is_closed.closure_subset_iff IsClosed.closure_subset_iff -theorem IsClosed.mem_iff_closure_subset {s : Set α} (hs : IsClosed s) {x : α} : - x ∈ s ↔ closure ({x} : Set α) ⊆ s := +theorem IsClosed.mem_iff_closure_subset {s : Set X} (hs : IsClosed s) {x : X} : + x ∈ s ↔ closure ({x} : Set X) ⊆ s := (hs.closure_subset_iff.trans Set.singleton_subset_iff).symm #align is_closed.mem_iff_closure_subset IsClosed.mem_iff_closure_subset @[mono] -theorem closure_mono {s t : Set α} (h : s ⊆ t) : closure s ⊆ closure t := +theorem closure_mono {s t : Set X} (h : s ⊆ t) : closure s ⊆ closure t := closure_minimal (Subset.trans h subset_closure) isClosed_closure #align closure_mono closure_mono -theorem monotone_closure (α : Type*) [TopologicalSpace α] : Monotone (@closure α _) := fun _ _ => +theorem monotone_closure (X : Type*) [TopologicalSpace X] : Monotone (@closure X _) := fun _ _ => closure_mono #align monotone_closure monotone_closure -theorem diff_subset_closure_iff {s t : Set α} : s \ t ⊆ closure t ↔ s ⊆ closure t := by +theorem diff_subset_closure_iff {s t : Set X} : s \ t ⊆ closure t ↔ s ⊆ closure t := by rw [diff_subset_iff, union_eq_self_of_subset_left subset_closure] #align diff_subset_closure_iff diff_subset_closure_iff -theorem closure_inter_subset_inter_closure (s t : Set α) : +theorem closure_inter_subset_inter_closure (s t : Set X) : closure (s ∩ t) ⊆ closure s ∩ closure t := - (monotone_closure α).map_inf_le s t + (monotone_closure X).map_inf_le s t #align closure_inter_subset_inter_closure closure_inter_subset_inter_closure -theorem isClosed_of_closure_subset {s : Set α} (h : closure s ⊆ s) : IsClosed s := by +theorem isClosed_of_closure_subset {s : Set X} (h : closure s ⊆ s) : IsClosed s := by rw [subset_closure.antisymm h]; exact isClosed_closure #align is_closed_of_closure_subset isClosed_of_closure_subset -theorem closure_eq_iff_isClosed {s : Set α} : closure s = s ↔ IsClosed s := +theorem closure_eq_iff_isClosed {s : Set X} : closure s = s ↔ IsClosed s := ⟨fun h => h ▸ isClosed_closure, IsClosed.closure_eq⟩ #align closure_eq_iff_is_closed closure_eq_iff_isClosed -theorem closure_subset_iff_isClosed {s : Set α} : closure s ⊆ s ↔ IsClosed s := +theorem closure_subset_iff_isClosed {s : Set X} : closure s ⊆ s ↔ IsClosed s := ⟨isClosed_of_closure_subset, IsClosed.closure_subset⟩ #align closure_subset_iff_is_closed closure_subset_iff_isClosed @[simp] -theorem closure_empty : closure (∅ : Set α) = ∅ := +theorem closure_empty : closure (∅ : Set X) = ∅ := isClosed_empty.closure_eq #align closure_empty closure_empty @[simp] -theorem closure_empty_iff (s : Set α) : closure s = ∅ ↔ s = ∅ := +theorem closure_empty_iff (s : Set X) : closure s = ∅ ↔ s = ∅ := ⟨subset_eq_empty subset_closure, fun h => h.symm ▸ closure_empty⟩ #align closure_empty_iff closure_empty_iff @[simp] -theorem closure_nonempty_iff {s : Set α} : (closure s).Nonempty ↔ s.Nonempty := by +theorem closure_nonempty_iff {s : Set X} : (closure s).Nonempty ↔ s.Nonempty := by simp only [nonempty_iff_ne_empty, Ne.def, closure_empty_iff] #align closure_nonempty_iff closure_nonempty_iff @@ -521,59 +526,60 @@ alias ⟨Set.Nonempty.of_closure, Set.Nonempty.closure⟩ := closure_nonempty_if #align set.nonempty.closure Set.Nonempty.closure @[simp] -theorem closure_univ : closure (univ : Set α) = univ := +theorem closure_univ : closure (univ : Set X) = univ := isClosed_univ.closure_eq #align closure_univ closure_univ @[simp] -theorem closure_closure {s : Set α} : closure (closure s) = closure s := +theorem closure_closure {s : Set X} : closure (closure s) = closure s := isClosed_closure.closure_eq #align closure_closure closure_closure +theorem closure_eq_compl_interior_compl {s : Set X} : closure s = (interior sᶜ)ᶜ := by + rw [interior, closure, compl_sUnion, compl_image_set_of] + simp only [compl_subset_compl, isOpen_compl_iff] +#align closure_eq_compl_interior_compl closure_eq_compl_interior_compl + @[simp] -theorem closure_union {s t : Set α} : closure (s ∪ t) = closure s ∪ closure t := - Subset.antisymm - (closure_minimal (union_subset_union subset_closure subset_closure) <| - IsClosed.union isClosed_closure isClosed_closure) - ((monotone_closure α).le_map_sup s t) +theorem closure_union {s t : Set X} : closure (s ∪ t) = closure s ∪ closure t := by + simp [closure_eq_compl_interior_compl, compl_inter] #align closure_union closure_union -@[simp] -theorem Finset.closure_biUnion {ι : Type*} (s : Finset ι) (f : ι → Set α) : +theorem Set.Finite.closure_biUnion {ι : Type*} {s : Set ι} (hs : s.Finite) (f : ι → Set X) : closure (⋃ i ∈ s, f i) = ⋃ i ∈ s, closure (f i) := by - classical - refine' s.induction_on (by simp) _ - intro i s _ h₂ - simp [h₂] + simp [closure_eq_compl_interior_compl, hs.interior_biInter] + +theorem Set.Finite.closure_sUnion {S : Set (Set X)} (hS : S.Finite) : + closure (⋃₀ S) = ⋃ s ∈ S, closure s := by + rw [sUnion_eq_biUnion, hS.closure_biUnion] + +@[simp] +theorem Finset.closure_biUnion {ι : Type*} (s : Finset ι) (f : ι → Set X) : + closure (⋃ i ∈ s, f i) = ⋃ i ∈ s, closure (f i) := + s.finite_toSet.closure_biUnion f #align finset.closure_bUnion Finset.closure_biUnion @[simp] -theorem closure_iUnion_of_finite {ι : Type*} [Finite ι] (f : ι → Set α) : +theorem closure_iUnion_of_finite [Finite ι] (f : ι → Set X) : closure (⋃ i, f i) = ⋃ i, closure (f i) := by - cases nonempty_fintype ι - convert Finset.univ.closure_biUnion f <;> simp + rw [← sUnion_range, (finite_range _).closure_sUnion, biUnion_range] #align closure_Union closure_iUnion_of_finite -theorem interior_subset_closure {s : Set α} : interior s ⊆ closure s := +theorem interior_subset_closure {s : Set X} : interior s ⊆ closure s := Subset.trans interior_subset subset_closure #align interior_subset_closure interior_subset_closure -theorem closure_eq_compl_interior_compl {s : Set α} : closure s = (interior sᶜ)ᶜ := by - rw [interior, closure, compl_sUnion, compl_image_set_of] - simp only [compl_subset_compl, isOpen_compl_iff] -#align closure_eq_compl_interior_compl closure_eq_compl_interior_compl - @[simp] -theorem interior_compl {s : Set α} : interior sᶜ = (closure s)ᶜ := by +theorem interior_compl {s : Set X} : interior sᶜ = (closure s)ᶜ := by simp [closure_eq_compl_interior_compl] #align interior_compl interior_compl @[simp] -theorem closure_compl {s : Set α} : closure sᶜ = (interior s)ᶜ := by +theorem closure_compl {s : Set X} : closure sᶜ = (interior s)ᶜ := by simp [closure_eq_compl_interior_compl] #align closure_compl closure_compl -theorem mem_closure_iff {s : Set α} {a : α} : +theorem mem_closure_iff {s : Set X} {a : X} : a ∈ closure s ↔ ∀ o, IsOpen o → a ∈ o → (o ∩ s).Nonempty := ⟨fun h o oo ao => by_contradiction fun os => @@ -585,56 +591,56 @@ theorem mem_closure_iff {s : Set α} {a : α} : hc (h₂ hs)⟩ #align mem_closure_iff mem_closure_iff -theorem closure_inter_open_nonempty_iff {s t : Set α} (h : IsOpen t) : +theorem closure_inter_open_nonempty_iff {s t : Set X} (h : IsOpen t) : (closure s ∩ t).Nonempty ↔ (s ∩ t).Nonempty := ⟨fun ⟨_x, hxcs, hxt⟩ => inter_comm t s ▸ mem_closure_iff.1 hxcs t h hxt, fun h => h.mono <| inf_le_inf_right t subset_closure⟩ #align closure_inter_open_nonempty_iff closure_inter_open_nonempty_iff -theorem Filter.le_lift'_closure (l : Filter α) : l ≤ l.lift' closure := +theorem Filter.le_lift'_closure (l : Filter X) : l ≤ l.lift' closure := le_lift'.2 fun _ h => mem_of_superset h subset_closure #align filter.le_lift'_closure Filter.le_lift'_closure -theorem Filter.HasBasis.lift'_closure {l : Filter α} {p : ι → Prop} {s : ι → Set α} +theorem Filter.HasBasis.lift'_closure {l : Filter X} {p : ι → Prop} {s : ι → Set X} (h : l.HasBasis p s) : (l.lift' closure).HasBasis p fun i => closure (s i) := - h.lift' (monotone_closure α) + h.lift' (monotone_closure X) #align filter.has_basis.lift'_closure Filter.HasBasis.lift'_closure -theorem Filter.HasBasis.lift'_closure_eq_self {l : Filter α} {p : ι → Prop} {s : ι → Set α} +theorem Filter.HasBasis.lift'_closure_eq_self {l : Filter X} {p : ι → Prop} {s : ι → Set X} (h : l.HasBasis p s) (hc : ∀ i, p i → IsClosed (s i)) : l.lift' closure = l := le_antisymm (h.ge_iff.2 fun i hi => (hc i hi).closure_eq ▸ mem_lift' (h.mem_of_mem hi)) l.le_lift'_closure #align filter.has_basis.lift'_closure_eq_self Filter.HasBasis.lift'_closure_eq_self @[simp] -theorem Filter.lift'_closure_eq_bot {l : Filter α} : l.lift' closure = ⊥ ↔ l = ⊥ := +theorem Filter.lift'_closure_eq_bot {l : Filter X} : l.lift' closure = ⊥ ↔ l = ⊥ := ⟨fun h => bot_unique <| h ▸ l.le_lift'_closure, fun h => h.symm ▸ by rw [lift'_bot (monotone_closure _), closure_empty, principal_empty]⟩ #align filter.lift'_closure_eq_bot Filter.lift'_closure_eq_bot /-- A set is dense in a topological space if every point belongs to its closure. -/ -def Dense (s : Set α) : Prop := +def Dense (s : Set X) : Prop := ∀ x, x ∈ closure s #align dense Dense -theorem dense_iff_closure_eq {s : Set α} : Dense s ↔ closure s = univ := +theorem dense_iff_closure_eq {s : Set X} : Dense s ↔ closure s = univ := eq_univ_iff_forall.symm #align dense_iff_closure_eq dense_iff_closure_eq alias ⟨Dense.closure_eq, _⟩ := dense_iff_closure_eq #align dense.closure_eq Dense.closure_eq -theorem interior_eq_empty_iff_dense_compl {s : Set α} : interior s = ∅ ↔ Dense sᶜ := by +theorem interior_eq_empty_iff_dense_compl {s : Set X} : interior s = ∅ ↔ Dense sᶜ := by rw [dense_iff_closure_eq, closure_compl, compl_univ_iff] #align interior_eq_empty_iff_dense_compl interior_eq_empty_iff_dense_compl -theorem Dense.interior_compl {s : Set α} (h : Dense s) : interior sᶜ = ∅ := +theorem Dense.interior_compl {s : Set X} (h : Dense s) : interior sᶜ = ∅ := interior_eq_empty_iff_dense_compl.2 <| by rwa [compl_compl] #align dense.interior_compl Dense.interior_compl /-- The closure of a set `s` is dense if and only if `s` is dense. -/ @[simp] -theorem dense_closure {s : Set α} : Dense (closure s) ↔ Dense s := by +theorem dense_closure {s : Set X} : Dense (closure s) ↔ Dense s := by rw [Dense, Dense, closure_closure] #align dense_closure dense_closure @@ -644,11 +650,11 @@ alias ⟨Dense.of_closure, _⟩ := dense_closure #align dense.closure Dense.closure @[simp] -theorem dense_univ : Dense (univ : Set α) := fun _ => subset_closure trivial +theorem dense_univ : Dense (univ : Set X) := fun _ => subset_closure trivial #align dense_univ dense_univ /-- A set is dense if and only if it has a nonempty intersection with each nonempty open set. -/ -theorem dense_iff_inter_open {s : Set α} : +theorem dense_iff_inter_open {s : Set X} : Dense s ↔ ∀ U, IsOpen U → U.Nonempty → (U ∩ s).Nonempty := by constructor <;> intro h · rintro U U_op ⟨x, x_in⟩ @@ -662,30 +668,30 @@ theorem dense_iff_inter_open {s : Set α} : alias ⟨Dense.inter_open_nonempty, _⟩ := dense_iff_inter_open #align dense.inter_open_nonempty Dense.inter_open_nonempty -theorem Dense.exists_mem_open {s : Set α} (hs : Dense s) {U : Set α} (ho : IsOpen U) +theorem Dense.exists_mem_open {s : Set X} (hs : Dense s) {U : Set X} (ho : IsOpen U) (hne : U.Nonempty) : ∃ x ∈ s, x ∈ U := let ⟨x, hx⟩ := hs.inter_open_nonempty U ho hne ⟨x, hx.2, hx.1⟩ #align dense.exists_mem_open Dense.exists_mem_open -theorem Dense.nonempty_iff {s : Set α} (hs : Dense s) : s.Nonempty ↔ Nonempty α := +theorem Dense.nonempty_iff {s : Set X} (hs : Dense s) : s.Nonempty ↔ Nonempty X := ⟨fun ⟨x, _⟩ => ⟨x⟩, fun ⟨x⟩ => let ⟨y, hy⟩ := hs.inter_open_nonempty _ isOpen_univ ⟨x, trivial⟩ ⟨y, hy.2⟩⟩ #align dense.nonempty_iff Dense.nonempty_iff -theorem Dense.nonempty [h : Nonempty α] {s : Set α} (hs : Dense s) : s.Nonempty := +theorem Dense.nonempty [h : Nonempty X] {s : Set X} (hs : Dense s) : s.Nonempty := hs.nonempty_iff.2 h #align dense.nonempty Dense.nonempty @[mono] -theorem Dense.mono {s₁ s₂ : Set α} (h : s₁ ⊆ s₂) (hd : Dense s₁) : Dense s₂ := fun x => +theorem Dense.mono {s₁ s₂ : Set X} (h : s₁ ⊆ s₂) (hd : Dense s₁) : Dense s₂ := fun x => closure_mono h (hd x) #align dense.mono Dense.mono /-- Complement to a singleton is dense if and only if the singleton is not an open set. -/ -theorem dense_compl_singleton_iff_not_open {x : α} : - Dense ({x}ᶜ : Set α) ↔ ¬IsOpen ({x} : Set α) := by +theorem dense_compl_singleton_iff_not_open {x : X} : + Dense ({x}ᶜ : Set X) ↔ ¬IsOpen ({x} : Set X) := by constructor · intro hd ho exact (hd.inter_open_nonempty _ ho (singleton_nonempty _)).ne_empty (inter_compl_self _) @@ -700,12 +706,12 @@ theorem dense_compl_singleton_iff_not_open {x : α} : -/ /-- The frontier of a set is the set of points between the closure and interior. -/ -def frontier (s : Set α) : Set α := +def frontier (s : Set X) : Set X := closure s \ interior s #align frontier frontier @[simp] -theorem closure_diff_interior (s : Set α) : closure s \ interior s = frontier s := +theorem closure_diff_interior (s : Set X) : closure s \ interior s = frontier s := rfl #align closure_diff_interior closure_diff_interior @@ -715,21 +721,21 @@ lemma disjoint_interior_frontier : Disjoint (interior s) (frontier s) := by ← inter_assoc, inter_comm, ← inter_assoc, compl_inter_self, empty_inter] @[simp] -theorem closure_diff_frontier (s : Set α) : closure s \ frontier s = interior s := by +theorem closure_diff_frontier (s : Set X) : closure s \ frontier s = interior s := by rw [frontier, diff_diff_right_self, inter_eq_self_of_subset_right interior_subset_closure] #align closure_diff_frontier closure_diff_frontier @[simp] -theorem self_diff_frontier (s : Set α) : s \ frontier s = interior s := by +theorem self_diff_frontier (s : Set X) : s \ frontier s = interior s := by rw [frontier, diff_diff_right, diff_eq_empty.2 subset_closure, inter_eq_self_of_subset_right interior_subset, empty_union] #align self_diff_frontier self_diff_frontier -theorem frontier_eq_closure_inter_closure {s : Set α} : frontier s = closure s ∩ closure sᶜ := by +theorem frontier_eq_closure_inter_closure {s : Set X} : frontier s = closure s ∩ closure sᶜ := by rw [closure_compl, frontier, diff_eq] #align frontier_eq_closure_inter_closure frontier_eq_closure_inter_closure -theorem frontier_subset_closure {s : Set α} : frontier s ⊆ closure s := +theorem frontier_subset_closure {s : Set X} : frontier s ⊆ closure s := diff_subset _ _ #align frontier_subset_closure frontier_subset_closure @@ -737,59 +743,59 @@ theorem IsClosed.frontier_subset (hs : IsClosed s) : frontier s ⊆ s := frontier_subset_closure.trans hs.closure_eq.subset #align is_closed.frontier_subset IsClosed.frontier_subset -theorem frontier_closure_subset {s : Set α} : frontier (closure s) ⊆ frontier s := +theorem frontier_closure_subset {s : Set X} : frontier (closure s) ⊆ frontier s := diff_subset_diff closure_closure.subset <| interior_mono subset_closure #align frontier_closure_subset frontier_closure_subset -theorem frontier_interior_subset {s : Set α} : frontier (interior s) ⊆ frontier s := +theorem frontier_interior_subset {s : Set X} : frontier (interior s) ⊆ frontier s := diff_subset_diff (closure_mono interior_subset) interior_interior.symm.subset #align frontier_interior_subset frontier_interior_subset /-- The complement of a set has the same frontier as the original set. -/ @[simp] -theorem frontier_compl (s : Set α) : frontier sᶜ = frontier s := by +theorem frontier_compl (s : Set X) : frontier sᶜ = frontier s := by simp only [frontier_eq_closure_inter_closure, compl_compl, inter_comm] #align frontier_compl frontier_compl @[simp] -theorem frontier_univ : frontier (univ : Set α) = ∅ := by simp [frontier] +theorem frontier_univ : frontier (univ : Set X) = ∅ := by simp [frontier] #align frontier_univ frontier_univ @[simp] -theorem frontier_empty : frontier (∅ : Set α) = ∅ := by simp [frontier] +theorem frontier_empty : frontier (∅ : Set X) = ∅ := by simp [frontier] #align frontier_empty frontier_empty -theorem frontier_inter_subset (s t : Set α) : +theorem frontier_inter_subset (s t : Set X) : frontier (s ∩ t) ⊆ frontier s ∩ closure t ∪ closure s ∩ frontier t := by simp only [frontier_eq_closure_inter_closure, compl_inter, closure_union] refine' (inter_subset_inter_left _ (closure_inter_subset_inter_closure s t)).trans_eq _ simp only [inter_distrib_left, inter_distrib_right, inter_assoc, inter_comm (closure t)] #align frontier_inter_subset frontier_inter_subset -theorem frontier_union_subset (s t : Set α) : +theorem frontier_union_subset (s t : Set X) : frontier (s ∪ t) ⊆ frontier s ∩ closure tᶜ ∪ closure sᶜ ∩ frontier t := by simpa only [frontier_compl, ← compl_union] using frontier_inter_subset sᶜ tᶜ #align frontier_union_subset frontier_union_subset -theorem IsClosed.frontier_eq {s : Set α} (hs : IsClosed s) : frontier s = s \ interior s := by +theorem IsClosed.frontier_eq {s : Set X} (hs : IsClosed s) : frontier s = s \ interior s := by rw [frontier, hs.closure_eq] #align is_closed.frontier_eq IsClosed.frontier_eq -theorem IsOpen.frontier_eq {s : Set α} (hs : IsOpen s) : frontier s = closure s \ s := by +theorem IsOpen.frontier_eq {s : Set X} (hs : IsOpen s) : frontier s = closure s \ s := by rw [frontier, hs.interior_eq] #align is_open.frontier_eq IsOpen.frontier_eq -theorem IsOpen.inter_frontier_eq {s : Set α} (hs : IsOpen s) : s ∩ frontier s = ∅ := by +theorem IsOpen.inter_frontier_eq {s : Set X} (hs : IsOpen s) : s ∩ frontier s = ∅ := by rw [hs.frontier_eq, inter_diff_self] #align is_open.inter_frontier_eq IsOpen.inter_frontier_eq /-- The frontier of a set is closed. -/ -theorem isClosed_frontier {s : Set α} : IsClosed (frontier s) := by +theorem isClosed_frontier {s : Set X} : IsClosed (frontier s) := by rw [frontier_eq_closure_inter_closure]; exact IsClosed.inter isClosed_closure isClosed_closure #align is_closed_frontier isClosed_frontier /-- The frontier of a closed set has no interior point. -/ -theorem interior_frontier {s : Set α} (h : IsClosed s) : interior (frontier s) = ∅ := by +theorem interior_frontier {s : Set X} (h : IsClosed s) : interior (frontier s) = ∅ := by have A : frontier s = s \ interior s := h.frontier_eq have B : interior (frontier s) ⊆ interior s := by rw [A]; exact interior_mono (diff_subset _ _) have C : interior (frontier s) ⊆ frontier s := interior_subset @@ -798,11 +804,11 @@ theorem interior_frontier {s : Set α} (h : IsClosed s) : interior (frontier s) rwa [inter_diff_self, subset_empty_iff] at this #align interior_frontier interior_frontier -theorem closure_eq_interior_union_frontier (s : Set α) : closure s = interior s ∪ frontier s := +theorem closure_eq_interior_union_frontier (s : Set X) : closure s = interior s ∪ frontier s := (union_diff_cancel interior_subset_closure).symm #align closure_eq_interior_union_frontier closure_eq_interior_union_frontier -theorem closure_eq_self_union_frontier (s : Set α) : closure s = s ∪ frontier s := +theorem closure_eq_self_union_frontier (s : Set X) : closure s = s ∪ frontier s := (union_diff_cancel' interior_subset subset_closure).symm #align closure_eq_self_union_frontier closure_eq_self_union_frontier @@ -815,12 +821,12 @@ theorem Disjoint.frontier_right (hs : IsOpen s) (hd : Disjoint s t) : Disjoint s (hd.symm.frontier_left hs).symm #align disjoint.frontier_right Disjoint.frontier_right -theorem frontier_eq_inter_compl_interior {s : Set α} : +theorem frontier_eq_inter_compl_interior {s : Set X} : frontier s = (interior s)ᶜ ∩ (interior sᶜ)ᶜ := by rw [← frontier_compl, ← closure_compl, ← diff_eq, closure_diff_interior] #align frontier_eq_inter_compl_interior frontier_eq_inter_compl_interior -theorem compl_frontier_eq_union_interior {s : Set α} : +theorem compl_frontier_eq_union_interior {s : Set X} : (frontier s)ᶜ = interior s ∪ interior sᶜ := by rw [frontier_eq_inter_compl_interior] simp only [compl_inter, compl_compl] @@ -833,14 +839,14 @@ theorem compl_frontier_eq_union_interior {s : Set α} : /-- A set is called a neighborhood of `a` if it contains an open set around `a`. The set of all neighborhoods of `a` forms a filter, the neighborhood filter at `a`, is here defined as the infimum over the principal filters of all open sets containing `a`. -/ -irreducible_def nhds (a : α) : Filter α := - ⨅ s ∈ { s : Set α | a ∈ s ∧ IsOpen s }, 𝓟 s +irreducible_def nhds (a : X) : Filter X := + ⨅ s ∈ { s : Set X | a ∈ s ∧ IsOpen s }, 𝓟 s #align nhds nhds #align nhds_def nhds_def /-- The "neighborhood within" filter. Elements of `𝓝[s] a` are sets containing the intersection of `s` and a neighborhood of `a`. -/ -def nhdsWithin (a : α) (s : Set α) : Filter α := +def nhdsWithin (a : X) (s : Set X) : Filter X := nhds a ⊓ 𝓟 s #align nhds_within nhdsWithin @@ -869,14 +875,14 @@ scoped[Topology] notation3 "𝓝[<] " x:100 => nhdsWithin x (Set.Iio x) end -theorem nhds_def' (a : α) : 𝓝 a = ⨅ (s : Set α) (_ : IsOpen s) (_ : a ∈ s), 𝓟 s := by +theorem nhds_def' (a : X) : 𝓝 a = ⨅ (s : Set X) (_ : IsOpen s) (_ : a ∈ s), 𝓟 s := by simp only [nhds_def, mem_setOf_eq, @and_comm (a ∈ _), iInf_and] #align nhds_def' nhds_def' /-- The open sets containing `a` are a basis for the neighborhood filter. See `nhds_basis_opens'` for a variant using open neighborhoods instead. -/ -theorem nhds_basis_opens (a : α) : - (𝓝 a).HasBasis (fun s : Set α => a ∈ s ∧ IsOpen s) fun s => s := by +theorem nhds_basis_opens (a : X) : + (𝓝 a).HasBasis (fun s : Set X => a ∈ s ∧ IsOpen s) fun s => s := by rw [nhds_def] exact hasBasis_biInf_principal (fun s ⟨has, hs⟩ t ⟨hat, ht⟩ => @@ -884,114 +890,114 @@ theorem nhds_basis_opens (a : α) : ⟨univ, ⟨mem_univ a, isOpen_univ⟩⟩ #align nhds_basis_opens nhds_basis_opens -theorem nhds_basis_closeds (a : α) : (𝓝 a).HasBasis (fun s : Set α => a ∉ s ∧ IsClosed s) compl := +theorem nhds_basis_closeds (a : X) : (𝓝 a).HasBasis (fun s : Set X => a ∉ s ∧ IsClosed s) compl := ⟨fun t => (nhds_basis_opens a).mem_iff.trans <| compl_surjective.exists.trans <| by simp only [isOpen_compl_iff, mem_compl_iff]⟩ #align nhds_basis_closeds nhds_basis_closeds /-- A filter lies below the neighborhood filter at `a` iff it contains every open set around `a`. -/ -theorem le_nhds_iff {f a} : f ≤ 𝓝 a ↔ ∀ s : Set α, a ∈ s → IsOpen s → s ∈ f := by simp [nhds_def] +theorem le_nhds_iff {f a} : f ≤ 𝓝 a ↔ ∀ s : Set X, a ∈ s → IsOpen s → s ∈ f := by simp [nhds_def] #align le_nhds_iff le_nhds_iff /-- To show a filter is above the neighborhood filter at `a`, it suffices to show that it is above the principal filter of some open set `s` containing `a`. -/ -theorem nhds_le_of_le {f a} {s : Set α} (h : a ∈ s) (o : IsOpen s) (sf : 𝓟 s ≤ f) : 𝓝 a ≤ f := by +theorem nhds_le_of_le {f a} {s : Set X} (h : a ∈ s) (o : IsOpen s) (sf : 𝓟 s ≤ f) : 𝓝 a ≤ f := by rw [nhds_def]; exact iInf₂_le_of_le s ⟨h, o⟩ sf #align nhds_le_of_le nhds_le_of_le -- porting note: use `∃ t, t ⊆ s ∧ _` instead of `∃ t ⊆ s, _` -theorem mem_nhds_iff {a : α} {s : Set α} : s ∈ 𝓝 a ↔ ∃ t, t ⊆ s ∧ IsOpen t ∧ a ∈ t := +theorem mem_nhds_iff {a : X} {s : Set X} : s ∈ 𝓝 a ↔ ∃ t, t ⊆ s ∧ IsOpen t ∧ a ∈ t := (nhds_basis_opens a).mem_iff.trans <| exists_congr fun _ => ⟨fun h => ⟨h.2, h.1.2, h.1.1⟩, fun h => ⟨⟨h.2.2, h.2.1⟩, h.1⟩⟩ #align mem_nhds_iff mem_nhds_iffₓ /-- A predicate is true in a neighborhood of `a` iff it is true for all the points in an open set containing `a`. -/ -theorem eventually_nhds_iff {a : α} {p : α → Prop} : - (∀ᶠ x in 𝓝 a, p x) ↔ ∃ t : Set α, (∀ x ∈ t, p x) ∧ IsOpen t ∧ a ∈ t := +theorem eventually_nhds_iff {a : X} {p : X → Prop} : + (∀ᶠ x in 𝓝 a, p x) ↔ ∃ t : Set X, (∀ x ∈ t, p x) ∧ IsOpen t ∧ a ∈ t := mem_nhds_iff.trans <| by simp only [subset_def, exists_prop, mem_setOf_eq] #align eventually_nhds_iff eventually_nhds_iff -theorem mem_interior_iff_mem_nhds {s : Set α} {a : α} : a ∈ interior s ↔ s ∈ 𝓝 a := +theorem mem_interior_iff_mem_nhds {s : Set X} {a : X} : a ∈ interior s ↔ s ∈ 𝓝 a := mem_interior.trans mem_nhds_iff.symm #align mem_interior_iff_mem_nhds mem_interior_iff_mem_nhds -theorem map_nhds {a : α} {f : α → β} : - map f (𝓝 a) = ⨅ s ∈ { s : Set α | a ∈ s ∧ IsOpen s }, 𝓟 (image f s) := +theorem map_nhds {a : X} {f : X → α} : + map f (𝓝 a) = ⨅ s ∈ { s : Set X | a ∈ s ∧ IsOpen s }, 𝓟 (f '' s) := ((nhds_basis_opens a).map f).eq_biInf #align map_nhds map_nhds -theorem mem_of_mem_nhds {a : α} {s : Set α} : s ∈ 𝓝 a → a ∈ s := fun H => +theorem mem_of_mem_nhds {a : X} {s : Set X} : s ∈ 𝓝 a → a ∈ s := fun H => let ⟨_t, ht, _, hs⟩ := mem_nhds_iff.1 H; ht hs #align mem_of_mem_nhds mem_of_mem_nhds /-- If a predicate is true in a neighborhood of `a`, then it is true for `a`. -/ -theorem Filter.Eventually.self_of_nhds {p : α → Prop} {a : α} (h : ∀ᶠ y in 𝓝 a, p y) : p a := +theorem Filter.Eventually.self_of_nhds {p : X → Prop} {a : X} (h : ∀ᶠ y in 𝓝 a, p y) : p a := mem_of_mem_nhds h #align filter.eventually.self_of_nhds Filter.Eventually.self_of_nhds -theorem IsOpen.mem_nhds {a : α} {s : Set α} (hs : IsOpen s) (ha : a ∈ s) : s ∈ 𝓝 a := +theorem IsOpen.mem_nhds {a : X} {s : Set X} (hs : IsOpen s) (ha : a ∈ s) : s ∈ 𝓝 a := mem_nhds_iff.2 ⟨s, Subset.refl _, hs, ha⟩ #align is_open.mem_nhds IsOpen.mem_nhds -protected theorem IsOpen.mem_nhds_iff {a : α} {s : Set α} (hs : IsOpen s) : s ∈ 𝓝 a ↔ a ∈ s := +protected theorem IsOpen.mem_nhds_iff {a : X} {s : Set X} (hs : IsOpen s) : s ∈ 𝓝 a ↔ a ∈ s := ⟨mem_of_mem_nhds, fun ha => mem_nhds_iff.2 ⟨s, Subset.rfl, hs, ha⟩⟩ #align is_open.mem_nhds_iff IsOpen.mem_nhds_iff -theorem IsClosed.compl_mem_nhds {a : α} {s : Set α} (hs : IsClosed s) (ha : a ∉ s) : sᶜ ∈ 𝓝 a := +theorem IsClosed.compl_mem_nhds {a : X} {s : Set X} (hs : IsClosed s) (ha : a ∉ s) : sᶜ ∈ 𝓝 a := hs.isOpen_compl.mem_nhds (mem_compl ha) #align is_closed.compl_mem_nhds IsClosed.compl_mem_nhds -theorem IsOpen.eventually_mem {a : α} {s : Set α} (hs : IsOpen s) (ha : a ∈ s) : +theorem IsOpen.eventually_mem {a : X} {s : Set X} (hs : IsOpen s) (ha : a ∈ s) : ∀ᶠ x in 𝓝 a, x ∈ s := IsOpen.mem_nhds hs ha #align is_open.eventually_mem IsOpen.eventually_mem /-- The open neighborhoods of `a` are a basis for the neighborhood filter. See `nhds_basis_opens` for a variant using open sets around `a` instead. -/ -theorem nhds_basis_opens' (a : α) : - (𝓝 a).HasBasis (fun s : Set α => s ∈ 𝓝 a ∧ IsOpen s) fun x => x := by +theorem nhds_basis_opens' (a : X) : + (𝓝 a).HasBasis (fun s : Set X => s ∈ 𝓝 a ∧ IsOpen s) fun x => x := by convert nhds_basis_opens a using 2 exact and_congr_left_iff.2 IsOpen.mem_nhds_iff #align nhds_basis_opens' nhds_basis_opens' /-- If `U` is a neighborhood of each point of a set `s` then it is a neighborhood of `s`: it contains an open set containing `s`. -/ -theorem exists_open_set_nhds {s U : Set α} (h : ∀ x ∈ s, U ∈ 𝓝 x) : - ∃ V : Set α, s ⊆ V ∧ IsOpen V ∧ V ⊆ U := +theorem exists_open_set_nhds {s U : Set X} (h : ∀ x ∈ s, U ∈ 𝓝 x) : + ∃ V : Set X, s ⊆ V ∧ IsOpen V ∧ V ⊆ U := ⟨interior U, fun x hx => mem_interior_iff_mem_nhds.2 <| h x hx, isOpen_interior, interior_subset⟩ #align exists_open_set_nhds exists_open_set_nhds /-- If `U` is a neighborhood of each point of a set `s` then it is a neighborhood of s: it contains an open set containing `s`. -/ -theorem exists_open_set_nhds' {s U : Set α} (h : U ∈ ⨆ x ∈ s, 𝓝 x) : - ∃ V : Set α, s ⊆ V ∧ IsOpen V ∧ V ⊆ U := +theorem exists_open_set_nhds' {s U : Set X} (h : U ∈ ⨆ x ∈ s, 𝓝 x) : + ∃ V : Set X, s ⊆ V ∧ IsOpen V ∧ V ⊆ U := exists_open_set_nhds (by simpa using h) #align exists_open_set_nhds' exists_open_set_nhds' /-- If a predicate is true in a neighbourhood of `a`, then for `y` sufficiently close to `a` this predicate is true in a neighbourhood of `y`. -/ -theorem Filter.Eventually.eventually_nhds {p : α → Prop} {a : α} (h : ∀ᶠ y in 𝓝 a, p y) : +theorem Filter.Eventually.eventually_nhds {p : X → Prop} {a : X} (h : ∀ᶠ y in 𝓝 a, p y) : ∀ᶠ y in 𝓝 a, ∀ᶠ x in 𝓝 y, p x := let ⟨t, htp, hto, ha⟩ := eventually_nhds_iff.1 h eventually_nhds_iff.2 ⟨t, fun _x hx => eventually_nhds_iff.2 ⟨t, htp, hto, hx⟩, hto, ha⟩ #align filter.eventually.eventually_nhds Filter.Eventually.eventually_nhds @[simp] -theorem eventually_eventually_nhds {p : α → Prop} {a : α} : +theorem eventually_eventually_nhds {p : X → Prop} {a : X} : (∀ᶠ y in 𝓝 a, ∀ᶠ x in 𝓝 y, p x) ↔ ∀ᶠ x in 𝓝 a, p x := ⟨fun h => h.self_of_nhds, fun h => h.eventually_nhds⟩ #align eventually_eventually_nhds eventually_eventually_nhds @[simp] -theorem frequently_frequently_nhds {p : α → Prop} {a : α} : +theorem frequently_frequently_nhds {p : X → Prop} {a : X} : (∃ᶠ y in 𝓝 a, ∃ᶠ x in 𝓝 y, p x) ↔ ∃ᶠ x in 𝓝 a, p x := by rw [← not_iff_not] simp only [not_frequently, eventually_eventually_nhds] #align frequently_frequently_nhds frequently_frequently_nhds @[simp] -theorem eventually_mem_nhds {s : Set α} {a : α} : (∀ᶠ x in 𝓝 a, s ∈ 𝓝 x) ↔ s ∈ 𝓝 a := +theorem eventually_mem_nhds {s : Set X} {a : X} : (∀ᶠ x in 𝓝 a, s ∈ 𝓝 x) ↔ s ∈ 𝓝 a := eventually_eventually_nhds #align eventually_mem_nhds eventually_mem_nhds @@ -1001,93 +1007,92 @@ theorem nhds_bind_nhds : (𝓝 a).bind 𝓝 = 𝓝 a := #align nhds_bind_nhds nhds_bind_nhds @[simp] -theorem eventually_eventuallyEq_nhds {f g : α → β} {a : α} : +theorem eventually_eventuallyEq_nhds {f g : X → α} {a : X} : (∀ᶠ y in 𝓝 a, f =ᶠ[𝓝 y] g) ↔ f =ᶠ[𝓝 a] g := eventually_eventually_nhds #align eventually_eventually_eq_nhds eventually_eventuallyEq_nhds -theorem Filter.EventuallyEq.eq_of_nhds {f g : α → β} {a : α} (h : f =ᶠ[𝓝 a] g) : f a = g a := +theorem Filter.EventuallyEq.eq_of_nhds {f g : X → α} {a : X} (h : f =ᶠ[𝓝 a] g) : f a = g a := h.self_of_nhds #align filter.eventually_eq.eq_of_nhds Filter.EventuallyEq.eq_of_nhds @[simp] -theorem eventually_eventuallyLE_nhds [LE β] {f g : α → β} {a : α} : +theorem eventually_eventuallyLE_nhds [LE α] {f g : X → α} {a : X} : (∀ᶠ y in 𝓝 a, f ≤ᶠ[𝓝 y] g) ↔ f ≤ᶠ[𝓝 a] g := eventually_eventually_nhds #align eventually_eventually_le_nhds eventually_eventuallyLE_nhds /-- If two functions are equal in a neighbourhood of `a`, then for `y` sufficiently close to `a` these functions are equal in a neighbourhood of `y`. -/ -theorem Filter.EventuallyEq.eventuallyEq_nhds {f g : α → β} {a : α} (h : f =ᶠ[𝓝 a] g) : +theorem Filter.EventuallyEq.eventuallyEq_nhds {f g : X → α} {a : X} (h : f =ᶠ[𝓝 a] g) : ∀ᶠ y in 𝓝 a, f =ᶠ[𝓝 y] g := h.eventually_nhds #align filter.eventually_eq.eventually_eq_nhds Filter.EventuallyEq.eventuallyEq_nhds /-- If `f x ≤ g x` in a neighbourhood of `a`, then for `y` sufficiently close to `a` we have `f x ≤ g x` in a neighbourhood of `y`. -/ -theorem Filter.EventuallyLE.eventuallyLE_nhds [LE β] {f g : α → β} {a : α} (h : f ≤ᶠ[𝓝 a] g) : +theorem Filter.EventuallyLE.eventuallyLE_nhds [LE α] {f g : X → α} {a : X} (h : f ≤ᶠ[𝓝 a] g) : ∀ᶠ y in 𝓝 a, f ≤ᶠ[𝓝 y] g := h.eventually_nhds #align filter.eventually_le.eventually_le_nhds Filter.EventuallyLE.eventuallyLE_nhds -theorem all_mem_nhds (x : α) (P : Set α → Prop) (hP : ∀ s t, s ⊆ t → P s → P t) : +theorem all_mem_nhds (x : X) (P : Set X → Prop) (hP : ∀ s t, s ⊆ t → P s → P t) : (∀ s ∈ 𝓝 x, P s) ↔ ∀ s, IsOpen s → x ∈ s → P s := ((nhds_basis_opens x).forall_iff hP).trans <| by simp only [@and_comm (x ∈ _), and_imp] #align all_mem_nhds all_mem_nhds -theorem all_mem_nhds_filter (x : α) (f : Set α → Set β) (hf : ∀ s t, s ⊆ t → f s ⊆ f t) - (l : Filter β) : (∀ s ∈ 𝓝 x, f s ∈ l) ↔ ∀ s, IsOpen s → x ∈ s → f s ∈ l := +theorem all_mem_nhds_filter (x : X) (f : Set X → Set α) (hf : ∀ s t, s ⊆ t → f s ⊆ f t) + (l : Filter α) : (∀ s ∈ 𝓝 x, f s ∈ l) ↔ ∀ s, IsOpen s → x ∈ s → f s ∈ l := all_mem_nhds _ _ fun s t ssubt h => mem_of_superset h (hf s t ssubt) #align all_mem_nhds_filter all_mem_nhds_filter -theorem tendsto_nhds {f : β → α} {l : Filter β} {a : α} : +theorem tendsto_nhds {f : α → X} {l : Filter α} {a : X} : Tendsto f l (𝓝 a) ↔ ∀ s, IsOpen s → a ∈ s → f ⁻¹' s ∈ l := all_mem_nhds_filter _ _ (fun _ _ h => preimage_mono h) _ #align tendsto_nhds tendsto_nhds -theorem tendsto_atTop_nhds [Nonempty β] [SemilatticeSup β] {f : β → α} {a : α} : - Tendsto f atTop (𝓝 a) ↔ ∀ U : Set α, a ∈ U → IsOpen U → ∃ N, ∀ n, N ≤ n → f n ∈ U := +theorem tendsto_atTop_nhds [Nonempty α] [SemilatticeSup α] {f : α → X} {a : X} : + Tendsto f atTop (𝓝 a) ↔ ∀ U : Set X, a ∈ U → IsOpen U → ∃ N, ∀ n, N ≤ n → f n ∈ U := (atTop_basis.tendsto_iff (nhds_basis_opens a)).trans <| by simp only [and_imp, exists_prop, true_and_iff, mem_Ici, ge_iff_le] #align tendsto_at_top_nhds tendsto_atTop_nhds -theorem tendsto_const_nhds {a : α} {f : Filter β} : Tendsto (fun _ : β => a) f (𝓝 a) := +theorem tendsto_const_nhds {a : X} {f : Filter α} : Tendsto (fun _ : α => a) f (𝓝 a) := tendsto_nhds.mpr fun _ _ ha => univ_mem' fun _ => ha #align tendsto_const_nhds tendsto_const_nhds -theorem tendsto_atTop_of_eventually_const {ι : Type*} [SemilatticeSup ι] [Nonempty ι] {x : α} - {u : ι → α} {i₀ : ι} (h : ∀ i ≥ i₀, u i = x) : Tendsto u atTop (𝓝 x) := +theorem tendsto_atTop_of_eventually_const {ι : Type*} [SemilatticeSup ι] [Nonempty ι] {x : X} + {u : ι → X} {i₀ : ι} (h : ∀ i ≥ i₀, u i = x) : Tendsto u atTop (𝓝 x) := Tendsto.congr' (EventuallyEq.symm (eventually_atTop.mpr ⟨i₀, h⟩)) tendsto_const_nhds #align tendsto_at_top_of_eventually_const tendsto_atTop_of_eventually_const -theorem tendsto_atBot_of_eventually_const {ι : Type*} [SemilatticeInf ι] [Nonempty ι] {x : α} - {u : ι → α} {i₀ : ι} (h : ∀ i ≤ i₀, u i = x) : Tendsto u atBot (𝓝 x) := +theorem tendsto_atBot_of_eventually_const {ι : Type*} [SemilatticeInf ι] [Nonempty ι] {x : X} + {u : ι → X} {i₀ : ι} (h : ∀ i ≤ i₀, u i = x) : Tendsto u atBot (𝓝 x) := Tendsto.congr' (EventuallyEq.symm (eventually_atBot.mpr ⟨i₀, h⟩)) tendsto_const_nhds #align tendsto_at_bot_of_eventually_const tendsto_atBot_of_eventually_const -theorem pure_le_nhds : pure ≤ (𝓝 : α → Filter α) := fun _ _ hs => mem_pure.2 <| mem_of_mem_nhds hs +theorem pure_le_nhds : pure ≤ (𝓝 : X → Filter X) := fun _ _ hs => mem_pure.2 <| mem_of_mem_nhds hs #align pure_le_nhds pure_le_nhds -theorem tendsto_pure_nhds {α : Type*} [TopologicalSpace β] (f : α → β) (a : α) : - Tendsto f (pure a) (𝓝 (f a)) := +theorem tendsto_pure_nhds (f : α → X) (a : α) : Tendsto f (pure a) (𝓝 (f a)) := (tendsto_pure_pure f a).mono_right (pure_le_nhds _) #align tendsto_pure_nhds tendsto_pure_nhds -theorem OrderTop.tendsto_atTop_nhds {α : Type*} [PartialOrder α] [OrderTop α] [TopologicalSpace β] - (f : α → β) : Tendsto f atTop (𝓝 (f ⊤)) := +theorem OrderTop.tendsto_atTop_nhds [PartialOrder α] [OrderTop α] (f : α → X) : + Tendsto f atTop (𝓝 (f ⊤)) := (tendsto_atTop_pure f).mono_right (pure_le_nhds _) #align order_top.tendsto_at_top_nhds OrderTop.tendsto_atTop_nhds @[simp] -instance nhds_neBot {a : α} : NeBot (𝓝 a) := +instance nhds_neBot {a : X} : NeBot (𝓝 a) := neBot_of_le (pure_le_nhds a) #align nhds_ne_bot nhds_neBot -theorem tendsto_nhds_of_eventually_eq {f : β → α} {a : α} (h : ∀ᶠ x in l, f x = a) : +theorem tendsto_nhds_of_eventually_eq {l : Filter α} {f : α → X} {a : X} (h : ∀ᶠ x in l, f x = a) : Tendsto f l (𝓝 a) := tendsto_const_nhds.congr' (.symm h) -theorem Filter.EventuallyEq.tendsto {f : β → α} {a : α} (hf : f =ᶠ[l] fun _ ↦ a) : +theorem Filter.EventuallyEq.tendsto {l : Filter α} {f : α → X} {a : X} (hf : f =ᶠ[l] fun _ ↦ a) : Tendsto f l (𝓝 a) := tendsto_nhds_of_eventually_eq hf @@ -1102,85 +1107,85 @@ In this section we define [cluster points](https://en.wikipedia.org/wiki/Limit_p /-- A point `x` is a cluster point of a filter `F` if `𝓝 x ⊓ F ≠ ⊥`. Also known as an accumulation point or a limit point, but beware that terminology varies. This is *not* the same as asking `𝓝[≠] x ⊓ F ≠ ⊥`. See `mem_closure_iff_clusterPt` in particular. -/ -def ClusterPt (x : α) (F : Filter α) : Prop := +def ClusterPt (x : X) (F : Filter X) : Prop := NeBot (𝓝 x ⊓ F) #align cluster_pt ClusterPt -theorem ClusterPt.neBot {x : α} {F : Filter α} (h : ClusterPt x F) : NeBot (𝓝 x ⊓ F) := +theorem ClusterPt.neBot {x : X} {F : Filter X} (h : ClusterPt x F) : NeBot (𝓝 x ⊓ F) := h #align cluster_pt.ne_bot ClusterPt.neBot -theorem Filter.HasBasis.clusterPt_iff {ιa ιF} {pa : ιa → Prop} {sa : ιa → Set α} {pF : ιF → Prop} - {sF : ιF → Set α} {F : Filter α} (ha : (𝓝 a).HasBasis pa sa) (hF : F.HasBasis pF sF) : +theorem Filter.HasBasis.clusterPt_iff {ιa ιF} {pa : ιa → Prop} {sa : ιa → Set X} {pF : ιF → Prop} + {sF : ιF → Set X} {F : Filter X} (ha : (𝓝 a).HasBasis pa sa) (hF : F.HasBasis pF sF) : ClusterPt a F ↔ ∀ ⦃i⦄, pa i → ∀ ⦃j⦄, pF j → (sa i ∩ sF j).Nonempty := ha.inf_basis_neBot_iff hF #align filter.has_basis.cluster_pt_iff Filter.HasBasis.clusterPt_iff -theorem clusterPt_iff {x : α} {F : Filter α} : - ClusterPt x F ↔ ∀ ⦃U : Set α⦄, U ∈ 𝓝 x → ∀ ⦃V⦄, V ∈ F → (U ∩ V).Nonempty := +theorem clusterPt_iff {x : X} {F : Filter X} : + ClusterPt x F ↔ ∀ ⦃U : Set X⦄, U ∈ 𝓝 x → ∀ ⦃V⦄, V ∈ F → (U ∩ V).Nonempty := inf_neBot_iff #align cluster_pt_iff clusterPt_iff -theorem clusterPt_iff_not_disjoint {x : α} {F : Filter α} : +theorem clusterPt_iff_not_disjoint {x : X} {F : Filter X} : ClusterPt x F ↔ ¬Disjoint (𝓝 x) F := by rw [disjoint_iff, ClusterPt, neBot_iff] /-- `x` is a cluster point of a set `s` if every neighbourhood of `x` meets `s` on a nonempty set. See also `mem_closure_iff_clusterPt`. -/ -theorem clusterPt_principal_iff {x : α} {s : Set α} : +theorem clusterPt_principal_iff {x : X} {s : Set X} : ClusterPt x (𝓟 s) ↔ ∀ U ∈ 𝓝 x, (U ∩ s).Nonempty := inf_principal_neBot_iff #align cluster_pt_principal_iff clusterPt_principal_iff -theorem clusterPt_principal_iff_frequently {x : α} {s : Set α} : +theorem clusterPt_principal_iff_frequently {x : X} {s : Set X} : ClusterPt x (𝓟 s) ↔ ∃ᶠ y in 𝓝 x, y ∈ s := by simp only [clusterPt_principal_iff, frequently_iff, Set.Nonempty, exists_prop, mem_inter_iff] #align cluster_pt_principal_iff_frequently clusterPt_principal_iff_frequently -theorem ClusterPt.of_le_nhds {x : α} {f : Filter α} (H : f ≤ 𝓝 x) [NeBot f] : ClusterPt x f := by +theorem ClusterPt.of_le_nhds {x : X} {f : Filter X} (H : f ≤ 𝓝 x) [NeBot f] : ClusterPt x f := by rwa [ClusterPt, inf_eq_right.mpr H] #align cluster_pt.of_le_nhds ClusterPt.of_le_nhds -theorem ClusterPt.of_le_nhds' {x : α} {f : Filter α} (H : f ≤ 𝓝 x) (_hf : NeBot f) : +theorem ClusterPt.of_le_nhds' {x : X} {f : Filter X} (H : f ≤ 𝓝 x) (_hf : NeBot f) : ClusterPt x f := ClusterPt.of_le_nhds H #align cluster_pt.of_le_nhds' ClusterPt.of_le_nhds' -theorem ClusterPt.of_nhds_le {x : α} {f : Filter α} (H : 𝓝 x ≤ f) : ClusterPt x f := by +theorem ClusterPt.of_nhds_le {x : X} {f : Filter X} (H : 𝓝 x ≤ f) : ClusterPt x f := by simp only [ClusterPt, inf_eq_left.mpr H, nhds_neBot] #align cluster_pt.of_nhds_le ClusterPt.of_nhds_le -theorem ClusterPt.mono {x : α} {f g : Filter α} (H : ClusterPt x f) (h : f ≤ g) : ClusterPt x g := +theorem ClusterPt.mono {x : X} {f g : Filter X} (H : ClusterPt x f) (h : f ≤ g) : ClusterPt x g := NeBot.mono H <| inf_le_inf_left _ h #align cluster_pt.mono ClusterPt.mono -theorem ClusterPt.of_inf_left {x : α} {f g : Filter α} (H : ClusterPt x <| f ⊓ g) : ClusterPt x f := +theorem ClusterPt.of_inf_left {x : X} {f g : Filter X} (H : ClusterPt x <| f ⊓ g) : ClusterPt x f := H.mono inf_le_left #align cluster_pt.of_inf_left ClusterPt.of_inf_left -theorem ClusterPt.of_inf_right {x : α} {f g : Filter α} (H : ClusterPt x <| f ⊓ g) : +theorem ClusterPt.of_inf_right {x : X} {f g : Filter X} (H : ClusterPt x <| f ⊓ g) : ClusterPt x g := H.mono inf_le_right #align cluster_pt.of_inf_right ClusterPt.of_inf_right -theorem Ultrafilter.clusterPt_iff {x : α} {f : Ultrafilter α} : ClusterPt x f ↔ ↑f ≤ 𝓝 x := +theorem Ultrafilter.clusterPt_iff {x : X} {f : Ultrafilter X} : ClusterPt x f ↔ ↑f ≤ 𝓝 x := ⟨f.le_of_inf_neBot', fun h => ClusterPt.of_le_nhds h⟩ #align ultrafilter.cluster_pt_iff Ultrafilter.clusterPt_iff /-- A point `x` is a cluster point of a sequence `u` along a filter `F` if it is a cluster point of `map u F`. -/ -def MapClusterPt {ι : Type*} (x : α) (F : Filter ι) (u : ι → α) : Prop := +def MapClusterPt {ι : Type*} (x : X) (F : Filter ι) (u : ι → X) : Prop := ClusterPt x (map u F) #align map_cluster_pt MapClusterPt -theorem mapClusterPt_iff {ι : Type*} (x : α) (F : Filter ι) (u : ι → α) : +theorem mapClusterPt_iff {ι : Type*} (x : X) (F : Filter ι) (u : ι → X) : MapClusterPt x F u ↔ ∀ s ∈ 𝓝 x, ∃ᶠ a in F, u a ∈ s := by simp_rw [MapClusterPt, ClusterPt, inf_neBot_iff_frequently_left, frequently_map] rfl #align map_cluster_pt_iff mapClusterPt_iff -theorem mapClusterPt_of_comp {ι δ : Type*} {F : Filter ι} {φ : δ → ι} {p : Filter δ} {x : α} - {u : ι → α} [NeBot p] (h : Tendsto φ p F) (H : Tendsto (u ∘ φ) p (𝓝 x)) : +theorem mapClusterPt_of_comp {F : Filter α} {φ : β → α} {p : Filter β} {x : X} + {u : α → X} [NeBot p] (h : Tendsto φ p F) (H : Tendsto (u ∘ φ) p (𝓝 x)) : MapClusterPt x F u := by have := calc @@ -1191,36 +1196,36 @@ theorem mapClusterPt_of_comp {ι δ : Type*} {F : Filter ι} {φ : δ → ι} {p #align map_cluster_pt_of_comp mapClusterPt_of_comp /-- A point `x` is an accumulation point of a filter `F` if `𝓝[≠] x ⊓ F ≠ ⊥`.-/ -def AccPt (x : α) (F : Filter α) : Prop := +def AccPt (x : X) (F : Filter X) : Prop := NeBot (𝓝[≠] x ⊓ F) #align acc_pt AccPt -theorem acc_iff_cluster (x : α) (F : Filter α) : AccPt x F ↔ ClusterPt x (𝓟 {x}ᶜ ⊓ F) := by +theorem acc_iff_cluster (x : X) (F : Filter X) : AccPt x F ↔ ClusterPt x (𝓟 {x}ᶜ ⊓ F) := by rw [AccPt, nhdsWithin, ClusterPt, inf_assoc] #align acc_iff_cluster acc_iff_cluster /-- `x` is an accumulation point of a set `C` iff it is a cluster point of `C ∖ {x}`.-/ -theorem acc_principal_iff_cluster (x : α) (C : Set α) : +theorem acc_principal_iff_cluster (x : X) (C : Set X) : AccPt x (𝓟 C) ↔ ClusterPt x (𝓟 (C \ {x})) := by rw [acc_iff_cluster, inf_principal, inter_comm, diff_eq] #align acc_principal_iff_cluster acc_principal_iff_cluster /-- `x` is an accumulation point of a set `C` iff every neighborhood of `x` contains a point of `C` other than `x`. -/ -theorem accPt_iff_nhds (x : α) (C : Set α) : AccPt x (𝓟 C) ↔ ∀ U ∈ 𝓝 x, ∃ y ∈ U ∩ C, y ≠ x := by +theorem accPt_iff_nhds (x : X) (C : Set X) : AccPt x (𝓟 C) ↔ ∀ U ∈ 𝓝 x, ∃ y ∈ U ∩ C, y ≠ x := by simp [acc_principal_iff_cluster, clusterPt_principal_iff, Set.Nonempty, exists_prop, and_assoc, @and_comm (¬_ = x)] #align acc_pt_iff_nhds accPt_iff_nhds /-- `x` is an accumulation point of a set `C` iff there are points near `x` in `C` and different from `x`.-/ -theorem accPt_iff_frequently (x : α) (C : Set α) : AccPt x (𝓟 C) ↔ ∃ᶠ y in 𝓝 x, y ≠ x ∧ y ∈ C := by +theorem accPt_iff_frequently (x : X) (C : Set X) : AccPt x (𝓟 C) ↔ ∃ᶠ y in 𝓝 x, y ≠ x ∧ y ∈ C := by simp [acc_principal_iff_cluster, clusterPt_principal_iff_frequently, and_comm] #align acc_pt_iff_frequently accPt_iff_frequently /-- If `x` is an accumulation point of `F` and `F ≤ G`, then `x` is an accumulation point of `D`. -/ -theorem AccPt.mono {x : α} {F G : Filter α} (h : AccPt x F) (hFG : F ≤ G) : AccPt x G := +theorem AccPt.mono {x : X} {F G : Filter X} (h : AccPt x F) (hFG : F ≤ G) : AccPt x G := NeBot.mono h (inf_le_inf_left _ hFG) #align acc_pt.mono AccPt.mono @@ -1228,53 +1233,53 @@ theorem AccPt.mono {x : α} {F G : Filter α} (h : AccPt x F) (hFG : F ≤ G) : ### Interior, closure and frontier in terms of neighborhoods -/ -theorem interior_eq_nhds' {s : Set α} : interior s = { a | s ∈ 𝓝 a } := +theorem interior_eq_nhds' {s : Set X} : interior s = { a | s ∈ 𝓝 a } := Set.ext fun x => by simp only [mem_interior, mem_nhds_iff, mem_setOf_eq] #align interior_eq_nhds' interior_eq_nhds' -theorem interior_eq_nhds {s : Set α} : interior s = { a | 𝓝 a ≤ 𝓟 s } := +theorem interior_eq_nhds {s : Set X} : interior s = { a | 𝓝 a ≤ 𝓟 s } := interior_eq_nhds'.trans <| by simp only [le_principal_iff] #align interior_eq_nhds interior_eq_nhds @[simp] -theorem interior_mem_nhds {s : Set α} {a : α} : interior s ∈ 𝓝 a ↔ s ∈ 𝓝 a := +theorem interior_mem_nhds {s : Set X} {a : X} : interior s ∈ 𝓝 a ↔ s ∈ 𝓝 a := ⟨fun h => mem_of_superset h interior_subset, fun h => IsOpen.mem_nhds isOpen_interior (mem_interior_iff_mem_nhds.2 h)⟩ #align interior_mem_nhds interior_mem_nhds -theorem interior_setOf_eq {p : α → Prop} : interior { x | p x } = { x | ∀ᶠ y in 𝓝 x, p y } := +theorem interior_setOf_eq {p : X → Prop} : interior { x | p x } = { x | ∀ᶠ y in 𝓝 x, p y } := interior_eq_nhds' #align interior_set_of_eq interior_setOf_eq -theorem isOpen_setOf_eventually_nhds {p : α → Prop} : IsOpen { x | ∀ᶠ y in 𝓝 x, p y } := by +theorem isOpen_setOf_eventually_nhds {p : X → Prop} : IsOpen { x | ∀ᶠ y in 𝓝 x, p y } := by simp only [← interior_setOf_eq, isOpen_interior] #align is_open_set_of_eventually_nhds isOpen_setOf_eventually_nhds -theorem subset_interior_iff_nhds {s V : Set α} : s ⊆ interior V ↔ ∀ x ∈ s, V ∈ 𝓝 x := by +theorem subset_interior_iff_nhds {s V : Set X} : s ⊆ interior V ↔ ∀ x ∈ s, V ∈ 𝓝 x := by simp_rw [subset_def, mem_interior_iff_mem_nhds] #align subset_interior_iff_nhds subset_interior_iff_nhds -theorem isOpen_iff_nhds {s : Set α} : IsOpen s ↔ ∀ a ∈ s, 𝓝 a ≤ 𝓟 s := +theorem isOpen_iff_nhds {s : Set X} : IsOpen s ↔ ∀ a ∈ s, 𝓝 a ≤ 𝓟 s := calc IsOpen s ↔ s ⊆ interior s := subset_interior_iff_isOpen.symm _ ↔ ∀ a ∈ s, 𝓝 a ≤ 𝓟 s := by simp_rw [interior_eq_nhds, subset_def, mem_setOf] #align is_open_iff_nhds isOpen_iff_nhds -theorem isOpen_iff_mem_nhds {s : Set α} : IsOpen s ↔ ∀ a ∈ s, s ∈ 𝓝 a := +theorem isOpen_iff_mem_nhds {s : Set X} : IsOpen s ↔ ∀ a ∈ s, s ∈ 𝓝 a := isOpen_iff_nhds.trans <| forall_congr' fun _ => imp_congr_right fun _ => le_principal_iff #align is_open_iff_mem_nhds isOpen_iff_mem_nhds /-- A set `s` is open iff for every point `x` in `s` and every `y` close to `x`, `y` is in `s`. -/ -theorem isOpen_iff_eventually {s : Set α} : IsOpen s ↔ ∀ x, x ∈ s → ∀ᶠ y in 𝓝 x, y ∈ s := +theorem isOpen_iff_eventually {s : Set X} : IsOpen s ↔ ∀ x, x ∈ s → ∀ᶠ y in 𝓝 x, y ∈ s := isOpen_iff_mem_nhds #align is_open_iff_eventually isOpen_iff_eventually -theorem isOpen_iff_ultrafilter {s : Set α} : - IsOpen s ↔ ∀ x ∈ s, ∀ (l : Ultrafilter α), ↑l ≤ 𝓝 x → s ∈ l := by +theorem isOpen_iff_ultrafilter {s : Set X} : + IsOpen s ↔ ∀ x ∈ s, ∀ (l : Ultrafilter X), ↑l ≤ 𝓝 x → s ∈ l := by simp_rw [isOpen_iff_mem_nhds, ← mem_iff_ultrafilter] #align is_open_iff_ultrafilter isOpen_iff_ultrafilter -theorem isOpen_singleton_iff_nhds_eq_pure (a : α) : IsOpen ({a} : Set α) ↔ 𝓝 a = pure a := by +theorem isOpen_singleton_iff_nhds_eq_pure (a : X) : IsOpen ({a} : Set X) ↔ 𝓝 a = pure a := by constructor · intro h apply le_antisymm _ (pure_le_nhds a) @@ -1284,13 +1289,12 @@ theorem isOpen_singleton_iff_nhds_eq_pure (a : α) : IsOpen ({a} : Set α) ↔ simp [isOpen_iff_nhds, h] #align is_open_singleton_iff_nhds_eq_pure isOpen_singleton_iff_nhds_eq_pure -theorem isOpen_singleton_iff_punctured_nhds {α : Type*} [TopologicalSpace α] (a : α) : - IsOpen ({a} : Set α) ↔ 𝓝[≠] a = ⊥ := by +theorem isOpen_singleton_iff_punctured_nhds (a : X) : IsOpen ({a} : Set X) ↔ 𝓝[≠] a = ⊥ := by rw [isOpen_singleton_iff_nhds_eq_pure, nhdsWithin, ← mem_iff_inf_principal_compl, ← le_pure_iff, nhds_neBot.le_pure_iff] #align is_open_singleton_iff_punctured_nhds isOpen_singleton_iff_punctured_nhds -theorem mem_closure_iff_frequently {s : Set α} {a : α} : a ∈ closure s ↔ ∃ᶠ x in 𝓝 a, x ∈ s := by +theorem mem_closure_iff_frequently {s : Set X} {a : X} : a ∈ closure s ↔ ∃ᶠ x in 𝓝 a, x ∈ s := by rw [Filter.Frequently, Filter.Eventually, ← mem_interior_iff_mem_nhds, closure_eq_compl_interior_compl, mem_compl_iff, compl_def] #align mem_closure_iff_frequently mem_closure_iff_frequently @@ -1300,7 +1304,7 @@ alias ⟨_, Filter.Frequently.mem_closure⟩ := mem_closure_iff_frequently /-- A set `s` is closed iff for every point `x`, if there is a point `y` close to `x` that belongs to `s` then `x` is in `s`. -/ -theorem isClosed_iff_frequently {s : Set α} : IsClosed s ↔ ∀ x, (∃ᶠ y in 𝓝 x, y ∈ s) → x ∈ s := by +theorem isClosed_iff_frequently {s : Set X} : IsClosed s ↔ ∀ x, (∃ᶠ y in 𝓝 x, y ∈ s) → x ∈ s := by rw [← closure_subset_iff_isClosed] refine' forall_congr' fun x => _ rw [mem_closure_iff_frequently] @@ -1308,30 +1312,30 @@ theorem isClosed_iff_frequently {s : Set α} : IsClosed s ↔ ∀ x, (∃ᶠ y i /-- The set of cluster points of a filter is closed. In particular, the set of limit points of a sequence is closed. -/ -theorem isClosed_setOf_clusterPt {f : Filter α} : IsClosed { x | ClusterPt x f } := by +theorem isClosed_setOf_clusterPt {f : Filter X} : IsClosed { x | ClusterPt x f } := by simp only [ClusterPt, inf_neBot_iff_frequently_left, setOf_forall, imp_iff_not_or] refine' isClosed_iInter fun p => IsClosed.union _ _ <;> apply isClosed_compl_iff.2 exacts [isOpen_setOf_eventually_nhds, isOpen_const] #align is_closed_set_of_cluster_pt isClosed_setOf_clusterPt -theorem mem_closure_iff_clusterPt {s : Set α} {a : α} : a ∈ closure s ↔ ClusterPt a (𝓟 s) := +theorem mem_closure_iff_clusterPt {s : Set X} {a : X} : a ∈ closure s ↔ ClusterPt a (𝓟 s) := mem_closure_iff_frequently.trans clusterPt_principal_iff_frequently.symm #align mem_closure_iff_cluster_pt mem_closure_iff_clusterPt -theorem mem_closure_iff_nhds_neBot {s : Set α} : a ∈ closure s ↔ 𝓝 a ⊓ 𝓟 s ≠ ⊥ := +theorem mem_closure_iff_nhds_neBot {s : Set X} : a ∈ closure s ↔ 𝓝 a ⊓ 𝓟 s ≠ ⊥ := mem_closure_iff_clusterPt.trans neBot_iff #align mem_closure_iff_nhds_ne_bot mem_closure_iff_nhds_neBot -theorem mem_closure_iff_nhdsWithin_neBot {s : Set α} {x : α} : x ∈ closure s ↔ NeBot (𝓝[s] x) := +theorem mem_closure_iff_nhdsWithin_neBot {s : Set X} {x : X} : x ∈ closure s ↔ NeBot (𝓝[s] x) := mem_closure_iff_clusterPt #align mem_closure_iff_nhds_within_ne_bot mem_closure_iff_nhdsWithin_neBot -lemma not_mem_closure_iff_nhdsWithin_eq_bot {s : Set α} {x : α} : x ∉ closure s ↔ 𝓝[s] x = ⊥ := by +lemma not_mem_closure_iff_nhdsWithin_eq_bot {s : Set X} {x : X} : x ∉ closure s ↔ 𝓝[s] x = ⊥ := by rw [mem_closure_iff_nhdsWithin_neBot, not_neBot] /-- If `x` is not an isolated point of a topological space, then `{x}ᶜ` is dense in the whole space. -/ -theorem dense_compl_singleton (x : α) [NeBot (𝓝[≠] x)] : Dense ({x}ᶜ : Set α) := by +theorem dense_compl_singleton (x : X) [NeBot (𝓝[≠] x)] : Dense ({x}ᶜ : Set X) := by intro y rcases eq_or_ne y x with (rfl | hne) · rwa [mem_closure_iff_nhdsWithin_neBot] @@ -1341,95 +1345,95 @@ theorem dense_compl_singleton (x : α) [NeBot (𝓝[≠] x)] : Dense ({x}ᶜ : S /-- If `x` is not an isolated point of a topological space, then the closure of `{x}ᶜ` is the whole space. -/ -- porting note: was a `@[simp]` lemma but `simp` can prove it -theorem closure_compl_singleton (x : α) [NeBot (𝓝[≠] x)] : closure {x}ᶜ = (univ : Set α) := +theorem closure_compl_singleton (x : X) [NeBot (𝓝[≠] x)] : closure {x}ᶜ = (univ : Set X) := (dense_compl_singleton x).closure_eq #align closure_compl_singleton closure_compl_singleton /-- If `x` is not an isolated point of a topological space, then the interior of `{x}` is empty. -/ @[simp] -theorem interior_singleton (x : α) [NeBot (𝓝[≠] x)] : interior {x} = (∅ : Set α) := +theorem interior_singleton (x : X) [NeBot (𝓝[≠] x)] : interior {x} = (∅ : Set X) := interior_eq_empty_iff_dense_compl.2 (dense_compl_singleton x) #align interior_singleton interior_singleton -theorem not_isOpen_singleton (x : α) [NeBot (𝓝[≠] x)] : ¬IsOpen ({x} : Set α) := +theorem not_isOpen_singleton (x : X) [NeBot (𝓝[≠] x)] : ¬IsOpen ({x} : Set X) := dense_compl_singleton_iff_not_open.1 (dense_compl_singleton x) #align not_is_open_singleton not_isOpen_singleton -theorem closure_eq_cluster_pts {s : Set α} : closure s = { a | ClusterPt a (𝓟 s) } := +theorem closure_eq_cluster_pts {s : Set X} : closure s = { a | ClusterPt a (𝓟 s) } := Set.ext fun _ => mem_closure_iff_clusterPt #align closure_eq_cluster_pts closure_eq_cluster_pts -theorem mem_closure_iff_nhds {s : Set α} {a : α} : a ∈ closure s ↔ ∀ t ∈ 𝓝 a, (t ∩ s).Nonempty := +theorem mem_closure_iff_nhds {s : Set X} {a : X} : a ∈ closure s ↔ ∀ t ∈ 𝓝 a, (t ∩ s).Nonempty := mem_closure_iff_clusterPt.trans clusterPt_principal_iff #align mem_closure_iff_nhds mem_closure_iff_nhds -theorem mem_closure_iff_nhds' {s : Set α} {a : α} : a ∈ closure s ↔ ∀ t ∈ 𝓝 a, ∃ y : s, ↑y ∈ t := by +theorem mem_closure_iff_nhds' {s : Set X} {a : X} : a ∈ closure s ↔ ∀ t ∈ 𝓝 a, ∃ y : s, ↑y ∈ t := by simp only [mem_closure_iff_nhds, Set.inter_nonempty_iff_exists_right, SetCoe.exists, exists_prop] #align mem_closure_iff_nhds' mem_closure_iff_nhds' -theorem mem_closure_iff_comap_neBot {A : Set α} {x : α} : - x ∈ closure A ↔ NeBot (comap ((↑) : A → α) (𝓝 x)) := by +theorem mem_closure_iff_comap_neBot {A : Set X} {x : X} : + x ∈ closure A ↔ NeBot (comap ((↑) : A → X) (𝓝 x)) := by simp_rw [mem_closure_iff_nhds, comap_neBot_iff, Set.inter_nonempty_iff_exists_right, SetCoe.exists, exists_prop] #align mem_closure_iff_comap_ne_bot mem_closure_iff_comap_neBot -theorem mem_closure_iff_nhds_basis' {a : α} {p : ι → Prop} {s : ι → Set α} (h : (𝓝 a).HasBasis p s) - {t : Set α} : a ∈ closure t ↔ ∀ i, p i → (s i ∩ t).Nonempty := +theorem mem_closure_iff_nhds_basis' {a : X} {p : ι → Prop} {s : ι → Set X} (h : (𝓝 a).HasBasis p s) + {t : Set X} : a ∈ closure t ↔ ∀ i, p i → (s i ∩ t).Nonempty := mem_closure_iff_clusterPt.trans <| (h.clusterPt_iff (hasBasis_principal _)).trans <| by simp only [exists_prop, forall_const] #align mem_closure_iff_nhds_basis' mem_closure_iff_nhds_basis' -theorem mem_closure_iff_nhds_basis {a : α} {p : ι → Prop} {s : ι → Set α} (h : (𝓝 a).HasBasis p s) - {t : Set α} : a ∈ closure t ↔ ∀ i, p i → ∃ y ∈ t, y ∈ s i := +theorem mem_closure_iff_nhds_basis {a : X} {p : ι → Prop} {s : ι → Set X} (h : (𝓝 a).HasBasis p s) + {t : Set X} : a ∈ closure t ↔ ∀ i, p i → ∃ y ∈ t, y ∈ s i := (mem_closure_iff_nhds_basis' h).trans <| by simp only [Set.Nonempty, mem_inter_iff, exists_prop, and_comm] #align mem_closure_iff_nhds_basis mem_closure_iff_nhds_basis -theorem clusterPt_iff_forall_mem_closure {F : Filter α} {a : α} : +theorem clusterPt_iff_forall_mem_closure {F : Filter X} {a : X} : ClusterPt a F ↔ ∀ s ∈ F, a ∈ closure s := by simp_rw [ClusterPt, inf_neBot_iff, mem_closure_iff_nhds] rw [forall₂_swap] -theorem clusterPt_iff_lift'_closure {F : Filter α} {a : α} : +theorem clusterPt_iff_lift'_closure {F : Filter X} {a : X} : ClusterPt a F ↔ pure a ≤ (F.lift' closure) := by simp_rw [clusterPt_iff_forall_mem_closure, (hasBasis_pure _).le_basis_iff F.basis_sets.lift'_closure, id, singleton_subset_iff, true_and, exists_const] -theorem clusterPt_iff_lift'_closure' {F : Filter α} {a : α} : +theorem clusterPt_iff_lift'_closure' {F : Filter X} {a : X} : ClusterPt a F ↔ (F.lift' closure ⊓ pure a).NeBot := by rw [clusterPt_iff_lift'_closure, ← Ultrafilter.coe_pure, inf_comm, Ultrafilter.inf_neBot_iff] @[simp] -theorem clusterPt_lift'_closure_iff {F : Filter α} {a : α} : +theorem clusterPt_lift'_closure_iff {F : Filter X} {a : X} : ClusterPt a (F.lift' closure) ↔ ClusterPt a F := by - simp [clusterPt_iff_lift'_closure, lift'_lift'_assoc (monotone_closure α) (monotone_closure α)] + simp [clusterPt_iff_lift'_closure, lift'_lift'_assoc (monotone_closure X) (monotone_closure X)] /-- `x` belongs to the closure of `s` if and only if some ultrafilter supported on `s` converges to `x`. -/ -theorem mem_closure_iff_ultrafilter {s : Set α} {x : α} : - x ∈ closure s ↔ ∃ u : Ultrafilter α, s ∈ u ∧ ↑u ≤ 𝓝 x := by +theorem mem_closure_iff_ultrafilter {s : Set X} {x : X} : + x ∈ closure s ↔ ∃ u : Ultrafilter X, s ∈ u ∧ ↑u ≤ 𝓝 x := by simp [closure_eq_cluster_pts, ClusterPt, ← exists_ultrafilter_iff, and_comm] #align mem_closure_iff_ultrafilter mem_closure_iff_ultrafilter -theorem isClosed_iff_clusterPt {s : Set α} : IsClosed s ↔ ∀ a, ClusterPt a (𝓟 s) → a ∈ s := +theorem isClosed_iff_clusterPt {s : Set X} : IsClosed s ↔ ∀ a, ClusterPt a (𝓟 s) → a ∈ s := calc IsClosed s ↔ closure s ⊆ s := closure_subset_iff_isClosed.symm _ ↔ ∀ a, ClusterPt a (𝓟 s) → a ∈ s := by simp only [subset_def, mem_closure_iff_clusterPt] #align is_closed_iff_cluster_pt isClosed_iff_clusterPt -theorem isClosed_iff_nhds {s : Set α} : +theorem isClosed_iff_nhds {s : Set X} : IsClosed s ↔ ∀ x, (∀ U ∈ 𝓝 x, (U ∩ s).Nonempty) → x ∈ s := by simp_rw [isClosed_iff_clusterPt, ClusterPt, inf_principal_neBot_iff] #align is_closed_iff_nhds isClosed_iff_nhds -lemma isClosed_iff_forall_filter {s : Set α} : - IsClosed s ↔ ∀ x, ∀ F : Filter α, F.NeBot → F ≤ 𝓟 s → F ≤ 𝓝 x → x ∈ s := by +lemma isClosed_iff_forall_filter {s : Set X} : + IsClosed s ↔ ∀ x, ∀ F : Filter X, F.NeBot → F ≤ 𝓟 s → F ≤ 𝓝 x → x ∈ s := by simp_rw [isClosed_iff_clusterPt] exact ⟨fun hs x F F_ne FS Fx ↦ hs _ <| NeBot.mono F_ne (le_inf Fx FS), fun hs x hx ↦ hs x (𝓝 x ⊓ 𝓟 s) hx inf_le_right inf_le_left⟩ -theorem IsClosed.interior_union_left {s t : Set α} (_ : IsClosed s) : +theorem IsClosed.interior_union_left {s t : Set X} (_ : IsClosed s) : interior (s ∪ t) ⊆ s ∪ interior t := fun a ⟨u, ⟨⟨hu₁, hu₂⟩, ha⟩⟩ => (Classical.em (a ∈ s)).imp_right fun h => mem_interior.mpr @@ -1437,28 +1441,28 @@ theorem IsClosed.interior_union_left {s t : Set α} (_ : IsClosed s) : ⟨ha, h⟩⟩ #align is_closed.interior_union_left IsClosed.interior_union_left -theorem IsClosed.interior_union_right {s t : Set α} (h : IsClosed t) : +theorem IsClosed.interior_union_right {s t : Set X} (h : IsClosed t) : interior (s ∪ t) ⊆ interior s ∪ t := by simpa only [union_comm _ t] using h.interior_union_left #align is_closed.interior_union_right IsClosed.interior_union_right -theorem IsOpen.inter_closure {s t : Set α} (h : IsOpen s) : s ∩ closure t ⊆ closure (s ∩ t) := +theorem IsOpen.inter_closure {s t : Set X} (h : IsOpen s) : s ∩ closure t ⊆ closure (s ∩ t) := compl_subset_compl.mp <| by simpa only [← interior_compl, compl_inter] using IsClosed.interior_union_left h.isClosed_compl #align is_open.inter_closure IsOpen.inter_closure -theorem IsOpen.closure_inter {s t : Set α} (h : IsOpen t) : closure s ∩ t ⊆ closure (s ∩ t) := by +theorem IsOpen.closure_inter {s t : Set X} (h : IsOpen t) : closure s ∩ t ⊆ closure (s ∩ t) := by simpa only [inter_comm t] using h.inter_closure #align is_open.closure_inter IsOpen.closure_inter -theorem Dense.open_subset_closure_inter {s t : Set α} (hs : Dense s) (ht : IsOpen t) : +theorem Dense.open_subset_closure_inter {s t : Set X} (hs : Dense s) (ht : IsOpen t) : t ⊆ closure (t ∩ s) := calc t = t ∩ closure s := by rw [hs.closure_eq, inter_univ] _ ⊆ closure (t ∩ s) := ht.inter_closure #align dense.open_subset_closure_inter Dense.open_subset_closure_inter -theorem mem_closure_of_mem_closure_union {s₁ s₂ : Set α} {x : α} (h : x ∈ closure (s₁ ∪ s₂)) +theorem mem_closure_of_mem_closure_union {s₁ s₂ : Set X} {x : X} (h : x ∈ closure (s₁ ∪ s₂)) (h₁ : s₁ᶜ ∈ 𝓝 x) : x ∈ closure s₂ := by rw [mem_closure_iff_nhds_neBot] at * rwa [← @@ -1471,24 +1475,24 @@ theorem mem_closure_of_mem_closure_union {s₁ s₂ : Set α} {x : α} (h : x #align mem_closure_of_mem_closure_union mem_closure_of_mem_closure_union /-- The intersection of an open dense set with a dense set is a dense set. -/ -theorem Dense.inter_of_isOpen_left {s t : Set α} (hs : Dense s) (ht : Dense t) (hso : IsOpen s) : +theorem Dense.inter_of_isOpen_left {s t : Set X} (hs : Dense s) (ht : Dense t) (hso : IsOpen s) : Dense (s ∩ t) := fun x => closure_minimal hso.inter_closure isClosed_closure <| by simp [hs.closure_eq, ht.closure_eq] #align dense.inter_of_open_left Dense.inter_of_isOpen_left /-- The intersection of a dense set with an open dense set is a dense set. -/ -theorem Dense.inter_of_isOpen_right {s t : Set α} (hs : Dense s) (ht : Dense t) (hto : IsOpen t) : +theorem Dense.inter_of_isOpen_right {s t : Set X} (hs : Dense s) (ht : Dense t) (hto : IsOpen t) : Dense (s ∩ t) := inter_comm t s ▸ ht.inter_of_isOpen_left hs hto #align dense.inter_of_open_right Dense.inter_of_isOpen_right -theorem Dense.inter_nhds_nonempty {s t : Set α} (hs : Dense s) {x : α} (ht : t ∈ 𝓝 x) : +theorem Dense.inter_nhds_nonempty {s t : Set X} (hs : Dense s) {x : X} (ht : t ∈ 𝓝 x) : (s ∩ t).Nonempty := let ⟨U, hsub, ho, hx⟩ := mem_nhds_iff.1 ht (hs.inter_open_nonempty U ho ⟨x, hx⟩).mono fun _y hy => ⟨hy.2, hsub hy.1⟩ #align dense.inter_nhds_nonempty Dense.inter_nhds_nonempty -theorem closure_diff {s t : Set α} : closure s \ closure t ⊆ closure (s \ t) := +theorem closure_diff {s t : Set X} : closure s \ closure t ⊆ closure (s \ t) := calc closure s \ closure t = (closure t)ᶜ ∩ closure s := by simp only [diff_eq, inter_comm] _ ⊆ closure ((closure t)ᶜ ∩ s) := (isOpen_compl_iff.mpr <| isClosed_closure).inter_closure @@ -1496,35 +1500,35 @@ theorem closure_diff {s t : Set α} : closure s \ closure t ⊆ closure (s \ t) _ ⊆ closure (s \ t) := closure_mono <| diff_subset_diff (Subset.refl s) subset_closure #align closure_diff closure_diff -theorem Filter.Frequently.mem_of_closed {a : α} {s : Set α} (h : ∃ᶠ x in 𝓝 a, x ∈ s) +theorem Filter.Frequently.mem_of_closed {a : X} {s : Set X} (h : ∃ᶠ x in 𝓝 a, x ∈ s) (hs : IsClosed s) : a ∈ s := hs.closure_subset h.mem_closure #align filter.frequently.mem_of_closed Filter.Frequently.mem_of_closed -theorem IsClosed.mem_of_frequently_of_tendsto {f : β → α} {b : Filter β} {a : α} {s : Set α} +theorem IsClosed.mem_of_frequently_of_tendsto {f : α → X} {b : Filter α} {a : X} {s : Set X} (hs : IsClosed s) (h : ∃ᶠ x in b, f x ∈ s) (hf : Tendsto f b (𝓝 a)) : a ∈ s := (hf.frequently <| show ∃ᶠ x in b, (fun y => y ∈ s) (f x) from h).mem_of_closed hs #align is_closed.mem_of_frequently_of_tendsto IsClosed.mem_of_frequently_of_tendsto -theorem IsClosed.mem_of_tendsto {f : β → α} {b : Filter β} {a : α} {s : Set α} [NeBot b] +theorem IsClosed.mem_of_tendsto {f : α → X} {b : Filter α} {a : X} {s : Set X} [NeBot b] (hs : IsClosed s) (hf : Tendsto f b (𝓝 a)) (h : ∀ᶠ x in b, f x ∈ s) : a ∈ s := hs.mem_of_frequently_of_tendsto h.frequently hf #align is_closed.mem_of_tendsto IsClosed.mem_of_tendsto -theorem mem_closure_of_frequently_of_tendsto {f : β → α} {b : Filter β} {a : α} {s : Set α} +theorem mem_closure_of_frequently_of_tendsto {f : α → X} {b : Filter α} {a : X} {s : Set X} (h : ∃ᶠ x in b, f x ∈ s) (hf : Tendsto f b (𝓝 a)) : a ∈ closure s := (hf.frequently h).mem_closure #align mem_closure_of_frequently_of_tendsto mem_closure_of_frequently_of_tendsto -theorem mem_closure_of_tendsto {f : β → α} {b : Filter β} {a : α} {s : Set α} [NeBot b] +theorem mem_closure_of_tendsto {f : α → X} {b : Filter α} {a : X} {s : Set X} [NeBot b] (hf : Tendsto f b (𝓝 a)) (h : ∀ᶠ x in b, f x ∈ s) : a ∈ closure s := mem_closure_of_frequently_of_tendsto h.frequently hf #align mem_closure_of_tendsto mem_closure_of_tendsto /-- Suppose that `f` sends the complement to `s` to a single point `a`, and `l` is some filter. Then `f` tends to `a` along `l` restricted to `s` if and only if it tends to `a` along `l`. -/ -theorem tendsto_inf_principal_nhds_iff_of_forall_eq {f : β → α} {l : Filter β} {s : Set β} {a : α} - (h : ∀ (x) (_ : x ∉ s), f x = a) : Tendsto f (l ⊓ 𝓟 s) (𝓝 a) ↔ Tendsto f l (𝓝 a) := by +theorem tendsto_inf_principal_nhds_iff_of_forall_eq {f : α → X} {l : Filter α} {s : Set α} {a : X} + (h : ∀ x ∉ s, f x = a) : Tendsto f (l ⊓ 𝓟 s) (𝓝 a) ↔ Tendsto f l (𝓝 a) := by rw [tendsto_iff_comap, tendsto_iff_comap] replace h : 𝓟 sᶜ ≤ comap f (𝓝 a) · rintro U ⟨t, ht, htU⟩ x hx @@ -1553,37 +1557,37 @@ section lim set_option linter.uppercaseLean3 false /-- If `f` is a filter, then `Filter.lim f` is a limit of the filter, if it exists. -/ -noncomputable def lim [Nonempty α] (f : Filter α) : α := +noncomputable def lim [Nonempty X] (f : Filter X) : X := Classical.epsilon fun a => f ≤ 𝓝 a #align Lim lim /-- If `F` is an ultrafilter, then `Filter.Ultrafilter.lim F` is a limit of the filter, if it exists. -Note that dot notation `F.lim` can be used for `F : Filter.Ultrafilter α`. +Note that dot notation `F.lim` can be used for `F : Filter.Ultrafilter X`. -/ -noncomputable nonrec def Ultrafilter.lim (F : Ultrafilter α) : α := - @lim α _ (nonempty_of_neBot F) F +noncomputable nonrec def Ultrafilter.lim (F : Ultrafilter X) : X := + @lim X _ (nonempty_of_neBot F) F #align ultrafilter.Lim Ultrafilter.lim -/-- If `f` is a filter in `β` and `g : β → α` is a function, then `limUnder f g` is a limit of `g` +/-- If `f` is a filter in `α` and `g : α → X` is a function, then `limUnder f g` is a limit of `g` at `f`, if it exists. -/ -noncomputable def limUnder [Nonempty α] (f : Filter β) (g : β → α) : α := +noncomputable def limUnder [Nonempty X] (f : Filter α) (g : α → X) : X := lim (f.map g) #align lim limUnder /-- If a filter `f` is majorated by some `𝓝 a`, then it is majorated by `𝓝 (Filter.lim f)`. We -formulate this lemma with a `[Nonempty α]` argument of `lim` derived from `h` to make it useful for -types without a `[Nonempty α]` instance. Because of the built-in proof irrelevance, Lean will unify +formulate this lemma with a `[Nonempty X]` argument of `lim` derived from `h` to make it useful for +types without a `[Nonempty X]` instance. Because of the built-in proof irrelevance, Lean will unify this instance with any other instance. -/ -theorem le_nhds_lim {f : Filter α} (h : ∃ a, f ≤ 𝓝 a) : f ≤ 𝓝 (@lim _ _ (nonempty_of_exists h) f) := +theorem le_nhds_lim {f : Filter X} (h : ∃ a, f ≤ 𝓝 a) : f ≤ 𝓝 (@lim _ _ (nonempty_of_exists h) f) := Classical.epsilon_spec h #align le_nhds_Lim le_nhds_lim /-- If `g` tends to some `𝓝 a` along `f`, then it tends to `𝓝 (Filter.limUnder f g)`. We formulate -this lemma with a `[Nonempty α]` argument of `lim` derived from `h` to make it useful for types -without a `[Nonempty α]` instance. Because of the built-in proof irrelevance, Lean will unify this +this lemma with a `[Nonempty X]` argument of `lim` derived from `h` to make it useful for types +without a `[Nonempty X]` instance. Because of the built-in proof irrelevance, Lean will unify this instance with any other instance. -/ -theorem tendsto_nhds_limUnder {f : Filter β} {g : β → α} (h : ∃ a, Tendsto g f (𝓝 a)) : +theorem tendsto_nhds_limUnder {f : Filter α} {g : α → X} (h : ∃ a, Tendsto g f (𝓝 a)) : Tendsto g f (𝓝 (@limUnder _ _ _ (nonempty_of_exists h) f g)) := le_nhds_lim h #align tendsto_nhds_lim tendsto_nhds_limUnder @@ -1600,15 +1604,13 @@ open Topology section Continuous -variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} - -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] +variable {X Y Z : Type*} [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] open TopologicalSpace /-- A function between topological spaces is continuous if the preimage of every open set is open. Registered as a structure to make sure it is not unfolded by Lean. -/ -structure Continuous (f : α → β) : Prop where +structure Continuous (f : X → Y) : Prop where /-- The preimage of an open set under a continuous function is an open set. Use `IsOpen.preimage` instead. -/ isOpen_preimage : ∀ s, IsOpen s → IsOpen (f ⁻¹' s) @@ -1619,225 +1621,227 @@ set_option quotPrecheck false in scoped[Topology] notation (name := Continuous_of) "Continuous[" t₁ ", " t₂ "]" => @Continuous _ _ t₁ t₂ -theorem continuous_def {_ : TopologicalSpace α} {_ : TopologicalSpace β} {f : α → β} : +theorem continuous_def {_ : TopologicalSpace X} {_ : TopologicalSpace Y} {f : X → Y} : Continuous f ↔ ∀ s, IsOpen s → IsOpen (f ⁻¹' s) := ⟨fun hf => hf.1, fun h => ⟨h⟩⟩ #align continuous_def continuous_def -theorem IsOpen.preimage {f : α → β} (hf : Continuous f) {s : Set β} (h : IsOpen s) : +theorem IsOpen.preimage {f : X → Y} (hf : Continuous f) {s : Set Y} (h : IsOpen s) : IsOpen (f ⁻¹' s) := hf.isOpen_preimage s h #align is_open.preimage IsOpen.preimage -theorem continuous_congr {f g : α → β} (h : ∀ x, f x = g x) : +theorem continuous_congr {f g : X → Y} (h : ∀ x, f x = g x) : Continuous f ↔ Continuous g := .of_eq <| congrArg _ <| funext h -theorem Continuous.congr {f g : α → β} (h : Continuous f) (h' : ∀ x, f x = g x) : Continuous g := +theorem Continuous.congr {f g : X → Y} (h : Continuous f) (h' : ∀ x, f x = g x) : Continuous g := continuous_congr h' |>.mp h #align continuous.congr Continuous.congr /-- A function between topological spaces is continuous at a point `x₀` if `f x` tends to `f x₀` when `x` tends to `x₀`. -/ -def ContinuousAt (f : α → β) (x : α) := +def ContinuousAt (f : X → Y) (x : X) := Tendsto f (𝓝 x) (𝓝 (f x)) #align continuous_at ContinuousAt -theorem ContinuousAt.tendsto {f : α → β} {x : α} (h : ContinuousAt f x) : +theorem ContinuousAt.tendsto {f : X → Y} {x : X} (h : ContinuousAt f x) : Tendsto f (𝓝 x) (𝓝 (f x)) := h #align continuous_at.tendsto ContinuousAt.tendsto -theorem continuousAt_def {f : α → β} {x : α} : ContinuousAt f x ↔ ∀ A ∈ 𝓝 (f x), f ⁻¹' A ∈ 𝓝 x := +theorem continuousAt_def {f : X → Y} {x : X} : ContinuousAt f x ↔ ∀ A ∈ 𝓝 (f x), f ⁻¹' A ∈ 𝓝 x := Iff.rfl #align continuous_at_def continuousAt_def -theorem continuousAt_congr {f g : α → β} {x : α} (h : f =ᶠ[𝓝 x] g) : +theorem continuousAt_congr {f g : X → Y} {x : X} (h : f =ᶠ[𝓝 x] g) : ContinuousAt f x ↔ ContinuousAt g x := by simp only [ContinuousAt, tendsto_congr' h, h.eq_of_nhds] #align continuous_at_congr continuousAt_congr -theorem ContinuousAt.congr {f g : α → β} {x : α} (hf : ContinuousAt f x) (h : f =ᶠ[𝓝 x] g) : +theorem ContinuousAt.congr {f g : X → Y} {x : X} (hf : ContinuousAt f x) (h : f =ᶠ[𝓝 x] g) : ContinuousAt g x := (continuousAt_congr h).1 hf #align continuous_at.congr ContinuousAt.congr -theorem ContinuousAt.preimage_mem_nhds {f : α → β} {x : α} {t : Set β} (h : ContinuousAt f x) +theorem ContinuousAt.preimage_mem_nhds {f : X → Y} {x : X} {t : Set Y} (h : ContinuousAt f x) (ht : t ∈ 𝓝 (f x)) : f ⁻¹' t ∈ 𝓝 x := h ht #align continuous_at.preimage_mem_nhds ContinuousAt.preimage_mem_nhds -theorem eventuallyEq_zero_nhds {M₀} [Zero M₀] {a : α} {f : α → M₀} : +/-- Deprecated, please use `not_mem_tsupport_iff_eventuallyEq` instead. -/ +@[deprecated] -- 15 January 2024 +theorem eventuallyEq_zero_nhds {M₀} [Zero M₀] {a : X} {f : X → M₀} : f =ᶠ[𝓝 a] 0 ↔ a ∉ closure (Function.support f) := by rw [← mem_compl_iff, ← interior_compl, mem_interior_iff_mem_nhds, Function.compl_support, EventuallyEq, eventually_iff] simp only [Pi.zero_apply] #align eventually_eq_zero_nhds eventuallyEq_zero_nhds -theorem ClusterPt.map {x : α} {la : Filter α} {lb : Filter β} (H : ClusterPt x la) {f : α → β} +theorem ClusterPt.map {x : X} {la : Filter X} {lb : Filter Y} (H : ClusterPt x la) {f : X → Y} (hfc : ContinuousAt f x) (hf : Tendsto f la lb) : ClusterPt (f x) lb := (NeBot.map H f).mono <| hfc.tendsto.inf hf #align cluster_pt.map ClusterPt.map /-- See also `interior_preimage_subset_preimage_interior`. -/ -theorem preimage_interior_subset_interior_preimage {f : α → β} {s : Set β} (hf : Continuous f) : +theorem preimage_interior_subset_interior_preimage {f : X → Y} {s : Set Y} (hf : Continuous f) : f ⁻¹' interior s ⊆ interior (f ⁻¹' s) := interior_maximal (preimage_mono interior_subset) (isOpen_interior.preimage hf) #align preimage_interior_subset_interior_preimage preimage_interior_subset_interior_preimage @[continuity] -theorem continuous_id : Continuous (id : α → α) := +theorem continuous_id : Continuous (id : X → X) := continuous_def.2 fun _ => id #align continuous_id continuous_id -- This is needed due to reducibility issues with the `continuity` tactic. @[continuity] -theorem continuous_id' : Continuous (fun (x : α) => x) := continuous_id +theorem continuous_id' : Continuous (fun (x : X) => x) := continuous_id -theorem Continuous.comp {g : β → γ} {f : α → β} (hg : Continuous g) (hf : Continuous f) : +theorem Continuous.comp {g : Y → Z} {f : X → Y} (hg : Continuous g) (hf : Continuous f) : Continuous (g ∘ f) := continuous_def.2 fun _ h => (h.preimage hg).preimage hf #align continuous.comp Continuous.comp -- This is needed due to reducibility issues with the `continuity` tactic. @[continuity] -theorem Continuous.comp' {g : β → γ} {f : α → β} (hg : Continuous g) (hf : Continuous f) : +theorem Continuous.comp' {g : Y → Z} {f : X → Y} (hg : Continuous g) (hf : Continuous f) : Continuous (fun x => g (f x)) := hg.comp hf -theorem Continuous.iterate {f : α → α} (h : Continuous f) (n : ℕ) : Continuous f^[n] := +theorem Continuous.iterate {f : X → X} (h : Continuous f) (n : ℕ) : Continuous f^[n] := Nat.recOn n continuous_id fun _ ihn => ihn.comp h #align continuous.iterate Continuous.iterate -nonrec theorem ContinuousAt.comp {g : β → γ} {f : α → β} {x : α} (hg : ContinuousAt g (f x)) +nonrec theorem ContinuousAt.comp {g : Y → Z} {f : X → Y} {x : X} (hg : ContinuousAt g (f x)) (hf : ContinuousAt f x) : ContinuousAt (g ∘ f) x := hg.comp hf #align continuous_at.comp ContinuousAt.comp /-- See note [comp_of_eq lemmas] -/ -theorem ContinuousAt.comp_of_eq {g : β → γ} {f : α → β} {x : α} {y : β} (hg : ContinuousAt g y) +theorem ContinuousAt.comp_of_eq {g : Y → Z} {f : X → Y} {x : X} {y : Y} (hg : ContinuousAt g y) (hf : ContinuousAt f x) (hy : f x = y) : ContinuousAt (g ∘ f) x := by subst hy; exact hg.comp hf #align continuous_at.comp_of_eq ContinuousAt.comp_of_eq -theorem Continuous.tendsto {f : α → β} (hf : Continuous f) (x) : Tendsto f (𝓝 x) (𝓝 (f x)) := +theorem Continuous.tendsto {f : X → Y} (hf : Continuous f) (x) : Tendsto f (𝓝 x) (𝓝 (f x)) := ((nhds_basis_opens x).tendsto_iff <| nhds_basis_opens <| f x).2 fun t ⟨hxt, ht⟩ => ⟨f ⁻¹' t, ⟨hxt, ht.preimage hf⟩, Subset.rfl⟩ #align continuous.tendsto Continuous.tendsto /-- A version of `Continuous.tendsto` that allows one to specify a simpler form of the limit. E.g., one can write `continuous_exp.tendsto' 0 1 exp_zero`. -/ -theorem Continuous.tendsto' {f : α → β} (hf : Continuous f) (x : α) (y : β) (h : f x = y) : +theorem Continuous.tendsto' {f : X → Y} (hf : Continuous f) (x : X) (y : Y) (h : f x = y) : Tendsto f (𝓝 x) (𝓝 y) := h ▸ hf.tendsto x #align continuous.tendsto' Continuous.tendsto' -theorem Continuous.continuousAt {f : α → β} {x : α} (h : Continuous f) : ContinuousAt f x := +theorem Continuous.continuousAt {f : X → Y} {x : X} (h : Continuous f) : ContinuousAt f x := h.tendsto x #align continuous.continuous_at Continuous.continuousAt -theorem continuous_iff_continuousAt {f : α → β} : Continuous f ↔ ∀ x, ContinuousAt f x := +theorem continuous_iff_continuousAt {f : X → Y} : Continuous f ↔ ∀ x, ContinuousAt f x := ⟨Continuous.tendsto, fun hf => continuous_def.2 fun _U hU => isOpen_iff_mem_nhds.2 fun x hx => hf x <| hU.mem_nhds hx⟩ #align continuous_iff_continuous_at continuous_iff_continuousAt -theorem continuousAt_const {x : α} {b : β} : ContinuousAt (fun _ : α => b) x := +theorem continuousAt_const {x : X} {b : Y} : ContinuousAt (fun _ : X => b) x := tendsto_const_nhds #align continuous_at_const continuousAt_const @[continuity] -theorem continuous_const {b : β} : Continuous fun _ : α => b := +theorem continuous_const {b : Y} : Continuous fun _ : X => b := continuous_iff_continuousAt.mpr fun _ => continuousAt_const #align continuous_const continuous_const -theorem Filter.EventuallyEq.continuousAt {x : α} {f : α → β} {y : β} (h : f =ᶠ[𝓝 x] fun _ => y) : +theorem Filter.EventuallyEq.continuousAt {x : X} {f : X → Y} {y : Y} (h : f =ᶠ[𝓝 x] fun _ => y) : ContinuousAt f x := (continuousAt_congr h).2 tendsto_const_nhds #align filter.eventually_eq.continuous_at Filter.EventuallyEq.continuousAt -theorem continuous_of_const {f : α → β} (h : ∀ x y, f x = f y) : Continuous f := +theorem continuous_of_const {f : X → Y} (h : ∀ x y, f x = f y) : Continuous f := continuous_iff_continuousAt.mpr fun x => Filter.EventuallyEq.continuousAt <| eventually_of_forall fun y => h y x #align continuous_of_const continuous_of_const -theorem continuousAt_id {x : α} : ContinuousAt id x := +theorem continuousAt_id {x : X} : ContinuousAt id x := continuous_id.continuousAt #align continuous_at_id continuousAt_id -theorem ContinuousAt.iterate {f : α → α} {x : α} (hf : ContinuousAt f x) (hx : f x = x) (n : ℕ) : +theorem ContinuousAt.iterate {f : X → X} {x : X} (hf : ContinuousAt f x) (hx : f x = x) (n : ℕ) : ContinuousAt f^[n] x := Nat.recOn n continuousAt_id fun n ihn => show ContinuousAt (f^[n] ∘ f) x from ContinuousAt.comp (hx.symm ▸ ihn) hf #align continuous_at.iterate ContinuousAt.iterate -theorem continuous_iff_isClosed {f : α → β} : Continuous f ↔ ∀ s, IsClosed s → IsClosed (f ⁻¹' s) := +theorem continuous_iff_isClosed {f : X → Y} : Continuous f ↔ ∀ s, IsClosed s → IsClosed (f ⁻¹' s) := continuous_def.trans <| compl_surjective.forall.trans <| by simp only [isOpen_compl_iff, preimage_compl] #align continuous_iff_is_closed continuous_iff_isClosed -theorem IsClosed.preimage {f : α → β} (hf : Continuous f) {s : Set β} (h : IsClosed s) : +theorem IsClosed.preimage {f : X → Y} (hf : Continuous f) {s : Set Y} (h : IsClosed s) : IsClosed (f ⁻¹' s) := continuous_iff_isClosed.mp hf s h #align is_closed.preimage IsClosed.preimage -theorem mem_closure_image {f : α → β} {x : α} {s : Set α} (hf : ContinuousAt f x) +theorem mem_closure_image {f : X → Y} {x : X} {s : Set X} (hf : ContinuousAt f x) (hx : x ∈ closure s) : f x ∈ closure (f '' s) := mem_closure_of_frequently_of_tendsto ((mem_closure_iff_frequently.1 hx).mono fun _ => mem_image_of_mem _) hf #align mem_closure_image mem_closure_image -theorem continuousAt_iff_ultrafilter {f : α → β} {x} : - ContinuousAt f x ↔ ∀ g : Ultrafilter α, ↑g ≤ 𝓝 x → Tendsto f g (𝓝 (f x)) := +theorem continuousAt_iff_ultrafilter {f : X → Y} {x} : + ContinuousAt f x ↔ ∀ g : Ultrafilter X, ↑g ≤ 𝓝 x → Tendsto f g (𝓝 (f x)) := tendsto_iff_ultrafilter f (𝓝 x) (𝓝 (f x)) #align continuous_at_iff_ultrafilter continuousAt_iff_ultrafilter -theorem continuous_iff_ultrafilter {f : α → β} : - Continuous f ↔ ∀ (x) (g : Ultrafilter α), ↑g ≤ 𝓝 x → Tendsto f g (𝓝 (f x)) := by +theorem continuous_iff_ultrafilter {f : X → Y} : + Continuous f ↔ ∀ (x) (g : Ultrafilter X), ↑g ≤ 𝓝 x → Tendsto f g (𝓝 (f x)) := by simp only [continuous_iff_continuousAt, continuousAt_iff_ultrafilter] #align continuous_iff_ultrafilter continuous_iff_ultrafilter -theorem Continuous.closure_preimage_subset {f : α → β} (hf : Continuous f) (t : Set β) : +theorem Continuous.closure_preimage_subset {f : X → Y} (hf : Continuous f) (t : Set Y) : closure (f ⁻¹' t) ⊆ f ⁻¹' closure t := by rw [← (isClosed_closure.preimage hf).closure_eq] exact closure_mono (preimage_mono subset_closure) #align continuous.closure_preimage_subset Continuous.closure_preimage_subset -theorem Continuous.frontier_preimage_subset {f : α → β} (hf : Continuous f) (t : Set β) : +theorem Continuous.frontier_preimage_subset {f : X → Y} (hf : Continuous f) (t : Set Y) : frontier (f ⁻¹' t) ⊆ f ⁻¹' frontier t := diff_subset_diff (hf.closure_preimage_subset t) (preimage_interior_subset_interior_preimage hf) #align continuous.frontier_preimage_subset Continuous.frontier_preimage_subset /-- If a continuous map `f` maps `s` to `t`, then it maps `closure s` to `closure t`. -/ -protected theorem Set.MapsTo.closure {s : Set α} {t : Set β} {f : α → β} (h : MapsTo f s t) +protected theorem Set.MapsTo.closure {s : Set X} {t : Set Y} {f : X → Y} (h : MapsTo f s t) (hc : Continuous f) : MapsTo f (closure s) (closure t) := by simp only [MapsTo, mem_closure_iff_clusterPt] exact fun x hx => hx.map hc.continuousAt (tendsto_principal_principal.2 h) #align set.maps_to.closure Set.MapsTo.closure /-- See also `IsClosedMap.closure_image_eq_of_continuous`. -/ -theorem image_closure_subset_closure_image {f : α → β} {s : Set α} (h : Continuous f) : +theorem image_closure_subset_closure_image {f : X → Y} {s : Set X} (h : Continuous f) : f '' closure s ⊆ closure (f '' s) := ((mapsTo_image f s).closure h).image_subset #align image_closure_subset_closure_image image_closure_subset_closure_image -- porting note: new lemma -theorem closure_image_closure {f : α → β} {s : Set α} (h : Continuous f) : +theorem closure_image_closure {f : X → Y} {s : Set X} (h : Continuous f) : closure (f '' closure s) = closure (f '' s) := Subset.antisymm (closure_minimal (image_closure_subset_closure_image h) isClosed_closure) (closure_mono <| image_subset _ subset_closure) -theorem closure_subset_preimage_closure_image {f : α → β} {s : Set α} (h : Continuous f) : +theorem closure_subset_preimage_closure_image {f : X → Y} {s : Set X} (h : Continuous f) : closure s ⊆ f ⁻¹' closure (f '' s) := by rw [← Set.image_subset_iff] exact image_closure_subset_closure_image h #align closure_subset_preimage_closure_image closure_subset_preimage_closure_image -theorem map_mem_closure {s : Set α} {t : Set β} {f : α → β} {a : α} (hf : Continuous f) +theorem map_mem_closure {s : Set X} {t : Set Y} {f : X → Y} {a : X} (hf : Continuous f) (ha : a ∈ closure s) (ht : MapsTo f s t) : f a ∈ closure t := ht.closure hf ha #align map_mem_closure map_mem_closure /-- If a continuous map `f` maps `s` to a closed set `t`, then it maps `closure s` to `t`. -/ -theorem Set.MapsTo.closure_left {s : Set α} {t : Set β} {f : α → β} (h : MapsTo f s t) +theorem Set.MapsTo.closure_left {s : Set X} {t : Set Y} {f : X → Y} (h : MapsTo f s t) (hc : Continuous f) (ht : IsClosed t) : MapsTo f (closure s) t := ht.closure_eq ▸ h.closure hc #align set.maps_to.closure_left Set.MapsTo.closure_left @@ -1848,9 +1852,9 @@ theorem Set.MapsTo.closure_left {s : Set α} {t : Set β} {f : α → β} (h : M section DenseRange -variable {κ ι : Type*} (f : κ → β) (g : β → γ) +variable {α ι : Type*} (f : α → X) (g : X → Y) -/-- `f : ι → β` has dense range if its range (image) is a dense subset of β. -/ +/-- `f : α → X` has dense range if its range (image) is a dense subset of `X`. -/ def DenseRange := Dense (range f) #align dense_range DenseRange @@ -1861,7 +1865,7 @@ theorem Function.Surjective.denseRange (hf : Function.Surjective f) : DenseRange simp [hf.range_eq] #align function.surjective.dense_range Function.Surjective.denseRange -theorem denseRange_id : DenseRange (id : α → α) := +theorem denseRange_id : DenseRange (id : X → X) := Function.Surjective.denseRange Function.surjective_id #align dense_range_id denseRange_id @@ -1873,25 +1877,25 @@ theorem DenseRange.closure_range (h : DenseRange f) : closure (range f) = univ : h.closure_eq #align dense_range.closure_range DenseRange.closure_range -theorem Dense.denseRange_val {s : Set α} (h : Dense s) : DenseRange ((↑) : s → α) := by +theorem Dense.denseRange_val {s : Set X} (h : Dense s) : DenseRange ((↑) : s → X) := by simpa only [DenseRange, Subtype.range_coe_subtype] #align dense.dense_range_coe Dense.denseRange_val -theorem Continuous.range_subset_closure_image_dense {f : α → β} (hf : Continuous f) {s : Set α} +theorem Continuous.range_subset_closure_image_dense {f : X → Y} (hf : Continuous f) {s : Set X} (hs : Dense s) : range f ⊆ closure (f '' s) := by rw [← image_univ, ← hs.closure_eq] exact image_closure_subset_closure_image hf #align continuous.range_subset_closure_image_dense Continuous.range_subset_closure_image_dense /-- The image of a dense set under a continuous map with dense range is a dense set. -/ -theorem DenseRange.dense_image {f : α → β} (hf' : DenseRange f) (hf : Continuous f) {s : Set α} +theorem DenseRange.dense_image {f : X → Y} (hf' : DenseRange f) (hf : Continuous f) {s : Set X} (hs : Dense s) : Dense (f '' s) := (hf'.mono <| hf.range_subset_closure_image_dense hs).of_closure #align dense_range.dense_image DenseRange.dense_image /-- If `f` has dense range and `s` is an open set in the codomain of `f`, then the image of the preimage of `s` under `f` is dense in `s`. -/ -theorem DenseRange.subset_closure_image_preimage_of_isOpen (hf : DenseRange f) {s : Set β} +theorem DenseRange.subset_closure_image_preimage_of_isOpen (hf : DenseRange f) {s : Set X} (hs : IsOpen s) : s ⊆ closure (f '' (f ⁻¹' s)) := by rw [image_preimage_eq_inter_range] exact hf.open_subset_closure_inter hs @@ -1899,38 +1903,38 @@ theorem DenseRange.subset_closure_image_preimage_of_isOpen (hf : DenseRange f) { /-- If a continuous map with dense range maps a dense set to a subset of `t`, then `t` is a dense set. -/ -theorem DenseRange.dense_of_mapsTo {f : α → β} (hf' : DenseRange f) (hf : Continuous f) {s : Set α} - (hs : Dense s) {t : Set β} (ht : MapsTo f s t) : Dense t := +theorem DenseRange.dense_of_mapsTo {f : X → Y} (hf' : DenseRange f) (hf : Continuous f) {s : Set X} + (hs : Dense s) {t : Set Y} (ht : MapsTo f s t) : Dense t := (hf'.dense_image hf hs).mono ht.image_subset #align dense_range.dense_of_maps_to DenseRange.dense_of_mapsTo /-- Composition of a continuous map with dense range and a function with dense range has dense range. -/ -theorem DenseRange.comp {g : β → γ} {f : κ → β} (hg : DenseRange g) (hf : DenseRange f) +theorem DenseRange.comp {g : Y → Z} {f : α → Y} (hg : DenseRange g) (hf : DenseRange f) (cg : Continuous g) : DenseRange (g ∘ f) := by rw [DenseRange, range_comp] exact hg.dense_image cg hf #align dense_range.comp DenseRange.comp -nonrec theorem DenseRange.nonempty_iff (hf : DenseRange f) : Nonempty κ ↔ Nonempty β := +nonrec theorem DenseRange.nonempty_iff (hf : DenseRange f) : Nonempty α ↔ Nonempty X := range_nonempty_iff_nonempty.symm.trans hf.nonempty_iff #align dense_range.nonempty_iff DenseRange.nonempty_iff -theorem DenseRange.nonempty [h : Nonempty β] (hf : DenseRange f) : Nonempty κ := +theorem DenseRange.nonempty [h : Nonempty X] (hf : DenseRange f) : Nonempty α := hf.nonempty_iff.mpr h #align dense_range.nonempty DenseRange.nonempty -/-- Given a function `f : α → β` with dense range and `b : β`, returns some `a : α`. -/ -def DenseRange.some (hf : DenseRange f) (b : β) : κ := +/-- Given a function `f : X → Y` with dense range and `b : Y`, returns some `a : X`. -/ +def DenseRange.some (hf : DenseRange f) (b : X) : α := Classical.choice <| hf.nonempty_iff.mpr ⟨b⟩ #align dense_range.some DenseRange.some -nonrec theorem DenseRange.exists_mem_open (hf : DenseRange f) {s : Set β} (ho : IsOpen s) +nonrec theorem DenseRange.exists_mem_open (hf : DenseRange f) {s : Set X} (ho : IsOpen s) (hs : s.Nonempty) : ∃ a, f a ∈ s := exists_range_iff.1 <| hf.exists_mem_open ho hs #align dense_range.exists_mem_open DenseRange.exists_mem_open -theorem DenseRange.mem_nhds {f : κ → β} (h : DenseRange f) {b : β} {U : Set β} (U_in : U ∈ 𝓝 b) : +theorem DenseRange.mem_nhds (h : DenseRange f) {b : X} {U : Set X} (U_in : U ∈ 𝓝 b) : ∃ a, f a ∈ U := let ⟨a, ha⟩ := h.exists_mem_open isOpen_interior ⟨b, mem_interior_iff_mem_nhds.2 U_in⟩ ⟨a, interior_subset ha⟩ @@ -1984,7 +1988,7 @@ This has the following advantages As an example for a unary operation, we have `Continuous.neg`. ``` -Continuous.neg {f : α → G} (hf : Continuous f) : Continuous (fun x ↦ -f x) +Continuous.neg {f : X → G} (hf : Continuous f) : Continuous (fun x ↦ -f x) ``` For unary functions, the elaborator is not confused when applying the traditional lemma (like `continuous_neg`), but it's still convenient to have the short version available (compare @@ -2056,7 +2060,7 @@ Only after elaborating the two `ContinuousAt` arguments, Lean will try to unify which is often easy after having chosen the correct functions for `f` and `g`. Here is an example that shows the difference: ``` -example [TopologicalSpace α] [TopologicalSpace β] {x₀ : α} (f : α → α → β) +example [TopologicalSpace X] [TopologicalSpace Y] {x₀ : X} (f : X → X → Y) (hf : ContinuousAt (Function.uncurry f) (x₀, x₀)) : ContinuousAt (fun x ↦ f x x) x₀ := -- hf.comp (continuousAt_id.prod continuousAt_id) -- type mismatch diff --git a/Mathlib/Topology/Bornology/Absorbs.lean b/Mathlib/Topology/Bornology/Absorbs.lean new file mode 100644 index 0000000000000..5b68b3b8ec4f0 --- /dev/null +++ b/Mathlib/Topology/Bornology/Absorbs.lean @@ -0,0 +1,268 @@ +/- +Copyright (c) 2020 Jean Lo, Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jean Lo, Yury Kudryashov +-/ +import Mathlib.Data.Set.Pointwise.SMul +import Mathlib.Topology.Bornology.Basic + +#align_import analysis.locally_convex.basic from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" + +/-! +# Absorption of sets + +Let `M` act on `α`, let `A` and `B` be sets in `α`. +We say that `A` *absorbs* `B` if for sufficiently large `a : M`, we have `B ⊆ a • A`. +Formally, "for sufficiently large `a : M`" means "for all but a bounded set of `a`". + +Traditionally, this definition is formulated +for the action of a (semi)normed ring on a module over that ring. + +We formulate it in a more general settings for two reasons: + +- this way we don't have to depend on metric spaces, normed rings etc; +- some proofs look nicer with this definition than with something like + `∃ r : ℝ, ∀ a : R, r ≤ ‖a‖ → B ⊆ a • A`. + +## Implementation notes + +For now, all theorems assume that we deal with (a generalization of) a module over a division ring. +Some lemmas have multiplicative versions for `MulDistribMulAction`s. +They can be added later when someone needs them. + +## Keywords + +absorbs, absorbent +-/ + +open Set Bornology Filter +open scoped Pointwise + +assert_not_exists Real + +section Defs + +variable (M : Type*) {α : Type*} [Bornology M] [SMul M α] + +/-- A set `s` absorbs another set `t` if `t` is contained in all scalings of `s` +by all but a bounded set of elements. -/ +def Absorbs (s t : Set α) : Prop := + ∀ᶠ a in cobounded M, t ⊆ a • s +#align absorbs Absorbs + +/-- A set is *absorbent* if it absorbs every singleton. -/ +def Absorbent (s : Set α) : Prop := + ∀ x, Absorbs M s {x} +#align absorbent Absorbent + +end Defs + +namespace Absorbs + +section SMul + +variable {M α : Type*} [Bornology M] [SMul M α] {s s₁ s₂ t t₁ t₂ : Set α} {S T : Set (Set α)} + +protected lemma empty : Absorbs M s ∅ := by simp [Absorbs] +#align absorbs_empty Absorbs.empty + +@[deprecated] -- Deprecated since 16 January 2024 +alias _root_.absorbs_empty := Absorbs.empty + +protected lemma eventually (h : Absorbs M s t) : ∀ᶠ a in cobounded M, t ⊆ a • s := h + +@[simp] lemma of_boundedSpace [BoundedSpace M] : Absorbs M s t := by simp [Absorbs] + +lemma mono_left (h : Absorbs M s₁ t) (hs : s₁ ⊆ s₂) : Absorbs M s₂ t := + h.mono fun _a ha ↦ ha.trans <| smul_set_mono hs +#align absorbs.mono_left Absorbs.mono_left + +lemma mono_right (h : Absorbs M s t₁) (ht : t₂ ⊆ t₁) : Absorbs M s t₂ := + h.mono fun _ ↦ ht.trans +#align absorbs.mono_right Absorbs.mono_right + +lemma mono (h : Absorbs M s₁ t₁) (hs : s₁ ⊆ s₂) (ht : t₂ ⊆ t₁) : Absorbs M s₂ t₂ := + (h.mono_left hs).mono_right ht +#align absorbs.mono Absorbs.mono + +@[simp] +lemma _root_.absorbs_union : Absorbs M s (t₁ ∪ t₂) ↔ Absorbs M s t₁ ∧ Absorbs M s t₂ := by + simp [Absorbs] +#align absorbs_union absorbs_union + +protected lemma union (h₁ : Absorbs M s t₁) (h₂ : Absorbs M s t₂) : Absorbs M s (t₁ ∪ t₂) := + absorbs_union.2 ⟨h₁, h₂⟩ +#align absorbs.union Absorbs.union + +lemma _root_.Set.Finite.absorbs_sUnion {T : Set (Set α)} (hT : T.Finite) : + Absorbs M s (⋃₀ T) ↔ ∀ t ∈ T, Absorbs M s t := by + simp [Absorbs, hT] + +protected lemma sUnion (hT : T.Finite) (hs : ∀ t ∈ T, Absorbs M s t) : + Absorbs M s (⋃₀ T) := + hT.absorbs_sUnion.2 hs + +@[simp] +lemma _root_.absorbs_iUnion {ι : Sort*} [Finite ι] {t : ι → Set α} : + Absorbs M s (⋃ i, t i) ↔ ∀ i, Absorbs M s (t i) := + (finite_range t).absorbs_sUnion.trans forall_range_iff + +protected alias ⟨_, iUnion⟩ := absorbs_iUnion + +lemma _root_.Set.Finite.absorbs_biUnion {ι : Type*} {t : ι → Set α} {I : Set ι} (hI : I.Finite) : + Absorbs M s (⋃ i ∈ I, t i) ↔ ∀ i ∈ I, Absorbs M s (t i) := by + simp [Absorbs, hI] +#align set.finite.absorbs_Union Set.Finite.absorbs_biUnion + +protected alias ⟨_, biUnion⟩ := Set.Finite.absorbs_biUnion + +@[deprecated] -- Deprecated since 16 January 2024 +alias _root_.Set.Finite.absorbs_iUnion := Set.Finite.absorbs_biUnion + +@[simp] +lemma _root_.absorbs_biUnion_finset {ι : Type*} {t : ι → Set α} {I : Finset ι} : + Absorbs M s (⋃ i ∈ I, t i) ↔ ∀ i ∈ I, Absorbs M s (t i) := + I.finite_toSet.absorbs_biUnion +#align absorbs_Union_finset absorbs_biUnion_finset + +protected alias ⟨_, biUnion_finset⟩ := absorbs_biUnion_finset + +@[deprecated] -- Deprecated since 16 January 2024 +alias _root_.absorbs_iUnion_finset := absorbs_biUnion_finset + +end SMul + +section AddZero + +variable {M E : Type*} [Bornology M] {s₁ s₂ t₁ t₂ : Set E} + +protected lemma add [AddZeroClass E] [DistribSMul M E] + (h₁ : Absorbs M s₁ t₁) (h₂ : Absorbs M s₂ t₂) : Absorbs M (s₁ + s₂) (t₁ + t₂) := + h₂.mp <| h₁.eventually.mono fun x hx₁ hx₂ ↦ by rw [smul_add]; exact add_subset_add hx₁ hx₂ +#align absorbs.add Absorbs.add + +protected lemma zero [Zero E] [SMulZeroClass M E] {s : Set E} (hs : 0 ∈ s) : Absorbs M s 0 := + eventually_of_forall fun _ ↦ zero_subset.2 <| zero_mem_smul_set hs + +end AddZero + +section GroupWithZero + +variable {G₀ α : Type*} [GroupWithZero G₀] [Bornology G₀] [MulAction G₀ α] + {s t u : Set α} {S : Set (Set α)} + +@[simp] +protected lemma univ : Absorbs G₀ univ s := + (eventually_ne_cobounded 0).mono fun a ha ↦ by rw [smul_set_univ₀ ha]; apply subset_univ + +lemma _root_.Set.Finite.absorbs_sInter (hS : S.Finite) : + Absorbs G₀ (⋂₀ S) t ↔ ∀ s ∈ S, Absorbs G₀ s t := by + simp only [Absorbs, ← hS.eventually_all] + refine eventually_congr <| (eventually_ne_cobounded 0).mono fun a ha ↦ ?_ + simp only [← preimage_smul_inv₀ ha, preimage_sInter, subset_iInter_iff] + +protected alias ⟨_, sInter⟩ := Set.Finite.absorbs_sInter + +@[simp] +lemma _root_.absorbs_inter : Absorbs G₀ (s ∩ t) u ↔ Absorbs G₀ s u ∧ Absorbs G₀ t u := by + simpa using ((finite_singleton t).insert s).absorbs_sInter +#align absorbs_inter absorbs_inter + +protected lemma inter (hs : Absorbs G₀ s u) (ht : Absorbs G₀ t u) : Absorbs G₀ (s ∩ t) u := + absorbs_inter.2 ⟨hs, ht⟩ +#align absorbs.inter Absorbs.inter + +@[simp] +lemma _root_.absorbs_iInter {ι : Sort*} [Finite ι] {s : ι → Set α} : + Absorbs G₀ (⋂ i, s i) t ↔ ∀ i, Absorbs G₀ (s i) t := + (finite_range s).absorbs_sInter.trans forall_range_iff + +protected alias ⟨_, iInter⟩ := absorbs_iInter + +lemma _root_.Set.Finite.absorbs_biInter {ι : Type*} {I : Set ι} (hI : I.Finite) {s : ι → Set α} : + Absorbs G₀ (⋂ i ∈ I, s i) t ↔ ∀ i ∈ I, Absorbs G₀ (s i) t := by + simpa only [sInter_image, ball_image_iff] using (hI.image s).absorbs_sInter + +protected alias ⟨_, biInter⟩ := Set.Finite.absorbs_biInter + +@[simp] +lemma _root_.absorbs_zero_iff [NeBot (cobounded G₀)] {E : Type*} [AddMonoid E] + [DistribMulAction G₀ E] {s : Set E} : Absorbs G₀ s 0 ↔ 0 ∈ s := by + refine ⟨fun h ↦ ?_, .zero⟩ + rcases (h.and (eventually_ne_cobounded 0)).exists with ⟨c, hc, hc₀⟩ + rcases hc rfl with ⟨x, hx, hx₀⟩ + rwa [← smul_zero c⁻¹, ← hx₀, inv_smul_smul₀ hc₀] +#align absorbs_zero_iff absorbs_zero_iff + +end GroupWithZero + +end Absorbs + +section AddGroup + +variable {M E : Type*} [Monoid M] [AddGroup E] [DistribMulAction M E] [Bornology M] + +@[simp] +lemma absorbs_neg_neg {s t : Set E} : Absorbs M (-s) (-t) ↔ Absorbs M s t := by simp [Absorbs] + +alias ⟨Absorbs.of_neg_neg, Absorbs.neg_neg⟩ := absorbs_neg_neg +#align absorbs.neg Absorbs.neg_neg + +lemma Absorbs.sub {s₁ s₂ t₁ t₂ : Set E} (h₁ : Absorbs M s₁ t₁) (h₂ : Absorbs M s₂ t₂) : + Absorbs M (s₁ - s₂) (t₁ - t₂) := by + simpa only [sub_eq_add_neg] using h₁.add h₂.neg_neg +#align absorbs.sub Absorbs.sub + +end AddGroup + +namespace Absorbent + +section SMul + +variable {M α : Type*} [Bornology M] [SMul M α] {s t : Set α} + +protected theorem mono (ht : Absorbent M s) (hsub : s ⊆ t) : Absorbent M t := fun x ↦ + (ht x).mono_left hsub +#align absorbent.subset Absorbent.mono + +@[deprecated] -- Deprecated since 16 January 2024 +protected alias subset := Absorbent.mono + +theorem _root_.absorbent_iff_forall_absorbs_singleton : Absorbent M s ↔ ∀ x, Absorbs M s {x} := .rfl +#align absorbent_iff_forall_absorbs_singleton absorbent_iff_forall_absorbs_singleton + +protected theorem absorbs (hs : Absorbent M s) {x : α} : Absorbs M s {x} := hs x +#align absorbent.absorbs Absorbent.absorbs + +#noalign absorbent_iff_nonneg_lt + +theorem absorbs_finite (hs : Absorbent M s) (ht : t.Finite) : Absorbs M s t := by + rw [← Set.biUnion_of_singleton t] + exact .biUnion ht fun _ _ => hs.absorbs +#align absorbent.absorbs_finite Absorbent.absorbs_finite + +end SMul + +theorem vadd_absorbs {M E : Type*} [Bornology M] [AddZeroClass E] [DistribSMul M E] + {s₁ s₂ t : Set E} {x : E} (h₁ : Absorbent M s₁) (h₂ : Absorbs M s₂ t) : + Absorbs M (s₁ + s₂) (x +ᵥ t) := by + rw [← singleton_vadd]; exact (h₁ x).add h₂ + +end Absorbent + +section GroupWithZero + +variable {G₀ α E : Type*} [GroupWithZero G₀] [Bornology G₀] [MulAction G₀ α] + +lemma absorbent_univ : Absorbent G₀ (univ : Set α) := fun _ ↦ .univ +#align absorbent_univ absorbent_univ + +lemma absorbent_iff_inv_smul {s : Set α} : + Absorbent G₀ s ↔ ∀ x, ∀ᶠ c in cobounded G₀, c⁻¹ • x ∈ s := + forall_congr' fun x ↦ eventually_congr <| (eventually_ne_cobounded 0).mono fun c hc ↦ by + rw [singleton_subset_iff, ← preimage_smul_inv₀ hc, mem_preimage] + +lemma Absorbent.zero_mem [NeBot (cobounded G₀)] [AddMonoid E] [DistribMulAction G₀ E] + {s : Set E} (hs : Absorbent G₀ s) : (0 : E) ∈ s := + absorbs_zero_iff.1 (hs 0) +#align absorbent.zero_mem Absorbent.zero_mem diff --git a/Mathlib/Topology/Bornology/Hom.lean b/Mathlib/Topology/Bornology/Hom.lean index fdb903c109980..7618061e49ccd 100644 --- a/Mathlib/Topology/Bornology/Hom.lean +++ b/Mathlib/Topology/Bornology/Hom.lean @@ -12,7 +12,7 @@ import Mathlib.Topology.Bornology.Basic This file defines locally bounded maps between bornologies. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -44,7 +44,7 @@ section You should extend this class when you extend `LocallyBoundedMap`. -/ class LocallyBoundedMapClass (F : Type*) (α β : outParam <| Type*) [Bornology α] - [Bornology β] extends FunLike F α fun _ => β where + [Bornology β] extends DFunLike F α (fun _ => β) where /-- The pullback of the `Bornology.cobounded` filter under the function is contained in the cobounded filter. Equivalently, the function maps bounded sets to bounded sets. -/ comap_cobounded_le (f : F) : (cobounded β).comap f ≤ cobounded α @@ -85,7 +85,7 @@ instance : LocallyBoundedMapClass (LocallyBoundedMap α β) α β where comap_cobounded_le f := f.comap_cobounded_le' /- omitting helper instance because it is not needed in Lean 4. -/-- Helper instance for when there's too many metavariables to apply the coercion via `FunLike` +/-- Helper instance for when there's too many metavariables to apply the coercion via `DFunLike` directly. instance : CoeFun (LocallyBoundedMap α β) fun _ => α → β where coe := LocallyBoundedMap.toFun -/ -/ @@ -95,7 +95,7 @@ instance : CoeFun (LocallyBoundedMap α β) fun _ => α → β where @[ext] theorem ext {f g : LocallyBoundedMap α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align locally_bounded_map.ext LocallyBoundedMap.ext /-- Copy of a `LocallyBoundedMap` with a new `toFun` equal to the old one. Useful to fix @@ -110,7 +110,7 @@ theorem coe_copy (f : LocallyBoundedMap α β) (f' : α → β) (h : f' = f) : #align locally_bounded_map.coe_copy LocallyBoundedMap.coe_copy theorem copy_eq (f : LocallyBoundedMap α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align locally_bounded_map.copy_eq LocallyBoundedMap.copy_eq /-- Construct a `LocallyBoundedMap` from the fact that the function maps bounded sets to bounded @@ -191,7 +191,7 @@ theorem id_comp (f : LocallyBoundedMap α β) : (LocallyBoundedMap.id β).comp f @[simp] theorem cancel_right {g₁ g₂ : LocallyBoundedMap β γ} {f : LocallyBoundedMap α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congrArg (fun x => comp x f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congrArg (fun x => comp x f)⟩ -- porting note: unification was not strong enough to do `congrArg _`. #align locally_bounded_map.cancel_right LocallyBoundedMap.cancel_right diff --git a/Mathlib/Topology/Category/Born.lean b/Mathlib/Topology/Category/Born.lean index 2a2c435eb5be2..e82c680df8b63 100644 --- a/Mathlib/Topology/Category/Born.lean +++ b/Mathlib/Topology/Category/Born.lean @@ -45,7 +45,7 @@ instance : Inhabited Born := instance : BundledHom @LocallyBoundedMap where id := @LocallyBoundedMap.id comp := @LocallyBoundedMap.comp - hom_ext _ _ := FunLike.coe_injective + hom_ext _ _ := DFunLike.coe_injective instance : LargeCategory.{u} Born := BundledHom.category LocallyBoundedMap diff --git a/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean b/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean index 20ca41e1f4c0d..c87770b1d66a6 100644 --- a/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean @@ -47,15 +47,16 @@ noncomputable def struct {B X : CompHaus.{u}} (π : X ⟶ B) (hπ : Function.Surjective π) : EffectiveEpiStruct π where desc e h := (QuotientMap.of_surjective_continuous hπ π.continuous).lift e fun a b hab ↦ - FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ + DFunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) a fac e h := ((QuotientMap.of_surjective_continuous hπ π.continuous).lift_comp e - fun a b hab ↦ FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ + fun a b hab ↦ DFunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) a) uniq e h g hm := by suffices g = (QuotientMap.of_surjective_continuous hπ π.continuous).liftEquiv ⟨e, - fun a b hab ↦ FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ - (by ext; exact hab)) a⟩ by assumption + fun a b hab ↦ DFunLike.congr_fun + (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) + a⟩ by assumption rw [← Equiv.symm_apply_eq (QuotientMap.of_surjective_continuous hπ π.continuous).liftEquiv] ext simp only [QuotientMap.liftEquiv_symm_apply_coe, ContinuousMap.comp_apply, ← hm] diff --git a/Mathlib/Topology/Category/CompHaus/Projective.lean b/Mathlib/Topology/Category/CompHaus/Projective.lean index fbf4c976e868c..fcd317a692ef0 100644 --- a/Mathlib/Topology/Category/CompHaus/Projective.lean +++ b/Mathlib/Topology/Category/CompHaus/Projective.lean @@ -35,7 +35,7 @@ open CategoryTheory Function namespace CompHaus -attribute [local instance] ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.instFunLike instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X) where @@ -54,7 +54,7 @@ instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X) let g'' : ContinuousMap Y Z := g have : g'' ∘ g' = id := hg'.comp_eq_id -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [comp.assoc, ultrafilter_extend_extends, ← comp.assoc, this, comp.left_id] + erw [comp.assoc, ultrafilter_extend_extends, ← comp.assoc, this, id_comp] set_option linter.uppercaseLean3 false in #align CompHaus.projective_ultrafilter CompHaus.projective_ultrafilter diff --git a/Mathlib/Topology/Category/LightProfinite/Basic.lean b/Mathlib/Topology/Category/LightProfinite/Basic.lean index 6124893194c69..10d168e3e2297 100644 --- a/Mathlib/Topology/Category/LightProfinite/Basic.lean +++ b/Mathlib/Topology/Category/LightProfinite/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Dagur Asgeirsson -/ import Mathlib.Topology.Category.Profinite.Basic +import Mathlib.CategoryTheory.Limits.ConcreteCategory /-! # Light profinite sets diff --git a/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean b/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean index 8329eaf12e998..bb345838f7615 100644 --- a/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean @@ -45,15 +45,16 @@ noncomputable def struct {B X : Profinite.{u}} (π : X ⟶ B) (hπ : Function.Surjective π) : EffectiveEpiStruct π where desc e h := (QuotientMap.of_surjective_continuous hπ π.continuous).lift e fun a b hab ↦ - FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ + DFunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) a fac e h := ((QuotientMap.of_surjective_continuous hπ π.continuous).lift_comp e - fun a b hab ↦ FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ + fun a b hab ↦ DFunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) a) uniq e h g hm := by suffices g = (QuotientMap.of_surjective_continuous hπ π.continuous).liftEquiv ⟨e, - fun a b hab ↦ FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ - (by ext; exact hab)) a⟩ by assumption + fun a b hab ↦ DFunLike.congr_fun + (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) + a⟩ by assumption rw [← Equiv.symm_apply_eq (QuotientMap.of_surjective_continuous hπ π.continuous).liftEquiv] ext simp only [QuotientMap.liftEquiv_symm_apply_coe, ContinuousMap.comp_apply, ← hm] diff --git a/Mathlib/Topology/Category/Profinite/Nobeling.lean b/Mathlib/Topology/Category/Profinite/Nobeling.lean index ff6e389613661..bcae50c87539e 100644 --- a/Mathlib/Topology/Category/Profinite/Nobeling.lean +++ b/Mathlib/Topology/Category/Profinite/Nobeling.lean @@ -7,6 +7,8 @@ import Mathlib.Algebra.Category.ModuleCat.Free import Mathlib.Topology.Category.Profinite.CofilteredLimit import Mathlib.Topology.Category.Profinite.Product import Mathlib.Topology.LocallyConstant.Algebra +import Mathlib.Init.Data.Bool.Lemmas +import Mathlib.Init.IteSimp /-! @@ -801,7 +803,7 @@ theorem Products.lt_nil_empty : { m : Products I | m < Products.nil } = ∅ := b instance {α : Type*} [TopologicalSpace α] [Inhabited α] : Nontrivial (LocallyConstant α ℤ) := by refine ⟨0, 1, fun h ↦ ?_⟩ apply @zero_ne_one ℤ - exact FunLike.congr_fun h default + exact DFunLike.congr_fun h default theorem Products.isGood_nil : Products.isGood ({fun _ ↦ false} : Set (I → Bool)) Products.nil := by intro h diff --git a/Mathlib/Topology/Category/Profinite/Projective.lean b/Mathlib/Topology/Category/Profinite/Projective.lean index 65bbc0534b537..919452e9b28b4 100644 --- a/Mathlib/Topology/Category/Profinite/Projective.lean +++ b/Mathlib/Topology/Category/Profinite/Projective.lean @@ -50,7 +50,7 @@ instance projective_ultrafilter (X : Type u) : Projective (of <| Ultrafilter X) let g'' : ContinuousMap Y Z := g have : g'' ∘ g' = id := hg'.comp_eq_id -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [comp.assoc, ultrafilter_extend_extends, ← comp.assoc, this, comp.left_id] + erw [comp.assoc, ultrafilter_extend_extends, ← comp.assoc, this, id_comp] #align Profinite.projective_ultrafilter Profinite.projective_ultrafilter /-- For any profinite `X`, the natural map `Ultrafilter X → X` is a projective presentation. -/ diff --git a/Mathlib/Topology/Category/Stonean/Basic.lean b/Mathlib/Topology/Category/Stonean/Basic.lean index ce06f29a1c3bb..4292c876d49b0 100644 --- a/Mathlib/Topology/Category/Stonean/Basic.lean +++ b/Mathlib/Topology/Category/Stonean/Basic.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Adam Topaz -/ import Mathlib.Topology.ExtremallyDisconnected -import Mathlib.CategoryTheory.Sites.Coherent import Mathlib.Topology.Category.CompHaus.Projective import Mathlib.Topology.Category.Profinite.Basic /-! @@ -105,7 +104,7 @@ instance : ConcreteCategory Stonean where forget := toCompHaus ⋙ forget _ instance : CoeSort Stonean.{u} (Type u) := ConcreteCategory.hasCoeToSort _ -instance {X Y : Stonean.{u}} : FunLike (X ⟶ Y) X (fun _ => Y) := ConcreteCategory.funLike +instance {X Y : Stonean.{u}} : FunLike (X ⟶ Y) X Y := ConcreteCategory.instFunLike /-- Stonean spaces are topological spaces. -/ instance instTopologicalSpace (X : Stonean.{u}) : TopologicalSpace X := diff --git a/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean b/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean index af3cdf38ed0e2..a9390df7776fa 100644 --- a/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean @@ -44,15 +44,16 @@ The theorem `Stonean.effectiveEpi_tfae` should be used instead. noncomputable def struct {B X : Stonean.{u}} (π : X ⟶ B) (hπ : Function.Surjective π) : EffectiveEpiStruct π where desc e h := (QuotientMap.of_surjective_continuous hπ π.continuous).lift e fun a b hab ↦ - FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ + DFunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) a fac e h := ((QuotientMap.of_surjective_continuous hπ π.continuous).lift_comp e - fun a b hab ↦ FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ + fun a b hab ↦ DFunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) a) uniq e h g hm := by suffices g = (QuotientMap.of_surjective_continuous hπ π.continuous).liftEquiv ⟨e, - fun a b hab ↦ FunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ - (by ext; exact hab)) a⟩ by assumption + fun a b hab ↦ DFunLike.congr_fun + (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) + a⟩ by assumption rw [← Equiv.symm_apply_eq (QuotientMap.of_surjective_continuous hπ π.continuous).liftEquiv] ext simp only [QuotientMap.liftEquiv_symm_apply_coe, ContinuousMap.comp_apply, ← hm] diff --git a/Mathlib/Topology/Category/Stonean/Limits.lean b/Mathlib/Topology/Category/Stonean/Limits.lean index b5a398cb137fc..8242e42902404 100644 --- a/Mathlib/Topology/Category/Stonean/Limits.lean +++ b/Mathlib/Topology/Category/Stonean/Limits.lean @@ -218,7 +218,7 @@ def pullback.lift {X Y Z W : Stonean} (f : X ⟶ Z) {i : Y ⟶ Z} (hi : OpenEmbe toFun := fun z => ⟨a z, by simp only [Set.mem_preimage] use (b z) - exact congr_fun (FunLike.ext'_iff.mp w.symm) z⟩ + exact congr_fun (DFunLike.ext'_iff.mp w.symm) z⟩ continuous_toFun := by apply Continuous.subtype_mk exact a.continuous @@ -248,7 +248,7 @@ lemma pullback.lift_snd {X Y Z W : Stonean} (f : X ⟶ Z) {i : Y ⟶ Z} (hi : Op pullback.lift f hi a b w ≫ Stonean.pullback.snd f hi = b := by congr ext z - have := congr_fun (FunLike.ext'_iff.mp w.symm) z + have := congr_fun (DFunLike.ext'_iff.mp w.symm) z have h : i (b z) = f (a z) := this suffices : b z = (Homeomorph.ofEmbedding i hi.toEmbedding).symm (⟨f (a z), by rw [← h]; simp⟩) · exact this.symm diff --git a/Mathlib/Topology/Category/TopCat/Basic.lean b/Mathlib/Topology/Category/TopCat/Basic.lean index b534a4fb82620..4f1c01eab23cf 100644 --- a/Mathlib/Topology/Category/TopCat/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Basic.lean @@ -59,7 +59,7 @@ set_option linter.uppercaseLean3 false in #align Top.topological_space_unbundled TopCat.topologicalSpaceUnbundled -- Porting note: cannot find a coercion to function otherwise -attribute [instance] ConcreteCategory.funLike in +attribute [instance] ConcreteCategory.instFunLike in instance (X Y : TopCat.{u}) : CoeFun (X ⟶ Y) fun _ => X → Y where coe f := f diff --git a/Mathlib/Topology/Category/TopCat/Limits/Basic.lean b/Mathlib/Topology/Category/TopCat/Limits/Basic.lean index 614c94581ea3d..48c92ac1d13a0 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Scott Morrison, Mario Carneiro, Andrew Yang -/ import Mathlib.Topology.Category.TopCat.Basic -import Mathlib.CategoryTheory.Limits.ConcreteCategory +import Mathlib.CategoryTheory.Limits.Types #align_import topology.category.Top.limits.basic from "leanprover-community/mathlib"@"178a32653e369dce2da68dc6b2694e385d484ef1" diff --git a/Mathlib/Topology/Category/TopCat/Limits/Products.lean b/Mathlib/Topology/Category/TopCat/Limits/Products.lean index 9ed64c2c05aa0..8e7820b7b05aa 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Products.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Products.lean @@ -6,6 +6,7 @@ Authors: Patrick Massot, Scott Morrison, Mario Carneiro, Andrew Yang import Mathlib.Topology.Category.TopCat.EpiMono import Mathlib.Topology.Category.TopCat.Limits.Basic import Mathlib.CategoryTheory.Limits.Shapes.Products +import Mathlib.CategoryTheory.Limits.ConcreteCategory #align_import topology.category.Top.limits.products from "leanprover-community/mathlib"@"178a32653e369dce2da68dc6b2694e385d484ef1" diff --git a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean index 4313fe71a6f48..a6b3fd7fdf161 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Scott Morrison, Mario Carneiro, Andrew Yang -/ import Mathlib.Topology.Category.TopCat.Limits.Products -import Mathlib.CategoryTheory.ConcreteCategory.Elementwise #align_import topology.category.Top.limits.pullbacks from "leanprover-community/mathlib"@"178a32653e369dce2da68dc6b2694e385d484ef1" diff --git a/Mathlib/Topology/CompactOpen.lean b/Mathlib/Topology/CompactOpen.lean index 0648669b5504a..3c626072d3f32 100644 --- a/Mathlib/Topology/CompactOpen.lean +++ b/Mathlib/Topology/CompactOpen.lean @@ -15,7 +15,8 @@ topological spaces. ## Main definitions -* `CompactOpen` is the compact-open topology on `C(X, Y)`. It is declared as an instance. +* `ContinuousMap.compactOpen` is the compact-open topology on `C(X, Y)`. + It is declared as an instance. * `ContinuousMap.coev` is the coevaluation map `Y → C(X, Y × X)`. It is always continuous. * `ContinuousMap.curry` is the currying map `C(X × Y, Z) → C(X, C(Y, Z))`. This map always exists and it is continuous as long as `X × Y` is locally compact. @@ -39,9 +40,8 @@ namespace ContinuousMap section CompactOpen -variable {X : Type*} {Y : Type*} {Z : Type*} - -variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] +variable {α X Y Z : Type*} +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] {K : Set X} {U : Set Y} /-- A generating set for the compact-open topology (when `s` is compact and `u` is open). -/ def CompactOpen.gen (s : Set X) (u : Set Y) : Set C(X, Y) := @@ -85,23 +85,28 @@ theorem compactOpen_eq : @compactOpen X Y _ _ = .generateFrom (Set.image2 CompactOpen.gen {s | IsCompact s} {t | IsOpen t}) := congr_arg TopologicalSpace.generateFrom <| Set.ext fun _ ↦ by simp [eq_comm] +/-- Definition of `ContinuousMap.compactOpen` in terms of `Set.image2` and `Set.MapsTo`. -/ +theorem compactOpen_eq_mapsTo : @compactOpen X Y _ _ = + .generateFrom (Set.image2 (fun K U ↦ {f | MapsTo f K U}) {K | IsCompact K} {U | IsOpen U}) := by + simp only [mapsTo', compactOpen_eq]; rfl + protected theorem isOpen_gen {s : Set X} (hs : IsCompact s) {u : Set Y} (hu : IsOpen u) : IsOpen (CompactOpen.gen s u) := TopologicalSpace.GenerateOpen.basic _ (by dsimp [mem_setOf_eq]; tauto) #align continuous_map.is_open_gen ContinuousMap.isOpen_gen -lemma isOpen_setOf_mapsTo {K : Set X} (hK : IsCompact K) {U : Set Y} (hU : IsOpen U) : +lemma isOpen_setOf_mapsTo (hK : IsCompact K) (hU : IsOpen U) : IsOpen {f : C(X, Y) | MapsTo f K U} := by - simpa only [mapsTo'] using ContinuousMap.isOpen_gen hK hU + rw [compactOpen_eq_mapsTo]; exact .basic _ (mem_image2_of_mem hK hU) -lemma eventually_mapsTo {f : C(X, Y)} {K U} (hK : IsCompact K) (hU : IsOpen U) (h : MapsTo f K U) : +lemma eventually_mapsTo {f : C(X, Y)} (hK : IsCompact K) (hU : IsOpen U) (h : MapsTo f K U) : ∀ᶠ g : C(X, Y) in 𝓝 f, MapsTo g K U := (isOpen_setOf_mapsTo hK hU).mem_nhds h -lemma tendsto_nhds_compactOpen {α : Type*} {l : Filter α} {f : α → C(Y, Z)} {g : C(Y, Z)} : +lemma tendsto_nhds_compactOpen {l : Filter α} {f : α → C(Y, Z)} {g : C(Y, Z)} : Tendsto f l (𝓝 g) ↔ ∀ K, IsCompact K → ∀ U, IsOpen U → MapsTo g K U → ∀ᶠ a in l, MapsTo (f a) K U := by - simp_rw [compactOpen_eq, tendsto_nhds_generateFrom_iff, forall_image2_iff, mapsTo']; rfl + simp_rw [compactOpen_eq_mapsTo, tendsto_nhds_generateFrom_iff, forall_image2_iff]; rfl lemma continuous_compactOpen {f : X → C(Y, Z)} : Continuous f ↔ ∀ K, IsCompact K → ∀ U, IsOpen U → IsOpen {x | MapsTo (f x) K U} := by @@ -111,43 +116,26 @@ section Functorial variable (g : C(Y, Z)) -private theorem preimage_gen {s : Set X} {u : Set Z} : - ContinuousMap.comp g ⁻¹' CompactOpen.gen s u = CompactOpen.gen s (g ⁻¹' u) := by - ext ⟨f, _⟩ - change g ∘ f '' s ⊆ u ↔ f '' s ⊆ g ⁻¹' u - rw [image_comp, image_subset_iff] - -/-- C(X, -) is a functor. -/ -theorem continuous_comp : Continuous (ContinuousMap.comp g : C(X, Y) → C(X, Z)) := - continuous_generateFrom_iff.2 fun m ⟨s, hs, u, hu, hm⟩ => by - rw [hm, preimage_gen g]; exact ContinuousMap.isOpen_gen hs (hu.preimage g.2) +/-- `C(X, ·)` is a functor. -/ +theorem continuous_comp : Continuous (g.comp : C(X, Y) → C(X, Z)) := + continuous_compactOpen.2 fun _K hK _U hU ↦ isOpen_setOf_mapsTo hK (hU.preimage g.2) #align continuous_map.continuous_comp ContinuousMap.continuous_comp -/-- If `g : C(Y, Z)` is a topology inducing map, then the composition -`ContinuousMap.comp g : C(X, Y) → C(X, Z)` is a topology inducing map too. -/ +/-- If `g : C(Y, Z)` is a topology inducing map, +then the composition `ContinuousMap.comp g : C(X, Y) → C(X, Z)` is a topology inducing map too. -/ theorem inducing_comp (hg : Inducing g) : Inducing (g.comp : C(X, Y) → C(X, Z)) where - induced := by - simp only [compactOpen_eq, induced_generateFrom_eq, image_image2, preimage_gen, - hg.setOf_isOpen, image2_image_right] + induced := by simp only [compactOpen_eq_mapsTo, induced_generateFrom_eq, image_image2, + hg.setOf_isOpen, image2_image_right]; rfl /-- If `g : C(Y, Z)` is a topological embedding, then the composition `ContinuousMap.comp g : C(X, Y) → C(X, Z)` is an embedding too. -/ theorem embedding_comp (hg : Embedding g) : Embedding (g.comp : C(X, Y) → C(X, Z)) := ⟨inducing_comp g hg.1, fun _ _ ↦ (cancel_left hg.2).1⟩ -variable (f : C(X, Y)) - -private theorem image_gen {s : Set X} (_ : IsCompact s) {u : Set Z} (_ : IsOpen u) : - (fun g : C(Y, Z) => g.comp f) ⁻¹' CompactOpen.gen s u = CompactOpen.gen (f '' s) u := by - ext ⟨g, _⟩ - change g ∘ f '' s ⊆ u ↔ g '' (f '' s) ⊆ u - rw [Set.image_comp] - -/-- C(-, Z) is a functor. -/ -theorem continuous_comp_left : Continuous (fun g => g.comp f : C(Y, Z) → C(X, Z)) := - continuous_generateFrom_iff.2 fun m ⟨s, hs, u, hu, hm⟩ => by - rw [hm, image_gen f hs hu] - exact ContinuousMap.isOpen_gen (hs.image f.2) hu +/-- `C(·, Z)` is a functor. -/ +theorem continuous_comp_left (f : C(X, Y)) : Continuous (fun g => g.comp f : C(Y, Z) → C(X, Z)) := + continuous_compactOpen.2 fun K hK U hU ↦ by + simpa only [mapsTo_image_iff] using isOpen_setOf_mapsTo (hK.image f.2) hU #align continuous_map.continuous_comp_left ContinuousMap.continuous_comp_left /-- Composition is a continuous map from `C(X, Y) × C(Y, Z)` to `C(X, Z)`, provided that `Y` is @@ -193,11 +181,8 @@ theorem continuous_eval [LocallyCompactPair X Y] : Continuous fun p : C(X, Y) × Porting note: merged `continuous_eval_const` with `continuous_eval_const'` removing unneeded assumptions. -/ @[continuity] -theorem continuous_eval_const (x : X) : - Continuous fun f : C(X, Y) => f x := by - refine continuous_def.2 fun U hU ↦ ?_ - convert ContinuousMap.isOpen_gen (isCompact_singleton (x := x)) hU using 1 - ext; simp [CompactOpen.gen] +theorem continuous_eval_const (a : X) : Continuous fun f : C(X, Y) => f a := + continuous_def.2 fun U hU ↦ by simpa using isOpen_setOf_mapsTo (isCompact_singleton (x := a)) hU #align continuous_map.continuous_eval_const' ContinuousMap.continuous_eval_const #align continuous_map.continuous_eval_const ContinuousMap.continuous_eval_const @@ -214,33 +199,33 @@ lemma isClosed_setOf_mapsTo {t : Set Y} (ht : IsClosed t) (s : Set X) : IsClosed {f : C(X, Y) | MapsTo f s t} := ht.setOf_mapsTo fun _ _ ↦ continuous_eval_const _ -lemma isClopen_setOf_mapsTo {K : Set X} (hK : IsCompact K) {U : Set Y} (hU : IsClopen U) : +lemma isClopen_setOf_mapsTo (hK : IsCompact K) (hU : IsClopen U) : IsClopen {f : C(X, Y) | MapsTo f K U} := ⟨isOpen_setOf_mapsTo hK hU.isOpen, isClosed_setOf_mapsTo hU.isClosed K⟩ instance [T0Space Y] : T0Space C(X, Y) := - t0Space_of_injective_of_continuous FunLike.coe_injective continuous_coe + t0Space_of_injective_of_continuous DFunLike.coe_injective continuous_coe instance [T1Space Y] : T1Space C(X, Y) := - t1Space_of_injective_of_continuous FunLike.coe_injective continuous_coe + t1Space_of_injective_of_continuous DFunLike.coe_injective continuous_coe instance [T2Space Y] : T2Space C(X, Y) := - .of_injective_continuous FunLike.coe_injective continuous_coe + .of_injective_continuous DFunLike.coe_injective continuous_coe end Ev section InfInduced +/-- For any subset `s` of `X`, the restriction of continuous functions to `s` is continuous +as a function from `C(X, Y)` to `C(s, Y)` with their respective compact-open topologies. -/ +theorem continuous_restrict (s : Set X) : Continuous fun F : C(X, Y) => F.restrict s := + continuous_comp_left <| restrict s <| .id X +#align continuous_map.continuous_restrict ContinuousMap.continuous_restrict + theorem compactOpen_le_induced (s : Set X) : (ContinuousMap.compactOpen : TopologicalSpace C(X, Y)) ≤ - TopologicalSpace.induced (ContinuousMap.restrict s) ContinuousMap.compactOpen := by - simp only [induced_generateFrom_eq, ContinuousMap.compactOpen] - apply TopologicalSpace.generateFrom_anti - rintro b ⟨a, ⟨c, hc, u, hu, rfl⟩, rfl⟩ - refine' ⟨(↑) '' c, hc.image continuous_subtype_val, u, hu, _⟩ - ext f - simp only [CompactOpen.gen, mem_setOf_eq, mem_preimage, ContinuousMap.coe_restrict] - rw [image_comp f ((↑) : s → X)] + .induced (restrict s) ContinuousMap.compactOpen := + (continuous_restrict s).le_induced #align continuous_map.compact_open_le_induced ContinuousMap.compactOpen_le_induced /-- The compact-open topology on `C(X, Y)` is equal to the infimum of the compact-open topologies @@ -264,13 +249,6 @@ theorem compactOpen_eq_sInf_induced : simp #align continuous_map.compact_open_eq_Inf_induced ContinuousMap.compactOpen_eq_sInf_induced -/-- For any subset `s` of `X`, the restriction of continuous functions to `s` is continuous as a -function from `C(X, Y)` to `C(s, Y)` with their respective compact-open topologies. -/ -theorem continuous_restrict (s : Set X) : Continuous fun F : C(X, Y) => F.restrict s := by - rw [continuous_iff_le_induced] - exact compactOpen_le_induced s -#align continuous_map.continuous_restrict ContinuousMap.continuous_restrict - theorem nhds_compactOpen_eq_sInf_nhds_induced (f : C(X, Y)) : 𝓝 f = ⨅ (s) (hs : IsCompact s), (𝓝 (f.restrict s)).comap (ContinuousMap.restrict s) := by rw [compactOpen_eq_sInf_induced] diff --git a/Mathlib/Topology/Compactness/Compact.lean b/Mathlib/Topology/Compactness/Compact.lean index 54dc5979f52e9..a2f69e0de3b6c 100644 --- a/Mathlib/Topology/Compactness/Compact.lean +++ b/Mathlib/Topology/Compactness/Compact.lean @@ -675,12 +675,6 @@ theorem IsCompact.nhdsSet_prod_eq {t : Set Y} (hs : IsCompact s) (ht : IsCompact simp_rw [hs.nhdsSet_prod_eq_biSup, ht.prod_nhdsSet_eq_biSup, nhdsSet, sSup_image, biSup_prod, nhds_prod_eq] -/-- The product of a neighborhood of `s` and a neighborhood of `t` is a neighborhood of `s ×ˢ t`, -formulated in terms of a filter inequality. -/ -theorem nhdsSet_prod_le (s : Set X) (t : Set Y) : 𝓝ˢ (s ×ˢ t) ≤ 𝓝ˢ s ×ˢ 𝓝ˢ t := - ((hasBasis_nhdsSet _).prod (hasBasis_nhdsSet _)).ge_iff.2 fun (_u, _v) ⟨⟨huo, hsu⟩, hvo, htv⟩ ↦ - (huo.prod hvo).mem_nhdsSet.2 <| prod_mono hsu htv - /-- If `s` and `t` are compact sets and `n` is an open neighborhood of `s × t`, then there exist open neighborhoods `u ⊇ s` and `v ⊇ t` such that `u × v ⊆ n`. @@ -929,6 +923,15 @@ theorem Inducing.isCompact_preimage {f : X → Y} (hf : Inducing f) (hf' : IsClo replace hK := hK.inter_right hf' rwa [hf.isCompact_iff, image_preimage_eq_inter_range] +lemma Inducing.isCompact_preimage_iff {f : X → Y} (hf : Inducing f) {K : Set Y} + (Kf : K ⊆ range f) : IsCompact (f ⁻¹' K) ↔ IsCompact K := by + rw [hf.isCompact_iff, image_preimage_eq_of_subset Kf] + +/-- The preimage of a compact set in the image of an inducing map is compact. -/ +lemma Inducing.isCompact_preimage' {f : X → Y} (hf : Inducing f) {K : Set Y} + (hK: IsCompact K) (Kf : K ⊆ range f) : IsCompact (f ⁻¹' K) := + (hf.isCompact_preimage_iff Kf).2 hK + /-- The preimage of a compact set under a closed embedding is a compact set. -/ theorem ClosedEmbedding.isCompact_preimage {f : X → Y} (hf : ClosedEmbedding f) {K : Set Y} (hK : IsCompact K) : IsCompact (f ⁻¹' K) := diff --git a/Mathlib/Topology/Compactness/Lindelof.lean b/Mathlib/Topology/Compactness/Lindelof.lean new file mode 100644 index 0000000000000..d31c8b9af3428 --- /dev/null +++ b/Mathlib/Topology/Compactness/Lindelof.lean @@ -0,0 +1,708 @@ +/- +Copyright (c) 2023 Josha Dekker. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Josha Dekker +-/ +import Mathlib.Topology.Bases +import Mathlib.Order.Filter.CountableInter +import Mathlib.Topology.Compactness.Compact + +/-! +# Lindelöf sets and Lindelöf spaces + +## Main definitions + +We define the following properties for sets in a topological space: + +* `IsLindelof s`: Two definitions are possible here. The more standard definition is that +every open cover that contains `s` contains a countable subcover. We choose for the equivalent +definition where we require that every nontrivial filter on `s` with the countable intersection +property has a clusterpoint. Equivalence is established in `isLindelof_iff_countable_subcover`. +* `LindelofSpace X`: `X` is Lindelöf if it is Lindelöf as a set. +* `NonLindelofSpace`: a space that is not a Lindëlof space, e.g. the Long Line. + +## Main results + +* `isLindelof_iff_countable_subcover`: A set is Lindelöf iff every open cover has a + countable subcover. + +## Implementation details + +* This API is mainly based on the API for IsCompact and follows notation and style as much + as possible. +-/ +open Set Filter Topology TopologicalSpace + + +universe u v + +variable {X : Type u} {Y : Type v} {ι : Type*} + +variable [TopologicalSpace X] [TopologicalSpace Y] {s t : Set X} + +section Lindelof + +/-- A set `s` is Lindelöf if every nontrivial filter `f` with the countable intersection + property that contains `s`, has a clusterpoint in `s`. The filter-free definition is given by + `isLindelof_iff_countable_subcover`. -/ +def IsLindelof (s : Set X) := + ∀ ⦃f⦄ [NeBot f] [CountableInterFilter f], f ≤ 𝓟 s → ∃ x ∈ s, ClusterPt x f + +/-- The complement to a Lindelöf set belongs to a filter `f` with the countable intersection + property if it belongs to each filter `𝓝 x ⊓ f`, `x ∈ s`. -/ +theorem IsLindelof.compl_mem_sets (hs : IsLindelof s) {f : Filter X} [CountableInterFilter f] + (hf : ∀ x ∈ s, sᶜ ∈ 𝓝 x ⊓ f) : sᶜ ∈ f := by + contrapose! hf + simp only [not_mem_iff_inf_principal_compl, compl_compl, inf_assoc] at hf ⊢ + exact hs inf_le_right + +/-- The complement to a Lindelöf set belongs to a filter `f` with the countable intersection + property if each `x ∈ s` has a neighborhood `t` within `s` such that `tᶜ` belongs to `f`. -/ +theorem IsLindelof.compl_mem_sets_of_nhdsWithin (hs : IsLindelof s) {f : Filter X} + [CountableInterFilter f] (hf : ∀ x ∈ s, ∃ t ∈ 𝓝[s] x, tᶜ ∈ f) : sᶜ ∈ f := by + refine hs.compl_mem_sets fun x hx ↦ ?_ + rw [← disjoint_principal_right, disjoint_right_comm, (basis_sets _).disjoint_iff_left] + exact hf x hx + +/-- If `p : Set X → Prop` is stable under restriction and union, and each point `x` + of a Lindelöf set `s` has a neighborhood `t` within `s` such that `p t`, then `p s` holds. -/ +@[elab_as_elim] +theorem IsLindelof.induction_on (hs : IsLindelof s) {p : Set X → Prop} + (hmono : ∀ ⦃s t⦄, s ⊆ t → p t → p s) + (hcountable_union : ∀ (S : Set (Set X)), S.Countable → (∀ s ∈ S, p s) → p (⋃₀ S)) + (hnhds : ∀ x ∈ s, ∃ t ∈ 𝓝[s] x, p t) : p s := by + let f : Filter X := ofCountableUnion p hcountable_union (fun t ht _ hsub ↦ hmono hsub ht) + have : sᶜ ∈ f := hs.compl_mem_sets_of_nhdsWithin (by simpa using hnhds) + rwa [← compl_compl s] + +/-- The intersection of a Lindelöf set and a closed set is a Lindelöf set. -/ +theorem IsLindelof.inter_right (hs : IsLindelof s) (ht : IsClosed t) : IsLindelof (s ∩ t) := by + intro f hnf _ hstf + rw [← inf_principal, le_inf_iff] at hstf + obtain ⟨x, hsx, hx⟩ : ∃ x ∈ s, ClusterPt x f := hs hstf.1 + have hxt : x ∈ t := ht.mem_of_nhdsWithin_neBot <| hx.mono hstf.2 + exact ⟨x, ⟨hsx, hxt⟩, hx⟩ + + /-- The intersection of a closed set and a Lindelöf set is a Lindelöf set. -/ +theorem IsLindelof.inter_left (ht : IsLindelof t) (hs : IsClosed s) : IsLindelof (s ∩ t) := + inter_comm t s ▸ ht.inter_right hs + + /-- The set difference of a Lindelöf set and an open set is a Lindelöf set. -/ +theorem IsLindelof.diff (hs : IsLindelof s) (ht : IsOpen t) : IsLindelof (s \ t) := + hs.inter_right (isClosed_compl_iff.mpr ht) + +/-- A closed subset of a Lindelöf set is a Lindelöf set. -/ +theorem IsLindelof.of_isClosed_subset (hs : IsLindelof s) (ht : IsClosed t) (h : t ⊆ s) : + IsLindelof t := inter_eq_self_of_subset_right h ▸ hs.inter_right ht + +/-- A continuous image of a Lindelöf set is a Lindelöf set. -/ +theorem IsLindelof.image_of_continuousOn {f : X → Y} (hs : IsLindelof s) (hf : ContinuousOn f s) : + IsLindelof (f '' s) := by + intro l lne _ ls + have : NeBot (l.comap f ⊓ 𝓟 s) := + comap_inf_principal_neBot_of_image_mem lne (le_principal_iff.1 ls) + obtain ⟨x, hxs, hx⟩ : ∃ x ∈ s, ClusterPt x (l.comap f ⊓ 𝓟 s) := @hs _ this _ inf_le_right + haveI := hx.neBot + use f x, mem_image_of_mem f hxs + have : Tendsto f (𝓝 x ⊓ (comap f l ⊓ 𝓟 s)) (𝓝 (f x) ⊓ l) := by + convert (hf x hxs).inf (@tendsto_comap _ _ f l) using 1 + rw [nhdsWithin] + ac_rfl + exact this.neBot + +/-- A continuous image of a Lindelöf set is a Lindelöf set within the codomain. -/ +theorem IsLindelof.image {f : X → Y} (hs : IsLindelof s) (hf : Continuous f) : + IsLindelof (f '' s) := hs.image_of_continuousOn hf.continuousOn + +/-- A filter with the countable intersection property that is finer than the principal filter on +a Lindelöf set `s` contains any open set that contains all clusterpoints of `s`. -/ +theorem IsLindelof.adherence_nhdset {f : Filter X} [CountableInterFilter f] (hs : IsLindelof s) + (hf₂ : f ≤ 𝓟 s) (ht₁ : IsOpen t) (ht₂ : ∀ x ∈ s, ClusterPt x f → x ∈ t) : t ∈ f := + (eq_or_neBot _).casesOn mem_of_eq_bot fun _ ↦ + let ⟨x, hx, hfx⟩ := @hs (f ⊓ 𝓟 tᶜ) _ _ <| inf_le_of_left_le hf₂ + have : x ∈ t := ht₂ x hx hfx.of_inf_left + have : tᶜ ∩ t ∈ 𝓝[tᶜ] x := inter_mem_nhdsWithin _ (ht₁.mem_nhds this) + have A : 𝓝[tᶜ] x = ⊥ := empty_mem_iff_bot.1 <| compl_inter_self t ▸ this + have : 𝓝[tᶜ] x ≠ ⊥ := hfx.of_inf_right.ne + absurd A this + +/--For every open cover of a Lindelöf set, there exists a countable subcover. -/ +theorem IsLindelof.elim_countable_subcover {ι : Type v} (hs : IsLindelof s) (U : ι → Set X) + (hUo : ∀ i, IsOpen (U i)) (hsU : s ⊆ ⋃ i, U i) : + ∃ r : Set ι, r.Countable ∧ (s ⊆ ⋃ i ∈ r, U i) := by + have hmono : ∀ ⦃s t : Set X⦄, s ⊆ t → (∃ r : Set ι, r.Countable ∧ t ⊆ ⋃ i ∈ r, U i) + → (∃ r : Set ι, r.Countable ∧ s ⊆ ⋃ i ∈ r, U i) := by + intro _ _ hst ⟨r, ⟨hrcountable,hsub⟩⟩ + exact ⟨r,hrcountable,Subset.trans hst hsub⟩ + have hcountable_union : ∀ (S : Set (Set X)), S.Countable + → (∀ s ∈ S, ∃ r : Set ι, r.Countable ∧ (s ⊆ ⋃ i ∈ r, U i)) + → ∃ r : Set ι, r.Countable ∧ (⋃₀ S ⊆ ⋃ i ∈ r, U i) := by + intro S hS hsr + choose! r hr using hsr + refine ⟨⋃ s ∈ S, r s, hS.biUnion_iff.mpr (fun s hs ↦ (hr s hs).1), ?_⟩ + refine sUnion_subset ?h.right.h + simp only [mem_iUnion, exists_prop, iUnion_exists, biUnion_and'] + exact fun i is x hx ↦ mem_biUnion is ((hr i is).2 hx) + have h_nhds : ∀ x ∈ s, ∃ t ∈ 𝓝[s] x, ∃ r : Set ι, r.Countable ∧ (t ⊆ ⋃ i ∈ r, U i) := by + intro x hx + let ⟨i, hi⟩ := mem_iUnion.1 (hsU hx) + refine ⟨U i, mem_nhdsWithin_of_mem_nhds ((hUo i).mem_nhds hi),{i}, by simp, ?_⟩ + simp only [mem_singleton_iff, iUnion_iUnion_eq_left] + exact Subset.refl _ + exact hs.induction_on hmono hcountable_union h_nhds + +theorem IsLindelof.elim_nhds_subcover' (hs : IsLindelof s) (U : ∀ x ∈ s, Set X) + (hU : ∀ x (hx : x ∈ s), U x ‹x ∈ s› ∈ 𝓝 x) : + ∃ t : Set s, t.Countable ∧ s ⊆ ⋃ x ∈ t, U (x : s) x.2 := by + have := hs.elim_countable_subcover (fun x : s ↦ interior (U x x.2)) (fun _ ↦ isOpen_interior) + fun x hx ↦ + mem_iUnion.2 ⟨⟨x, hx⟩, mem_interior_iff_mem_nhds.2 <| hU _ _⟩ + rcases this with ⟨r,⟨hr,hs⟩⟩ + use r, hr + apply Subset.trans hs + apply iUnion₂_subset + intro i hi + apply Subset.trans interior_subset + exact subset_iUnion_of_subset i (subset_iUnion_of_subset hi (Subset.refl _)) + +theorem IsLindelof.elim_nhds_subcover (hs : IsLindelof s) (U : X → Set X) + (hU : ∀ x ∈ s, U x ∈ 𝓝 x) : + ∃ t : Set X, t.Countable ∧ (∀ x ∈ t, x ∈ s) ∧ s ⊆ ⋃ x ∈ t, U x := by + let ⟨t, ⟨htc,htsub⟩⟩ := hs.elim_nhds_subcover' (fun x _ ↦ U x) hU + refine ⟨↑t, Countable.image htc Subtype.val,?_⟩ + constructor + · intro _; simp only [mem_image, Subtype.exists, exists_and_right, exists_eq_right, + forall_exists_index]; tauto + · have : ⋃ x ∈ t, U ↑x = ⋃ x ∈ Subtype.val '' t, U x := biUnion_image.symm + rw [← this]; assumption + +/-- The neighborhood filter of a Lindelöf set is disjoint with a filter `l` with the countable +intersection property if and only if the neighborhood filter of each point of this set +is disjoint with `l`. -/ +theorem IsLindelof.disjoint_nhdsSet_left {l : Filter X} [CountableInterFilter l] + (hs : IsLindelof s) : + Disjoint (𝓝ˢ s) l ↔ ∀ x ∈ s, Disjoint (𝓝 x) l := by + refine ⟨fun h x hx ↦ h.mono_left <| nhds_le_nhdsSet hx, fun H ↦ ?_⟩ + choose! U hxU hUl using fun x hx ↦ (nhds_basis_opens x).disjoint_iff_left.1 (H x hx) + choose hxU hUo using hxU + rcases hs.elim_nhds_subcover U fun x hx ↦ (hUo x hx).mem_nhds (hxU x hx) with ⟨t, htc, hts, hst⟩ + refine (hasBasis_nhdsSet _).disjoint_iff_left.2 + ⟨⋃ x ∈ t, U x, ⟨isOpen_biUnion fun x hx ↦ hUo x (hts x hx), hst⟩, ?_⟩ + rw [compl_iUnion₂] + exact (countable_bInter_mem htc).mpr (fun i hi ↦ hUl _ (hts _ hi)) + +/-- A filter `l` with the countable intersection property is disjoint with the neighborhood +filter of a Lindelöf set if and only if it is disjoint with the neighborhood filter of each point +of this set. -/ +theorem IsLindelof.disjoint_nhdsSet_right {l : Filter X} [CountableInterFilter l] + (hs : IsLindelof s) : Disjoint l (𝓝ˢ s) ↔ ∀ x ∈ s, Disjoint l (𝓝 x) := by + simpa only [disjoint_comm] using hs.disjoint_nhdsSet_left + +/-- For every family of closed sets whose intersection avoids a Lindelö set, +there exists a countable subfamily whose intersection avoids this Lindelöf set. -/ +theorem IsLindelof.elim_countable_subfamily_closed {ι : Type v} (hs : IsLindelof s) + (t : ι → Set X) (htc : ∀ i, IsClosed (t i)) (hst : (s ∩ ⋂ i, t i) = ∅) : + ∃ u : Set ι, u.Countable ∧ (s ∩ ⋂ i ∈ u, t i) = ∅ := by + let U := tᶜ + have hUo : ∀ i, IsOpen (U i) := by simp only [Pi.compl_apply, isOpen_compl_iff]; exact htc + have hsU : s ⊆ ⋃ i, U i := by + simp only [Pi.compl_apply] + rw [← compl_iInter] + apply disjoint_compl_left_iff_subset.mp + simp only [compl_iInter, compl_iUnion, compl_compl] + apply Disjoint.symm + exact disjoint_iff_inter_eq_empty.mpr hst + rcases hs.elim_countable_subcover U hUo hsU with ⟨u, ⟨hucount, husub⟩⟩ + use u, hucount + rw [← disjoint_compl_left_iff_subset] at husub + simp only [Pi.compl_apply, compl_iUnion, compl_compl] at husub + exact disjoint_iff_inter_eq_empty.mp (Disjoint.symm husub) + +/--To show that a Lindelöf set intersects the intersection of a family of closed sets, + it is sufficient to show that it intersects every countable subfamily. -/ +theorem IsLindelof.inter_iInter_nonempty {ι : Type v} (hs : IsLindelof s) (t : ι → Set X) + (htc : ∀ i, IsClosed (t i)) (hst : ∀ u : Set ι, u.Countable ∧ (s ∩ ⋂ i ∈ u, t i).Nonempty) : + (s ∩ ⋂ i, t i).Nonempty := by + contrapose! hst + rcases hs.elim_countable_subfamily_closed t htc hst with ⟨u, ⟨_, husub⟩⟩ + use u + apply fun _ ↦ husub + +/-- For every open cover of a Lindelöf set, there exists a countable subcover. -/ +theorem IsLindelof.elim_countable_subcover_image {b : Set ι} {c : ι → Set X} (hs : IsLindelof s) + (hc₁ : ∀ i ∈ b, IsOpen (c i)) (hc₂ : s ⊆ ⋃ i ∈ b, c i) : + ∃ b', b' ⊆ b ∧ Set.Countable b' ∧ s ⊆ ⋃ i ∈ b', c i := by + simp only [Subtype.forall', biUnion_eq_iUnion] at hc₁ hc₂ + rcases hs.elim_countable_subcover (fun i ↦ c i : b → Set X) hc₁ hc₂ with ⟨d, hd⟩ + refine ⟨Subtype.val '' d, by simp, Countable.image hd.1 Subtype.val, ?_⟩ + · rw [biUnion_image] + apply hd.2 + + +/-- A set `s` is Lindelöf if for every open cover of `s`, there exists a countable subcover. -/ +theorem isLindelof_of_countable_subcover + (h : ∀ {ι : Type u} (U : ι → Set X), (∀ i, IsOpen (U i)) → (s ⊆ ⋃ i, U i) → + ∃ t : Set ι, t.Countable ∧ s ⊆ ⋃ i ∈ t, U i) : + IsLindelof s := fun f hf hfs ↦ by + contrapose! h + simp only [ClusterPt, not_neBot, ← disjoint_iff, SetCoe.forall', + (nhds_basis_opens _).disjoint_iff_left] at h + choose fsub U hU hUf using h + refine ⟨s, U, fun x ↦ (hU x).2, fun x hx ↦ mem_iUnion.2 ⟨⟨x, hx⟩, (hU _).1 ⟩, ?_ ⟩ + intro t ht h + have uinf := f.sets_of_superset (le_principal_iff.1 fsub) h + have uninf : ⋂ i ∈ t, (U i)ᶜ ∈ f := (countable_bInter_mem ht).mpr (fun _ _ ↦ hUf _) + rw [← compl_iUnion₂] at uninf + have uninf := compl_not_mem uninf + simp only [compl_compl] at uninf + contradiction + +/-- A set `s` is Lindelöf if for every family of closed sets whose intersection avoids `s`, +there exists a countable subfamily whose intersection avoids `s`. -/ +theorem isLindelof_of_countable_subfamily_closed + (h : ∀ {ι : Type u} (t : ι → Set X), (∀ i, IsClosed (t i)) → (s ∩ ⋂ i, t i) = ∅ → + ∃ u : Set ι, u.Countable ∧ (s ∩ ⋂ i ∈ u, t i) = ∅) : + IsLindelof s := + isLindelof_of_countable_subcover fun U hUo hsU ↦ by + rw [← disjoint_compl_right_iff_subset, compl_iUnion, disjoint_iff] at hsU + rcases h (fun i ↦ (U i)ᶜ) (fun i ↦ (hUo _).isClosed_compl) hsU with ⟨t, ht⟩ + refine ⟨t, ?_⟩ + rwa [← disjoint_compl_right_iff_subset, compl_iUnion₂, disjoint_iff] + +/-- A set `s` is Lindelöf if and only if +for every open cover of `s`, there exists a countable subcover. -/ +theorem isLindelof_iff_countable_subcover : + IsLindelof s ↔ ∀ {ι : Type u} (U : ι → Set X), + (∀ i, IsOpen (U i)) → (s ⊆ ⋃ i, U i) → ∃ t : Set ι, t.Countable ∧ s ⊆ ⋃ i ∈ t, U i := + ⟨fun hs ↦ hs.elim_countable_subcover, isLindelof_of_countable_subcover⟩ + +/-- A set `s` is Lindelöf if and only if +for every family of closed sets whose intersection avoids `s`, +there exists a countable subfamily whose intersection avoids `s`. -/ +theorem isLindelof_iff_countable_subfamily_closed : + IsLindelof s ↔ ∀ {ι : Type u} (t : ι → Set X), + (∀ i, IsClosed (t i)) → (s ∩ ⋂ i, t i) = ∅ + → ∃ u : Set ι, u.Countable ∧ (s ∩ ⋂ i ∈ u, t i) = ∅ := + ⟨fun hs ↦ hs.elim_countable_subfamily_closed, isLindelof_of_countable_subfamily_closed⟩ + +/-- The empty set is a Lindelof set. -/ +@[simp] +theorem isLindelof_empty : IsLindelof (∅ : Set X) := fun _f hnf _ hsf↦ + Not.elim hnf.ne <| empty_mem_iff_bot.1 <| le_principal_iff.1 hsf + +/-- A singleton set is a Lindelof set. -/ +@[simp] +theorem isLindelof_singleton {x : X} : IsLindelof ({x} : Set X) := fun f hf _ hfa ↦ + ⟨x, rfl, ClusterPt.of_le_nhds' + (hfa.trans <| by simpa only [principal_singleton] using pure_le_nhds x) hf⟩ + +theorem Set.Subsingleton.isLindelof (hs : s.Subsingleton) : IsLindelof s := + Subsingleton.induction_on hs isLindelof_empty fun _ ↦ isLindelof_singleton + +theorem Set.Countable.isLindelof_biUnion {s : Set ι} {f : ι → Set X} (hs : s.Countable) + (hf : ∀ i ∈ s, IsLindelof (f i)) : IsLindelof (⋃ i ∈ s, f i) := by + apply isLindelof_of_countable_subcover + intro i U hU hUcover + have hiU : ∀ i ∈ s, f i ⊆ ⋃ i, U i := fun _ is ↦ subset_trans (subset_biUnion_of_mem is) hUcover + have iSets := fun i is ↦ (hf i is).elim_countable_subcover U hU (hiU i is) + choose! r hr using iSets + use ⋃ i ∈ s, r i + constructor + · refine (Countable.biUnion_iff hs).mpr ?h.left.a + exact fun s hs ↦ (hr s hs).1 + · refine iUnion₂_subset ?h.right.h + intro i + simp + exact fun is x hx ↦ mem_biUnion is ((hr i is).2 hx) + + +theorem Set.Finite.isLindelof_biUnion {s : Set ι} {f : ι → Set X} (hs : s.Finite) + (hf : ∀ i ∈ s, IsLindelof (f i)) : IsLindelof (⋃ i ∈ s, f i) := by + apply Set.Countable.isLindelof_biUnion (countable hs) hf + +theorem Finset.isLindelof_biUnion (s : Finset ι) {f : ι → Set X} (hf : ∀ i ∈ s, IsLindelof (f i)) : + IsLindelof (⋃ i ∈ s, f i) := + s.finite_toSet.isLindelof_biUnion hf + +theorem isLindelof_accumulate {K : ℕ → Set X} (hK : ∀ n, IsLindelof (K n)) (n : ℕ) : + IsLindelof (Accumulate K n) := + (finite_le_nat n).isLindelof_biUnion fun k _ => hK k + +theorem Set.Countable.isLindelof_sUnion {S : Set (Set X)} (hf : S.Countable) + (hc : ∀ s ∈ S, IsLindelof s) : IsLindelof (⋃₀ S) := by + rw [sUnion_eq_biUnion]; exact hf.isLindelof_biUnion hc + +theorem Set.Finite.isLindelof_sUnion {S : Set (Set X)} (hf : S.Finite) + (hc : ∀ s ∈ S, IsLindelof s) : IsLindelof (⋃₀ S) := by + rw [sUnion_eq_biUnion]; exact hf.isLindelof_biUnion hc + +theorem isLindelof_iUnion {ι : Sort*} {f : ι → Set X} [Countable ι] (h : ∀ i, IsLindelof (f i)) : + IsLindelof (⋃ i, f i) := (countable_range f).isLindelof_sUnion <| forall_range_iff.2 h + +theorem Set.Countable.isLindelof (hs : s.Countable) : IsLindelof s := + biUnion_of_singleton s ▸ hs.isLindelof_biUnion fun _ _ => isLindelof_singleton + +theorem Set.Finite.isLindelof (hs : s.Finite) : IsLindelof s := + biUnion_of_singleton s ▸ hs.isLindelof_biUnion fun _ _ => isLindelof_singleton + +theorem IsLindelof.countable_of_discrete [DiscreteTopology X] (hs : IsLindelof s) : + s.Countable := by + have : ∀ x : X, ({x} : Set X) ∈ 𝓝 x := by simp [nhds_discrete] + rcases hs.elim_nhds_subcover (fun x => {x}) fun x _ => this x with ⟨t, _, _, hssubt⟩ + simp only [biUnion_of_singleton] at hssubt + apply Countable.mono hssubt + assumption + +theorem isLindelof_iff_countable [DiscreteTopology X] : IsLindelof s ↔ s.Countable := + ⟨fun h => h.countable_of_discrete, fun h => h.isLindelof⟩ + +theorem IsLindelof.union (hs : IsLindelof s) (ht : IsLindelof t) : IsLindelof (s ∪ t) := by + rw [union_eq_iUnion]; exact isLindelof_iUnion fun b => by cases b <;> assumption + +protected theorem IsLindelof.insert (hs : IsLindelof s) (a) : IsLindelof (insert a s) := + isLindelof_singleton.union hs + +/-- If `X` has a basis consisting of compact opens, then an open set in `X` is compact open iff +it is a finite union of some elements in the basis -/ +theorem isLindelof_open_iff_eq_countable_iUnion_of_isTopologicalBasis (b : ι → Set X) + (hb : IsTopologicalBasis (Set.range b)) (hb' : ∀ i, IsLindelof (b i)) (U : Set X) : + IsLindelof U ∧ IsOpen U ↔ ∃ s : Set ι, s.Countable ∧ U = ⋃ i ∈ s, b i := by + constructor + · rintro ⟨h₁, h₂⟩ + obtain ⟨Y, f, e, hf⟩ := hb.open_eq_iUnion h₂ + choose f' hf' using hf + have : b ∘ f' = f := funext hf' + subst this + obtain ⟨t, ht⟩ := + h₁.elim_countable_subcover (b ∘ f') (fun i => hb.isOpen (Set.mem_range_self _)) (by rw [e]) + refine ⟨t.image f', Countable.image (ht.1) f', le_antisymm ?_ ?_⟩ + · refine' Set.Subset.trans ht.2 _ + simp only [Set.iUnion_subset_iff] + intro i hi + erw [← Set.iUnion_subtype (fun x : ι => x ∈ t.image f') fun i => b i.1] + exact Set.subset_iUnion (fun i : t.image f' => b i) ⟨_, mem_image_of_mem _ hi⟩ + · apply Set.iUnion₂_subset + rintro i hi + have : ∃ j ∈ t, f' j = i := by exact hi + obtain ⟨j, -, rfl⟩ := this + rw [e] + exact Set.subset_iUnion (b ∘ f') j + · rintro ⟨s, hs, rfl⟩ + constructor + · exact hs.isLindelof_biUnion fun i _ => hb' i + · exact isOpen_biUnion fun i _ => hb.isOpen (Set.mem_range_self _) + +/--`Filter.coLindelof` is the filter generated by complements to Lindelöf sets. -/ +def Filter.coLindelof (X : Type*) [TopologicalSpace X] : Filter X := + --`Filter.coLindelof` is the filter generated by complements to Lindelöf sets. + ⨅ (s : Set X) (_ : IsLindelof s), 𝓟 sᶜ + +theorem hasBasis_coLindelof : (coLindelof X).HasBasis IsLindelof compl := + hasBasis_biInf_principal' + (fun s hs t ht => + ⟨s ∪ t, hs.union ht, compl_subset_compl.2 (subset_union_left s t), + compl_subset_compl.2 (subset_union_right s t)⟩) + ⟨∅, isLindelof_empty⟩ + +theorem mem_coLindelof : s ∈ coLindelof X ↔ ∃ t, IsLindelof t ∧ tᶜ ⊆ s := + hasBasis_coLindelof.mem_iff + +theorem mem_coLindelof' : s ∈ coLindelof X ↔ ∃ t, IsLindelof t ∧ sᶜ ⊆ t := + mem_coLindelof.trans <| exists_congr fun _ => and_congr_right fun _ => compl_subset_comm + +theorem _root_.IsLindelof.compl_mem_coLindelof (hs : IsLindelof s) : sᶜ ∈ coLindelof X := + hasBasis_coLindelof.mem_of_mem hs + +theorem coLindelof_le_cofinite : coLindelof X ≤ cofinite := fun s hs => + compl_compl s ▸ hs.isLindelof.compl_mem_coLindelof + +theorem Tendsto.isLindelof_insert_range_of_coLindelof {f : X → Y} {y} + (hf : Tendsto f (coLindelof X) (𝓝 y)) (hfc : Continuous f) : + IsLindelof (insert y (range f)) := by + intro l hne _ hle + by_cases hy : ClusterPt y l + · exact ⟨y, Or.inl rfl, hy⟩ + simp only [clusterPt_iff, not_forall, ← not_disjoint_iff_nonempty_inter, not_not] at hy + rcases hy with ⟨s, hsy, t, htl, hd⟩ + rcases mem_coLindelof.1 (hf hsy) with ⟨K, hKc, hKs⟩ + have : f '' K ∈ l := by + filter_upwards [htl, le_principal_iff.1 hle] with y hyt hyf + rcases hyf with (rfl | ⟨x, rfl⟩) + exacts [(hd.le_bot ⟨mem_of_mem_nhds hsy, hyt⟩).elim, + mem_image_of_mem _ (not_not.1 fun hxK => hd.le_bot ⟨hKs hxK, hyt⟩)] + rcases hKc.image hfc (le_principal_iff.2 this) with ⟨y, hy, hyl⟩ + exact ⟨y, Or.inr <| image_subset_range _ _ hy, hyl⟩ + +/-- `Filter.coclosedLindelof` is the filter generated by complements to closed Lindelof sets. -/ +def Filter.coclosedLindelof (X : Type*) [TopologicalSpace X] : Filter X := + -- `Filter.coclosedLindelof` is the filter generated by complements to closed Lindelof sets. + ⨅ (s : Set X) (_ : IsClosed s) (_ : IsLindelof s), 𝓟 sᶜ + +theorem hasBasis_coclosedLindelof : + (Filter.coclosedLindelof X).HasBasis (fun s => IsClosed s ∧ IsLindelof s) compl := by + simp only [Filter.coclosedLindelof, iInf_and'] + refine' hasBasis_biInf_principal' _ ⟨∅, isClosed_empty, isLindelof_empty⟩ + rintro s ⟨hs₁, hs₂⟩ t ⟨ht₁, ht₂⟩ + exact ⟨s ∪ t, ⟨⟨hs₁.union ht₁, hs₂.union ht₂⟩, compl_subset_compl.2 (subset_union_left _ _), + compl_subset_compl.2 (subset_union_right _ _)⟩⟩ + +theorem mem_coclosedLindelof : s ∈ coclosedLindelof X ↔ + ∃ t, IsClosed t ∧ IsLindelof t ∧ tᶜ ⊆ s := by + simp only [hasBasis_coclosedLindelof.mem_iff, and_assoc] + +theorem mem_coclosed_Lindelof' : s ∈ coclosedLindelof X ↔ + ∃ t, IsClosed t ∧ IsLindelof t ∧ sᶜ ⊆ t := by + simp only [mem_coclosedLindelof, compl_subset_comm] + +theorem coLindelof_le_coclosedLindelof : coLindelof X ≤ coclosedLindelof X := + iInf_mono fun _ => le_iInf fun _ => le_rfl + +theorem IsLindeof.compl_mem_coclosedLindelof_of_isClosed (hs : IsLindelof s) (hs' : IsClosed s) : + sᶜ ∈ Filter.coclosedLindelof X := + hasBasis_coclosedLindelof.mem_of_mem ⟨hs', hs⟩ + +/-- X is a Lindelöf space iff every open cover has a countable subcover.-/ +class LindelofSpace (X : Type*) [TopologicalSpace X] : Prop where + /-- In a Lindelöf space, `Set.univ` is a Lindelöf set. -/ + isLindelof_univ : IsLindelof (univ : Set X) + +instance (priority := 10) Subsingleton.lindelofSpace [Subsingleton X] : LindelofSpace X := + ⟨subsingleton_univ.isLindelof⟩ + +theorem isLindelof_univ_iff : IsLindelof (univ : Set X) ↔ LindelofSpace X := + ⟨fun h => ⟨h⟩, fun h => h.1⟩ + +theorem isLindelof_univ [h : LindelofSpace X] : IsLindelof (univ : Set X) := + h.isLindelof_univ + +theorem cluster_point_of_Lindelof [LindelofSpace X] (f : Filter X) [NeBot f] + [CountableInterFilter f] : ∃ x, ClusterPt x f := + by simpa using isLindelof_univ (show f ≤ 𝓟 univ by simp) + +theorem LindelofSpace.elim_nhds_subcover [LindelofSpace X] (U : X → Set X) (hU : ∀ x, U x ∈ 𝓝 x) : + ∃ t : Set X, t.Countable ∧ ⋃ x ∈ t, U x = ⊤ := by + obtain ⟨t, tc, -,s⟩ := IsLindelof.elim_nhds_subcover isLindelof_univ U fun x _ => hU x + use t, tc + apply top_unique s + +theorem lindelofSpace_of_countable_subfamily_closed + (h : ∀ {ι : Type u} (t : ι → Set X), (∀ i, IsClosed (t i)) → ⋂ i, t i = ∅ → + ∃ u : Set ι, u.Countable ∧ ⋂ i ∈ u, t i = ∅) : + LindelofSpace X where + isLindelof_univ := isLindelof_of_countable_subfamily_closed fun t => by simpa using h t + +theorem IsClosed.isLindelof [LindelofSpace X] (h : IsClosed s) : IsLindelof s := + isLindelof_univ.of_isClosed_subset h (subset_univ _) + +/-- A compact set `s` is Lindelöf. -/ +theorem IsCompact.isLindelof (hs : IsCompact s) : + IsLindelof s := by tauto + +/-- A compact space `X` is Lindelöf. -/ +instance (priority := 100) [CompactSpace X] : LindelofSpace X := + { isLindelof_univ := isCompact_univ.isLindelof} + +/-- `X` is a non-Lindelöf topological space if it is not a Lindelöf space. -/ +class NonLindelofSpace (X : Type*) [TopologicalSpace X] : Prop where + /-- In a non-Lindelöf space, `Set.univ` is not a Lindelöf set. -/ + nonLindelof_univ : ¬IsLindelof (univ : Set X) + + +lemma nonLindelof_univ (X : Type*) [TopologicalSpace X] [NonLindelofSpace X] : + ¬IsLindelof (univ : Set X) := + NonLindelofSpace.nonLindelof_univ + +theorem IsLindelof.ne_univ [NonLindelofSpace X] (hs : IsLindelof s) : s ≠ univ := fun h ↦ + nonLindelof_univ X (h ▸ hs) + +instance [NonLindelofSpace X] : NeBot (Filter.coLindelof X) := by + refine' hasBasis_coLindelof.neBot_iff.2 fun hs => _ + contrapose hs; rw [not_nonempty_iff_eq_empty, compl_empty_iff] at hs + rw [hs]; exact nonLindelof_univ X + +@[simp] +theorem Filter.coLindelof_eq_bot [LindelofSpace X] : Filter.coLindelof X = ⊥ := + hasBasis_coLindelof.eq_bot_iff.mpr ⟨Set.univ, isLindelof_univ, Set.compl_univ⟩ + +instance [NonLindelofSpace X] : NeBot (Filter.coclosedLindelof X) := + neBot_of_le coLindelof_le_coclosedLindelof + +theorem nonLindelofSpace_of_neBot (_ : NeBot (Filter.coLindelof X)) : NonLindelofSpace X := + ⟨fun h' => (Filter.nonempty_of_mem h'.compl_mem_coLindelof).ne_empty compl_univ⟩ + +theorem Filter.coLindelof_neBot_iff : NeBot (Filter.coLindelof X) ↔ NonLindelofSpace X := + ⟨nonLindelofSpace_of_neBot, fun _ => inferInstance⟩ + + +theorem not_LindelofSpace_iff : ¬LindelofSpace X ↔ NonLindelofSpace X := + ⟨fun h₁ => ⟨fun h₂ => h₁ ⟨h₂⟩⟩, fun ⟨h₁⟩ ⟨h₂⟩ => h₁ h₂⟩ + +/-- A compact space `X` is Lindelöf. -/ +instance (priority := 100) [CompactSpace X] : LindelofSpace X := + { isLindelof_univ := isCompact_univ.isLindelof} + +theorem countable_of_Lindelof_of_discrete [LindelofSpace X] [DiscreteTopology X] : Countable X := + countable_univ_iff.mp isLindelof_univ.countable_of_discrete + +theorem countable_cover_nhds_interior [LindelofSpace X] {U : X → Set X} (hU : ∀ x, U x ∈ 𝓝 x) : + ∃ t : Set X, t.Countable ∧ ⋃ x ∈ t, interior (U x) = univ := + let ⟨t, ht⟩ := isLindelof_univ.elim_countable_subcover (fun x => interior (U x)) + (fun _ => isOpen_interior) fun x _ => mem_iUnion.2 ⟨x, mem_interior_iff_mem_nhds.2 (hU x)⟩ + ⟨t, ⟨ht.1, univ_subset_iff.1 ht.2⟩⟩ + +theorem countable_cover_nhds [LindelofSpace X] {U : X → Set X} (hU : ∀ x, U x ∈ 𝓝 x) : + ∃ t : Set X, t.Countable ∧ ⋃ x ∈ t, U x = univ := + let ⟨t, ht⟩ := countable_cover_nhds_interior hU + ⟨t, ⟨ht.1, univ_subset_iff.1 <| ht.2.symm.subset.trans <| + iUnion₂_mono fun _ _ => interior_subset⟩⟩ + +/-- The comap of the coLindelöf filter on `Y` by a continuous function `f : X → Y` is less than or +equal to the coLindelöf filter on `X`. +This is a reformulation of the fact that images of Lindelöf sets are Lindelöf. -/ +theorem Filter.comap_coLindelof_le {f : X → Y} (hf : Continuous f) : + (Filter.coLindelof Y).comap f ≤ Filter.coLindelof X := by + rw [(hasBasis_coLindelof.comap f).le_basis_iff hasBasis_coLindelof] + intro t ht + refine' ⟨f '' t, ht.image hf, _⟩ + simpa using t.subset_preimage_image f + +theorem isLindelof_range [LindelofSpace X] {f : X → Y} (hf : Continuous f) : IsLindelof (range f) := + by rw [← image_univ]; exact isLindelof_univ.image hf + +theorem isLindelof_diagonal [LindelofSpace X] : IsLindelof (diagonal X) := + @range_diag X ▸ isLindelof_range (continuous_id.prod_mk continuous_id) + +/-- If `f : X → Y` is an `Inducing` map, the image `f '' s` of a set `s` is Lindelöf + if and only if `s` is compact. -/ +theorem Inducing.isLindelof_iff {f : X → Y} (hf : Inducing f) : + IsLindelof s ↔ IsLindelof (f '' s) := by + refine ⟨fun hs => hs.image hf.continuous, fun hs F F_ne_bot _ F_le => ?_⟩ + obtain ⟨_, ⟨x, x_in : x ∈ s, rfl⟩, hx : ClusterPt (f x) (map f F)⟩ := + hs ((map_mono F_le).trans_eq map_principal) + exact ⟨x, x_in, hf.mapClusterPt_iff.1 hx⟩ + +/-- If `f : X → Y` is an `Embedding`, the image `f '' s` of a set `s` is Lindelöf + if and only if `s` is Lindelöf. -/ +theorem Embedding.isLindelof_iff {f : X → Y} (hf : Embedding f) : + IsLindelof s ↔ IsLindelof (f '' s) := hf.toInducing.isLindelof_iff + +/-- The preimage of a Lindelöf set under an inducing map is a Lindelöf set. -/ +theorem Inducing.isLindelof_preimage {f : X → Y} (hf : Inducing f) (hf' : IsClosed (range f)) + {K : Set Y} (hK : IsLindelof K) : IsLindelof (f ⁻¹' K) := by + replace hK := hK.inter_right hf' + rwa [hf.isLindelof_iff, image_preimage_eq_inter_range] + +/-- The preimage of a Lindelöf set under a closed embedding is a Lindelöf set. -/ +theorem ClosedEmbedding.isLindelof_preimage {f : X → Y} (hf : ClosedEmbedding f) + {K : Set Y} (hK : IsLindelof K) : IsLindelof (f ⁻¹' K) := + hf.toInducing.isLindelof_preimage (hf.closed_range) hK + +/-- A closed embedding is proper, ie, inverse images of Lindelöf sets are contained in Lindelöf. +Moreover, the preimage of a Lindelöf set is Lindelöf, see `ClosedEmbedding.isLindelof_preimage`. -/ +theorem ClosedEmbedding.tendsto_coLindelof {f : X → Y} (hf : ClosedEmbedding f) : + Tendsto f (Filter.coLindelof X) (Filter.coLindelof Y) := + hasBasis_coLindelof.tendsto_right_iff.mpr fun _K hK => + (hf.isLindelof_preimage hK).compl_mem_coLindelof + +/-- Sets of subtype are Lindelöf iff the image under a coercion is. -/ +theorem Subtype.isLindelof_iff {p : X → Prop} {s : Set { x // p x }} : + IsLindelof s ↔ IsLindelof ((↑) '' s : Set X) := + embedding_subtype_val.isLindelof_iff + +theorem isLindelof_iff_isLindelof_univ : IsLindelof s ↔ IsLindelof (univ : Set s) := by + rw [Subtype.isLindelof_iff, image_univ, Subtype.range_coe] + +theorem isLindelof_iff_LindelofSpace : IsLindelof s ↔ LindelofSpace s := + isLindelof_iff_isLindelof_univ.trans isLindelof_univ_iff + +lemma IsLindelof.of_coe [LindelofSpace s] : IsLindelof s := isLindelof_iff_LindelofSpace.mpr ‹_› + +theorem IsLindelof.countable (hs : IsLindelof s) (hs' : DiscreteTopology s) : s.Countable := + countable_coe_iff.mp + (@countable_of_Lindelof_of_discrete _ _ (isLindelof_iff_LindelofSpace.mp hs) hs') + +protected theorem ClosedEmbedding.nonLindelofSpace [NonLindelofSpace X] {f : X → Y} + (hf : ClosedEmbedding f) : NonLindelofSpace Y := + nonLindelofSpace_of_neBot hf.tendsto_coLindelof.neBot + +protected theorem ClosedEmbedding.LindelofSpace [h : LindelofSpace Y] {f : X → Y} + (hf : ClosedEmbedding f) : LindelofSpace X := + ⟨by rw [hf.toInducing.isLindelof_iff, image_univ]; exact hf.closed_range.isLindelof⟩ + +/-- Countable topological spaces are Lindelof. -/ +instance (priority := 100) Countable.LindelofSpace [Countable X] : LindelofSpace X where + isLindelof_univ := countable_univ.isLindelof + +/-- The disjoint union of two Lindelöf spaces is Lindelöf. -/ +instance [LindelofSpace X] [LindelofSpace Y] : LindelofSpace (X ⊕ Y) := + ⟨by + rw [← range_inl_union_range_inr] + exact (isLindelof_range continuous_inl).union (isLindelof_range continuous_inr)⟩ + +instance {X : ι → Type*} [Countable ι] [∀ i, TopologicalSpace (X i)] [∀ i, LindelofSpace (X i)] : + LindelofSpace (Σi, X i) := by + refine' ⟨_⟩ + rw [Sigma.univ] + exact isLindelof_iUnion fun i => isLindelof_range continuous_sigmaMk + +instance Quot.LindelofSpace {r : X → X → Prop} [LindelofSpace X] : LindelofSpace (Quot r) := + ⟨by + rw [← range_quot_mk] + exact isLindelof_range continuous_quot_mk⟩ + +instance Quotient.LindelofSpace {s : Setoid X} [LindelofSpace X] : LindelofSpace (Quotient s) := + Quot.LindelofSpace + +/-- A continuous image of a Lindelöf set is a Lindelöf set within the codomain. -/ +theorem LindelofSpace.of_continuous_surjective {f : X → Y} [LindelofSpace X] (hf : Continuous f) + (hsur : Function.Surjective f) : LindelofSpace Y := by + refine { isLindelof_univ := ?isLindelof_univ } + rw [← Set.image_univ_of_surjective hsur] + exact IsLindelof.image (isLindelof_univ_iff.mpr ‹_›) hf + +/-- A set `s` is Hereditarily Lindelöf if every subset is a Lindelof set. We require this only +for open sets in the definition, and then conclude that this holds for all sets by ADD. -/ +def IsHereditarilyLindelof (s : Set X) := + ∀ t ⊆ s, IsLindelof t + +/-- Type class for Hereditarily Lindelöf spaces. -/ +class HereditarilyLindelofSpace (X : Type*) [TopologicalSpace X] : Prop where + /-- In a Hereditarily Lindelöf space, `Set.univ` is a Hereditarily Lindelöf set. -/ + isHereditarilyLindelof_univ : IsHereditarilyLindelof (univ : Set X) + +lemma IsHereditarilyLindelof.isLindelof_subset (hs : IsHereditarilyLindelof s) (ht : t ⊆ s) : + IsLindelof t := hs t ht + +lemma IsHereditarilyLindelof.isLindelof (hs : IsHereditarilyLindelof s) : + IsLindelof s := hs.isLindelof_subset Subset.rfl + +instance (priority := 100) HereditarilyLindelof.to_Lindelof [HereditarilyLindelofSpace X] : + LindelofSpace X where + isLindelof_univ := HereditarilyLindelofSpace.isHereditarilyLindelof_univ.isLindelof + +theorem HereditarilyLindelof_LindelofSets [HereditarilyLindelofSpace X] (s : Set X): + IsLindelof s := by + apply HereditarilyLindelofSpace.isHereditarilyLindelof_univ + exact subset_univ s + +instance (priority := 100) SecondCountableTopology.toHereditarilyLindelof + [SecondCountableTopology X] : HereditarilyLindelofSpace X where + isHereditarilyLindelof_univ := fun t _ _ ↦ by + apply isLindelof_iff_countable_subcover.mpr + intro ι U hι hcover + have := @isOpen_iUnion_countable X _ _ ι U hι + rcases this with ⟨t,⟨htc, htu⟩⟩ + use t, htc + exact subset_of_subset_of_eq hcover (id htu.symm) + +lemma eq_open_union_countable [HereditarilyLindelofSpace X] {ι : Type u} (U : ι → Set X) + (h : ∀ i, IsOpen (U i)) : ∃ t : Set ι, t.Countable ∧ ⋃ i∈t, U i = ⋃ i, U i := by + have : IsLindelof (⋃ i, U i) := HereditarilyLindelof_LindelofSets (⋃ i, U i) + rcases isLindelof_iff_countable_subcover.mp this U h (Eq.subset rfl) with ⟨t,⟨htc, htu⟩⟩ + use t, htc + apply eq_of_subset_of_subset (iUnion₂_subset_iUnion (fun i ↦ i ∈ t) fun i ↦ U i) htu + +instance HereditarilyLindelof.lindelofSpace_subtype [HereditarilyLindelofSpace X] (p : X → Prop) : + LindelofSpace {x // p x} := by + apply isLindelof_iff_LindelofSpace.mp + exact HereditarilyLindelof_LindelofSets fun x ↦ p x diff --git a/Mathlib/Topology/Compactness/LocallyCompact.lean b/Mathlib/Topology/Compactness/LocallyCompact.lean index 9a9a0708e76cc..fcc3fa87302dd 100644 --- a/Mathlib/Topology/Compactness/LocallyCompact.lean +++ b/Mathlib/Topology/Compactness/LocallyCompact.lean @@ -86,19 +86,22 @@ theorem local_compact_nhds [LocallyCompactSpace X] {x : X} {n : Set X} (h : n LocallyCompactSpace.local_compact_nhds _ _ h #align local_compact_nhds local_compact_nhds -theorem locallyCompactSpace_of_hasBasis {ι : X → Type*} {p : ∀ x, ι x → Prop} +theorem LocallyCompactSpace.of_hasBasis {ι : X → Type*} {p : ∀ x, ι x → Prop} {s : ∀ x, ι x → Set X} (h : ∀ x, (𝓝 x).HasBasis (p x) (s x)) (hc : ∀ x i, p x i → IsCompact (s x i)) : LocallyCompactSpace X := ⟨fun x _t ht => let ⟨i, hp, ht⟩ := (h x).mem_iff.1 ht ⟨s x i, (h x).mem_of_mem hp, ht, hc x i hp⟩⟩ -#align locally_compact_space_of_has_basis locallyCompactSpace_of_hasBasis +#align locally_compact_space_of_has_basis LocallyCompactSpace.of_hasBasis + +@[deprecated] -- since 29 Dec 2023 +alias locallyCompactSpace_of_hasBasis := LocallyCompactSpace.of_hasBasis instance Prod.locallyCompactSpace (X : Type*) (Y : Type*) [TopologicalSpace X] [TopologicalSpace Y] [LocallyCompactSpace X] [LocallyCompactSpace Y] : LocallyCompactSpace (X × Y) := have := fun x : X × Y => (compact_basis_nhds x.1).prod_nhds' (compact_basis_nhds x.2) - locallyCompactSpace_of_hasBasis this fun _ _ ⟨⟨_, h₁⟩, _, h₂⟩ => h₁.prod h₂ + .of_hasBasis this fun _ _ ⟨⟨_, h₁⟩, _, h₂⟩ => h₁.prod h₂ #align prod.locally_compact_space Prod.locallyCompactSpace section Pi @@ -214,11 +217,10 @@ theorem exists_compact_between [LocallyCompactSpace X] {K U : Set X} (hK : IsCom protected theorem ClosedEmbedding.locallyCompactSpace [LocallyCompactSpace Y] {f : X → Y} (hf : ClosedEmbedding f) : LocallyCompactSpace X := - haveI : ∀ x : X, (𝓝 x).HasBasis (fun s => s ∈ 𝓝 (f x) ∧ IsCompact s) fun s => f ⁻¹' s := by - intro x + haveI : ∀ x : X, (𝓝 x).HasBasis (fun s => s ∈ 𝓝 (f x) ∧ IsCompact s) (f ⁻¹' ·) := fun x ↦ by rw [hf.toInducing.nhds_eq_comap] exact (compact_basis_nhds _).comap _ - locallyCompactSpace_of_hasBasis this fun x s hs => hf.isCompact_preimage hs.2 + .of_hasBasis this fun x s hs => hf.isCompact_preimage hs.2 #align closed_embedding.locally_compact_space ClosedEmbedding.locallyCompactSpace protected theorem IsClosed.locallyCompactSpace [LocallyCompactSpace X] {s : Set X} @@ -228,13 +230,12 @@ protected theorem IsClosed.locallyCompactSpace [LocallyCompactSpace X] {s : Set protected theorem OpenEmbedding.locallyCompactSpace [LocallyCompactSpace Y] {f : X → Y} (hf : OpenEmbedding f) : LocallyCompactSpace X := by - have : ∀ x : X, (𝓝 x).HasBasis - (fun s => (s ∈ 𝓝 (f x) ∧ IsCompact s) ∧ s ⊆ range f) fun s => f ⁻¹' s := by - intro x - rw [hf.toInducing.nhds_eq_comap] - exact - ((compact_basis_nhds _).restrict_subset <| hf.open_range.mem_nhds <| mem_range_self _).comap _ - refine' locallyCompactSpace_of_hasBasis this fun x s hs => _ + have : ∀ x : X, + (𝓝 x).HasBasis (fun s ↦ (s ∈ 𝓝 (f x) ∧ IsCompact s) ∧ s ⊆ range f) (f ⁻¹' ·) := fun x ↦ by + rw [hf.nhds_eq_comap] + exact ((compact_basis_nhds _).restrict_subset <| hf.open_range.mem_nhds <| + mem_range_self _).comap _ + refine .of_hasBasis this fun x s hs => ?_ rw [hf.toInducing.isCompact_iff, image_preimage_eq_of_subset hs.2] exact hs.1.2 #align open_embedding.locally_compact_space OpenEmbedding.locallyCompactSpace diff --git a/Mathlib/Topology/Compactness/SigmaCompact.lean b/Mathlib/Topology/Compactness/SigmaCompact.lean index c6be308e14da6..fa5e6cc964080 100644 --- a/Mathlib/Topology/Compactness/SigmaCompact.lean +++ b/Mathlib/Topology/Compactness/SigmaCompact.lean @@ -290,7 +290,7 @@ protected noncomputable def LocallyFinite.encodable {ι : Type*} {f : ι → Set `x` of a closed set `s` to a neighborhood of `x` within `s`, then for some countable set `t ⊆ s`, the neighborhoods `f x`, `x ∈ t`, cover the whole set `s`. -/ theorem countable_cover_nhdsWithin_of_sigma_compact {f : X → Set X} {s : Set X} (hs : IsClosed s) - (hf : ∀ x ∈ s, f x ∈ 𝓝[s] x) : ∃ (t : _) (_ : t ⊆ s), t.Countable ∧ s ⊆ ⋃ x ∈ t, f x := by + (hf : ∀ x ∈ s, f x ∈ 𝓝[s] x) : ∃ t ⊆ s, t.Countable ∧ s ⊆ ⋃ x ∈ t, f x := by simp only [nhdsWithin, mem_inf_principal] at hf choose t ht hsub using fun n => ((isCompact_compactCovering X n).inter_right hs).elim_nhds_subcover _ fun x hx => hf x hx.right diff --git a/Mathlib/Topology/Connected/Basic.lean b/Mathlib/Topology/Connected/Basic.lean index 3baa51a8817de..e3091aefd5805 100644 --- a/Mathlib/Topology/Connected/Basic.lean +++ b/Mathlib/Topology/Connected/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Yury Kudryashov -/ +import Mathlib.Data.Set.Image import Mathlib.Order.SuccPred.Relation import Mathlib.Topology.Clopen import Mathlib.Topology.Irreducible @@ -331,7 +332,7 @@ protected theorem IsPreconnected.image [TopologicalSpace β] {s : Set α} (H : I /-- The image of a connected set is connected as well. -/ protected theorem IsConnected.image [TopologicalSpace β] {s : Set α} (H : IsConnected s) (f : α → β) (hf : ContinuousOn f s) : IsConnected (f '' s) := - ⟨nonempty_image_iff.mpr H.nonempty, H.isPreconnected.image f hf⟩ + ⟨image_nonempty.mpr H.nonempty, H.isPreconnected.image f hf⟩ #align is_connected.image IsConnected.image theorem isPreconnected_closed_iff {s : Set α} : diff --git a/Mathlib/Topology/Connected/PathConnected.lean b/Mathlib/Topology/Connected/PathConnected.lean index 5f6a426f7a65e..f8dfba6c443a3 100644 --- a/Mathlib/Topology/Connected/PathConnected.lean +++ b/Mathlib/Topology/Connected/PathConnected.lean @@ -78,12 +78,12 @@ structure Path (x y : X) extends C(I, X) where target' : toFun 1 = y #align path Path --- porting note: added this instance so that we can use `FunLike.coe` for `CoeFun` +-- porting note: added this instance so that we can use `DFunLike.coe` for `CoeFun` -- this also fixed very strange `simp` timeout issues instance Path.continuousMapClass : ContinuousMapClass (Path x y) I X where coe := fun γ ↦ ⇑γ.toContinuousMap coe_injective' := fun γ₁ γ₂ h => by - simp only [FunLike.coe_fn_eq] at h + simp only [DFunLike.coe_fn_eq] at h cases γ₁; cases γ₂; congr map_continuous := fun γ => by continuity @@ -190,7 +190,7 @@ theorem refl_symm {a : X} : (Path.refl a).symm = Path.refl a := by @[simp] theorem symm_range {a b : X} (γ : Path a b) : range γ.symm = range γ := by ext x - simp only [mem_range, Path.symm, FunLike.coe, unitInterval.symm, SetCoe.exists, comp_apply, + simp only [mem_range, Path.symm, DFunLike.coe, unitInterval.symm, SetCoe.exists, comp_apply, Subtype.coe_mk] constructor <;> rintro ⟨y, hy, hxy⟩ <;> refine' ⟨1 - y, mem_iff_one_sub_mem.mp hy, _⟩ <;> convert hxy @@ -202,7 +202,7 @@ theorem symm_range {a b : X} (γ : Path a b) : range γ.symm = range γ := by open ContinuousMap -/- porting note: because of the new `FunLike` instance, we already have a coercion to `C(I, X)` +/- porting note: because of the `DFunLike` instance, we already have a coercion to `C(I, X)` so we avoid adding another. --instance : Coe (Path x y) C(I, X) := --⟨fun γ => γ.1⟩ @@ -646,7 +646,7 @@ theorem truncate_range {a b : X} (γ : Path a b) {t₀ t₁ : ℝ} : rw [← γ.extend_range] simp only [range_subset_iff, SetCoe.exists, SetCoe.forall] intro x _hx - simp only [FunLike.coe, Path.truncate, mem_range_self] + simp only [DFunLike.coe, Path.truncate, mem_range_self] #align path.truncate_range Path.truncate_range /-- For a path `γ`, `γ.truncate` gives a "continuous family of paths", by which we @@ -671,7 +671,7 @@ theorem truncate_self {a b : X} (γ : Path a b) (t : ℝ) : γ.truncate t t = (Path.refl <| γ.extend t).cast (by rw [min_self]) rfl := by ext x rw [cast_coe] - simp only [truncate, FunLike.coe, refl, min_def, max_def] + simp only [truncate, DFunLike.coe, refl, min_def, max_def] split_ifs with h₁ h₂ <;> congr #align path.truncate_self Path.truncate_self @@ -991,7 +991,7 @@ nonrec theorem Inducing.isPathConnected_iff {f : X → Y} (hf : Inducing f) : IsPathConnected F ↔ IsPathConnected (f '' F) := by refine ⟨fun hF ↦ hF.image hf.continuous, fun hF ↦ ?_⟩ simp? [isPathConnected_iff] at hF ⊢ says - simp only [isPathConnected_iff, nonempty_image_iff, mem_image, forall_exists_index, + simp only [isPathConnected_iff, image_nonempty, mem_image, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] at hF ⊢ refine ⟨hF.1, fun x hx y hy ↦ ?_⟩ rcases hF.2 x hx y hy with ⟨γ, hγ⟩ diff --git a/Mathlib/Topology/Constructions.lean b/Mathlib/Topology/Constructions.lean index 768baa4b06cfb..614995b63b075 100644 --- a/Mathlib/Topology/Constructions.lean +++ b/Mathlib/Topology/Constructions.lean @@ -1705,3 +1705,27 @@ theorem IsClosed.trans (hγ : IsClosed γ) (hβ : IsClosed β) : IsClosed (γ : convert IsClosed.inter hδ hβ end Monad + +section NhdsSet +variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] {f : Filter X} + {s : Set X} {t : Set Y} {x : X} + +/-- The product of a neighborhood of `s` and a neighborhood of `t` is a neighborhood of `s ×ˢ t`, +formulated in terms of a filter inequality. -/ +theorem nhdsSet_prod_le (s : Set X) (t : Set Y) : 𝓝ˢ (s ×ˢ t) ≤ 𝓝ˢ s ×ˢ 𝓝ˢ t := + ((hasBasis_nhdsSet _).prod (hasBasis_nhdsSet _)).ge_iff.2 fun (_u, _v) ⟨⟨huo, hsu⟩, hvo, htv⟩ ↦ + (huo.prod hvo).mem_nhdsSet.2 <| prod_mono hsu htv + +theorem Filter.eventually_nhdsSet_prod_iff {p : X × Y → Prop} : + (∀ᶠ q in 𝓝ˢ (s ×ˢ t), p q) ↔ + ∀ x ∈ s, ∀ y ∈ t, + ∃ pa : X → Prop, (∀ᶠ x' in 𝓝 x, pa x') ∧ ∃ pb : Y → Prop, (∀ᶠ y' in 𝓝 y, pb y') ∧ + ∀ {x : X}, pa x → ∀ {y : Y}, pb y → p (x, y) := + by simp_rw [eventually_nhdsSet_iff_forall, Set.forall_prod_set, nhds_prod_eq, eventually_prod_iff] + +theorem Filter.Eventually.prod_nhdsSet {p : X × Y → Prop} {pa : X → Prop} {pb : Y → Prop} + (hp : ∀ {x : X}, pa x → ∀ {y : Y}, pb y → p (x, y)) (hs : ∀ᶠ x in 𝓝ˢ s, pa x) + (ht : ∀ᶠ y in 𝓝ˢ t, pb y) : ∀ᶠ q in 𝓝ˢ (s ×ˢ t), p q := + nhdsSet_prod_le _ _ (mem_of_superset (prod_mem_prod hs ht) fun _ ⟨hx, hy⟩ ↦ hp hx hy) + +end NhdsSet diff --git a/Mathlib/Topology/ContinuousFunction/Algebra.lean b/Mathlib/Topology/ContinuousFunction/Algebra.lean index 091f3f3efc1bd..ffee7b0f194d7 100644 --- a/Mathlib/Topology/ContinuousFunction/Algebra.lean +++ b/Mathlib/Topology/ContinuousFunction/Algebra.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Nicolò Cavalleri -/ import Mathlib.Algebra.Algebra.Pi -import Mathlib.Algebra.Order.LatticeGroup import Mathlib.Algebra.Periodic import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Algebra.Star.StarAlgHom @@ -177,22 +176,22 @@ attribute [simp] pow_comp /-! ### `inv` and `neg` -/ @[to_additive] -instance [Group β] [TopologicalGroup β] : Inv C(α, β) where inv f := ⟨f⁻¹, f.continuous.inv⟩ +instance [Inv β] [ContinuousInv β] : Inv C(α, β) where inv f := ⟨f⁻¹, f.continuous.inv⟩ @[to_additive (attr := simp)] -theorem coe_inv [Group β] [TopologicalGroup β] (f : C(α, β)) : ⇑f⁻¹ = (⇑f)⁻¹ := +theorem coe_inv [Inv β] [ContinuousInv β] (f : C(α, β)) : ⇑f⁻¹ = (⇑f)⁻¹ := rfl #align continuous_map.coe_inv ContinuousMap.coe_inv #align continuous_map.coe_neg ContinuousMap.coe_neg @[to_additive (attr := simp)] -theorem inv_apply [Group β] [TopologicalGroup β] (f : C(α, β)) (x : α) : f⁻¹ x = (f x)⁻¹ := +theorem inv_apply [Inv β] [ContinuousInv β] (f : C(α, β)) (x : α) : f⁻¹ x = (f x)⁻¹ := rfl #align continuous_map.inv_apply ContinuousMap.inv_apply #align continuous_map.neg_apply ContinuousMap.neg_apply @[to_additive (attr := simp)] -theorem inv_comp [Group γ] [TopologicalGroup γ] (f : C(β, γ)) (g : C(α, β)) : +theorem inv_comp [Inv γ] [ContinuousInv γ] (f : C(β, γ)) (g : C(α, β)) : f⁻¹.comp g = (f.comp g)⁻¹ := rfl #align continuous_map.inv_comp ContinuousMap.inv_comp @@ -561,9 +560,8 @@ attribute [local ext] Subtype.eq section ModuleStructure --- Porting note: Is "Semiodule" a typo of "Semimodule" or "Submodule"? /-! -### Semiodule structure +### Module structure In this section we show that continuous functions valued in a topological module `M` over a topological semiring `R` inherit the structure of a module. @@ -856,7 +854,7 @@ instance ContinuousMap.subsingleton_subalgebra (α : Type*) [TopologicalSpace α Subsingleton (Subalgebra R C(α, R)) := ⟨fun s₁ s₂ => by cases isEmpty_or_nonempty α - · haveI : Subsingleton C(α, R) := FunLike.coe_injective.subsingleton + · haveI : Subsingleton C(α, R) := DFunLike.coe_injective.subsingleton exact Subsingleton.elim _ _ · inhabit α ext f @@ -921,15 +919,24 @@ variable {β : Type*} [TopologicalSpace β] @[to_additive] instance instCovariantClass_mul_le_left [PartialOrder β] [Mul β] [ContinuousMul β] - [CovariantClass β β (· * ·) (· ≤ ·)] : - CovariantClass C(α, β) C(α, β) (· * ·) (· ≤ ·) := -⟨fun _ _ _ hg₁₂ x => mul_le_mul_left' (hg₁₂ x) _⟩ + [CovariantClass β β (· * ·) (· ≤ ·)] : + CovariantClass C(α, β) C(α, β) (· * ·) (· ≤ ·) := + ⟨fun _ _ _ hg₁₂ x => mul_le_mul_left' (hg₁₂ x) _⟩ @[to_additive] instance instCovariantClass_mul_le_right [PartialOrder β] [Mul β] [ContinuousMul β] - [CovariantClass β β (Function.swap (· * ·)) (· ≤ ·)] : - CovariantClass C(α, β) C(α, β) (Function.swap (· * ·)) (· ≤ ·) := -⟨fun _ _ _ hg₁₂ x => mul_le_mul_right' (hg₁₂ x) _⟩ + [CovariantClass β β (Function.swap (· * ·)) (· ≤ ·)] : + CovariantClass C(α, β) C(α, β) (Function.swap (· * ·)) (· ≤ ·) := + ⟨fun _ _ _ hg₁₂ x => mul_le_mul_right' (hg₁₂ x) _⟩ + +variable [Group β] [TopologicalGroup β] [Lattice β] [TopologicalLattice β] + +@[to_additive (attr := simp, norm_cast)] +lemma coe_mabs (f : C(α, β)) : ⇑|f|ₘ = |⇑f|ₘ := rfl + +@[to_additive (attr := simp)] +lemma mabs_apply (f : C(α, β)) (x : α) : |f|ₘ x = |f x|ₘ := rfl +#align continuous_map.abs_apply ContinuousMap.abs_apply end Lattice diff --git a/Mathlib/Topology/ContinuousFunction/Basic.lean b/Mathlib/Topology/ContinuousFunction/Basic.lean index b46778e7984b0..2876538bcd68f 100644 --- a/Mathlib/Topology/ContinuousFunction/Basic.lean +++ b/Mathlib/Topology/ContinuousFunction/Basic.lean @@ -13,7 +13,7 @@ import Mathlib.Topology.Homeomorph In this file we define the type `ContinuousMap` of continuous bundled maps. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. -/ @@ -42,7 +42,7 @@ section You should extend this class when you extend `ContinuousMap`. -/ class ContinuousMapClass (F : Type*) (α β : outParam <| Type*) [TopologicalSpace α] - [TopologicalSpace β] extends FunLike F α fun _ => β where + [TopologicalSpace β] extends DFunLike F α (fun _ => β) where /-- Continuity -/ map_continuous (f : F) : Continuous f #align continuous_map_class ContinuousMapClass @@ -86,17 +86,17 @@ instance toContinuousMapClass : ContinuousMapClass C(α, β) α β where map_continuous := ContinuousMap.continuous_toFun /- Porting note: Probably not needed anymore -/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun C(α, β) fun _ => α → β := - FunLike.hasCoeToFun-/ + DFunLike.hasCoeToFun-/ @[simp] theorem toFun_eq_coe {f : C(α, β)} : f.toFun = (f : α → β) := rfl #align continuous_map.to_fun_eq_coe ContinuousMap.toFun_eq_coe -instance : CanLift (α → β) C(α, β) FunLike.coe Continuous := ⟨fun f hf ↦ ⟨⟨f, hf⟩, rfl⟩⟩ +instance : CanLift (α → β) C(α, β) DFunLike.coe Continuous := ⟨fun f hf ↦ ⟨⟨f, hf⟩, rfl⟩⟩ /-- See note [custom simps projection]. -/ def Simps.apply (f : C(α, β)) : α → β := f @@ -111,7 +111,7 @@ protected theorem coe_coe {F : Type*} [ContinuousMapClass F α β] (f : F) : ⇑ @[ext] theorem ext {f g : C(α, β)} (h : ∀ a, f a = g a) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align continuous_map.ext ContinuousMap.ext /-- Copy of a `ContinuousMap` with a new `toFun` equal to the old one. Useful to fix definitional @@ -127,7 +127,7 @@ theorem coe_copy (f : C(α, β)) (f' : α → β) (h : f' = f) : ⇑(f.copy f' h #align continuous_map.coe_copy ContinuousMap.coe_copy theorem copy_eq (f : C(α, β)) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align continuous_map.copy_eq ContinuousMap.copy_eq variable {f g : C(α, β)} @@ -147,12 +147,12 @@ protected theorem continuousAt (f : C(α, β)) (x : α) : ContinuousAt f x := f.continuous.continuousAt #align continuous_map.continuous_at ContinuousMap.continuousAt -/-- Deprecated. Use `FunLike.congr_fun` instead. -/ +/-- Deprecated. Use `DFunLike.congr_fun` instead. -/ protected theorem congr_fun {f g : C(α, β)} (H : f = g) (x : α) : f x = g x := H ▸ rfl #align continuous_map.congr_fun ContinuousMap.congr_fun -/-- Deprecated. Use `FunLike.congr_arg` instead. -/ +/-- Deprecated. Use `DFunLike.congr_arg` instead. -/ protected theorem congr_arg (f : C(α, β)) {x y : α} (h : x = y) : f x = f y := h ▸ rfl #align continuous_map.congr_arg ContinuousMap.congr_arg @@ -273,7 +273,7 @@ theorem comp_const (f : C(β, γ)) (b : β) : f.comp (const α b) = const α (f @[simp] theorem cancel_right {f₁ f₂ : C(β, γ)} {g : C(α, β)} (hg : Surjective g) : f₁.comp g = f₂.comp g ↔ f₁ = f₂ := - ⟨fun h => ext <| hg.forall.2 <| FunLike.ext_iff.1 h, congr_arg (ContinuousMap.comp · g)⟩ + ⟨fun h => ext <| hg.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (ContinuousMap.comp · g)⟩ #align continuous_map.cancel_right ContinuousMap.cancel_right @[simp] @@ -284,7 +284,7 @@ theorem cancel_left {f : C(β, γ)} {g₁ g₂ : C(α, β)} (hf : Injective f) : instance [Nonempty α] [Nontrivial β] : Nontrivial C(α, β) := ⟨let ⟨b₁, b₂, hb⟩ := exists_pair_ne β - ⟨const _ b₁, const _ b₂, fun h => hb <| FunLike.congr_fun h <| Classical.arbitrary α⟩⟩ + ⟨const _ b₁, const _ b₂, fun h => hb <| DFunLike.congr_fun h <| Classical.arbitrary α⟩⟩ section Prod @@ -427,8 +427,8 @@ theorem restrict_apply_mk (f : C(α, β)) (s : Set α) (x : α) (hx : x ∈ s) : theorem injective_restrict [T2Space β] {s : Set α} (hs : Dense s) : Injective (restrict s : C(α, β) → C(s, β)) := fun f g h ↦ - FunLike.ext' <| f.continuous.ext_on hs g.continuous <| Set.restrict_eq_restrict_iff.1 <| - congr_arg FunLike.coe h + DFunLike.ext' <| f.continuous.ext_on hs g.continuous <| Set.restrict_eq_restrict_iff.1 <| + congr_arg DFunLike.coe h /-- The restriction of a continuous map to the preimage of a set. -/ @[simps] diff --git a/Mathlib/Topology/ContinuousFunction/Bounded.lean b/Mathlib/Topology/ContinuousFunction/Bounded.lean index d9f5443c49c46..f40edde0d4810 100644 --- a/Mathlib/Topology/ContinuousFunction/Bounded.lean +++ b/Mathlib/Topology/ContinuousFunction/Bounded.lean @@ -79,10 +79,10 @@ instance : BoundedContinuousMapClass (α →ᵇ β) α β where map_continuous f := f.continuous_toFun map_bounded f := f.map_bounded' -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (α →ᵇ β) fun _ => α → β := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun instance [BoundedContinuousMapClass F α β] : CoeTC F (α →ᵇ β) := ⟨fun f => @@ -111,7 +111,7 @@ protected theorem continuous (f : α →ᵇ β) : Continuous f := @[ext] theorem ext (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align bounded_continuous_function.ext BoundedContinuousFunction.ext theorem isBounded_range (f : α →ᵇ β) : IsBounded (range f) := @@ -475,7 +475,7 @@ nonrec theorem extend_apply' {f : α ↪ δ} {x : δ} (hx : x ∉ range f) (g : #align bounded_continuous_function.extend_apply' BoundedContinuousFunction.extend_apply' theorem extend_of_empty [IsEmpty α] (f : α ↪ δ) (g : α →ᵇ β) (h : δ →ᵇ β) : extend f g h = h := - FunLike.coe_injective <| Function.extend_of_isEmpty f g h + DFunLike.coe_injective <| Function.extend_of_isEmpty f g h #align bounded_continuous_function.extend_of_empty BoundedContinuousFunction.extend_of_empty @[simp] @@ -635,7 +635,7 @@ theorem mkOfCompact_one [CompactSpace α] : mkOfCompact (1 : C(α, β)) = 1 := r @[to_additive] theorem forall_coe_one_iff_one (f : α →ᵇ β) : (∀ x, f x = 1) ↔ f = 1 := - (@FunLike.ext_iff _ _ _ _ f 1).symm + (@DFunLike.ext_iff _ _ _ _ f 1).symm #align bounded_continuous_function.forall_coe_one_iff_one BoundedContinuousFunction.forall_coe_one_iff_one #align bounded_continuous_function.forall_coe_zero_iff_zero BoundedContinuousFunction.forall_coe_zero_iff_zero @@ -716,7 +716,7 @@ theorem nsmul_apply (r : ℕ) (f : α →ᵇ β) (v : α) : (r • f) v = r • #align bounded_continuous_function.nsmul_apply BoundedContinuousFunction.nsmul_apply instance addMonoid : AddMonoid (α →ᵇ β) := - FunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => coe_nsmul _ _ + DFunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => coe_nsmul _ _ instance : LipschitzAdd (α →ᵇ β) where lipschitz_add := @@ -991,7 +991,7 @@ theorem zsmul_apply (r : ℤ) (f : α →ᵇ β) (v : α) : (r • f) v = r • #align bounded_continuous_function.zsmul_apply BoundedContinuousFunction.zsmul_apply instance : AddCommGroup (α →ᵇ β) := - FunLike.coe_injective.addCommGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => coe_nsmul _ _) + DFunLike.coe_injective.addCommGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => coe_nsmul _ _) fun _ _ => coe_zsmul _ _ instance seminormedAddCommGroup : SeminormedAddCommGroup (α →ᵇ β) where @@ -1108,7 +1108,7 @@ section MulAction variable [MonoidWithZero 𝕜] [Zero β] [MulAction 𝕜 β] [BoundedSMul 𝕜 β] instance : MulAction 𝕜 (α →ᵇ β) := - FunLike.coe_injective.mulAction _ coe_smul + DFunLike.coe_injective.mulAction _ coe_smul end MulAction @@ -1119,7 +1119,7 @@ variable [MonoidWithZero 𝕜] [AddMonoid β] [DistribMulAction 𝕜 β] [Bounde variable [LipschitzAdd β] instance : DistribMulAction 𝕜 (α →ᵇ β) := - Function.Injective.distribMulAction ⟨⟨_, coe_zero⟩, coe_add⟩ FunLike.coe_injective coe_smul + Function.Injective.distribMulAction ⟨⟨_, coe_zero⟩, coe_add⟩ DFunLike.coe_injective coe_smul end DistribMulAction @@ -1132,7 +1132,7 @@ variable {f g : α →ᵇ β} {x : α} {C : ℝ} variable [LipschitzAdd β] instance module : Module 𝕜 (α →ᵇ β) := - Function.Injective.module _ ⟨⟨_, coe_zero⟩, coe_add⟩ FunLike.coe_injective coe_smul + Function.Injective.module _ ⟨⟨_, coe_zero⟩, coe_add⟩ DFunLike.coe_injective coe_smul variable (𝕜) @@ -1244,7 +1244,7 @@ theorem mul_apply (f g : α →ᵇ R) (x : α) : (f * g) x = f x * g x := rfl #align bounded_continuous_function.mul_apply BoundedContinuousFunction.mul_apply instance : NonUnitalRing (α →ᵇ R) := - FunLike.coe_injective.nonUnitalRing _ coe_zero coe_add coe_mul coe_neg coe_sub + DFunLike.coe_injective.nonUnitalRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ => coe_nsmul _ _) fun _ _ => coe_zsmul _ _ instance nonUnitalSeminormedRing : NonUnitalSeminormedRing (α →ᵇ R) := @@ -1301,7 +1301,7 @@ theorem coe_intCast (n : ℤ) : ((n : α →ᵇ R) : α → R) = n := rfl #align bounded_continuous_function.coe_int_cast BoundedContinuousFunction.coe_intCast instance ring : Ring (α →ᵇ R) := - FunLike.coe_injective.ring _ coe_zero coe_one coe_add coe_mul coe_neg coe_sub + DFunLike.coe_injective.ring _ coe_zero coe_one coe_add coe_mul coe_neg coe_sub (fun _ _ => coe_nsmul _ _) (fun _ _ => coe_zsmul _ _) (fun _ _ => coe_pow _ _) coe_natCast coe_intCast @@ -1591,7 +1591,7 @@ variable [TopologicalSpace α] /-- The nonnegative part of a bounded continuous `ℝ`-valued function as a bounded continuous `ℝ≥0`-valued function. -/ def nnrealPart (f : α →ᵇ ℝ) : α →ᵇ ℝ≥0 := - BoundedContinuousFunction.comp _ (show LipschitzWith 1 Real.toNNReal from lipschitzWith_pos) f + BoundedContinuousFunction.comp _ (show LipschitzWith 1 Real.toNNReal from lipschitzWith_posPart) f #align bounded_continuous_function.nnreal_part BoundedContinuousFunction.nnrealPart @[simp] diff --git a/Mathlib/Topology/ContinuousFunction/CocompactMap.lean b/Mathlib/Topology/ContinuousFunction/CocompactMap.lean index 20abbdd9ffd48..df793be44b2ff 100644 --- a/Mathlib/Topology/ContinuousFunction/CocompactMap.lean +++ b/Mathlib/Topology/ContinuousFunction/CocompactMap.lean @@ -84,10 +84,10 @@ instance : CocompactMapClass (CocompactMap α β) α β where cocompact_tendsto f := f.cocompact_tendsto' /- Porting note: not needed anymore -/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (CocompactMap α β) fun _ => α → β := - FunLike.hasCoeToFun-/ + DFunLike.hasCoeToFun-/ @[simp] theorem coe_toContinuousMap {f : CocompactMap α β} : (f.toContinuousMap : α → β) = f := @@ -96,7 +96,7 @@ theorem coe_toContinuousMap {f : CocompactMap α β} : (f.toContinuousMap : α @[ext] theorem ext {f g : CocompactMap α β} (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align cocompact_map.ext CocompactMap.ext /-- Copy of a `CocompactMap` with a new `toFun` equal to the old one. Useful @@ -117,7 +117,7 @@ theorem coe_copy (f : CocompactMap α β) (f' : α → β) (h : f' = f) : ⇑(f. #align cocompact_map.coe_copy CocompactMap.coe_copy theorem copy_eq (f : CocompactMap α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align cocompact_map.copy_eq CocompactMap.copy_eq @[simp] diff --git a/Mathlib/Topology/ContinuousFunction/Compact.lean b/Mathlib/Topology/ContinuousFunction/Compact.lean index 8a3aaa324933b..558e63b638ade 100644 --- a/Mathlib/Topology/ContinuousFunction/Compact.lean +++ b/Mathlib/Topology/ContinuousFunction/Compact.lean @@ -232,7 +232,7 @@ theorem apply_le_norm (f : C(α, ℝ)) (x : α) : f x ≤ ‖f‖ := #align continuous_map.apply_le_norm ContinuousMap.apply_le_norm theorem neg_norm_le_apply (f : C(α, ℝ)) (x : α) : -‖f‖ ≤ f x := - le_trans (neg_le_neg (f.norm_coe_le_norm x)) (neg_le.mp (neg_le_abs_self (f x))) + le_trans (neg_le_neg (f.norm_coe_le_norm x)) (neg_le.mp (neg_le_abs (f x))) #align continuous_map.neg_norm_le_apply ContinuousMap.neg_norm_le_apply theorem norm_eq_iSup_norm : ‖f‖ = ⨆ x : α, ‖f x‖ := diff --git a/Mathlib/Topology/ContinuousFunction/Ideals.lean b/Mathlib/Topology/ContinuousFunction/Ideals.lean index 6b3f8861a9fd5..84c79cbf92517 100644 --- a/Mathlib/Topology/ContinuousFunction/Ideals.lean +++ b/Mathlib/Topology/ContinuousFunction/Ideals.lean @@ -149,7 +149,7 @@ theorem setOfTop_eq_univ [Nontrivial R] : setOfIdeal (⊤ : Ideal C(X, R)) = Set theorem idealOfEmpty_eq_bot : idealOfSet R (∅ : Set X) = ⊥ := Ideal.ext fun f => by simp only [mem_idealOfSet, Set.compl_empty, Set.mem_univ, forall_true_left, Ideal.mem_bot, - FunLike.ext_iff, zero_apply] + DFunLike.ext_iff, zero_apply] #align continuous_map.ideal_of_empty_eq_bot ContinuousMap.idealOfEmpty_eq_bot @[simp] @@ -438,7 +438,7 @@ theorem continuousMapEval_bijective : Bijective (continuousMapEval X 𝕜) := by rcases exists_continuous_zero_one_of_isClosed (isClosed_singleton : _root_.IsClosed {x}) (isClosed_singleton : _root_.IsClosed {y}) (Set.disjoint_singleton.mpr hxy) with ⟨f, fx, fy, -⟩ - rw [FunLike.ne_iff] + rw [DFunLike.ne_iff] use (⟨fun (x : ℝ) => (x : 𝕜), IsROrC.continuous_ofReal⟩ : C(ℝ, 𝕜)).comp f simpa only [continuousMapEval_apply_apply, ContinuousMap.comp_apply, coe_mk, Ne.def, IsROrC.ofReal_inj] using diff --git a/Mathlib/Topology/ContinuousFunction/Ordered.lean b/Mathlib/Topology/ContinuousFunction/Ordered.lean index 6ba74575b23cf..c43a43fbfc6a3 100644 --- a/Mathlib/Topology/ContinuousFunction/Ordered.lean +++ b/Mathlib/Topology/ContinuousFunction/Ordered.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Shing Tak Lam -/ import Mathlib.Topology.Algebra.Order.ProjIcc -import Mathlib.Topology.Algebra.Order.Group import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.Order.Lattice #align_import topology.continuous_function.ordered from "leanprover-community/mathlib"@"84dc0bd6619acaea625086d6f53cb35cdd554219" @@ -21,33 +21,11 @@ variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] namespace ContinuousMap -section - -variable [LinearOrderedAddCommGroup β] [OrderTopology β] - -/-- The pointwise absolute value of a continuous function as a continuous function. -/ -def abs (f : C(α, β)) : C(α, β) where toFun x := |f x| -#align continuous_map.abs ContinuousMap.abs - --- see Note [lower instance priority] -instance (priority := 100) : Abs C(α, β) := - ⟨fun f => abs f⟩ - -@[simp] -theorem abs_apply (f : C(α, β)) (x : α) : |f| x = |f x| := - rfl -#align continuous_map.abs_apply ContinuousMap.abs_apply - -end - /-! We now set up the partial order and lattice structure (given by pointwise min and max) on continuous functions. -/ - -section Lattice - instance partialOrder [PartialOrder β] : PartialOrder C(α, β) := PartialOrder.lift (fun f => f.toFun) (fun f g _ => by cases f; cases g; congr) -- porting note: was `by tidy`, and `by aesop` alone didn't work @@ -61,92 +39,64 @@ theorem lt_def [PartialOrder β] {f g : C(α, β)} : f < g ↔ (∀ a, f a ≤ g Pi.lt_def #align continuous_map.lt_def ContinuousMap.lt_def -instance sup [LinearOrder β] [OrderClosedTopology β] : Sup C(α, β) where - sup f g := { toFun := fun a => max (f a) (g a) } +section SemilatticeSup +variable [SemilatticeSup β] [ContinuousSup β] + +instance sup : Sup C(α, β) where sup f g := { toFun := fun a ↦ f a ⊔ g a } #align continuous_map.has_sup ContinuousMap.sup -@[simp, norm_cast] -theorem sup_coe [LinearOrder β] [OrderClosedTopology β] (f g : C(α, β)) : - ((f ⊔ g : C(α, β)) : α → β) = (f ⊔ g : α → β) := - rfl -#align continuous_map.sup_coe ContinuousMap.sup_coe +@[simp, norm_cast] lemma coe_sup (f g : C(α, β)) : ⇑(f ⊔ g) = ⇑f ⊔ g := rfl +#align continuous_map.sup_coe ContinuousMap.coe_sup -@[simp] -theorem sup_apply [LinearOrder β] [OrderClosedTopology β] (f g : C(α, β)) (a : α) : - (f ⊔ g) a = max (f a) (g a) := - rfl +@[simp] lemma sup_apply (f g : C(α, β)) (a : α) : (f ⊔ g) a = f a ⊔ g a := rfl #align continuous_map.sup_apply ContinuousMap.sup_apply -instance semilatticeSup [LinearOrder β] [OrderClosedTopology β] : SemilatticeSup C(α, β) := - { ContinuousMap.partialOrder, - ContinuousMap.sup with - le_sup_left := fun f g => le_def.mpr (by simp [le_refl]) - le_sup_right := fun f g => le_def.mpr (by simp [le_refl]) - sup_le := fun f₁ f₂ g w₁ w₂ => le_def.mpr fun a => by simp [le_def.mp w₁ a, le_def.mp w₂ a] } +instance semilatticeSup : SemilatticeSup C(α, β) := + DFunLike.coe_injective.semilatticeSup _ fun _ _ ↦ rfl -instance inf [LinearOrder β] [OrderClosedTopology β] : Inf C(α, β) where - inf f g := { toFun := fun a => min (f a) (g a) } -#align continuous_map.has_inf ContinuousMap.inf +lemma sup'_apply {ι : Type*} {s : Finset ι} (H : s.Nonempty) (f : ι → C(α, β)) (a : α) : + s.sup' H f a = s.sup' H fun i ↦ f i a := + Finset.comp_sup'_eq_sup'_comp H (fun g : C(α, β) ↦ g a) fun _ _ ↦ rfl +#align continuous_map.sup'_apply ContinuousMap.sup'_apply @[simp, norm_cast] -theorem inf_coe [LinearOrder β] [OrderClosedTopology β] (f g : C(α, β)) : - ((f ⊓ g : C(α, β)) : α → β) = (f ⊓ g : α → β) := - rfl -#align continuous_map.inf_coe ContinuousMap.inf_coe - -@[simp] -theorem inf_apply [LinearOrder β] [OrderClosedTopology β] (f g : C(α, β)) (a : α) : - (f ⊓ g) a = min (f a) (g a) := - rfl -#align continuous_map.inf_apply ContinuousMap.inf_apply - -instance semilatticeInf [LinearOrder β] [OrderClosedTopology β] : SemilatticeInf C(α, β) := - { ContinuousMap.partialOrder, - ContinuousMap.inf with - inf_le_left := fun f g => le_def.mpr (by simp [le_refl]) - inf_le_right := fun f g => le_def.mpr (by simp [le_refl]) - le_inf := fun f₁ f₂ g w₁ w₂ => le_def.mpr fun a => by simp [le_def.mp w₁ a, le_def.mp w₂ a] } - -instance [LinearOrder β] [OrderClosedTopology β] : Lattice C(α, β) := - { ContinuousMap.semilatticeInf, ContinuousMap.semilatticeSup with } +lemma coe_sup' {ι : Type*} {s : Finset ι} (H : s.Nonempty) (f : ι → C(α, β)) : + ⇑(s.sup' H f) = s.sup' H fun i ↦ ⇑(f i) := by ext; simp [sup'_apply] +#align continuous_map.sup'_coe ContinuousMap.coe_sup' --- TODO transfer this lattice structure to `BoundedContinuousFunction` -section Sup' - -variable [LinearOrder γ] [OrderClosedTopology γ] +end SemilatticeSup -theorem sup'_apply {ι : Type*} {s : Finset ι} (H : s.Nonempty) (f : ι → C(β, γ)) (b : β) : - s.sup' H f b = s.sup' H fun a => f a b := - Finset.comp_sup'_eq_sup'_comp H (fun f : C(β, γ) => f b) fun _ _ => rfl -#align continuous_map.sup'_apply ContinuousMap.sup'_apply +section SemilatticeInf +variable [SemilatticeInf β] [ContinuousInf β] -@[simp, norm_cast] -theorem sup'_coe {ι : Type*} {s : Finset ι} (H : s.Nonempty) (f : ι → C(β, γ)) : - ((s.sup' H f : C(β, γ)) : β → γ) = s.sup' H fun a => (f a : β → γ) := by - ext - simp [sup'_apply] -#align continuous_map.sup'_coe ContinuousMap.sup'_coe +instance inf : Inf C(α, β) where inf f g := { toFun := fun a ↦ f a ⊓ g a } +#align continuous_map.has_inf ContinuousMap.inf -end Sup' +@[simp, norm_cast] lemma coe_inf (f g : C(α, β)) : ⇑(f ⊓ g) = ⇑f ⊓ g := rfl +#align continuous_map.inf_coe ContinuousMap.coe_inf -section Inf' +@[simp] lemma inf_apply (f g : C(α, β)) (a : α) : (f ⊓ g) a = f a ⊓ g a := rfl +#align continuous_map.inf_apply ContinuousMap.inf_apply -variable [LinearOrder γ] [OrderClosedTopology γ] +instance semilatticeInf : SemilatticeInf C(α, β) := + DFunLike.coe_injective.semilatticeInf _ fun _ _ ↦ rfl -theorem inf'_apply {ι : Type*} {s : Finset ι} (H : s.Nonempty) (f : ι → C(β, γ)) (b : β) : - s.inf' H f b = s.inf' H fun a => f a b := - @sup'_apply _ γᵒᵈ _ _ _ _ _ _ H f b +lemma inf'_apply {ι : Type*} {s : Finset ι} (H : s.Nonempty) (f : ι → C(α, β)) (a : α) : + s.inf' H f a = s.inf' H fun i ↦ f i a := + Finset.comp_inf'_eq_inf'_comp H (fun g : C(α, β) ↦ g a) fun _ _ ↦ rfl #align continuous_map.inf'_apply ContinuousMap.inf'_apply @[simp, norm_cast] -theorem inf'_coe {ι : Type*} {s : Finset ι} (H : s.Nonempty) (f : ι → C(β, γ)) : - ((s.inf' H f : C(β, γ)) : β → γ) = s.inf' H fun a => (f a : β → γ) := - @sup'_coe _ γᵒᵈ _ _ _ _ _ _ H f -#align continuous_map.inf'_coe ContinuousMap.inf'_coe +lemma coe_inf' {ι : Type*} {s : Finset ι} (H : s.Nonempty) (f : ι → C(α, β)) : + ⇑(s.inf' H f) = s.inf' H fun i ↦ ⇑(f i) := by ext; simp [inf'_apply] +#align continuous_map.inf'_coe ContinuousMap.coe_inf' -end Inf' +end SemilatticeInf -end Lattice +instance [Lattice β] [TopologicalLattice β] : Lattice C(α, β) := + DFunLike.coe_injective.lattice _ (fun _ _ ↦ rfl) fun _ _ ↦ rfl + +-- TODO transfer this lattice structure to `BoundedContinuousFunction` section Extend diff --git a/Mathlib/Topology/ContinuousFunction/Polynomial.lean b/Mathlib/Topology/ContinuousFunction/Polynomial.lean index b8f9620f86c78..44b2250ad1b87 100644 --- a/Mathlib/Topology/ContinuousFunction/Polynomial.lean +++ b/Mathlib/Topology/ContinuousFunction/Polynomial.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Mathlib.Topology.Algebra.Polynomial -import Mathlib.Topology.Algebra.StarSubalgebra import Mathlib.Topology.ContinuousFunction.Algebra import Mathlib.Topology.UnitInterval +import Mathlib.Algebra.Star.Subalgebra #align_import topology.continuous_function.polynomial from "leanprover-community/mathlib"@"a148d797a1094ab554ad4183a4ad6f130358ef64" @@ -170,7 +170,7 @@ theorem polynomialFunctions.comap_compRightAlgHom_iccHomeoI (a b : ℝ) (h : a < ext f fconstructor · rintro ⟨p, ⟨-, w⟩⟩ - rw [FunLike.ext_iff] at w + rw [DFunLike.ext_iff] at w dsimp at w let q := p.comp ((b - a)⁻¹ • Polynomial.X + Polynomial.C (-a * (b - a)⁻¹)) refine' ⟨q, ⟨_, _⟩⟩ diff --git a/Mathlib/Topology/ContinuousFunction/Sigma.lean b/Mathlib/Topology/ContinuousFunction/Sigma.lean index 621111cd9e990..e963dd537602b 100644 --- a/Mathlib/Topology/ContinuousFunction/Sigma.lean +++ b/Mathlib/Topology/ContinuousFunction/Sigma.lean @@ -50,7 +50,7 @@ theorem embedding_sigmaMk_comp [Nonempty X] : inj := by · rintro ⟨i, g⟩ ⟨i', g'⟩ h obtain ⟨rfl, hg⟩ : i = i' ∧ HEq (⇑g) (⇑g') := - Function.eq_of_sigmaMk_comp <| congr_arg FunLike.coe h + Function.eq_of_sigmaMk_comp <| congr_arg DFunLike.coe h simpa using hg section ConnectedSpace @@ -64,7 +64,7 @@ with unbundled functions and `ContinuousMap.sigmaCodHomeomorph` for a homeomorph this fact. -/ theorem exists_lift_sigma (f : C(X, Σ i, Y i)) : ∃ i g, f = (sigmaMk i).comp g := let ⟨i, g, hg, hfg⟩ := f.continuous.exists_lift_sigma - ⟨i, ⟨g, hg⟩, FunLike.ext' hfg⟩ + ⟨i, ⟨g, hg⟩, DFunLike.ext' hfg⟩ variable (X Y) diff --git a/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean b/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean index 2dad55c4743d8..e7c7b65e0c20b 100644 --- a/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean +++ b/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean @@ -3,8 +3,9 @@ Copyright (c) 2021 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Heather Macbeth -/ -import Mathlib.Topology.ContinuousFunction.Weierstrass import Mathlib.Data.IsROrC.Basic +import Mathlib.Topology.Algebra.StarSubalgebra +import Mathlib.Topology.ContinuousFunction.Weierstrass #align_import topology.continuous_function.stone_weierstrass from "leanprover-community/mathlib"@"16e59248c0ebafabd5d071b1cd41743eb8698ffb" @@ -111,7 +112,7 @@ theorem comp_attachBound_mem_closure (A : Subalgebra ℝ C(X, ℝ)) (f : A) #align continuous_map.comp_attach_bound_mem_closure ContinuousMap.comp_attachBound_mem_closure theorem abs_mem_subalgebra_closure (A : Subalgebra ℝ C(X, ℝ)) (f : A) : - (f : C(X, ℝ)).abs ∈ A.topologicalClosure := by + |(f : C(X, ℝ))| ∈ A.topologicalClosure := by let f' := attachBound (f : C(X, ℝ)) let abs : C(Set.Icc (-‖f‖) ‖f‖, ℝ) := { toFun := fun x : Set.Icc (-‖f‖) ‖f‖ => |(x : ℝ)| } change abs.comp f' ∈ A.topologicalClosure @@ -208,25 +209,25 @@ theorem sublattice_closure_eq_top (L : Set C(X, ℝ)) (nA : L.Nonempty) -- and still equal to `f x` at `x`. -- Since `X` is compact, for every `x` there is some finset `ys t` -- so the union of the `U x y` for `y ∈ ys x` still covers everything. - let ys : ∀ _, Finset X := fun x => (CompactSpace.elim_nhds_subcover (U x) (U_nhd_y x)).choose + let ys : X → Finset X := fun x => (CompactSpace.elim_nhds_subcover (U x) (U_nhd_y x)).choose let ys_w : ∀ x, ⋃ y ∈ ys x, U x y = ⊤ := fun x => (CompactSpace.elim_nhds_subcover (U x) (U_nhd_y x)).choose_spec have ys_nonempty : ∀ x, (ys x).Nonempty := fun x => Set.nonempty_of_union_eq_top_of_nonempty _ _ nX (ys_w x) -- Thus for each `x` we have the desired `h x : A` so `f z - ε < h x z` everywhere -- and `h x x = f x`. - let h : ∀ _, L := fun x => + let h : X → L := fun x => ⟨(ys x).sup' (ys_nonempty x) fun y => (g x y : C(X, ℝ)), Finset.sup'_mem _ sup_mem _ _ _ fun y _ => hg x y⟩ have lt_h : ∀ x z, f z - ε < (h x : X → ℝ) z := by intro x z obtain ⟨y, ym, zm⟩ := Set.exists_set_mem_of_union_eq_top _ _ (ys_w x) z dsimp - simp only [Subtype.coe_mk, sup'_coe, Finset.sup'_apply, Finset.lt_sup'_iff] + simp only [Subtype.coe_mk, coe_sup', Finset.sup'_apply, Finset.lt_sup'_iff] exact ⟨y, ym, zm⟩ have h_eq : ∀ x, (h x : X → ℝ) x = f x := by intro x; simp [w₁] -- For each `x`, we define `W x` to be `{z | h x z < f z + ε}`, - let W : ∀ _, Set X := fun x => {z | (h x : X → ℝ) z < f z + ε} + let W : X → Set X := fun x => {z | (h x : X → ℝ) z < f z + ε} -- This is still a neighbourhood of `x`. have W_nhd : ∀ x, W x ∈ 𝓝 x := by intro x @@ -364,16 +365,14 @@ theorem Subalgebra.SeparatesPoints.isROrC_to_real {A : StarSubalgebra 𝕜 C(X, simp only [coe_smul, coe_one, smul_apply, one_apply, Algebra.id.smul_eq_mul, mul_one, const_apply] -- Consider now the function `fun x ↦ |f x - f x₂| ^ 2` - refine' ⟨_, ⟨(⟨IsROrC.normSq, continuous_normSq⟩ : C(𝕜, ℝ)).comp F, _, rfl⟩, _⟩ + refine' ⟨_, ⟨⟨(‖F ·‖ ^ 2), by continuity⟩, _, rfl⟩, _⟩ · -- This is also an element of the subalgebra, and takes only real values rw [SetLike.mem_coe, Subalgebra.mem_comap] convert (A.restrictScalars ℝ).mul_mem hFA (star_mem hFA : star F ∈ A) ext1 - exact (IsROrC.mul_conj (K := 𝕜) _).symm + simp [← IsROrC.mul_conj] · -- And it also separates the points `x₁`, `x₂` - have : f x₁ - f x₂ ≠ 0 := sub_ne_zero.mpr hf - simpa only [comp_apply, coe_sub, coe_const, sub_apply, coe_mk, sub_self, map_zero, Ne.def, - normSq_eq_zero, const_apply] using this + simpa using sub_ne_zero.mpr hf #align subalgebra.separates_points.is_R_or_C_to_real Subalgebra.SeparatesPoints.isROrC_to_real variable [CompactSpace X] diff --git a/Mathlib/Topology/ContinuousFunction/Weierstrass.lean b/Mathlib/Topology/ContinuousFunction/Weierstrass.lean index 6e1e4434136e8..ec1468619e374 100644 --- a/Mathlib/Topology/ContinuousFunction/Weierstrass.lean +++ b/Mathlib/Topology/ContinuousFunction/Weierstrass.lean @@ -75,7 +75,7 @@ theorem polynomialFunctions_closure_eq_top (a b : ℝ) : -- 🎉 exact p · -- Otherwise, `b ≤ a`, and the interval is a subsingleton, - have : Subsingleton (Set.Icc a b) := (Set.subsingleton_coe _).mpr $ Set.subsingleton_Icc_of_ge h + have : Subsingleton (Set.Icc a b) := (Set.subsingleton_Icc_of_ge h).coe_sort apply Subsingleton.elim #align polynomial_functions_closure_eq_top polynomialFunctions_closure_eq_top diff --git a/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean b/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean index 2023274eb8e86..92fc1475e5755 100644 --- a/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean +++ b/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean @@ -84,10 +84,10 @@ instance instZeroAtInftyContinuousMapClass : ZeroAtInftyContinuousMapClass C₀( map_continuous f := f.continuous_toFun zero_at_infty f := f.zero_at_infty' -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance instCoeFun : CoeFun C₀(α, β) fun _ => α → β := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun instance instCoeTC : CoeTC F C₀(α, β) := ⟨fun f => @@ -102,7 +102,7 @@ theorem coe_toContinuousMap (f : C₀(α, β)) : (f.toContinuousMap : α → β) @[ext] theorem ext {f g : C₀(α, β)} (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align zero_at_infty_continuous_map.ext ZeroAtInftyContinuousMap.ext /-- Copy of a `ZeroAtInftyContinuousMap` with a new `toFun` equal to the old one. Useful @@ -123,7 +123,7 @@ theorem coe_copy (f : C₀(α, β)) (f' : α → β) (h : f' = f) : ⇑(f.copy f #align zero_at_infty_continuous_map.coe_copy ZeroAtInftyContinuousMap.coe_copy theorem copy_eq (f : C₀(α, β)) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align zero_at_infty_continuous_map.copy_eq ZeroAtInftyContinuousMap.copy_eq theorem eq_of_empty [IsEmpty α] (f g : C₀(α, β)) : f = g := @@ -152,7 +152,7 @@ infinity. This is not an instance to avoid type class loops. -/ def zeroAtInftyContinuousMapClass.ofCompact {G : Type*} [ContinuousMapClass G α β] [CompactSpace α] : ZeroAtInftyContinuousMapClass G α β where coe g := g - coe_injective' f g h := FunLike.coe_fn_eq.mp h + coe_injective' f g h := DFunLike.coe_fn_eq.mp h map_continuous := map_continuous zero_at_infty := by simp #align zero_at_infty_continuous_map.zero_at_infty_continuous_map_class.of_compact ZeroAtInftyContinuousMap.zeroAtInftyContinuousMapClass.ofCompact @@ -200,11 +200,11 @@ theorem mul_apply [MulZeroClass β] [ContinuousMul β] (f g : C₀(α, β)) : (f #align zero_at_infty_continuous_map.mul_apply ZeroAtInftyContinuousMap.mul_apply instance instMulZeroClass [MulZeroClass β] [ContinuousMul β] : MulZeroClass C₀(α, β) := - FunLike.coe_injective.mulZeroClass _ coe_zero coe_mul + DFunLike.coe_injective.mulZeroClass _ coe_zero coe_mul instance instSemigroupWithZero [SemigroupWithZero β] [ContinuousMul β] : SemigroupWithZero C₀(α, β) := - FunLike.coe_injective.semigroupWithZero _ coe_zero coe_mul + DFunLike.coe_injective.semigroupWithZero _ coe_zero coe_mul instance instAdd [AddZeroClass β] [ContinuousAdd β] : Add C₀(α, β) := ⟨fun f g => ⟨f + g, by simpa only [add_zero] using (zero_at_infty f).add (zero_at_infty g)⟩⟩ @@ -219,7 +219,7 @@ theorem add_apply [AddZeroClass β] [ContinuousAdd β] (f g : C₀(α, β)) : (f #align zero_at_infty_continuous_map.add_apply ZeroAtInftyContinuousMap.add_apply instance instAddZeroClass [AddZeroClass β] [ContinuousAdd β] : AddZeroClass C₀(α, β) := - FunLike.coe_injective.addZeroClass _ coe_zero coe_add + DFunLike.coe_injective.addZeroClass _ coe_zero coe_add section AddMonoid @@ -237,12 +237,12 @@ instance instNatSMul : SMul ℕ C₀(α, β) := #align zero_at_infty_continuous_map.has_nat_scalar ZeroAtInftyContinuousMap.instNatSMul instance instAddMonoid : AddMonoid C₀(α, β) := - FunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => rfl + DFunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => rfl end AddMonoid instance instAddCommMonoid [AddCommMonoid β] [ContinuousAdd β] : AddCommMonoid C₀(α, β) := - FunLike.coe_injective.addCommMonoid _ coe_zero coe_add fun _ _ => rfl + DFunLike.coe_injective.addCommMonoid _ coe_zero coe_add fun _ _ => rfl section AddGroup @@ -285,12 +285,12 @@ instance instIntSMul : SMul ℤ C₀(α, β) := #align zero_at_infty_continuous_map.has_int_scalar ZeroAtInftyContinuousMap.instIntSMul instance instAddGroup : AddGroup C₀(α, β) := - FunLike.coe_injective.addGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) fun _ _ => rfl + DFunLike.coe_injective.addGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) fun _ _ => rfl end AddGroup instance instAddCommGroup [AddCommGroup β] [TopologicalAddGroup β] : AddCommGroup C₀(α, β) := - FunLike.coe_injective.addCommGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) fun _ _ => + DFunLike.coe_injective.addCommGroup _ coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) fun _ _ => rfl instance instSMul [Zero β] {R : Type*} [Zero R] [SMulWithZero R β] [ContinuousConstSMul R β] : @@ -316,40 +316,40 @@ instance instIsCentralScalar [Zero β] {R : Type*} [Zero R] [SMulWithZero R β] instance instSMulWithZero [Zero β] {R : Type*} [Zero R] [SMulWithZero R β] [ContinuousConstSMul R β] : SMulWithZero R C₀(α, β) := - Function.Injective.smulWithZero ⟨_, coe_zero⟩ FunLike.coe_injective coe_smul + Function.Injective.smulWithZero ⟨_, coe_zero⟩ DFunLike.coe_injective coe_smul instance instMulActionWithZero [Zero β] {R : Type*} [MonoidWithZero R] [MulActionWithZero R β] [ContinuousConstSMul R β] : MulActionWithZero R C₀(α, β) := - Function.Injective.mulActionWithZero ⟨_, coe_zero⟩ FunLike.coe_injective coe_smul + Function.Injective.mulActionWithZero ⟨_, coe_zero⟩ DFunLike.coe_injective coe_smul instance instModule [AddCommMonoid β] [ContinuousAdd β] {R : Type*} [Semiring R] [Module R β] [ContinuousConstSMul R β] : Module R C₀(α, β) := - Function.Injective.module R ⟨⟨_, coe_zero⟩, coe_add⟩ FunLike.coe_injective coe_smul + Function.Injective.module R ⟨⟨_, coe_zero⟩, coe_add⟩ DFunLike.coe_injective coe_smul instance instNonUnitalNonAssocSemiring [NonUnitalNonAssocSemiring β] [TopologicalSemiring β] : NonUnitalNonAssocSemiring C₀(α, β) := - FunLike.coe_injective.nonUnitalNonAssocSemiring _ coe_zero coe_add coe_mul fun _ _ => rfl + DFunLike.coe_injective.nonUnitalNonAssocSemiring _ coe_zero coe_add coe_mul fun _ _ => rfl instance instNonUnitalSemiring [NonUnitalSemiring β] [TopologicalSemiring β] : NonUnitalSemiring C₀(α, β) := - FunLike.coe_injective.nonUnitalSemiring _ coe_zero coe_add coe_mul fun _ _ => rfl + DFunLike.coe_injective.nonUnitalSemiring _ coe_zero coe_add coe_mul fun _ _ => rfl instance instNonUnitalCommSemiring [NonUnitalCommSemiring β] [TopologicalSemiring β] : NonUnitalCommSemiring C₀(α, β) := - FunLike.coe_injective.nonUnitalCommSemiring _ coe_zero coe_add coe_mul fun _ _ => rfl + DFunLike.coe_injective.nonUnitalCommSemiring _ coe_zero coe_add coe_mul fun _ _ => rfl instance instNonUnitalNonAssocRing [NonUnitalNonAssocRing β] [TopologicalRing β] : NonUnitalNonAssocRing C₀(α, β) := - FunLike.coe_injective.nonUnitalNonAssocRing _ coe_zero coe_add coe_mul coe_neg coe_sub + DFunLike.coe_injective.nonUnitalNonAssocRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ => rfl) fun _ _ => rfl instance instNonUnitalRing [NonUnitalRing β] [TopologicalRing β] : NonUnitalRing C₀(α, β) := - FunLike.coe_injective.nonUnitalRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ => rfl) + DFunLike.coe_injective.nonUnitalRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ => rfl) fun _ _ => rfl instance instNonUnitalCommRing [NonUnitalCommRing β] [TopologicalRing β] : NonUnitalCommRing C₀(α, β) := - FunLike.coe_injective.nonUnitalCommRing _ coe_zero coe_add coe_mul coe_neg coe_sub + DFunLike.coe_injective.nonUnitalCommRing _ coe_zero coe_add coe_mul coe_neg coe_sub (fun _ _ => rfl) fun _ _ => rfl instance instIsScalarTower {R : Type*} [Semiring R] [NonUnitalNonAssocSemiring β] @@ -383,7 +383,7 @@ end Uniform /-! ### Metric structure When `β` is a metric space, then every element of `C₀(α, β)` is bounded, and so there is a natural -inclusion map `ZeroAtInftyContinuousMap.toBcf : C₀(α, β) → (α →ᵇ β)`. Via this map `C₀(α, β)` +inclusion map `ZeroAtInftyContinuousMap.toBCF : C₀(α, β) → (α →ᵇ β)`. Via this map `C₀(α, β)` inherits a metric as the pullback of the metric on `α →ᵇ β`. Moreover, this map has closed range in `α →ᵇ β` and consequently `C₀(α, β)` is a complete space whenever `β` is complete. -/ @@ -393,7 +393,7 @@ section Metric open Metric Set -variable [MetricSpace β] [Zero β] [ZeroAtInftyContinuousMapClass F α β] +variable [PseudoMetricSpace β] [Zero β] [ZeroAtInftyContinuousMapClass F α β] protected theorem bounded (f : F) : ∃ C, ∀ x y : α, dist ((f : α → β) x) (f y) ≤ C := by obtain ⟨K : Set α, hK₁, hK₂⟩ := mem_cocompact.mp @@ -423,32 +423,38 @@ instance (priority := 100) instBoundedContinuousMapClass : BoundedContinuousMapC /-- Construct a bounded continuous function from a continuous function vanishing at infinity. -/ @[simps!] -def toBcf (f : C₀(α, β)) : α →ᵇ β := +def toBCF (f : C₀(α, β)) : α →ᵇ β := ⟨f, map_bounded f⟩ -#align zero_at_infty_continuous_map.to_bcf ZeroAtInftyContinuousMap.toBcf +#align zero_at_infty_continuous_map.to_bcf ZeroAtInftyContinuousMap.toBCF section variable (α) (β) -theorem toBcf_injective : Function.Injective (toBcf : C₀(α, β) → α →ᵇ β) := fun f g h => by +theorem toBCF_injective : Function.Injective (toBCF : C₀(α, β) → α →ᵇ β) := fun f g h => by ext x - simpa only using FunLike.congr_fun h x -#align zero_at_infty_continuous_map.to_bcf_injective ZeroAtInftyContinuousMap.toBcf_injective + simpa only using DFunLike.congr_fun h x +#align zero_at_infty_continuous_map.to_bcf_injective ZeroAtInftyContinuousMap.toBCF_injective end variable {C : ℝ} {f g : C₀(α, β)} /-- The type of continuous functions vanishing at infinity, with the uniform distance induced by the -inclusion `ZeroAtInftyContinuousMap.toBcf`, is a metric space. -/ -noncomputable instance instMetricSpace : MetricSpace C₀(α, β) := - MetricSpace.induced _ (toBcf_injective α β) inferInstance +inclusion `ZeroAtInftyContinuousMap.toBCF`, is a pseudo-metric space. -/ +noncomputable instance instPseudoMetricSpace : PseudoMetricSpace C₀(α, β) := + PseudoMetricSpace.induced toBCF inferInstance + +/-- The type of continuous functions vanishing at infinity, with the uniform distance induced by the +inclusion `ZeroAtInftyContinuousMap.toBCF`, is a metric space. -/ +noncomputable instance instMetricSpace {β : Type*} [MetricSpace β] [Zero β] : + MetricSpace C₀(α, β) := + MetricSpace.induced _ (toBCF_injective α β) inferInstance @[simp] -theorem dist_toBcf_eq_dist {f g : C₀(α, β)} : dist f.toBcf g.toBcf = dist f g := +theorem dist_toBCF_eq_dist {f g : C₀(α, β)} : dist f.toBCF g.toBCF = dist f g := rfl -#align zero_at_infty_continuous_map.dist_to_bcf_eq_dist ZeroAtInftyContinuousMap.dist_toBcf_eq_dist +#align zero_at_infty_continuous_map.dist_to_bcf_eq_dist ZeroAtInftyContinuousMap.dist_toBCF_eq_dist open BoundedContinuousFunction @@ -456,14 +462,14 @@ open BoundedContinuousFunction theorem tendsto_iff_tendstoUniformly {ι : Type*} {F : ι → C₀(α, β)} {f : C₀(α, β)} {l : Filter ι} : Tendsto F l (𝓝 f) ↔ TendstoUniformly (fun i => F i) f l := by simpa only [Metric.tendsto_nhds] using - @BoundedContinuousFunction.tendsto_iff_tendstoUniformly _ _ _ _ _ (fun i => (F i).toBcf) - f.toBcf l + @BoundedContinuousFunction.tendsto_iff_tendstoUniformly _ _ _ _ _ (fun i => (F i).toBCF) + f.toBCF l #align zero_at_infty_continuous_map.tendsto_iff_tendsto_uniformly ZeroAtInftyContinuousMap.tendsto_iff_tendstoUniformly -theorem isometry_toBcf : Isometry (toBcf : C₀(α, β) → α →ᵇ β) := by tauto -#align zero_at_infty_continuous_map.isometry_to_bcf ZeroAtInftyContinuousMap.isometry_toBcf +theorem isometry_toBCF : Isometry (toBCF : C₀(α, β) → α →ᵇ β) := by tauto +#align zero_at_infty_continuous_map.isometry_to_bcf ZeroAtInftyContinuousMap.isometry_toBCF -theorem closed_range_toBcf : IsClosed (range (toBcf : C₀(α, β) → α →ᵇ β)) := by +theorem closed_range_toBCF : IsClosed (range (toBCF : C₀(α, β) → α →ᵇ β)) := by refine' isClosed_iff_clusterPt.mpr fun f hf => _ rw [clusterPt_principal_iff] at hf have : Tendsto f (cocompact α) (𝓝 0) := by @@ -472,17 +478,17 @@ theorem closed_range_toBcf : IsClosed (range (toBcf : C₀(α, β) → α →ᵇ refine' (Metric.tendsto_nhds.mp (zero_at_infty g) (ε / 2) (half_pos hε)).mp (eventually_of_forall fun x hx => _) calc - dist (f x) 0 ≤ dist (g.toBcf x) (f x) + dist (g x) 0 := dist_triangle_left _ _ _ - _ < dist g.toBcf f + ε / 2 := (add_lt_add_of_le_of_lt (dist_coe_le_dist x) hx) + dist (f x) 0 ≤ dist (g.toBCF x) (f x) + dist (g x) 0 := dist_triangle_left _ _ _ + _ < dist g.toBCF f + ε / 2 := (add_lt_add_of_le_of_lt (dist_coe_le_dist x) hx) _ < ε := by simpa [add_halves ε] using add_lt_add_right (mem_ball.1 hg) (ε / 2) exact ⟨⟨f.toContinuousMap, this⟩, rfl⟩ -#align zero_at_infty_continuous_map.closed_range_to_bcf ZeroAtInftyContinuousMap.closed_range_toBcf +#align zero_at_infty_continuous_map.closed_range_to_bcf ZeroAtInftyContinuousMap.closed_range_toBCF /-- Continuous functions vanishing at infinity taking values in a complete space form a complete space. -/ instance instCompleteSpace [CompleteSpace β] : CompleteSpace C₀(α, β) := - (completeSpace_iff_isComplete_range isometry_toBcf.uniformInducing).mpr - closed_range_toBcf.isComplete + (completeSpace_iff_isComplete_range isometry_toBCF.uniformInducing).mpr + closed_range_toBCF.isComplete end Metric @@ -490,7 +496,7 @@ section Norm /-! ### Normed space -The norm structure on `C₀(α, β)` is the one induced by the inclusion `toBcf : C₀(α, β) → (α →ᵇ b)`, +The norm structure on `C₀(α, β)` is the one induced by the inclusion `toBCF : C₀(α, β) → (α →ᵇ b)`, viewed as an additive monoid homomorphism. Then `C₀(α, β)` is naturally a normed space over a normed field `𝕜` whenever `β` is as well. -/ @@ -498,28 +504,45 @@ field `𝕜` whenever `β` is as well. section NormedSpace -variable [NormedAddCommGroup β] {𝕜 : Type*} [NormedField 𝕜] [NormedSpace 𝕜 β] +noncomputable instance instSeminormedAddCommGroup [SeminormedAddCommGroup β] : + SeminormedAddCommGroup C₀(α, β) := + SeminormedAddCommGroup.induced _ _ (⟨⟨toBCF, rfl⟩, fun _ _ => rfl⟩ : C₀(α, β) →+ α →ᵇ β) + +noncomputable instance instNormedAddCommGroup [NormedAddCommGroup β] : + NormedAddCommGroup C₀(α, β) := + NormedAddCommGroup.induced _ _ (⟨⟨toBCF, rfl⟩, fun _ _ => rfl⟩ : C₀(α, β) →+ α →ᵇ β) + (toBCF_injective α β) -noncomputable instance instNormedAddCommGroup : NormedAddCommGroup C₀(α, β) := - NormedAddCommGroup.induced C₀(α, β) (α →ᵇ β) (⟨⟨toBcf, rfl⟩, fun _ _ => rfl⟩ : C₀(α, β) →+ α →ᵇ β) - (toBcf_injective α β) +variable [SeminormedAddCommGroup β] {𝕜 : Type*} [NormedField 𝕜] [NormedSpace 𝕜 β] @[simp] -theorem norm_toBcf_eq_norm {f : C₀(α, β)} : ‖f.toBcf‖ = ‖f‖ := +theorem norm_toBCF_eq_norm {f : C₀(α, β)} : ‖f.toBCF‖ = ‖f‖ := rfl -#align zero_at_infty_continuous_map.norm_to_bcf_eq_norm ZeroAtInftyContinuousMap.norm_toBcf_eq_norm +#align zero_at_infty_continuous_map.norm_to_bcf_eq_norm ZeroAtInftyContinuousMap.norm_toBCF_eq_norm -instance : NormedSpace 𝕜 C₀(α, β) where norm_smul_le k f := (norm_smul_le k f.toBcf : _) +instance : NormedSpace 𝕜 C₀(α, β) where norm_smul_le k f := (norm_smul_le k f.toBCF : _) end NormedSpace section NormedRing -variable [NonUnitalNormedRing β] +noncomputable instance instNonUnitalSeminormedRing [NonUnitalSeminormedRing β] : + NonUnitalSeminormedRing C₀(α, β) := + { instNonUnitalRing, instSeminormedAddCommGroup with + norm_mul := fun f g => norm_mul_le f.toBCF g.toBCF } + +noncomputable instance instNonUnitalNormedRing [NonUnitalNormedRing β] : + NonUnitalNormedRing C₀(α, β) := + { instNonUnitalRing, instNormedAddCommGroup with + norm_mul := fun f g => norm_mul_le f.toBCF g.toBCF } + +noncomputable instance instNonUnitalSeminormedCommRing [NonUnitalSeminormedCommRing β] : + NonUnitalSeminormedCommRing C₀(α, β) := + { instNonUnitalSeminormedRing, instNonUnitalCommRing with } -noncomputable instance instNonUnitalNormedRing : NonUnitalNormedRing C₀(α, β) := - { ZeroAtInftyContinuousMap.instNonUnitalRing, ZeroAtInftyContinuousMap.instNormedAddCommGroup with - norm_mul := fun f g => norm_mul_le f.toBcf g.toBcf } +noncomputable instance instNonUnitalNormedCommRing [NonUnitalNormedCommRing β] : + NonUnitalNormedCommRing C₀(α, β) := + { instNonUnitalNormedRing, instNonUnitalCommRing with } end NormedRing @@ -567,7 +590,7 @@ section NormedStar variable [NormedAddCommGroup β] [StarAddMonoid β] [NormedStarGroup β] instance instNormedStarGroup : NormedStarGroup C₀(α, β) where - norm_star f := (norm_star f.toBcf : _) + norm_star f := (norm_star f.toBCF : _) end NormedStar @@ -595,7 +618,7 @@ end StarRing section CstarRing instance instCstarRing [NonUnitalNormedRing β] [StarRing β] [CstarRing β] : CstarRing C₀(α, β) where - norm_star_mul_self {f} := CstarRing.norm_star_mul_self (x := f.toBcf) + norm_star_mul_self {f} := CstarRing.norm_star_mul_self (x := f.toBCF) end CstarRing diff --git a/Mathlib/Topology/EMetricSpace/Basic.lean b/Mathlib/Topology/EMetricSpace/Basic.lean index 82d2ded130d93..853862d81fb0b 100644 --- a/Mathlib/Topology/EMetricSpace/Basic.lean +++ b/Mathlib/Topology/EMetricSpace/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Robert Y. Lewis, Johannes Hölzl, Mario Carneiro, Sébastien Gouëzel -/ import Mathlib.Data.Nat.Interval -import Mathlib.Data.Real.ENNReal +import Mathlib.Data.ENNReal.Basic import Mathlib.Topology.UniformSpace.Pi import Mathlib.Topology.UniformSpace.UniformConvergence import Mathlib.Topology.UniformSpace.UniformEmbedding @@ -1180,7 +1180,7 @@ instance [PseudoEMetricSpace X] : EMetricSpace (UniformSpace.SeparationQuotient edist_comm := fun x y => Quotient.inductionOn₂' x y edist_comm, edist_triangle := fun x y z => Quotient.inductionOn₃' x y z edist_triangle, toUniformSpace := inferInstance, - uniformity_edist := (uniformity_basis_edist.map _).eq_biInf.trans $ iInf_congr fun ε => + uniformity_edist := (uniformity_basis_edist.map _).eq_biInf.trans <| iInf_congr fun ε => iInf_congr fun _ => congr_arg 𝓟 <| by ext ⟨⟨x⟩, ⟨y⟩⟩ refine ⟨?_, fun h => ⟨(x, y), h, rfl⟩⟩ diff --git a/Mathlib/Topology/EMetricSpace/Lipschitz.lean b/Mathlib/Topology/EMetricSpace/Lipschitz.lean index ffedc002aa0ca..6631a490d7f3b 100644 --- a/Mathlib/Topology/EMetricSpace/Lipschitz.lean +++ b/Mathlib/Topology/EMetricSpace/Lipschitz.lean @@ -41,8 +41,6 @@ coercions both to `ℝ` and `ℝ≥0∞`. Constructors whose names end with `'` argument, and return `LipschitzWith (Real.toNNReal K) f`. -/ -set_option autoImplicit true - universe u v w x open Filter Function Set Topology NNReal ENNReal Bornology @@ -313,8 +311,8 @@ protected theorem continuousOn (hf : LipschitzOnWith K f s) : ContinuousOn f s : hf.uniformContinuousOn.continuousOn #align lipschitz_on_with.continuous_on LipschitzOnWith.continuousOn -theorem edist_le_mul_of_le (h : LipschitzOnWith K f s) (hx : x ∈ s) (hy : y ∈ s) - (hr : edist x y ≤ r) : +theorem edist_le_mul_of_le (h : LipschitzOnWith K f s) {x y : α} (hx : x ∈ s) (hy : y ∈ s) + {r : ℝ≥0∞} (hr : edist x y ≤ r) : edist (f x) (f y) ≤ K * r := (h hx hy).trans <| ENNReal.mul_left_mono hr diff --git a/Mathlib/Topology/ExtremallyDisconnected.lean b/Mathlib/Topology/ExtremallyDisconnected.lean index 5d622bca84f94..d5d0c2948a443 100644 --- a/Mathlib/Topology/ExtremallyDisconnected.lean +++ b/Mathlib/Topology/ExtremallyDisconnected.lean @@ -90,7 +90,7 @@ theorem StoneCech.projective [DiscreteTopology X] : CompactT2.Projective (StoneC let h : StoneCech X → Y := stoneCechExtend ht have hh : Continuous h := continuous_stoneCechExtend ht refine' ⟨h, hh, denseRange_stoneCechUnit.equalizer (hg.comp hh) hf _⟩ - rw [comp.assoc, stoneCechExtend_extends ht, ← comp.assoc, hs, comp.left_id] + rw [comp.assoc, stoneCechExtend_extends ht, ← comp.assoc, hs, id_comp] #align stone_cech.projective StoneCech.projective protected theorem CompactT2.Projective.extremallyDisconnected [CompactSpace X] [T2Space X] @@ -274,7 +274,7 @@ protected theorem CompactT2.ExtremallyDisconnected.projective [ExtremallyDisconn have π₂_cont : Continuous π₂ := continuous_snd.comp continuous_subtype_val refine ⟨E.restrict π₂ ∘ ρ'.symm, ⟨π₂_cont.continuousOn.restrict.comp ρ'.symm.continuous, ?_⟩⟩ suffices f ∘ E.restrict π₂ = φ ∘ ρ' by - rw [← comp.assoc, this, comp.assoc, Homeomorph.self_comp_symm, comp.right_id] + rw [← comp.assoc, this, comp.assoc, Homeomorph.self_comp_symm, comp_id] ext x exact x.val.mem.symm diff --git a/Mathlib/Topology/FiberBundle/Constructions.lean b/Mathlib/Topology/FiberBundle/Constructions.lean index d2401793d34bb..c16340dd323c7 100644 --- a/Mathlib/Topology/FiberBundle/Constructions.lean +++ b/Mathlib/Topology/FiberBundle/Constructions.lean @@ -326,7 +326,8 @@ theorem Pullback.continuous_totalSpaceMk [∀ x, TopologicalSpace (E x)] [FiberB exact le_of_eq (FiberBundle.totalSpaceMk_inducing F E (f x)).induced #align pullback.continuous_total_space_mk Pullback.continuous_totalSpaceMk -variable {E F} [∀ _b, Zero (E _b)] {K : Type U} [ContinuousMapClass K B' B] +variable {E F} +variable [∀ b, Zero (E b)] {K : Type U} [ContinuousMapClass K B' B] -- Porting note: universe levels are explicitly provided /-- A fiber bundle trivialization can be pulled back to a trivialization on the pullback bundle. -/ diff --git a/Mathlib/Topology/FiberBundle/Trivialization.lean b/Mathlib/Topology/FiberBundle/Trivialization.lean index dc16c6787110d..0042b548bc18c 100644 --- a/Mathlib/Topology/FiberBundle/Trivialization.lean +++ b/Mathlib/Topology/FiberBundle/Trivialization.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Data.Bundle -import Mathlib.Topology.Algebra.Order.Field +import Mathlib.Data.Set.Image import Mathlib.Topology.PartialHomeomorph +import Mathlib.Topology.Order.Basic #align_import topology.fiber_bundle.trivialization from "leanprover-community/mathlib"@"e473c3198bb41f68560cab68a0529c854b618833" @@ -48,9 +49,6 @@ Indeed, since trivializations only have meaning on their base sets (taking junk type of linear trivializations is not even particularly well-behaved. -/ -set_option autoImplicit true - - open TopologicalSpace Filter Set Bundle Function open scoped Topology Classical Bundle @@ -458,7 +456,7 @@ theorem image_preimage_eq_prod_univ {s : Set B} (hb : s ⊆ e.baseSet) : ⟨e.invFun p, mem_preimage.mpr ((e.proj_symm_apply hp').symm ▸ hp.1), e.apply_symm_apply hp'⟩ #align trivialization.image_preimage_eq_prod_univ Trivialization.image_preimage_eq_prod_univ -theorem tendsto_nhds_iff {l : Filter α} {f : α → Z} {z : Z} (hz : z ∈ e.source) : +theorem tendsto_nhds_iff {α : Type*} {l : Filter α} {f : α → Z} {z : Z} (hz : z ∈ e.source) : Tendsto f l (𝓝 z) ↔ Tendsto (proj ∘ f) l (𝓝 (proj z)) ∧ Tendsto (fun x ↦ (e (f x)).2) l (𝓝 (e z).2) := by rw [e.nhds_eq_comap_inf_principal hz, tendsto_inf, tendsto_comap_iff, Prod.tendsto_iff, coe_coe, diff --git a/Mathlib/Topology/GDelta.lean b/Mathlib/Topology/GDelta.lean index ebbc4dcab911c..f9cbb6c1312f8 100644 --- a/Mathlib/Topology/GDelta.lean +++ b/Mathlib/Topology/GDelta.lean @@ -32,7 +32,7 @@ continuity set of a function from a topological space to an (e)metric space is a - `isClosed_isNowhereDense_iff_compl`: a closed set is nowhere dense iff its complement is open and dense -- `meagre_iff_countable_union_isNowhereDense`: a set is meagre iff it is contained in a countable +- `isMeagre_iff_countable_union_isNowhereDense`: a set is meagre iff it is contained in a countable union of nowhere dense sets - subsets of meagre sets are meagre; countable unions of meagre sets are meagre @@ -283,13 +283,13 @@ lemma IsMeagre.inter {s t : Set X} (hs : IsMeagre s) : IsMeagre (s ∩ t) := hs.mono (inter_subset_left s t) /-- A countable union of meagre sets is meagre. -/ -lemma meagre_iUnion {s : ℕ → Set X} (hs : ∀ n, IsMeagre (s n)) : IsMeagre (⋃ n, s n) := by +lemma isMeagre_iUnion {s : ℕ → Set X} (hs : ∀ n, IsMeagre (s n)) : IsMeagre (⋃ n, s n) := by rw [IsMeagre, compl_iUnion] exact countable_iInter_mem.mpr hs /-- A set is meagre iff it is contained in a countable union of nowhere dense sets. -/ -lemma meagre_iff_countable_union_isNowhereDense {s : Set X} : IsMeagre s ↔ - ∃ S : Set (Set X), (∀ t ∈ S, IsNowhereDense t) ∧ S.Countable ∧ s ⊆ ⋃₀ S := by +lemma isMeagre_iff_countable_union_isNowhereDense {s : Set X} : + IsMeagre s ↔ ∃ S : Set (Set X), (∀ t ∈ S, IsNowhereDense t) ∧ S.Countable ∧ s ⊆ ⋃₀ S := by rw [IsMeagre, mem_residual_iff, compl_bijective.surjective.image_surjective.exists] simp_rw [← and_assoc, ← forall_and, ball_image_iff, ← isClosed_isNowhereDense_iff_compl, sInter_image, ← compl_iUnion₂, compl_subset_compl, ← sUnion_eq_biUnion, and_assoc] diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index 9bdf29f93691a..0df359472115d 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.CategoryTheory.GlueData -import Mathlib.CategoryTheory.ConcreteCategory.Elementwise import Mathlib.Topology.Category.TopCat.Limits.Pullbacks import Mathlib.Topology.Category.TopCat.Opens import Mathlib.Tactic.LibrarySearch diff --git a/Mathlib/Topology/Hom/Open.lean b/Mathlib/Topology/Hom/Open.lean index 79ef639c509a0..3cf082e792ba3 100644 --- a/Mathlib/Topology/Hom/Open.lean +++ b/Mathlib/Topology/Hom/Open.lean @@ -12,7 +12,7 @@ import Mathlib.Topology.ContinuousFunction.Basic This file defines bundled continuous open maps. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -80,7 +80,7 @@ theorem coe_toContinuousMap (f : α →CO β) : (f.toContinuousMap : α → β) @[ext] theorem ext {f g : α →CO β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align continuous_open_map.ext ContinuousOpenMap.ext /-- Copy of a `ContinuousOpenMap` with a new `ContinuousMap` equal to the old one. Useful to fix @@ -95,7 +95,7 @@ theorem coe_copy (f : α →CO β) (f' : α → β) (h : f' = f) : ⇑(f.copy f' #align continuous_open_map.coe_copy ContinuousOpenMap.coe_copy theorem copy_eq (f : α →CO β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align continuous_open_map.copy_eq ContinuousOpenMap.copy_eq variable (α) @@ -154,7 +154,7 @@ theorem id_comp (f : α →CO β) : (ContinuousOpenMap.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : β →CO γ} {f : α →CO β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ #align continuous_open_map.cancel_right ContinuousOpenMap.cancel_right @[simp] diff --git a/Mathlib/Topology/Homeomorph.lean b/Mathlib/Topology/Homeomorph.lean index 62369062ba06a..b4b116bd5828d 100644 --- a/Mathlib/Topology/Homeomorph.lean +++ b/Mathlib/Topology/Homeomorph.lean @@ -6,6 +6,7 @@ Authors: Johannes Hölzl, Patrick Massot, Sébastien Gouëzel, Zhouhang Zhou, Re import Mathlib.Logic.Equiv.Fin import Mathlib.Topology.DenseEmbedding import Mathlib.Topology.Support +import Mathlib.Topology.Connected.LocallyConnected #align_import topology.homeomorph from "leanprover-community/mathlib"@"4c3e1721c58ef9087bbc2c8c38b540f70eda2e53" @@ -61,9 +62,9 @@ instance : EquivLike (X ≃ₜ Y) X Y where inv := fun h => h.toEquiv.symm left_inv := fun h => h.left_inv right_inv := fun h => h.right_inv - coe_injective' := fun _ _ H _ => toEquiv_injective <| FunLike.ext' H + coe_injective' := fun _ _ H _ => toEquiv_injective <| DFunLike.ext' H -instance : CoeFun (X ≃ₜ Y) fun _ ↦ X → Y := ⟨FunLike.coe⟩ +instance : CoeFun (X ≃ₜ Y) fun _ ↦ X → Y := ⟨DFunLike.coe⟩ @[simp] theorem homeomorph_mk_coe (a : X ≃ Y) (b c) : (Homeomorph.mk a b c : X → Y) = a := rfl @@ -106,7 +107,7 @@ theorem coe_symm_toEquiv (h : X ≃ₜ Y) : ⇑h.toEquiv.symm = h.symm := @[ext] theorem ext {h h' : X ≃ₜ Y} (H : ∀ x, h x = h' x) : h = h' := - FunLike.ext _ _ H + DFunLike.ext _ _ H #align homeomorph.ext Homeomorph.ext /-- Identity map as a homeomorphism. -/ @@ -234,6 +235,9 @@ theorem preimage_image (h : X ≃ₜ Y) (s : Set X) : h ⁻¹' (h '' s) = s := h.toEquiv.preimage_image s #align homeomorph.preimage_image Homeomorph.preimage_image +lemma image_compl (h : X ≃ₜ Y) (s : Set X) : h '' (sᶜ) = (h '' s)ᶜ := + h.toEquiv.image_compl s + protected theorem inducing (h : X ≃ₜ Y) : Inducing h := inducing_of_inducing_compose h.continuous h.symm.continuous <| by simp only [symm_comp_self, inducing_id] @@ -307,7 +311,7 @@ theorem isPreconnected_preimage {s : Set Y} (h : X ≃ₜ Y) : @[simp] theorem isConnected_image {s : Set X} (h : X ≃ₜ Y) : IsConnected (h '' s) ↔ IsConnected s := - nonempty_image_iff.and h.isPreconnected_image + image_nonempty.and h.isPreconnected_image @[simp] theorem isConnected_preimage {s : Set Y} (h : X ≃ₜ Y) : @@ -427,6 +431,11 @@ theorem map_nhds_eq (h : X ≃ₜ Y) (x : X) : map h (𝓝 x) = 𝓝 (h x) := h.embedding.map_nhds_of_mem _ (by simp) #align homeomorph.map_nhds_eq Homeomorph.map_nhds_eq +@[simp] +theorem map_punctured_nhds_eq (h : X ≃ₜ Y) (x : X) : map h (𝓝[≠] x) = 𝓝[≠] (h x) := by + convert h.embedding.map_nhdsWithin_eq ({x}ᶜ) x + rw [h.image_compl, Set.image_singleton] + theorem symm_map_nhds_eq (h : X ≃ₜ Y) (x : X) : map h.symm (𝓝 (h x)) = 𝓝 x := by rw [h.symm.map_nhds_eq, h.symm_apply_apply] #align homeomorph.symm_map_nhds_eq Homeomorph.symm_map_nhds_eq @@ -497,7 +506,7 @@ theorem comp_continuousWithinAt_iff (h : X ≃ₜ Y) (f : Z → X) (s : Set Z) ( theorem comp_isOpenMap_iff (h : X ≃ₜ Y) {f : Z → X} : IsOpenMap (h ∘ f) ↔ IsOpenMap f := by refine' ⟨_, fun hf => h.isOpenMap.comp hf⟩ intro hf - rw [← Function.comp.left_id f, ← h.symm_comp_self, Function.comp.assoc] + rw [← Function.id_comp f, ← h.symm_comp_self, Function.comp.assoc] exact h.symm.isOpenMap.comp hf #align homeomorph.comp_is_open_map_iff Homeomorph.comp_isOpenMap_iff @@ -505,7 +514,7 @@ theorem comp_isOpenMap_iff (h : X ≃ₜ Y) {f : Z → X} : IsOpenMap (h ∘ f) theorem comp_isOpenMap_iff' (h : X ≃ₜ Y) {f : Y → Z} : IsOpenMap (f ∘ h) ↔ IsOpenMap f := by refine' ⟨_, fun hf => hf.comp h.isOpenMap⟩ intro hf - rw [← Function.comp.right_id f, ← h.self_comp_symm, ← Function.comp.assoc] + rw [← Function.comp_id f, ← h.self_comp_symm, ← Function.comp.assoc] exact hf.comp h.symm.isOpenMap #align homeomorph.comp_is_open_map_iff' Homeomorph.comp_isOpenMap_iff' diff --git a/Mathlib/Topology/Homotopy/Basic.lean b/Mathlib/Topology/Homotopy/Basic.lean index 7278cec8eea98..b56fd5b5ec04e 100644 --- a/Mathlib/Topology/Homotopy/Basic.lean +++ b/Mathlib/Topology/Homotopy/Basic.lean @@ -115,14 +115,14 @@ instance : HomotopyLike (Homotopy f₀ f₁) f₀ f₁ where map_one_left f := f.map_one_left /- porting note: probably not needed anymore -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (Homotopy f₀ f₁) fun _ => I × X → Y := - FunLike.hasCoeToFun -/ + DFunLike.hasCoeToFun -/ @[ext] theorem ext {F G : Homotopy f₀ f₁} (h : ∀ x, F x = G x) : F = G := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align continuous_map.homotopy.ext ContinuousMap.Homotopy.ext /-- See Note [custom simps projection]. We need to specify this projection explicitly in this case, @@ -431,11 +431,11 @@ instance : HomotopyLike (HomotopyWith f₀ f₁ P) f₀ f₁ where map_one_left F := F.map_one_left theorem coeFn_injective : @Function.Injective (HomotopyWith f₀ f₁ P) (I × X → Y) (⇑) := - FunLike.coe_injective' + DFunLike.coe_injective' #align continuous_map.homotopy_with.coe_fn_injective ContinuousMap.HomotopyWith.coeFn_injective @[ext] -theorem ext {F G : HomotopyWith f₀ f₁ P} (h : ∀ x, F x = G x) : F = G := FunLike.ext F G h +theorem ext {F G : HomotopyWith f₀ f₁ P} (h : ∀ x, F x = G x) : F = G := DFunLike.ext F G h #align continuous_map.homotopy_with.ext ContinuousMap.HomotopyWith.ext /-- See Note [custom simps projection]. We need to specify this projection explicitly in this case, diff --git a/Mathlib/Topology/Homotopy/HSpaces.lean b/Mathlib/Topology/Homotopy/HSpaces.lean index 1c03f280d5ddd..794de152bdc1f 100644 --- a/Mathlib/Topology/Homotopy/HSpaces.lean +++ b/Mathlib/Topology/Homotopy/HSpaces.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Filippo A. E. Nuccio, Junyan Xu -/ import Mathlib.Topology.CompactOpen -import Mathlib.Topology.Homotopy.Path +import Mathlib.Topology.Connected.PathConnected +import Mathlib.Topology.Homotopy.Basic #align_import topology.homotopy.H_spaces from "leanprover-community/mathlib"@"729d23f9e1640e1687141be89b106d3c8f9d10c0" diff --git a/Mathlib/Topology/Homotopy/HomotopyGroup.lean b/Mathlib/Topology/Homotopy/HomotopyGroup.lean index 95031d6846a99..3bf9198692c36 100644 --- a/Mathlib/Topology/Homotopy/HomotopyGroup.lean +++ b/Mathlib/Topology/Homotopy/HomotopyGroup.lean @@ -112,14 +112,14 @@ variable {N X x} namespace GenLoop -instance funLike : FunLike (Ω^ N X x) (I^N) fun _ => X where +instance instFunLike : FunLike (Ω^ N X x) (I^N) X where coe f := f.1 coe_injective' := fun ⟨⟨f, _⟩, _⟩ ⟨⟨g, _⟩, _⟩ _ => by congr -#align gen_loop.fun_like GenLoop.funLike +#align gen_loop.fun_like GenLoop.instFunLike @[ext] theorem ext (f g : Ω^ N X x) (H : ∀ y, f y = g y) : f = g := - FunLike.coe_injective' (funext H) + DFunLike.coe_injective' (funext H) #align gen_loop.ext GenLoop.ext @[simp] @@ -133,7 +133,7 @@ def copy (f : Ω^ N X x) (g : (I^N) → X) (h : g = f) : Ω^ N X x := ⟨⟨g, h.symm ▸ f.1.2⟩, by convert f.2⟩ #align gen_loop.copy GenLoop.copy -/- porting note: this now requires the `funLike` instance, +/- porting note: this now requires the `instFunLike` instance, so the instance is now put before `copy`. -/ theorem coe_copy (f : Ω^ N X x) {g : (I^N) → X} (h : g = f) : ⇑(copy f g h) = g := rfl @@ -332,18 +332,16 @@ theorem homotopicFrom (i : N) {p q : Ω^ N X x} : obtain rfl | h := eq_or_ne j i · rw [H.eq_fst]; exacts [congr_arg p ((Cube.splitAt j).left_inv _), jH] · rw [p.2 _ ⟨j, jH⟩]; apply boundary; exact ⟨⟨j, h⟩, jH⟩ - /- porting note: the following is indented two spaces more than it should be due to - strange behavior of `erw` -/ - all_goals - intro - apply (homotopyFrom_apply _ _ _).trans - first - | rw [H.apply_zero] - | rw [H.apply_one] - first - | apply congr_arg p - | apply congr_arg q - apply (Cube.splitAt i).left_inv + all_goals + intro + apply (homotopyFrom_apply _ _ _).trans + first + | rw [H.apply_zero] + | rw [H.apply_one] + first + | apply congr_arg p + | apply congr_arg q + apply (Cube.splitAt i).left_inv #align gen_loop.homotopic_from GenLoop.homotopicFrom /-- Concatenation of two `GenLoop`s along the `i`th coordinate. -/ diff --git a/Mathlib/Topology/Homotopy/Path.lean b/Mathlib/Topology/Homotopy/Path.lean index dc7b288f306c2..eb1dfbfee07f5 100644 --- a/Mathlib/Topology/Homotopy/Path.lean +++ b/Mathlib/Topology/Homotopy/Path.lean @@ -57,7 +57,7 @@ section variable {p₀ p₁ : Path x₀ x₁} theorem coeFn_injective : @Function.Injective (Homotopy p₀ p₁) (I × I → X) (⇑) := - FunLike.coe_injective + DFunLike.coe_injective #align path.homotopy.coe_fn_injective Path.Homotopy.coeFn_injective @[simp] diff --git a/Mathlib/Topology/Inseparable.lean b/Mathlib/Topology/Inseparable.lean index dd6b905417c50..17facf148dccd 100644 --- a/Mathlib/Topology/Inseparable.lean +++ b/Mathlib/Topology/Inseparable.lean @@ -552,39 +552,39 @@ theorem lift_comp_mk {f : X → α} (hf : ∀ x y, (x ~ᵢ y) → f x = f y) : l #align separation_quotient.lift_comp_mk SeparationQuotient.lift_comp_mk @[simp] -theorem tendsto_lift_nhds_mk {f : X → α} {hf : ∀ x y, (x ~ᵢ y) → f x = f y} {x : X} {l : Filter α} : +theorem tendsto_lift_nhds_mk {f : X → α} {hf : ∀ x y, (x ~ᵢ y) → f x = f y} {l : Filter α} : Tendsto (lift f hf) (𝓝 <| mk x) l ↔ Tendsto f (𝓝 x) l := by simp only [← map_mk_nhds, tendsto_map'_iff, lift_comp_mk] #align separation_quotient.tendsto_lift_nhds_mk SeparationQuotient.tendsto_lift_nhds_mk @[simp] -theorem tendsto_lift_nhdsWithin_mk {f : X → α} {hf : ∀ x y, (x ~ᵢ y) → f x = f y} {x : X} +theorem tendsto_lift_nhdsWithin_mk {f : X → α} {hf : ∀ x y, (x ~ᵢ y) → f x = f y} {s : Set (SeparationQuotient X)} {l : Filter α} : Tendsto (lift f hf) (𝓝[s] mk x) l ↔ Tendsto f (𝓝[mk ⁻¹' s] x) l := by simp only [← map_mk_nhdsWithin_preimage, tendsto_map'_iff, lift_comp_mk] #align separation_quotient.tendsto_lift_nhds_within_mk SeparationQuotient.tendsto_lift_nhdsWithin_mk @[simp] -theorem continuousAt_lift {f : X → Y} {hf : ∀ x y, (x ~ᵢ y) → f x = f y} {x : X} : +theorem continuousAt_lift {hf : ∀ x y, (x ~ᵢ y) → f x = f y}: ContinuousAt (lift f hf) (mk x) ↔ ContinuousAt f x := tendsto_lift_nhds_mk #align separation_quotient.continuous_at_lift SeparationQuotient.continuousAt_lift @[simp] -theorem continuousWithinAt_lift {f : X → Y} {hf : ∀ x y, (x ~ᵢ y) → f x = f y} - {s : Set (SeparationQuotient X)} {x : X} : +theorem continuousWithinAt_lift {hf : ∀ x y, (x ~ᵢ y) → f x = f y} + {s : Set (SeparationQuotient X)}: ContinuousWithinAt (lift f hf) s (mk x) ↔ ContinuousWithinAt f (mk ⁻¹' s) x := tendsto_lift_nhdsWithin_mk #align separation_quotient.continuous_within_at_lift SeparationQuotient.continuousWithinAt_lift @[simp] -theorem continuousOn_lift {f : X → Y} {hf : ∀ x y, (x ~ᵢ y) → f x = f y} - {s : Set (SeparationQuotient X)} : ContinuousOn (lift f hf) s ↔ ContinuousOn f (mk ⁻¹' s) := by +theorem continuousOn_lift {hf : ∀ x y, (x ~ᵢ y) → f x = f y} {s : Set (SeparationQuotient X)} : + ContinuousOn (lift f hf) s ↔ ContinuousOn f (mk ⁻¹' s) := by simp only [ContinuousOn, surjective_mk.forall, continuousWithinAt_lift, mem_preimage] #align separation_quotient.continuous_on_lift SeparationQuotient.continuousOn_lift @[simp] -theorem continuous_lift {f : X → Y} {hf : ∀ x y, (x ~ᵢ y) → f x = f y} : +theorem continuous_lift {hf : ∀ x y, (x ~ᵢ y) → f x = f y} : Continuous (lift f hf) ↔ Continuous f := by simp only [continuous_iff_continuousOn_univ, continuousOn_lift, preimage_univ] #align separation_quotient.continuous_lift SeparationQuotient.continuous_lift @@ -652,5 +652,5 @@ end SeparationQuotient theorem continuous_congr_of_inseparable (h : ∀ x, f x ~ᵢ g x) : Continuous f ↔ Continuous g := by - simp_rw [SeparationQuotient.inducing_mk.continuous_iff (β := Y)] + simp_rw [SeparationQuotient.inducing_mk.continuous_iff (Y := Y)] exact continuous_congr fun x ↦ SeparationQuotient.mk_eq_mk.mpr (h x) diff --git a/Mathlib/Topology/Instances/AddCircle.lean b/Mathlib/Topology/Instances/AddCircle.lean index bbd27374a501b..a327fc2fc675a 100644 --- a/Mathlib/Topology/Instances/AddCircle.lean +++ b/Mathlib/Topology/Instances/AddCircle.lean @@ -484,7 +484,7 @@ end LinearOrderedField variable (p : ℝ) -instance pathConnectedSpace : PathConnectedSpace $ AddCircle p := +instance pathConnectedSpace : PathConnectedSpace <| AddCircle p := (inferInstance : PathConnectedSpace (Quotient _)) /-- The "additive circle" `ℝ ⧸ (ℤ ∙ p)` is compact. -/ diff --git a/Mathlib/Topology/Instances/ENNReal.lean b/Mathlib/Topology/Instances/ENNReal.lean index 27954a2ca35e2..4b3ab3bee3e7d 100644 --- a/Mathlib/Topology/Instances/ENNReal.lean +++ b/Mathlib/Topology/Instances/ENNReal.lean @@ -8,7 +8,7 @@ import Mathlib.Topology.Algebra.Order.MonotoneContinuity import Mathlib.Topology.Algebra.InfiniteSum.Real import Mathlib.Topology.Algebra.Order.LiminfLimsup import Mathlib.Topology.Algebra.Order.T5 -import Mathlib.Topology.MetricSpace.Lipschitz +import Mathlib.Topology.EMetricSpace.Lipschitz import Mathlib.Topology.Metrizable.Basic #align_import topology.instances.ennreal from "leanprover-community/mathlib"@"ec4b2eeb50364487f80421c0b4c41328a611f30d" @@ -35,7 +35,7 @@ open TopologicalSpace /-- Topology on `ℝ≥0∞`. Note: this is different from the `EMetricSpace` topology. The `EMetricSpace` topology has -`IsOpen {⊤}`, while this topology doesn't have singleton elements. -/ +`IsOpen {∞}`, while this topology doesn't have singleton elements. -/ instance : TopologicalSpace ℝ≥0∞ := Preorder.topology ℝ≥0∞ instance : OrderTopology ℝ≥0∞ := ⟨rfl⟩ @@ -55,7 +55,7 @@ theorem embedding_coe : Embedding ((↑) : ℝ≥0 → ℝ≥0∞) := coe_strictMono.embedding_of_ordConnected <| by rw [range_coe']; exact ordConnected_Iio #align ennreal.embedding_coe ENNReal.embedding_coe -theorem isOpen_ne_top : IsOpen { a : ℝ≥0∞ | a ≠ ⊤ } := isOpen_ne +theorem isOpen_ne_top : IsOpen { a : ℝ≥0∞ | a ≠ ∞ } := isOpen_ne #align ennreal.is_open_ne_top ENNReal.isOpen_ne_top theorem isOpen_Ico_zero : IsOpen (Ico 0 b) := by @@ -114,7 +114,7 @@ theorem tendsto_ofReal {f : Filter α} {m : α → ℝ} {a : ℝ} (h : Tendsto m (continuous_ofReal.tendsto a).comp h #align ennreal.tendsto_of_real ENNReal.tendsto_ofReal -theorem tendsto_toNNReal {a : ℝ≥0∞} (ha : a ≠ ⊤) : +theorem tendsto_toNNReal {a : ℝ≥0∞} (ha : a ≠ ∞) : Tendsto ENNReal.toNNReal (𝓝 a) (𝓝 a.toNNReal) := by lift a to ℝ≥0 using ha rw [nhds_coe, tendsto_map'_iff] @@ -132,7 +132,7 @@ theorem continuousOn_toNNReal : ContinuousOn ENNReal.toNNReal { a | a ≠ ∞ } ContinuousAt.continuousWithinAt (tendsto_toNNReal ha) #align ennreal.continuous_on_to_nnreal ENNReal.continuousOn_toNNReal -theorem tendsto_toReal {a : ℝ≥0∞} (ha : a ≠ ⊤) : Tendsto ENNReal.toReal (𝓝 a) (𝓝 a.toReal) := +theorem tendsto_toReal {a : ℝ≥0∞} (ha : a ≠ ∞) : Tendsto ENNReal.toReal (𝓝 a) (𝓝 a.toReal) := NNReal.tendsto_coe.2 <| tendsto_toNNReal ha #align ennreal.tendsto_to_real ENNReal.tendsto_toReal @@ -165,12 +165,12 @@ theorem nhds_top_basis : (𝓝 ∞).HasBasis (fun a => a < ∞) fun a => Ioi a : #align ennreal.nhds_top_basis ENNReal.nhds_top_basis theorem tendsto_nhds_top_iff_nnreal {m : α → ℝ≥0∞} {f : Filter α} : - Tendsto m f (𝓝 ⊤) ↔ ∀ x : ℝ≥0, ∀ᶠ a in f, ↑x < m a := by + Tendsto m f (𝓝 ∞) ↔ ∀ x : ℝ≥0, ∀ᶠ a in f, ↑x < m a := by simp only [nhds_top', tendsto_iInf, tendsto_principal, mem_Ioi] #align ennreal.tendsto_nhds_top_iff_nnreal ENNReal.tendsto_nhds_top_iff_nnreal theorem tendsto_nhds_top_iff_nat {m : α → ℝ≥0∞} {f : Filter α} : - Tendsto m f (𝓝 ⊤) ↔ ∀ n : ℕ, ∀ᶠ a in f, ↑n < m a := + Tendsto m f (𝓝 ∞) ↔ ∀ n : ℕ, ∀ᶠ a in f, ↑n < m a := tendsto_nhds_top_iff_nnreal.trans ⟨fun h n => by simpa only [ENNReal.coe_nat] using h n, fun h x => let ⟨n, hn⟩ := exists_nat_gt x @@ -178,7 +178,7 @@ theorem tendsto_nhds_top_iff_nat {m : α → ℝ≥0∞} {f : Filter α} : #align ennreal.tendsto_nhds_top_iff_nat ENNReal.tendsto_nhds_top_iff_nat theorem tendsto_nhds_top {m : α → ℝ≥0∞} {f : Filter α} (h : ∀ n : ℕ, ∀ᶠ a in f, ↑n < m a) : - Tendsto m f (𝓝 ⊤) := + Tendsto m f (𝓝 ∞) := tendsto_nhds_top_iff_nat.2 h #align ennreal.tendsto_nhds_top ENNReal.tendsto_nhds_top @@ -212,7 +212,7 @@ theorem nhds_zero_basis_Iic : (𝓝 (0 : ℝ≥0∞)).HasBasis (fun a : ℝ≥0 -- porting note: todo: add a TC for `≠ ∞`? @[instance] theorem nhdsWithin_Ioi_coe_neBot {r : ℝ≥0} : (𝓝[>] (r : ℝ≥0∞)).NeBot := - nhdsWithin_Ioi_self_neBot' ⟨⊤, ENNReal.coe_lt_top⟩ + nhdsWithin_Ioi_self_neBot' ⟨∞, ENNReal.coe_lt_top⟩ #align ennreal.nhds_within_Ioi_coe_ne_bot ENNReal.nhdsWithin_Ioi_coe_neBot @[instance] @@ -261,12 +261,12 @@ theorem Icc_mem_nhds (xt : x ≠ ∞) (ε0 : ε ≠ 0) : Icc (x - ε) (x + ε) (hasBasis_nhds_of_ne_top' xt).mem_of_mem ε0 #align ennreal.Icc_mem_nhds ENNReal.Icc_mem_nhds -theorem nhds_of_ne_top (xt : x ≠ ⊤) : 𝓝 x = ⨅ ε > 0, 𝓟 (Icc (x - ε) (x + ε)) := +theorem nhds_of_ne_top (xt : x ≠ ∞) : 𝓝 x = ⨅ ε > 0, 𝓟 (Icc (x - ε) (x + ε)) := (hasBasis_nhds_of_ne_top xt).eq_biInf #align ennreal.nhds_of_ne_top ENNReal.nhds_of_ne_top theorem biInf_le_nhds : ∀ x : ℝ≥0∞, ⨅ ε > 0, 𝓟 (Icc (x - ε) (x + ε)) ≤ 𝓝 x - | ⊤ => iInf₂_le_of_le 1 one_pos <| by + | ∞ => iInf₂_le_of_le 1 one_pos <| by simpa only [← coe_one, top_sub_coe, top_add, Icc_self, principal_singleton] using pure_le_nhds _ | (x : ℝ≥0) => (nhds_of_ne_top coe_ne_top).ge @@ -278,7 +278,7 @@ protected theorem tendsto_nhds_of_Icc {f : Filter α} {u : α → ℝ≥0∞} {a /-- Characterization of neighborhoods for `ℝ≥0∞` numbers. See also `tendsto_order` for a version with strict inequalities. -/ -protected theorem tendsto_nhds {f : Filter α} {u : α → ℝ≥0∞} {a : ℝ≥0∞} (ha : a ≠ ⊤) : +protected theorem tendsto_nhds {f : Filter α} {u : α → ℝ≥0∞} {a : ℝ≥0∞} (ha : a ≠ ∞) : Tendsto u f (𝓝 a) ↔ ∀ ε > 0, ∀ᶠ x in f, u x ∈ Icc (a - ε) (a + ε) := by simp only [nhds_of_ne_top ha, tendsto_iInf, tendsto_principal] #align ennreal.tendsto_nhds ENNReal.tendsto_nhds @@ -289,7 +289,7 @@ protected theorem tendsto_nhds_zero {f : Filter α} {u : α → ℝ≥0∞} : #align ennreal.tendsto_nhds_zero ENNReal.tendsto_nhds_zero protected theorem tendsto_atTop [Nonempty β] [SemilatticeSup β] {f : β → ℝ≥0∞} {a : ℝ≥0∞} - (ha : a ≠ ⊤) : Tendsto f atTop (𝓝 a) ↔ ∀ ε > 0, ∃ N, ∀ n ≥ N, f n ∈ Icc (a - ε) (a + ε) := + (ha : a ≠ ∞) : Tendsto f atTop (𝓝 a) ↔ ∀ ε > 0, ∃ N, ∀ n ≥ N, f n ∈ Icc (a - ε) (a + ε) := .trans (atTop_basis.tendsto_iff (hasBasis_nhds_of_ne_top ha)) (by simp only [true_and]; rfl) #align ennreal.tendsto_at_top ENNReal.tendsto_atTop @@ -309,15 +309,15 @@ protected theorem tendsto_atTop_zero [Nonempty β] [SemilatticeSup β] {f : β theorem tendsto_sub : ∀ {a b : ℝ≥0∞}, (a ≠ ∞ ∨ b ≠ ∞) → Tendsto (fun p : ℝ≥0∞ × ℝ≥0∞ => p.1 - p.2) (𝓝 (a, b)) (𝓝 (a - b)) - | ⊤, ⊤, h => by simp only [ne_eq, not_true_eq_false, or_self] at h - | ⊤, (b : ℝ≥0), _ => by + | ∞, ∞, h => by simp only [ne_eq, not_true_eq_false, or_self] at h + | ∞, (b : ℝ≥0), _ => by rw [top_sub_coe, tendsto_nhds_top_iff_nnreal] refine fun x => ((lt_mem_nhds <| @coe_lt_top (b + 1 + x)).prod_nhds (ge_mem_nhds <| coe_lt_coe.2 <| lt_add_one b)).mono fun y hy => ?_ rw [lt_tsub_iff_left] calc y.2 + x ≤ ↑(b + 1) + x := add_le_add_right hy.2 _ _ < y.1 := hy.1 - | (a : ℝ≥0), ⊤, _ => by + | (a : ℝ≥0), ∞, _ => by rw [sub_top] refine (tendsto_pure.2 ?_).mono_right (pure_le_nhds _) exact ((gt_mem_nhds <| coe_lt_coe.2 <| lt_add_one a).prod_nhds @@ -335,10 +335,10 @@ protected theorem Tendsto.sub {f : Filter α} {ma : α → ℝ≥0∞} {mb : α Tendsto.comp (ENNReal.tendsto_sub h) (hma.prod_mk_nhds hmb) #align ennreal.tendsto.sub ENNReal.Tendsto.sub -protected theorem tendsto_mul (ha : a ≠ 0 ∨ b ≠ ⊤) (hb : b ≠ 0 ∨ a ≠ ⊤) : +protected theorem tendsto_mul (ha : a ≠ 0 ∨ b ≠ ∞) (hb : b ≠ 0 ∨ a ≠ ∞) : Tendsto (fun p : ℝ≥0∞ × ℝ≥0∞ => p.1 * p.2) (𝓝 (a, b)) (𝓝 (a * b)) := by have ht : ∀ b : ℝ≥0∞, b ≠ 0 → - Tendsto (fun p : ℝ≥0∞ × ℝ≥0∞ => p.1 * p.2) (𝓝 ((⊤ : ℝ≥0∞), b)) (𝓝 ⊤) := fun b hb => by + Tendsto (fun p : ℝ≥0∞ × ℝ≥0∞ => p.1 * p.2) (𝓝 (∞, b)) (𝓝 ∞) := fun b hb => by refine' tendsto_nhds_top_iff_nnreal.2 fun n => _ rcases lt_iff_exists_nnreal_btwn.1 (pos_iff_ne_zero.2 hb) with ⟨ε, hε, hεb⟩ have : ∀ᶠ c : ℝ≥0∞ × ℝ≥0∞ in 𝓝 (∞, b), ↑n / ↑ε < c.1 ∧ ↑ε < c.2 := @@ -352,14 +352,14 @@ protected theorem tendsto_mul (ha : a ≠ 0 ∨ b ≠ ⊤) (hb : b ≠ 0 ∨ a | top => simp only [ne_eq, or_false, not_true_eq_false] at ha simpa [(· ∘ ·), mul_comm, mul_top ha] - using (ht a ha).comp (continuous_swap.tendsto (ofNNReal a, ⊤)) + using (ht a ha).comp (continuous_swap.tendsto (ofNNReal a, ∞)) | coe b => simp only [nhds_coe_coe, ← coe_mul, tendsto_coe, tendsto_map'_iff, (· ∘ ·), tendsto_mul] #align ennreal.tendsto_mul ENNReal.tendsto_mul protected theorem Tendsto.mul {f : Filter α} {ma : α → ℝ≥0∞} {mb : α → ℝ≥0∞} {a b : ℝ≥0∞} - (hma : Tendsto ma f (𝓝 a)) (ha : a ≠ 0 ∨ b ≠ ⊤) (hmb : Tendsto mb f (𝓝 b)) - (hb : b ≠ 0 ∨ a ≠ ⊤) : Tendsto (fun a => ma a * mb a) f (𝓝 (a * b)) := + (hma : Tendsto ma f (𝓝 a)) (ha : a ≠ 0 ∨ b ≠ ∞) (hmb : Tendsto mb f (𝓝 b)) + (hb : b ≠ 0 ∨ a ≠ ∞) : Tendsto (fun a => ma a * mb a) f (𝓝 (a * b)) := show Tendsto ((fun p : ℝ≥0∞ × ℝ≥0∞ => p.1 * p.2) ∘ fun a => (ma a, mb a)) f (𝓝 (a * b)) from Tendsto.comp (ENNReal.tendsto_mul ha hb) (hma.prod_mk_nhds hmb) #align ennreal.tendsto.mul ENNReal.Tendsto.mul @@ -378,13 +378,13 @@ theorem _root_.Continuous.ennreal_mul [TopologicalSpace α] {f g : α → ℝ≥ #align continuous.ennreal_mul Continuous.ennreal_mul protected theorem Tendsto.const_mul {f : Filter α} {m : α → ℝ≥0∞} {a b : ℝ≥0∞} - (hm : Tendsto m f (𝓝 b)) (hb : b ≠ 0 ∨ a ≠ ⊤) : Tendsto (fun b => a * m b) f (𝓝 (a * b)) := + (hm : Tendsto m f (𝓝 b)) (hb : b ≠ 0 ∨ a ≠ ∞) : Tendsto (fun b => a * m b) f (𝓝 (a * b)) := by_cases (fun (this : a = 0) => by simp [this, tendsto_const_nhds]) fun ha : a ≠ 0 => ENNReal.Tendsto.mul tendsto_const_nhds (Or.inl ha) hm hb #align ennreal.tendsto.const_mul ENNReal.Tendsto.const_mul protected theorem Tendsto.mul_const {f : Filter α} {m : α → ℝ≥0∞} {a b : ℝ≥0∞} - (hm : Tendsto m f (𝓝 a)) (ha : a ≠ 0 ∨ b ≠ ⊤) : Tendsto (fun x => m x * b) f (𝓝 (a * b)) := by + (hm : Tendsto m f (𝓝 a)) (ha : a ≠ 0 ∨ b ≠ ∞) : Tendsto (fun x => m x * b) f (𝓝 (a * b)) := by simpa only [mul_comm] using ENNReal.Tendsto.const_mul hm ha #align ennreal.tendsto.mul_const ENNReal.Tendsto.mul_const @@ -402,21 +402,21 @@ theorem tendsto_finset_prod_of_ne_top {ι : Type*} {f : ι → α → ℝ≥0∞ · exact Or.inr (h' _ (Finset.mem_insert_self _ _)) #align ennreal.tendsto_finset_prod_of_ne_top ENNReal.tendsto_finset_prod_of_ne_top -protected theorem continuousAt_const_mul {a b : ℝ≥0∞} (h : a ≠ ⊤ ∨ b ≠ 0) : +protected theorem continuousAt_const_mul {a b : ℝ≥0∞} (h : a ≠ ∞ ∨ b ≠ 0) : ContinuousAt (a * ·) b := Tendsto.const_mul tendsto_id h.symm #align ennreal.continuous_at_const_mul ENNReal.continuousAt_const_mul -protected theorem continuousAt_mul_const {a b : ℝ≥0∞} (h : a ≠ ⊤ ∨ b ≠ 0) : +protected theorem continuousAt_mul_const {a b : ℝ≥0∞} (h : a ≠ ∞ ∨ b ≠ 0) : ContinuousAt (fun x => x * a) b := Tendsto.mul_const tendsto_id h.symm #align ennreal.continuous_at_mul_const ENNReal.continuousAt_mul_const -protected theorem continuous_const_mul {a : ℝ≥0∞} (ha : a ≠ ⊤) : Continuous (a * ·) := +protected theorem continuous_const_mul {a : ℝ≥0∞} (ha : a ≠ ∞) : Continuous (a * ·) := continuous_iff_continuousAt.2 fun _ => ENNReal.continuousAt_const_mul (Or.inl ha) #align ennreal.continuous_const_mul ENNReal.continuous_const_mul -protected theorem continuous_mul_const {a : ℝ≥0∞} (ha : a ≠ ⊤) : Continuous fun x => x * a := +protected theorem continuous_mul_const {a : ℝ≥0∞} (ha : a ≠ ∞) : Continuous fun x => x * a := continuous_iff_continuousAt.2 fun _ => ENNReal.continuousAt_mul_const (Or.inl ha) #align ennreal.continuous_mul_const ENNReal.continuous_mul_const @@ -449,7 +449,7 @@ theorem continuousOn_sub : refine' tendsto_nhdsWithin_of_tendsto_nhds (tendsto_sub (not_and_or.mp hp)) #align ennreal.continuous_on_sub ENNReal.continuousOn_sub -theorem continuous_sub_left {a : ℝ≥0∞} (a_ne_top : a ≠ ⊤) : Continuous (a - ·) := by +theorem continuous_sub_left {a : ℝ≥0∞} (a_ne_top : a ≠ ∞) : Continuous (a - ·) := by change Continuous (Function.uncurry Sub.sub ∘ (a, ·)) refine continuousOn_sub.comp_continuous (Continuous.Prod.mk a) fun x => ?_ simp only [a_ne_top, Ne.def, mem_setOf_eq, Prod.mk.inj_iff, false_and_iff, not_false_iff] @@ -487,9 +487,9 @@ theorem le_of_forall_lt_one_mul_le {x y : ℝ≥0∞} (h : ∀ a < 1, a * x ≤ exact le_of_tendsto this (eventually_nhdsWithin_iff.2 <| eventually_of_forall h) #align ennreal.le_of_forall_lt_one_mul_le ENNReal.le_of_forall_lt_one_mul_le -theorem iInf_mul_left' {ι} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} (h : a = ⊤ → ⨅ i, f i = 0 → ∃ i, f i = 0) +theorem iInf_mul_left' {ι} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} (h : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) (h0 : a = 0 → Nonempty ι) : ⨅ i, a * f i = a * ⨅ i, f i := by - by_cases H : a = ⊤ ∧ ⨅ i, f i = 0 + by_cases H : a = ∞ ∧ ⨅ i, f i = 0 · rcases h H.1 H.2 with ⟨i, hi⟩ rw [H.2, mul_zero, ← bot_eq_zero, iInf_eq_bot] exact fun b hb => ⟨i, by rwa [hi, mul_zero, ← bot_eq_zero]⟩ @@ -502,17 +502,17 @@ theorem iInf_mul_left' {ι} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} (h : a = #align ennreal.infi_mul_left' ENNReal.iInf_mul_left' theorem iInf_mul_left {ι} [Nonempty ι] {f : ι → ℝ≥0∞} {a : ℝ≥0∞} - (h : a = ⊤ → ⨅ i, f i = 0 → ∃ i, f i = 0) : ⨅ i, a * f i = a * ⨅ i, f i := + (h : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) : ⨅ i, a * f i = a * ⨅ i, f i := iInf_mul_left' h fun _ => ‹Nonempty ι› #align ennreal.infi_mul_left ENNReal.iInf_mul_left -theorem iInf_mul_right' {ι} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} (h : a = ⊤ → ⨅ i, f i = 0 → ∃ i, f i = 0) +theorem iInf_mul_right' {ι} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} (h : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) (h0 : a = 0 → Nonempty ι) : ⨅ i, f i * a = (⨅ i, f i) * a := by simpa only [mul_comm a] using iInf_mul_left' h h0 #align ennreal.infi_mul_right' ENNReal.iInf_mul_right' theorem iInf_mul_right {ι} [Nonempty ι] {f : ι → ℝ≥0∞} {a : ℝ≥0∞} - (h : a = ⊤ → ⨅ i, f i = 0 → ∃ i, f i = 0) : ⨅ i, f i * a = (⨅ i, f i) * a := + (h : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) : ⨅ i, f i * a = (⨅ i, f i) * a := iInf_mul_right' h fun _ => ‹Nonempty ι› #align ennreal.infi_mul_right ENNReal.iInf_mul_right @@ -544,12 +544,12 @@ protected theorem tendsto_inv_iff {f : Filter α} {m : α → ℝ≥0∞} {a : protected theorem Tendsto.div {f : Filter α} {ma : α → ℝ≥0∞} {mb : α → ℝ≥0∞} {a b : ℝ≥0∞} (hma : Tendsto ma f (𝓝 a)) (ha : a ≠ 0 ∨ b ≠ 0) (hmb : Tendsto mb f (𝓝 b)) - (hb : b ≠ ⊤ ∨ a ≠ ⊤) : Tendsto (fun a => ma a / mb a) f (𝓝 (a / b)) := by + (hb : b ≠ ∞ ∨ a ≠ ∞) : Tendsto (fun a => ma a / mb a) f (𝓝 (a / b)) := by apply Tendsto.mul hma _ (ENNReal.tendsto_inv_iff.2 hmb) _ <;> simp [ha, hb] #align ennreal.tendsto.div ENNReal.Tendsto.div protected theorem Tendsto.const_div {f : Filter α} {m : α → ℝ≥0∞} {a b : ℝ≥0∞} - (hm : Tendsto m f (𝓝 b)) (hb : b ≠ ⊤ ∨ a ≠ ⊤) : Tendsto (fun b => a / m b) f (𝓝 (a / b)) := by + (hm : Tendsto m f (𝓝 b)) (hb : b ≠ ∞ ∨ a ≠ ∞) : Tendsto (fun b => a / m b) f (𝓝 (a / b)) := by apply Tendsto.const_mul (ENNReal.tendsto_inv_iff.2 hm) simp [hb] #align ennreal.tendsto.const_div ENNReal.Tendsto.const_div @@ -681,7 +681,7 @@ protected theorem tendsto_coe_sub {b : ℝ≥0∞} : continuous_nnreal_sub.tendsto _ #align ennreal.tendsto_coe_sub ENNReal.tendsto_coe_sub -theorem sub_iSup {ι : Sort*} [Nonempty ι] {b : ι → ℝ≥0∞} (hr : a < ⊤) : +theorem sub_iSup {ι : Sort*} [Nonempty ι] {b : ι → ℝ≥0∞} (hr : a < ∞) : (a - ⨆ i, b i) = ⨅ i, a - b i := antitone_const_tsub.map_iSup_of_continuousAt' (continuous_sub_left hr.ne).continuousAt #align ennreal.sub_supr ENNReal.sub_iSup @@ -727,7 +727,7 @@ theorem exists_frequently_lt_of_liminf_ne_top' {ι : Type*} {l : Filter ι} {x : simp_rw [not_exists, not_frequently, not_lt] at h refine hx (ENNReal.eq_top_of_forall_nnreal_le fun r => le_limsInf_of_le (by isBoundedDefault) ?_) simp only [eventually_map, ENNReal.coe_le_coe] - filter_upwards [h (-r)] with i hi using(le_neg.1 hi).trans (neg_le_abs_self _) + filter_upwards [h (-r)] with i hi using(le_neg.1 hi).trans (neg_le_abs _) #align ennreal.exists_frequently_lt_of_liminf_ne_top' ENNReal.exists_frequently_lt_of_liminf_ne_top' theorem exists_upcrossings_of_not_bounded_under {ι : Type*} {l : Filter ι} {x : ι → ℝ} @@ -1046,7 +1046,7 @@ theorem finite_const_le_of_tsum_ne_top {ι : Type*} {a : ι → ℝ≥0∞} (tsu by_contra h have := Infinite.to_subtype h refine tsum_ne_top (top_unique ?_) - calc ⊤ = ∑' _ : { i | ε ≤ a i }, ε := (tsum_const_eq_top_of_ne_zero ε_ne_zero).symm + calc ∞ = ∑' _ : { i | ε ≤ a i }, ε := (tsum_const_eq_top_of_ne_zero ε_ne_zero).symm _ ≤ ∑' i, a i := tsum_le_tsum_of_inj (↑) Subtype.val_injective (fun _ _ => zero_le _) (fun i => i.2) ENNReal.summable ENNReal.summable #align ennreal.finite_const_le_of_tsum_ne_top ENNReal.finite_const_le_of_tsum_ne_top @@ -1273,10 +1273,10 @@ theorem tsum_le_of_sum_range_le {f : ℕ → ℝ≥0∞} {c : ℝ≥0∞} #align ennreal.tsum_le_of_sum_range_le ENNReal.tsum_le_of_sum_range_le theorem hasSum_lt {f g : α → ℝ≥0∞} {sf sg : ℝ≥0∞} {i : α} (h : ∀ a : α, f a ≤ g a) (hi : f i < g i) - (hsf : sf ≠ ⊤) (hf : HasSum f sf) (hg : HasSum g sg) : sf < sg := by - by_cases hsg : sg = ⊤ + (hsf : sf ≠ ∞) (hf : HasSum f sf) (hg : HasSum g sg) : sf < sg := by + by_cases hsg : sg = ∞ · exact hsg.symm ▸ lt_of_le_of_ne le_top hsf - · have hg' : ∀ x, g x ≠ ⊤ := ENNReal.ne_top_of_tsum_ne_top (hg.tsum_eq.symm ▸ hsg) + · have hg' : ∀ x, g x ≠ ∞ := ENNReal.ne_top_of_tsum_ne_top (hg.tsum_eq.symm ▸ hsg) lift f to α → ℝ≥0 using fun x => ne_of_lt (lt_of_le_of_lt (h x) <| lt_of_le_of_ne le_top (hg' x)) lift g to α → ℝ≥0 using hg' @@ -1286,7 +1286,7 @@ theorem hasSum_lt {f g : α → ℝ≥0∞} {sf sg : ℝ≥0∞} {i : α} (h : exact NNReal.hasSum_lt h hi (ENNReal.hasSum_coe.1 hf) (ENNReal.hasSum_coe.1 hg) #align ennreal.has_sum_lt ENNReal.hasSum_lt -theorem tsum_lt_tsum {f g : α → ℝ≥0∞} {i : α} (hfi : tsum f ≠ ⊤) (h : ∀ a : α, f a ≤ g a) +theorem tsum_lt_tsum {f g : α → ℝ≥0∞} {i : α} (hfi : tsum f ≠ ∞) (h : ∀ a : α, f a ≤ g a) (hi : f i < g i) : ∑' x, f x < ∑' x, g x := hasSum_lt h hi hfi ENNReal.summable.hasSum ENNReal.summable.hasSum #align ennreal.tsum_lt_tsum ENNReal.tsum_lt_tsum @@ -1316,7 +1316,7 @@ theorem Summable.toNNReal {f : α → ℝ} (hf : Summable f) : Summable fun n => #align summable.to_nnreal Summable.toNNReal /-- Finitely summable non-negative functions have countable support -/ -theorem _root_.Summable.countable_support_ennreal {f : α → ℝ≥0∞} (h : ∑' (i : α), f i ≠ ⊤) : +theorem _root_.Summable.countable_support_ennreal {f : α → ℝ≥0∞} (h : ∑' (i : α), f i ≠ ∞) : f.support.Countable := by lift f to α → ℝ≥0 using ENNReal.ne_top_of_tsum_ne_top h simpa [support] using (ENNReal.tsum_coe_ne_top_iff_summable.1 h).countable_support_nnreal @@ -1389,12 +1389,12 @@ variable [EMetricSpace β] open ENNReal Filter EMetric /-- In an emetric ball, the distance between points is everywhere finite -/ -theorem edist_ne_top_of_mem_ball {a : β} {r : ℝ≥0∞} (x y : ball a r) : edist x.1 y.1 ≠ ⊤ := +theorem edist_ne_top_of_mem_ball {a : β} {r : ℝ≥0∞} (x y : ball a r) : edist x.1 y.1 ≠ ∞ := ne_of_lt <| calc edist x y ≤ edist a x + edist a y := edist_triangle_left x.1 y.1 a _ < r + r := by rw [edist_comm a x, edist_comm a y]; exact add_lt_add x.2 y.2 - _ ≤ ⊤ := le_top + _ ≤ ∞ := le_top #align edist_ne_top_of_mem_ball edist_ne_top_of_mem_ball /-- Each ball in an extended metric space gives us a metric space, as the edist @@ -1447,7 +1447,7 @@ theorem EMetric.cauchySeq_iff_le_tendsto_0 [Nonempty β] [SemilatticeSup β] {s _ < ε := hN #align emetric.cauchy_seq_iff_le_tendsto_0 EMetric.cauchySeq_iff_le_tendsto_0 -theorem continuous_of_le_add_edist {f : α → ℝ≥0∞} (C : ℝ≥0∞) (hC : C ≠ ⊤) +theorem continuous_of_le_add_edist {f : α → ℝ≥0∞} (C : ℝ≥0∞) (hC : C ≠ ∞) (h : ∀ x y, f x ≤ f y + C * edist x y) : Continuous f := by refine continuous_iff_continuousAt.2 fun x => ENNReal.tendsto_nhds_of_Icc fun ε ε0 => ?_ rcases ENNReal.exists_nnreal_pos_mul_lt hC ε0.ne' with ⟨δ, δ0, hδ⟩ @@ -1647,7 +1647,7 @@ end truncateToReal section LimsupLiminf -set_option autoImplicit true +variable {ι : Type*} lemma limsup_sub_const (F : Filter ι) [NeBot F] (f : ι → ℝ≥0∞) (c : ℝ≥0∞) : Filter.limsup (fun i ↦ f i - c) F = Filter.limsup f F - c := diff --git a/Mathlib/Topology/Instances/Int.lean b/Mathlib/Topology/Instances/Int.lean index 931a4217703d9..2683dd278e0b9 100644 --- a/Mathlib/Topology/Instances/Int.lean +++ b/Mathlib/Topology/Instances/Int.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Data.Int.Interval +import Mathlib.Topology.MetricSpace.Basic import Mathlib.Topology.MetricSpace.PseudoMetric import Mathlib.Topology.MetricSpace.Bounded import Mathlib.Order.Filter.Archimedean diff --git a/Mathlib/Topology/Instances/NNReal.lean b/Mathlib/Topology/Instances/NNReal.lean index 8bd81f84d22a7..426a710757fdc 100644 --- a/Mathlib/Topology/Instances/NNReal.lean +++ b/Mathlib/Topology/Instances/NNReal.lean @@ -99,7 +99,7 @@ def _root_.ContinuousMap.coeNNRealReal : C(ℝ≥0, ℝ) := instance ContinuousMap.canLift {X : Type*} [TopologicalSpace X] : CanLift C(X, ℝ) C(X, ℝ≥0) ContinuousMap.coeNNRealReal.comp fun f => ∀ x, 0 ≤ f x where - prf f hf := ⟨⟨fun x => ⟨f x, hf x⟩, f.2.subtype_mk _⟩, FunLike.ext' rfl⟩ + prf f hf := ⟨⟨fun x => ⟨f x, hf x⟩, f.2.subtype_mk _⟩, DFunLike.ext' rfl⟩ #align nnreal.continuous_map.can_lift NNReal.ContinuousMap.canLift @[simp, norm_cast] diff --git a/Mathlib/Topology/Instances/Real.lean b/Mathlib/Topology/Instances/Real.lean index 8eeec5f8d1bb1..9658c74c5c1cb 100644 --- a/Mathlib/Topology/Instances/Real.lean +++ b/Mathlib/Topology/Instances/Real.lean @@ -3,10 +3,11 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ +import Mathlib.Algebra.GroupPower.Lemmas +import Mathlib.Algebra.Periodic import Mathlib.Topology.Algebra.UniformMulAction import Mathlib.Topology.Algebra.Star import Mathlib.Topology.Algebra.Order.Field -import Mathlib.Algebra.Periodic import Mathlib.Topology.Instances.Int #align_import topology.instances.real from "leanprover-community/mathlib"@"9a59dcb7a2d06bf55da57b9030169219980660cd" @@ -247,7 +248,7 @@ theorem tendsto_coe_cofinite : Tendsto ((↑) : ℤ → ℝ) cofinite (cocompact inverse images of compact sets are finite. -/ theorem tendsto_zmultiplesHom_cofinite {a : ℝ} (ha : a ≠ 0) : Tendsto (zmultiplesHom ℝ a) cofinite (cocompact ℝ) := by - apply (zmultiplesHom ℝ a).tendsto_coe_cofinite_of_discrete $ smul_left_injective ℤ ha + apply (zmultiplesHom ℝ a).tendsto_coe_cofinite_of_discrete <| smul_left_injective ℤ ha rw [AddSubgroup.range_zmultiplesHom] infer_instance #align int.tendsto_zmultiples_hom_cofinite Int.tendsto_zmultiplesHom_cofinite diff --git a/Mathlib/Topology/Instances/TrivSqZeroExt.lean b/Mathlib/Topology/Instances/TrivSqZeroExt.lean index dc105fd35c88e..9149d549e042b 100644 --- a/Mathlib/Topology/Instances/TrivSqZeroExt.lean +++ b/Mathlib/Topology/Instances/TrivSqZeroExt.lean @@ -34,9 +34,11 @@ local notation "tsze" => TrivSqZeroExt namespace TrivSqZeroExt +section Topology + variable [TopologicalSpace R] [TopologicalSpace M] -instance : TopologicalSpace (tsze R M) := +instance instTopologicalSpace : TopologicalSpace (tsze R M) := TopologicalSpace.induced fst ‹_› ⊓ TopologicalSpace.induced snd ‹_› instance [T2Space R] [T2Space M] : T2Space (tsze R M) := @@ -163,4 +165,41 @@ theorem hasSum_snd [AddCommMonoid R] [AddCommMonoid M] {f : α → tsze R M} {a h.map (⟨⟨snd, snd_zero⟩, snd_add⟩ : tsze R M →+ M) continuous_snd #align triv_sq_zero_ext.has_sum_snd TrivSqZeroExt.hasSum_snd +end Topology + +section Uniformity +variable [UniformSpace R] [UniformSpace M] + +instance instUniformSpace : UniformSpace (tsze R M) where + toTopologicalSpace := instTopologicalSpace + __ := instUniformSpaceProd + +instance [CompleteSpace R] [CompleteSpace M] : CompleteSpace (tsze R M) := + inferInstanceAs <| CompleteSpace (R × M) + +instance [AddGroup R] [AddGroup M] [UniformAddGroup R] [UniformAddGroup M] : + UniformAddGroup (tsze R M) := + inferInstanceAs <| UniformAddGroup (R × M) + +open Uniformity + +theorem uniformity_def : + 𝓤 (tsze R M) = + ((𝓤 R).comap fun p => (p.1.fst, p.2.fst)) ⊓ ((𝓤 M).comap fun p => (p.1.snd, p.2.snd)) := + rfl + +nonrec theorem uniformContinuous_fst : UniformContinuous (fst : tsze R M → R) := + uniformContinuous_fst + +nonrec theorem uniformContinuous_snd : UniformContinuous (snd : tsze R M → M) := + uniformContinuous_snd + +theorem uniformContinuous_inl [Zero M] : UniformContinuous (inl : R → tsze R M) := + uniformContinuous_id.prod_mk uniformContinuous_const + +theorem uniformContinuous_inr [Zero R] : UniformContinuous (inr : M → tsze R M) := + uniformContinuous_const.prod_mk uniformContinuous_id + +end Uniformity + end TrivSqZeroExt diff --git a/Mathlib/Topology/LocalExtr.lean b/Mathlib/Topology/LocalExtr.lean index 9f7a70e708007..9835e730ac25b 100644 --- a/Mathlib/Topology/LocalExtr.lean +++ b/Mathlib/Topology/LocalExtr.lean @@ -5,6 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Order.Filter.Extr import Mathlib.Topology.ContinuousOn +import Mathlib.Algebra.Group.Defs #align_import topology.local_extr from "leanprover-community/mathlib"@"bcfa726826abd57587355b4b5b7e78ad6527b7e4" diff --git a/Mathlib/Topology/LocallyConstant/Algebra.lean b/Mathlib/Topology/LocallyConstant/Algebra.lean index abaebafe616eb..e1b33ca9c099a 100644 --- a/Mathlib/Topology/LocallyConstant/Algebra.lean +++ b/Mathlib/Topology/LocallyConstant/Algebra.lean @@ -71,12 +71,12 @@ theorem mul_apply [Mul Y] (f g : LocallyConstant X Y) (x : X) : (f * g) x = f x @[to_additive] instance [MulOneClass Y] : MulOneClass (LocallyConstant X Y) := - Function.Injective.mulOneClass FunLike.coe FunLike.coe_injective' rfl fun _ _ => rfl + Function.Injective.mulOneClass DFunLike.coe DFunLike.coe_injective' rfl fun _ _ => rfl -/-- `FunLike.coe` as a `MonoidHom`. -/ -@[to_additive (attr := simps) "`FunLike.coe` as an `AddMonoidHom`."] +/-- `DFunLike.coe` as a `MonoidHom`. -/ +@[to_additive (attr := simps) "`DFunLike.coe` as an `AddMonoidHom`."] def coeFnMonoidHom [MulOneClass Y] : LocallyConstant X Y →* X → Y where - toFun := FunLike.coe + toFun := DFunLike.coe map_one' := rfl map_mul' _ _ := rfl #align locally_constant.coe_fn_monoid_hom LocallyConstant.coeFnMonoidHom @@ -92,10 +92,10 @@ def constMonoidHom [MulOneClass Y] : Y →* LocallyConstant X Y where #align locally_constant.const_add_monoid_hom LocallyConstant.constAddMonoidHom instance [MulZeroClass Y] : MulZeroClass (LocallyConstant X Y) := - Function.Injective.mulZeroClass FunLike.coe FunLike.coe_injective' rfl fun _ _ => rfl + Function.Injective.mulZeroClass DFunLike.coe DFunLike.coe_injective' rfl fun _ _ => rfl instance [MulZeroOneClass Y] : MulZeroOneClass (LocallyConstant X Y) := - Function.Injective.mulZeroOneClass FunLike.coe FunLike.coe_injective' rfl rfl fun _ _ => rfl + Function.Injective.mulZeroOneClass DFunLike.coe DFunLike.coe_injective' rfl rfl fun _ _ => rfl section CharFn @@ -144,14 +144,14 @@ theorem div_apply [Div Y] (f g : LocallyConstant X Y) (x : X) : (f / g) x = f x @[to_additive] instance [Semigroup Y] : Semigroup (LocallyConstant X Y) := - Function.Injective.semigroup FunLike.coe FunLike.coe_injective' fun _ _ => rfl + Function.Injective.semigroup DFunLike.coe DFunLike.coe_injective' fun _ _ => rfl instance [SemigroupWithZero Y] : SemigroupWithZero (LocallyConstant X Y) := - Function.Injective.semigroupWithZero FunLike.coe FunLike.coe_injective' rfl fun _ _ => rfl + Function.Injective.semigroupWithZero DFunLike.coe DFunLike.coe_injective' rfl fun _ _ => rfl @[to_additive] instance [CommSemigroup Y] : CommSemigroup (LocallyConstant X Y) := - Function.Injective.commSemigroup FunLike.coe FunLike.coe_injective' fun _ _ => rfl + Function.Injective.commSemigroup DFunLike.coe DFunLike.coe_injective' fun _ _ => rfl @[to_additive] instance smul [SMul α Y] : SMul α (LocallyConstant X Y) where @@ -173,7 +173,7 @@ instance [Pow Y α] : Pow (LocallyConstant X Y) α where @[to_additive] instance [Monoid Y] : Monoid (LocallyConstant X Y) := - Function.Injective.monoid FunLike.coe FunLike.coe_injective' rfl (fun _ _ => rfl) fun _ _ => rfl + Function.Injective.monoid DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) fun _ _ => rfl instance [NatCast Y] : NatCast (LocallyConstant X Y) where natCast n := const X n @@ -182,37 +182,37 @@ instance [IntCast Y] : IntCast (LocallyConstant X Y) where intCast n := const X n instance [AddMonoidWithOne Y] : AddMonoidWithOne (LocallyConstant X Y) := - Function.Injective.addMonoidWithOne FunLike.coe FunLike.coe_injective' rfl rfl (fun _ _ => rfl) + Function.Injective.addMonoidWithOne DFunLike.coe DFunLike.coe_injective' rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl @[to_additive] instance [CommMonoid Y] : CommMonoid (LocallyConstant X Y) := - Function.Injective.commMonoid FunLike.coe FunLike.coe_injective' rfl (fun _ _ => rfl) + Function.Injective.commMonoid DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) fun _ _ => rfl @[to_additive] instance [Group Y] : Group (LocallyConstant X Y) := - Function.Injective.group FunLike.coe FunLike.coe_injective' rfl (fun _ _ => rfl) + Function.Injective.group DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) @[to_additive] instance [CommGroup Y] : CommGroup (LocallyConstant X Y) := - Function.Injective.commGroup FunLike.coe FunLike.coe_injective' rfl (fun _ _ => rfl) + Function.Injective.commGroup DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) instance [Distrib Y] : Distrib (LocallyConstant X Y) := - Function.Injective.distrib FunLike.coe FunLike.coe_injective' (fun _ _ => rfl) fun _ _ => rfl + Function.Injective.distrib DFunLike.coe DFunLike.coe_injective' (fun _ _ => rfl) fun _ _ => rfl instance [NonUnitalNonAssocSemiring Y] : NonUnitalNonAssocSemiring (LocallyConstant X Y) := - Function.Injective.nonUnitalNonAssocSemiring FunLike.coe FunLike.coe_injective' rfl + Function.Injective.nonUnitalNonAssocSemiring DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) instance [NonUnitalSemiring Y] : NonUnitalSemiring (LocallyConstant X Y) := - Function.Injective.nonUnitalSemiring FunLike.coe FunLike.coe_injective' rfl + Function.Injective.nonUnitalSemiring DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) instance [NonAssocSemiring Y] : NonAssocSemiring (LocallyConstant X Y) := - Function.Injective.nonAssocSemiring FunLike.coe FunLike.coe_injective' rfl rfl + Function.Injective.nonAssocSemiring DFunLike.coe DFunLike.coe_injective' rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- The constant-function embedding, as a ring hom. -/ @@ -222,41 +222,41 @@ def constRingHom [NonAssocSemiring Y] : Y →+* LocallyConstant X Y := #align locally_constant.const_ring_hom LocallyConstant.constRingHom instance [Semiring Y] : Semiring (LocallyConstant X Y) := - Function.Injective.semiring FunLike.coe FunLike.coe_injective' rfl rfl + Function.Injective.semiring DFunLike.coe DFunLike.coe_injective' rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl instance [NonUnitalCommSemiring Y] : NonUnitalCommSemiring (LocallyConstant X Y) := - Function.Injective.nonUnitalCommSemiring FunLike.coe FunLike.coe_injective' rfl + Function.Injective.nonUnitalCommSemiring DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) instance [CommSemiring Y] : CommSemiring (LocallyConstant X Y) := - Function.Injective.commSemiring FunLike.coe FunLike.coe_injective' rfl rfl + Function.Injective.commSemiring DFunLike.coe DFunLike.coe_injective' rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl instance [NonUnitalNonAssocRing Y] : NonUnitalNonAssocRing (LocallyConstant X Y) := - Function.Injective.nonUnitalNonAssocRing FunLike.coe FunLike.coe_injective' rfl (fun _ _ => rfl) + Function.Injective.nonUnitalNonAssocRing DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) instance [NonUnitalRing Y] : NonUnitalRing (LocallyConstant X Y) := - Function.Injective.nonUnitalRing FunLike.coe FunLike.coe_injective' rfl (fun _ _ => rfl) + Function.Injective.nonUnitalRing DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) instance [NonAssocRing Y] : NonAssocRing (LocallyConstant X Y) := - Function.Injective.nonAssocRing FunLike.coe FunLike.coe_injective' rfl rfl (fun _ _ => rfl) + Function.Injective.nonAssocRing DFunLike.coe DFunLike.coe_injective' rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ => rfl) instance [Ring Y] : Ring (LocallyConstant X Y) := - Function.Injective.ring FunLike.coe FunLike.coe_injective' rfl rfl (fun _ _ => rfl) + Function.Injective.ring DFunLike.coe DFunLike.coe_injective' rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl instance [NonUnitalCommRing Y] : NonUnitalCommRing (LocallyConstant X Y) := - Function.Injective.nonUnitalCommRing FunLike.coe FunLike.coe_injective' rfl (fun _ _ => rfl) + Function.Injective.nonUnitalCommRing DFunLike.coe DFunLike.coe_injective' rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) instance [CommRing Y] : CommRing (LocallyConstant X Y) := - Function.Injective.commRing FunLike.coe FunLike.coe_injective' rfl rfl (fun _ _ => rfl) + Function.Injective.commRing DFunLike.coe DFunLike.coe_injective' rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl @@ -296,18 +296,18 @@ end Algebra section coeFn -/-- `FunLike.coe` as a `RingHom`. -/ +/-- `DFunLike.coe` as a `RingHom`. -/ @[simps!] def coeFnRingHom [Semiring Y] : LocallyConstant X Y →+* X → Y where toMonoidHom := coeFnMonoidHom __ := coeFnAddMonoidHom -/-- `FunLike.coe` as a linear map. -/ +/-- `DFunLike.coe` as a linear map. -/ @[simps!] def coeFnₗ (R : Type*) [Semiring R] [AddCommMonoid Y] [Module R Y] : LocallyConstant X Y →ₗ[R] X → Y where toAddHom := coeFnAddMonoidHom.toAddHom map_smul' _ _ := rfl -/-- `FunLike.coe` as an `AlgHom`. -/ +/-- `DFunLike.coe` as an `AlgHom`. -/ @[simps!] def coeFnAlgHom (R : Type*) [CommSemiring R] [Semiring Y] [Algebra R Y] : LocallyConstant X Y →ₐ[R] X → Y where toRingHom := coeFnRingHom diff --git a/Mathlib/Topology/LocallyConstant/Basic.lean b/Mathlib/Topology/LocallyConstant/Basic.lean index 3f4a1a5e8c4f0..cff59267e784c 100644 --- a/Mathlib/Topology/LocallyConstant/Basic.lean +++ b/Mathlib/Topology/LocallyConstant/Basic.lean @@ -250,7 +250,7 @@ namespace LocallyConstant instance [Inhabited Y] : Inhabited (LocallyConstant X Y) := ⟨⟨_, IsLocallyConstant.const default⟩⟩ -instance : FunLike (LocallyConstant X Y) X (fun _ => Y) where +instance : FunLike (LocallyConstant X Y) X Y where coe := LocallyConstant.toFun coe_injective' := by rintro ⟨_, _⟩ ⟨_, _⟩ _; congr @@ -270,15 +270,15 @@ theorem coe_mk (f : X → Y) (h) : ⇑(⟨f, h⟩ : LocallyConstant X Y) = f := #align locally_constant.coe_mk LocallyConstant.coe_mk theorem congr_fun {f g : LocallyConstant X Y} (h : f = g) (x : X) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align locally_constant.congr_fun LocallyConstant.congr_fun theorem congr_arg (f : LocallyConstant X Y) {x y : X} (h : x = y) : f x = f y := - FunLike.congr_arg f h + DFunLike.congr_arg f h #align locally_constant.congr_arg LocallyConstant.congr_arg theorem coe_injective : @Function.Injective (LocallyConstant X Y) (X → Y) (↑) := fun _ _ => - FunLike.ext' + DFunLike.ext' #align locally_constant.coe_injective LocallyConstant.coe_injective @[norm_cast] @@ -288,10 +288,10 @@ theorem coe_inj {f g : LocallyConstant X Y} : (f : X → Y) = g ↔ f = g := @[ext] theorem ext ⦃f g : LocallyConstant X Y⦄ (h : ∀ x, f x = g x) : f = g := - FunLike.ext _ _ h + DFunLike.ext _ _ h #align locally_constant.ext LocallyConstant.ext -theorem ext_iff {f g : LocallyConstant X Y} : f = g ↔ ∀ x, f x = g x := FunLike.ext_iff +theorem ext_iff {f g : LocallyConstant X Y} : f = g ↔ ∀ x, f x = g x := DFunLike.ext_iff #align locally_constant.ext_iff LocallyConstant.ext_iff section CodomainTopologicalSpace @@ -486,7 +486,7 @@ theorem coe_comap_apply (f : X → Y) (g : LocallyConstant Y Z) (hf : Continuous @[simp] theorem comap_id : comap (@id X) = @id (LocallyConstant X Z) := by ext - simp only [continuous_id, id.def, Function.comp.right_id, coe_comap] + simp only [continuous_id, id.def, Function.comp_id, coe_comap] #align locally_constant.comap_id LocallyConstant.comap_id theorem comap_comp [TopologicalSpace Z] (f : X → Y) (g : Y → Z) (hf : Continuous f) diff --git a/Mathlib/Topology/Maps.lean b/Mathlib/Topology/Maps.lean index 8929f76e94585..16f18318d1af0 100644 --- a/Mathlib/Topology/Maps.lean +++ b/Mathlib/Topology/Maps.lean @@ -49,249 +49,251 @@ open Set Filter Function open TopologicalSpace Topology Filter -variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} +variable {X : Type*} {Y : Type*} {Z : Type*} {ι : Type*} {f : X → Y} {g : Y → Z} section Inducing -/-- A function `f : α → β` between topological spaces is inducing if the topology on `α` is induced -by the topology on `β` through `f`, meaning that a set `s : Set α` is open iff it is the preimage -under `f` of some open set `t : Set β`. -/ +/-- A function `f : X → Y` between topological spaces is inducing if the topology on `X` is induced +by the topology on `Y` through `f`, meaning that a set `s : Set X` is open iff it is the preimage +under `f` of some open set `t : Set Y`. -/ @[mk_iff] -structure Inducing [tα : TopologicalSpace α] [tβ : TopologicalSpace β] (f : α → β) : Prop where +structure Inducing [tX : TopologicalSpace X] [tY : TopologicalSpace Y] (f : X → Y) : Prop where /-- The topology on the domain is equal to the induced topology. -/ - induced : tα = tβ.induced f + induced : tX = tY.induced f #align inducing Inducing #align inducing_iff inducing_iff -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] [TopologicalSpace δ] +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] -theorem inducing_induced (f : α → β) : @Inducing α β (TopologicalSpace.induced f ‹_›) _ f := +theorem inducing_induced (f : X → Y) : @Inducing X Y (TopologicalSpace.induced f ‹_›) _ f := @Inducing.mk _ _ (TopologicalSpace.induced f ‹_›) _ _ rfl -theorem inducing_id : Inducing (@id α) := +theorem inducing_id : Inducing (@id X) := ⟨induced_id.symm⟩ #align inducing_id inducing_id -protected theorem Inducing.comp {g : β → γ} {f : α → β} (hg : Inducing g) (hf : Inducing f) : +protected theorem Inducing.comp (hg : Inducing g) (hf : Inducing f) : Inducing (g ∘ f) := ⟨by rw [hf.induced, hg.induced, induced_compose]⟩ #align inducing.comp Inducing.comp -theorem inducing_of_inducing_compose {f : α → β} {g : β → γ} (hf : Continuous f) (hg : Continuous g) - (hgf : Inducing (g ∘ f)) : Inducing f := +theorem inducing_of_inducing_compose + (hf : Continuous f) (hg : Continuous g) (hgf : Inducing (g ∘ f)) : Inducing f := ⟨le_antisymm (by rwa [← continuous_iff_le_induced]) (by rw [hgf.induced, ← induced_compose] exact induced_mono hg.le_induced)⟩ #align inducing_of_inducing_compose inducing_of_inducing_compose -theorem inducing_iff_nhds {f : α → β} : Inducing f ↔ ∀ a, 𝓝 a = comap f (𝓝 (f a)) := +theorem inducing_iff_nhds : Inducing f ↔ ∀ x, 𝓝 x = comap f (𝓝 (f x)) := (inducing_iff _).trans (induced_iff_nhds_eq f) #align inducing_iff_nhds inducing_iff_nhds -theorem Inducing.nhds_eq_comap {f : α → β} (hf : Inducing f) : ∀ a : α, 𝓝 a = comap f (𝓝 <| f a) := +namespace Inducing + +theorem nhds_eq_comap (hf : Inducing f) : ∀ x : X, 𝓝 x = comap f (𝓝 <| f x) := inducing_iff_nhds.1 hf #align inducing.nhds_eq_comap Inducing.nhds_eq_comap -theorem Inducing.nhdsSet_eq_comap {f : α → β} (hf : Inducing f) (s : Set α) : +theorem nhdsSet_eq_comap (hf : Inducing f) (s : Set X) : 𝓝ˢ s = comap f (𝓝ˢ (f '' s)) := by simp only [nhdsSet, sSup_image, comap_iSup, hf.nhds_eq_comap, iSup_image] #align inducing.nhds_set_eq_comap Inducing.nhdsSet_eq_comap -theorem Inducing.map_nhds_eq {f : α → β} (hf : Inducing f) (a : α) : (𝓝 a).map f = 𝓝[range f] f a := - hf.induced.symm ▸ map_nhds_induced_eq a +theorem map_nhds_eq (hf : Inducing f) (x : X) : (𝓝 x).map f = 𝓝[range f] f x := + hf.induced.symm ▸ map_nhds_induced_eq x #align inducing.map_nhds_eq Inducing.map_nhds_eq -theorem Inducing.map_nhds_of_mem {f : α → β} (hf : Inducing f) (a : α) (h : range f ∈ 𝓝 (f a)) : - (𝓝 a).map f = 𝓝 (f a) := +theorem map_nhds_of_mem (hf : Inducing f) (x : X) (h : range f ∈ 𝓝 (f x)) : + (𝓝 x).map f = 𝓝 (f x) := hf.induced.symm ▸ map_nhds_induced_of_mem h #align inducing.map_nhds_of_mem Inducing.map_nhds_of_mem -- porting note: new lemma -theorem Inducing.mapClusterPt_iff {f : α → β} (hf : Inducing f) {a : α} {l : Filter α} : - MapClusterPt (f a) l f ↔ ClusterPt a l := by +theorem mapClusterPt_iff (hf : Inducing f) {x : X} {l : Filter X} : + MapClusterPt (f x) l f ↔ ClusterPt x l := by delta MapClusterPt ClusterPt rw [← Filter.push_pull', ← hf.nhds_eq_comap, map_neBot_iff] -theorem Inducing.image_mem_nhdsWithin {f : α → β} (hf : Inducing f) {a : α} {s : Set α} - (hs : s ∈ 𝓝 a) : f '' s ∈ 𝓝[range f] f a := - hf.map_nhds_eq a ▸ image_mem_map hs +theorem image_mem_nhdsWithin (hf : Inducing f) {x : X} {s : Set X} (hs : s ∈ 𝓝 x) : + f '' s ∈ 𝓝[range f] f x := + hf.map_nhds_eq x ▸ image_mem_map hs #align inducing.image_mem_nhds_within Inducing.image_mem_nhdsWithin -theorem Inducing.tendsto_nhds_iff {ι : Type*} {f : ι → β} {g : β → γ} {a : Filter ι} {b : β} - (hg : Inducing g) : Tendsto f a (𝓝 b) ↔ Tendsto (g ∘ f) a (𝓝 (g b)) := by +theorem tendsto_nhds_iff {f : ι → Y} {l : Filter ι} {y : Y} (hg : Inducing g) : + Tendsto f l (𝓝 y) ↔ Tendsto (g ∘ f) l (𝓝 (g y)) := by rw [hg.nhds_eq_comap, tendsto_comap_iff] #align inducing.tendsto_nhds_iff Inducing.tendsto_nhds_iff -theorem Inducing.continuousAt_iff {f : α → β} {g : β → γ} (hg : Inducing g) {x : α} : +theorem continuousAt_iff (hg : Inducing g) {x : X} : ContinuousAt f x ↔ ContinuousAt (g ∘ f) x := hg.tendsto_nhds_iff #align inducing.continuous_at_iff Inducing.continuousAt_iff -theorem Inducing.continuous_iff {f : α → β} {g : β → γ} (hg : Inducing g) : +theorem continuous_iff (hg : Inducing g) : Continuous f ↔ Continuous (g ∘ f) := by simp_rw [continuous_iff_continuousAt, hg.continuousAt_iff] #align inducing.continuous_iff Inducing.continuous_iff -theorem Inducing.continuousAt_iff' {f : α → β} {g : β → γ} (hf : Inducing f) {x : α} - (h : range f ∈ 𝓝 (f x)) : ContinuousAt (g ∘ f) x ↔ ContinuousAt g (f x) := by +theorem continuousAt_iff' (hf : Inducing f) {x : X} (h : range f ∈ 𝓝 (f x)) : + ContinuousAt (g ∘ f) x ↔ ContinuousAt g (f x) := by simp_rw [ContinuousAt, Filter.Tendsto, ← hf.map_nhds_of_mem _ h, Filter.map_map, comp] #align inducing.continuous_at_iff' Inducing.continuousAt_iff' -protected theorem Inducing.continuous {f : α → β} (hf : Inducing f) : Continuous f := +protected theorem continuous (hf : Inducing f) : Continuous f := hf.continuous_iff.mp continuous_id #align inducing.continuous Inducing.continuous -protected theorem Inducing.inducing_iff {f : α → β} {g : β → γ} (hg : Inducing g) : +protected theorem inducing_iff (hg : Inducing g) : Inducing f ↔ Inducing (g ∘ f) := by refine' ⟨fun h => hg.comp h, fun hgf => inducing_of_inducing_compose _ hg.continuous hgf⟩ rw [hg.continuous_iff] exact hgf.continuous #align inducing.inducing_iff Inducing.inducing_iff -theorem Inducing.closure_eq_preimage_closure_image {f : α → β} (hf : Inducing f) (s : Set α) : +theorem closure_eq_preimage_closure_image (hf : Inducing f) (s : Set X) : closure s = f ⁻¹' closure (f '' s) := by ext x rw [Set.mem_preimage, ← closure_induced, hf.induced] #align inducing.closure_eq_preimage_closure_image Inducing.closure_eq_preimage_closure_image -theorem Inducing.isClosed_iff {f : α → β} (hf : Inducing f) {s : Set α} : +theorem isClosed_iff (hf : Inducing f) {s : Set X} : IsClosed s ↔ ∃ t, IsClosed t ∧ f ⁻¹' t = s := by rw [hf.induced, isClosed_induced_iff] #align inducing.is_closed_iff Inducing.isClosed_iff -theorem Inducing.isClosed_iff' {f : α → β} (hf : Inducing f) {s : Set α} : +theorem isClosed_iff' (hf : Inducing f) {s : Set X} : IsClosed s ↔ ∀ x, f x ∈ closure (f '' s) → x ∈ s := by rw [hf.induced, isClosed_induced_iff'] #align inducing.is_closed_iff' Inducing.isClosed_iff' -theorem Inducing.isClosed_preimage {f : α → β} (h : Inducing f) (s : Set β) (hs : IsClosed s) : +theorem isClosed_preimage (h : Inducing f) (s : Set Y) (hs : IsClosed s) : IsClosed (f ⁻¹' s) := - (Inducing.isClosed_iff h).mpr ⟨s, hs, rfl⟩ + (isClosed_iff h).mpr ⟨s, hs, rfl⟩ #align inducing.is_closed_preimage Inducing.isClosed_preimage -theorem Inducing.isOpen_iff {f : α → β} (hf : Inducing f) {s : Set α} : +theorem isOpen_iff (hf : Inducing f) {s : Set X} : IsOpen s ↔ ∃ t, IsOpen t ∧ f ⁻¹' t = s := by rw [hf.induced, isOpen_induced_iff] #align inducing.is_open_iff Inducing.isOpen_iff -theorem Inducing.setOf_isOpen {f : α → β} (hf : Inducing f) : - {s : Set α | IsOpen s} = preimage f '' {t | IsOpen t} := +theorem setOf_isOpen (hf : Inducing f) : + {s : Set X | IsOpen s} = preimage f '' {t | IsOpen t} := Set.ext fun _ ↦ hf.isOpen_iff -theorem Inducing.dense_iff {f : α → β} (hf : Inducing f) {s : Set α} : +theorem dense_iff (hf : Inducing f) {s : Set X} : Dense s ↔ ∀ x, f x ∈ closure (f '' s) := by simp only [Dense, hf.closure_eq_preimage_closure_image, mem_preimage] #align inducing.dense_iff Inducing.dense_iff end Inducing +end Inducing + section Embedding /-- A function between topological spaces is an embedding if it is injective, - and for all `s : Set α`, `s` is open iff it is the preimage of an open set. -/ + and for all `s : Set X`, `s` is open iff it is the preimage of an open set. -/ @[mk_iff] -structure Embedding [TopologicalSpace α] [TopologicalSpace β] (f : α → β) extends +structure Embedding [TopologicalSpace X] [TopologicalSpace Y] (f : X → Y) extends Inducing f : Prop where /-- A topological embedding is injective. -/ inj : Injective f #align embedding Embedding #align embedding_iff embedding_iff -theorem Function.Injective.embedding_induced [t : TopologicalSpace β] {f : α → β} - (hf : Injective f) : @_root_.Embedding α β (t.induced f) t f := - @_root_.Embedding.mk α β (t.induced f) t _ (inducing_induced f) hf +theorem Function.Injective.embedding_induced [t : TopologicalSpace Y] (hf : Injective f) : + @_root_.Embedding X Y (t.induced f) t f := + @_root_.Embedding.mk X Y (t.induced f) t _ (inducing_induced f) hf #align function.injective.embedding_induced Function.Injective.embedding_induced -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] -theorem Embedding.mk' (f : α → β) (inj : Injective f) (induced : ∀ a, comap f (𝓝 (f a)) = 𝓝 a) : +theorem Embedding.mk' (f : X → Y) (inj : Injective f) (induced : ∀ x, comap f (𝓝 (f x)) = 𝓝 x) : Embedding f := - ⟨inducing_iff_nhds.2 fun a => (induced a).symm, inj⟩ + ⟨inducing_iff_nhds.2 fun x => (induced x).symm, inj⟩ #align embedding.mk' Embedding.mk' -theorem embedding_id : Embedding (@id α) := +theorem embedding_id : Embedding (@id X) := ⟨inducing_id, fun _ _ h => h⟩ #align embedding_id embedding_id -protected theorem Embedding.comp {g : β → γ} {f : α → β} (hg : Embedding g) (hf : Embedding f) : +protected theorem Embedding.comp (hg : Embedding g) (hf : Embedding f) : Embedding (g ∘ f) := { hg.toInducing.comp hf.toInducing with inj := fun _ _ h => hf.inj <| hg.inj h } #align embedding.comp Embedding.comp -theorem embedding_of_embedding_compose {f : α → β} {g : β → γ} (hf : Continuous f) - (hg : Continuous g) (hgf : Embedding (g ∘ f)) : Embedding f := +theorem embedding_of_embedding_compose + (hf : Continuous f) (hg : Continuous g) (hgf : Embedding (g ∘ f)) : Embedding f := { induced := (inducing_of_inducing_compose hf hg hgf.toInducing).induced - inj := fun a₁ a₂ h => hgf.inj <| by simp [h, (· ∘ ·)] } + inj := fun x₁ x₂ h => hgf.inj <| by simp [h, (· ∘ ·)] } #align embedding_of_embedding_compose embedding_of_embedding_compose -protected theorem Function.LeftInverse.embedding {f : α → β} {g : β → α} (h : LeftInverse f g) +protected theorem Function.LeftInverse.embedding {f : X → Y} {g : Y → X} (h : LeftInverse f g) (hf : Continuous f) (hg : Continuous g) : _root_.Embedding g := embedding_of_embedding_compose hg hf <| h.comp_eq_id.symm ▸ embedding_id #align function.left_inverse.embedding Function.LeftInverse.embedding -theorem Embedding.map_nhds_eq {f : α → β} (hf : Embedding f) (a : α) : - (𝓝 a).map f = 𝓝[range f] f a := - hf.1.map_nhds_eq a +theorem Embedding.map_nhds_eq (hf : Embedding f) (x : X) : + (𝓝 x).map f = 𝓝[range f] f x := + hf.1.map_nhds_eq x #align embedding.map_nhds_eq Embedding.map_nhds_eq -theorem Embedding.map_nhds_of_mem {f : α → β} (hf : Embedding f) (a : α) (h : range f ∈ 𝓝 (f a)) : - (𝓝 a).map f = 𝓝 (f a) := - hf.1.map_nhds_of_mem a h +theorem Embedding.map_nhds_of_mem (hf : Embedding f) (x : X) (h : range f ∈ 𝓝 (f x)) : + (𝓝 x).map f = 𝓝 (f x) := + hf.1.map_nhds_of_mem x h #align embedding.map_nhds_of_mem Embedding.map_nhds_of_mem -theorem Embedding.tendsto_nhds_iff {ι : Type*} {f : ι → β} {g : β → γ} {a : Filter ι} {b : β} - (hg : Embedding g) : Tendsto f a (𝓝 b) ↔ Tendsto (g ∘ f) a (𝓝 (g b)) := +theorem Embedding.tendsto_nhds_iff {f : ι → Y} {l : Filter ι} {y : Y} + (hg : Embedding g) : Tendsto f l (𝓝 y) ↔ Tendsto (g ∘ f) l (𝓝 (g y)) := hg.toInducing.tendsto_nhds_iff #align embedding.tendsto_nhds_iff Embedding.tendsto_nhds_iff -theorem Embedding.continuous_iff {f : α → β} {g : β → γ} (hg : Embedding g) : +theorem Embedding.continuous_iff (hg : Embedding g) : Continuous f ↔ Continuous (g ∘ f) := Inducing.continuous_iff hg.1 #align embedding.continuous_iff Embedding.continuous_iff -theorem Embedding.continuous {f : α → β} (hf : Embedding f) : Continuous f := +theorem Embedding.continuous (hf : Embedding f) : Continuous f := Inducing.continuous hf.1 #align embedding.continuous Embedding.continuous -theorem Embedding.closure_eq_preimage_closure_image {e : α → β} (he : Embedding e) (s : Set α) : - closure s = e ⁻¹' closure (e '' s) := - he.1.closure_eq_preimage_closure_image s +theorem Embedding.closure_eq_preimage_closure_image (hf : Embedding f) (s : Set X) : + closure s = f ⁻¹' closure (f '' s) := + hf.1.closure_eq_preimage_closure_image s #align embedding.closure_eq_preimage_closure_image Embedding.closure_eq_preimage_closure_image /-- The topology induced under an inclusion `f : X → Y` from a discrete topological space `Y` is the discrete topology on `X`. See also `DiscreteTopology.of_continuous_injective`. -/ -theorem Embedding.discreteTopology {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] - [DiscreteTopology Y] {f : X → Y} (hf : Embedding f) : DiscreteTopology X := +theorem Embedding.discreteTopology [DiscreteTopology Y] (hf : Embedding f) : DiscreteTopology X := .of_continuous_injective hf.continuous hf.inj #align embedding.discrete_topology Embedding.discreteTopology end Embedding +section QuotientMap /-- A function between topological spaces is a quotient map if it is surjective, - and for all `s : Set β`, `s` is open iff its preimage is an open set. -/ -def QuotientMap {α : Type*} {β : Type*} [tα : TopologicalSpace α] [tβ : TopologicalSpace β] - (f : α → β) : Prop := - Surjective f ∧ tβ = tα.coinduced f + and for all `s : Set Y`, `s` is open iff its preimage is an open set. -/ +def QuotientMap {X : Type*} {Y : Type*} [tX : TopologicalSpace X] [tY : TopologicalSpace Y] + (f : X → Y) : Prop := + Surjective f ∧ tY = tX.coinduced f #align quotient_map QuotientMap -theorem quotientMap_iff [TopologicalSpace α] [TopologicalSpace β] {f : α → β} : - QuotientMap f ↔ Surjective f ∧ ∀ s : Set β, IsOpen s ↔ IsOpen (f ⁻¹' s) := +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] + +theorem quotientMap_iff : QuotientMap f ↔ Surjective f ∧ ∀ s : Set Y, IsOpen s ↔ IsOpen (f ⁻¹' s) := and_congr Iff.rfl TopologicalSpace.ext_iff #align quotient_map_iff quotientMap_iff -theorem quotientMap_iff_closed [TopologicalSpace α] [TopologicalSpace β] {f : α → β} : - QuotientMap f ↔ Surjective f ∧ ∀ s : Set β, IsClosed s ↔ IsClosed (f ⁻¹' s) := +theorem quotientMap_iff_closed : + QuotientMap f ↔ Surjective f ∧ ∀ s : Set Y, IsClosed s ↔ IsClosed (f ⁻¹' s) := quotientMap_iff.trans <| Iff.rfl.and <| compl_surjective.forall.trans <| by simp only [isOpen_compl_iff, preimage_compl] #align quotient_map_iff_closed quotientMap_iff_closed namespace QuotientMap -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] [TopologicalSpace δ] - {g : β → γ} {f : α → β} - -protected theorem id : QuotientMap (@id α) := - ⟨fun a => ⟨a, rfl⟩, coinduced_id.symm⟩ +protected theorem id : QuotientMap (@id X) := + ⟨fun x => ⟨x, rfl⟩, coinduced_id.symm⟩ #align quotient_map.id QuotientMap.id protected theorem comp (hg : QuotientMap g) (hf : QuotientMap f) : QuotientMap (g ∘ f) := @@ -306,7 +308,7 @@ protected theorem of_quotientMap_compose (hf : Continuous f) (hg : Continuous g) hg.coinduced_le⟩ #align quotient_map.of_quotient_map_compose QuotientMap.of_quotientMap_compose -theorem of_inverse {g : β → α} (hf : Continuous f) (hg : Continuous g) (h : LeftInverse g f) : +theorem of_inverse {g : Y → X} (hf : Continuous f) (hg : Continuous g) (h : LeftInverse g f) : QuotientMap g := QuotientMap.of_quotientMap_compose hf hg <| h.comp_eq_id.symm ▸ QuotientMap.id #align quotient_map.of_inverse QuotientMap.of_inverse @@ -323,31 +325,34 @@ protected theorem surjective (hf : QuotientMap f) : Surjective f := hf.1 #align quotient_map.surjective QuotientMap.surjective -protected theorem isOpen_preimage (hf : QuotientMap f) {s : Set β} : IsOpen (f ⁻¹' s) ↔ IsOpen s := +protected theorem isOpen_preimage (hf : QuotientMap f) {s : Set Y} : IsOpen (f ⁻¹' s) ↔ IsOpen s := ((quotientMap_iff.1 hf).2 s).symm #align quotient_map.is_open_preimage QuotientMap.isOpen_preimage -protected theorem isClosed_preimage (hf : QuotientMap f) {s : Set β} : +protected theorem isClosed_preimage (hf : QuotientMap f) {s : Set Y} : IsClosed (f ⁻¹' s) ↔ IsClosed s := ((quotientMap_iff_closed.1 hf).2 s).symm #align quotient_map.is_closed_preimage QuotientMap.isClosed_preimage end QuotientMap -/-- A map `f : α → β` is said to be an *open map*, if the image of any open `U : Set α` -is open in `β`. -/ -def IsOpenMap [TopologicalSpace α] [TopologicalSpace β] (f : α → β) := - ∀ U : Set α, IsOpen U → IsOpen (f '' U) +end QuotientMap + +section OpenMap +/-- A map `f : X → Y` is said to be an *open map*, if the image of any open `U : Set X` +is open in `Y`. -/ +def IsOpenMap [TopologicalSpace X] [TopologicalSpace Y] (f : X → Y) := + ∀ U : Set X, IsOpen U → IsOpen (f '' U) #align is_open_map IsOpenMap -namespace IsOpenMap +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] {f : α → β} +namespace IsOpenMap -protected theorem id : IsOpenMap (@id α) := fun s hs => by rwa [image_id] +protected theorem id : IsOpenMap (@id X) := fun s hs => by rwa [image_id] #align is_open_map.id IsOpenMap.id -protected theorem comp {g : β → γ} {f : α → β} (hg : IsOpenMap g) (hf : IsOpenMap f) : +protected theorem comp (hg : IsOpenMap g) (hf : IsOpenMap f) : IsOpenMap (g ∘ f) := fun s hs => by rw [image_comp]; exact hg _ (hf _ hs) #align is_open_map.comp IsOpenMap.comp @@ -356,36 +361,36 @@ theorem isOpen_range (hf : IsOpenMap f) : IsOpen (range f) := by exact hf _ isOpen_univ #align is_open_map.is_open_range IsOpenMap.isOpen_range -theorem image_mem_nhds (hf : IsOpenMap f) {x : α} {s : Set α} (hx : s ∈ 𝓝 x) : f '' s ∈ 𝓝 (f x) := +theorem image_mem_nhds (hf : IsOpenMap f) {x : X} {s : Set X} (hx : s ∈ 𝓝 x) : f '' s ∈ 𝓝 (f x) := let ⟨t, hts, ht, hxt⟩ := mem_nhds_iff.1 hx mem_of_superset (IsOpen.mem_nhds (hf t ht) (mem_image_of_mem _ hxt)) (image_subset _ hts) #align is_open_map.image_mem_nhds IsOpenMap.image_mem_nhds -theorem range_mem_nhds (hf : IsOpenMap f) (x : α) : range f ∈ 𝓝 (f x) := +theorem range_mem_nhds (hf : IsOpenMap f) (x : X) : range f ∈ 𝓝 (f x) := hf.isOpen_range.mem_nhds <| mem_range_self _ #align is_open_map.range_mem_nhds IsOpenMap.range_mem_nhds -theorem mapsTo_interior (hf : IsOpenMap f) {s : Set α} {t : Set β} (h : MapsTo f s t) : +theorem mapsTo_interior (hf : IsOpenMap f) {s : Set X} {t : Set Y} (h : MapsTo f s t) : MapsTo f (interior s) (interior t) := mapsTo'.2 <| interior_maximal (h.mono interior_subset Subset.rfl).image_subset (hf _ isOpen_interior) #align is_open_map.maps_to_interior IsOpenMap.mapsTo_interior -theorem image_interior_subset (hf : IsOpenMap f) (s : Set α) : +theorem image_interior_subset (hf : IsOpenMap f) (s : Set X) : f '' interior s ⊆ interior (f '' s) := (hf.mapsTo_interior (mapsTo_image f s)).image_subset #align is_open_map.image_interior_subset IsOpenMap.image_interior_subset -theorem nhds_le (hf : IsOpenMap f) (a : α) : 𝓝 (f a) ≤ (𝓝 a).map f := +theorem nhds_le (hf : IsOpenMap f) (x : X) : 𝓝 (f x) ≤ (𝓝 x).map f := le_map fun _ => hf.image_mem_nhds #align is_open_map.nhds_le IsOpenMap.nhds_le -theorem of_nhds_le (hf : ∀ a, 𝓝 (f a) ≤ map f (𝓝 a)) : IsOpenMap f := fun _s hs => - isOpen_iff_mem_nhds.2 fun _b ⟨_a, has, hab⟩ => hab ▸ hf _ (image_mem_map <| hs.mem_nhds has) +theorem of_nhds_le (hf : ∀ x, 𝓝 (f x) ≤ map f (𝓝 x)) : IsOpenMap f := fun _s hs => + isOpen_iff_mem_nhds.2 fun _y ⟨_x, hxs, hxy⟩ => hxy ▸ hf _ (image_mem_map <| hs.mem_nhds hxs) #align is_open_map.of_nhds_le IsOpenMap.of_nhds_le -theorem of_sections {f : α → β} - (h : ∀ x, ∃ g : β → α, ContinuousAt g (f x) ∧ g (f x) = x ∧ RightInverse g f) : IsOpenMap f := +theorem of_sections + (h : ∀ x, ∃ g : Y → X, ContinuousAt g (f x) ∧ g (f x) = x ∧ RightInverse g f) : IsOpenMap f := of_nhds_le fun x => let ⟨g, hgc, hgx, hgf⟩ := h x calc @@ -394,48 +399,48 @@ theorem of_sections {f : α → β} _ = map f (𝓝 x) := by rw [hgx] #align is_open_map.of_sections IsOpenMap.of_sections -theorem of_inverse {f : α → β} {f' : β → α} (h : Continuous f') (l_inv : LeftInverse f f') +theorem of_inverse {f' : Y → X} (h : Continuous f') (l_inv : LeftInverse f f') (r_inv : RightInverse f f') : IsOpenMap f := of_sections fun _ => ⟨f', h.continuousAt, r_inv _, l_inv⟩ #align is_open_map.of_inverse IsOpenMap.of_inverse /-- A continuous surjective open map is a quotient map. -/ -theorem to_quotientMap {f : α → β} (open_map : IsOpenMap f) (cont : Continuous f) - (surj : Surjective f) : QuotientMap f := +theorem to_quotientMap (open_map : IsOpenMap f) (cont : Continuous f) (surj : Surjective f) : + QuotientMap f := quotientMap_iff.2 ⟨surj, fun s => ⟨fun h => h.preimage cont, fun h => surj.image_preimage s ▸ open_map _ h⟩⟩ #align is_open_map.to_quotient_map IsOpenMap.to_quotientMap -theorem interior_preimage_subset_preimage_interior (hf : IsOpenMap f) {s : Set β} : +theorem interior_preimage_subset_preimage_interior (hf : IsOpenMap f) {s : Set Y} : interior (f ⁻¹' s) ⊆ f ⁻¹' interior s := hf.mapsTo_interior (mapsTo_preimage _ _) #align is_open_map.interior_preimage_subset_preimage_interior IsOpenMap.interior_preimage_subset_preimage_interior theorem preimage_interior_eq_interior_preimage (hf₁ : IsOpenMap f) (hf₂ : Continuous f) - (s : Set β) : f ⁻¹' interior s = interior (f ⁻¹' s) := + (s : Set Y) : f ⁻¹' interior s = interior (f ⁻¹' s) := Subset.antisymm (preimage_interior_subset_interior_preimage hf₂) (interior_preimage_subset_preimage_interior hf₁) #align is_open_map.preimage_interior_eq_interior_preimage IsOpenMap.preimage_interior_eq_interior_preimage -theorem preimage_closure_subset_closure_preimage (hf : IsOpenMap f) {s : Set β} : +theorem preimage_closure_subset_closure_preimage (hf : IsOpenMap f) {s : Set Y} : f ⁻¹' closure s ⊆ closure (f ⁻¹' s) := by rw [← compl_subset_compl] simp only [← interior_compl, ← preimage_compl, hf.interior_preimage_subset_preimage_interior] #align is_open_map.preimage_closure_subset_closure_preimage IsOpenMap.preimage_closure_subset_closure_preimage -theorem preimage_closure_eq_closure_preimage (hf : IsOpenMap f) (hfc : Continuous f) (s : Set β) : +theorem preimage_closure_eq_closure_preimage (hf : IsOpenMap f) (hfc : Continuous f) (s : Set Y) : f ⁻¹' closure s = closure (f ⁻¹' s) := hf.preimage_closure_subset_closure_preimage.antisymm (hfc.closure_preimage_subset s) #align is_open_map.preimage_closure_eq_closure_preimage IsOpenMap.preimage_closure_eq_closure_preimage -theorem preimage_frontier_subset_frontier_preimage (hf : IsOpenMap f) {s : Set β} : +theorem preimage_frontier_subset_frontier_preimage (hf : IsOpenMap f) {s : Set Y} : f ⁻¹' frontier s ⊆ frontier (f ⁻¹' s) := by simpa only [frontier_eq_closure_inter_closure, preimage_inter] using inter_subset_inter hf.preimage_closure_subset_closure_preimage hf.preimage_closure_subset_closure_preimage #align is_open_map.preimage_frontier_subset_frontier_preimage IsOpenMap.preimage_frontier_subset_frontier_preimage -theorem preimage_frontier_eq_frontier_preimage (hf : IsOpenMap f) (hfc : Continuous f) (s : Set β) : +theorem preimage_frontier_eq_frontier_preimage (hf : IsOpenMap f) (hfc : Continuous f) (s : Set Y) : f ⁻¹' frontier s = frontier (f ⁻¹' s) := by simp only [frontier_eq_closure_inter_closure, preimage_inter, preimage_compl, hf.preimage_closure_eq_closure_preimage hfc] @@ -443,13 +448,11 @@ theorem preimage_frontier_eq_frontier_preimage (hf : IsOpenMap f) (hfc : Continu end IsOpenMap -theorem isOpenMap_iff_nhds_le [TopologicalSpace α] [TopologicalSpace β] {f : α → β} : - IsOpenMap f ↔ ∀ a : α, 𝓝 (f a) ≤ (𝓝 a).map f := +theorem isOpenMap_iff_nhds_le : IsOpenMap f ↔ ∀ x : X, 𝓝 (f x) ≤ (𝓝 x).map f := ⟨fun hf => hf.nhds_le, IsOpenMap.of_nhds_le⟩ #align is_open_map_iff_nhds_le isOpenMap_iff_nhds_le -theorem isOpenMap_iff_interior [TopologicalSpace α] [TopologicalSpace β] {f : α → β} : - IsOpenMap f ↔ ∀ s, f '' interior s ⊆ interior (f '' s) := +theorem isOpenMap_iff_interior : IsOpenMap f ↔ ∀ s, f '' interior s ⊆ interior (f '' s) := ⟨IsOpenMap.image_interior_subset, fun hs u hu => subset_interior_iff_isOpen.mp <| calc @@ -458,62 +461,57 @@ theorem isOpenMap_iff_interior [TopologicalSpace α] [TopologicalSpace β] {f : #align is_open_map_iff_interior isOpenMap_iff_interior /-- An inducing map with an open range is an open map. -/ -protected theorem Inducing.isOpenMap [TopologicalSpace α] [TopologicalSpace β] {f : α → β} - (hi : Inducing f) (ho : IsOpen (range f)) : IsOpenMap f := +protected theorem Inducing.isOpenMap (hi : Inducing f) (ho : IsOpen (range f)) : IsOpenMap f := IsOpenMap.of_nhds_le fun _ => (hi.map_nhds_of_mem _ <| IsOpen.mem_nhds ho <| mem_range_self _).ge #align inducing.is_open_map Inducing.isOpenMap +end OpenMap + section IsClosedMap -variable [TopologicalSpace α] [TopologicalSpace β] +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] -/-- A map `f : α → β` is said to be a *closed map*, if the image of any closed `U : Set α` -is closed in `β`. -/ -def IsClosedMap (f : α → β) := - ∀ U : Set α, IsClosed U → IsClosed (f '' U) +/-- A map `f : X → Y` is said to be a *closed map*, if the image of any closed `U : Set X` +is closed in `Y`. -/ +def IsClosedMap (f : X → Y) := + ∀ U : Set X, IsClosed U → IsClosed (f '' U) #align is_closed_map IsClosedMap -end IsClosedMap - namespace IsClosedMap - -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] - open Function -protected theorem id : IsClosedMap (@id α) := fun s hs => by rwa [image_id] +protected theorem id : IsClosedMap (@id X) := fun s hs => by rwa [image_id] #align is_closed_map.id IsClosedMap.id -protected theorem comp {g : β → γ} {f : α → β} (hg : IsClosedMap g) (hf : IsClosedMap f) : - IsClosedMap (g ∘ f) := by +protected theorem comp (hg : IsClosedMap g) (hf : IsClosedMap f) : IsClosedMap (g ∘ f) := by intro s hs rw [image_comp] exact hg _ (hf _ hs) #align is_closed_map.comp IsClosedMap.comp -theorem closure_image_subset {f : α → β} (hf : IsClosedMap f) (s : Set α) : +theorem closure_image_subset (hf : IsClosedMap f) (s : Set X) : closure (f '' s) ⊆ f '' closure s := closure_minimal (image_subset _ subset_closure) (hf _ isClosed_closure) #align is_closed_map.closure_image_subset IsClosedMap.closure_image_subset -theorem of_inverse {f : α → β} {f' : β → α} (h : Continuous f') (l_inv : LeftInverse f f') +theorem of_inverse {f' : Y → X} (h : Continuous f') (l_inv : LeftInverse f f') (r_inv : RightInverse f f') : IsClosedMap f := fun s hs => by rw [image_eq_preimage_of_inverse r_inv l_inv] exact hs.preimage h #align is_closed_map.of_inverse IsClosedMap.of_inverse -theorem of_nonempty {f : α → β} (h : ∀ s, IsClosed s → s.Nonempty → IsClosed (f '' s)) : +theorem of_nonempty (h : ∀ s, IsClosed s → s.Nonempty → IsClosed (f '' s)) : IsClosedMap f := by intro s hs; rcases eq_empty_or_nonempty s with h2s | h2s · simp_rw [h2s, image_empty, isClosed_empty] · exact h s hs h2s #align is_closed_map.of_nonempty IsClosedMap.of_nonempty -theorem closed_range {f : α → β} (hf : IsClosedMap f) : IsClosed (range f) := +theorem closed_range (hf : IsClosedMap f) : IsClosed (range f) := @image_univ _ _ f ▸ hf _ isClosed_univ #align is_closed_map.closed_range IsClosedMap.closed_range -theorem to_quotientMap {f : α → β} (hcl : IsClosedMap f) (hcont : Continuous f) +theorem to_quotientMap (hcl : IsClosedMap f) (hcont : Continuous f) (hsurj : Surjective f) : QuotientMap f := quotientMap_iff_closed.2 ⟨hsurj, fun s => ⟨fun hs => hs.preimage hcont, fun hs => hsurj.image_preimage s ▸ hcl _ hs⟩⟩ @@ -521,15 +519,14 @@ theorem to_quotientMap {f : α → β} (hcl : IsClosedMap f) (hcont : Continuous end IsClosedMap -theorem Inducing.isClosedMap [TopologicalSpace α] [TopologicalSpace β] {f : α → β} (hf : Inducing f) - (h : IsClosed (range f)) : IsClosedMap f := by +theorem Inducing.isClosedMap (hf : Inducing f) (h : IsClosed (range f)) : IsClosedMap f := by intro s hs rcases hf.isClosed_iff.1 hs with ⟨t, ht, rfl⟩ rw [image_preimage_eq_inter_range] exact ht.inter h #align inducing.is_closed_map Inducing.isClosedMap -theorem isClosedMap_iff_closure_image [TopologicalSpace α] [TopologicalSpace β] {f : α → β} : +theorem isClosedMap_iff_closure_image : IsClosedMap f ↔ ∀ s, closure (f '' s) ⊆ f '' closure s := ⟨IsClosedMap.closure_image_subset, fun hs c hc => isClosed_of_closure_subset <| @@ -542,181 +539,187 @@ theorem isClosedMap_iff_closure_image [TopologicalSpace α] [TopologicalSpace β the image by `f` of some cluster point of `s`. If you require this for all filters instead of just principal filters, and also that `f` is continuous, you get the notion of **proper map**. See `isProperMap_iff_clusterPt`. -/ -theorem isClosedMap_iff_clusterPt [TopologicalSpace α] [TopologicalSpace β] {f : α → β} : +theorem isClosedMap_iff_clusterPt : IsClosedMap f ↔ ∀ s y, MapClusterPt y (𝓟 s) f → ∃ x, f x = y ∧ ClusterPt x (𝓟 s) := by simp [MapClusterPt, isClosedMap_iff_closure_image, subset_def, mem_closure_iff_clusterPt, and_comm] -theorem IsClosedMap.closure_image_eq_of_continuous [TopologicalSpace α] [TopologicalSpace β] - {f : α → β} (f_closed : IsClosedMap f) (f_cont : Continuous f) (s : Set α) : +theorem IsClosedMap.closure_image_eq_of_continuous + (f_closed : IsClosedMap f) (f_cont : Continuous f) (s : Set X) : closure (f '' s) = f '' closure s := subset_antisymm (f_closed.closure_image_subset s) (image_closure_subset_closure_image f_cont) -theorem IsClosedMap.lift'_closure_map_eq [TopologicalSpace α] [TopologicalSpace β] - {f : α → β} (f_closed : IsClosedMap f) (f_cont : Continuous f) (F : Filter α) : +theorem IsClosedMap.lift'_closure_map_eq + (f_closed : IsClosedMap f) (f_cont : Continuous f) (F : Filter X) : (map f F).lift' closure = map f (F.lift' closure) := by - rw [map_lift'_eq2 (monotone_closure β), map_lift'_eq (monotone_closure α)] + rw [map_lift'_eq2 (monotone_closure Y), map_lift'_eq (monotone_closure X)] congr ext s : 1 exact f_closed.closure_image_eq_of_continuous f_cont s -theorem IsClosedMap.mapClusterPt_iff_lift'_closure [TopologicalSpace α] [TopologicalSpace β] - {F : Filter α} {f : α → β} (f_closed : IsClosedMap f) (f_cont : Continuous f) {y : β} : +theorem IsClosedMap.mapClusterPt_iff_lift'_closure + {F : Filter X} (f_closed : IsClosedMap f) (f_cont : Continuous f) {y : Y} : MapClusterPt y F f ↔ ((F.lift' closure) ⊓ 𝓟 (f ⁻¹' {y})).NeBot := by rw [MapClusterPt, clusterPt_iff_lift'_closure', f_closed.lift'_closure_map_eq f_cont, ← comap_principal, ← map_neBot_iff f, Filter.push_pull, principal_singleton] +end IsClosedMap + section OpenEmbedding -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] /-- An open embedding is an embedding with open image. -/ @[mk_iff] -structure OpenEmbedding (f : α → β) extends Embedding f : Prop where +structure OpenEmbedding (f : X → Y) extends Embedding f : Prop where /-- The range of an open embedding is an open set. -/ open_range : IsOpen <| range f #align open_embedding OpenEmbedding #align open_embedding_iff openEmbedding_iff -theorem OpenEmbedding.isOpenMap {f : α → β} (hf : OpenEmbedding f) : IsOpenMap f := +theorem OpenEmbedding.isOpenMap (hf : OpenEmbedding f) : IsOpenMap f := hf.toEmbedding.toInducing.isOpenMap hf.open_range #align open_embedding.is_open_map OpenEmbedding.isOpenMap -theorem OpenEmbedding.map_nhds_eq {f : α → β} (hf : OpenEmbedding f) (a : α) : - map f (𝓝 a) = 𝓝 (f a) := +theorem OpenEmbedding.map_nhds_eq (hf : OpenEmbedding f) (x : X) : + map f (𝓝 x) = 𝓝 (f x) := hf.toEmbedding.map_nhds_of_mem _ <| hf.open_range.mem_nhds <| mem_range_self _ #align open_embedding.map_nhds_eq OpenEmbedding.map_nhds_eq -theorem OpenEmbedding.open_iff_image_open {f : α → β} (hf : OpenEmbedding f) {s : Set α} : +theorem OpenEmbedding.open_iff_image_open (hf : OpenEmbedding f) {s : Set X} : IsOpen s ↔ IsOpen (f '' s) := ⟨hf.isOpenMap s, fun h => by convert ← h.preimage hf.toEmbedding.continuous apply preimage_image_eq _ hf.inj⟩ #align open_embedding.open_iff_image_open OpenEmbedding.open_iff_image_open -theorem OpenEmbedding.tendsto_nhds_iff {ι : Type*} {f : ι → β} {g : β → γ} {a : Filter ι} {b : β} - (hg : OpenEmbedding g) : Tendsto f a (𝓝 b) ↔ Tendsto (g ∘ f) a (𝓝 (g b)) := +theorem OpenEmbedding.tendsto_nhds_iff {f : ι → Y} {l : Filter ι} {y : Y} (hg : OpenEmbedding g) : + Tendsto f l (𝓝 y) ↔ Tendsto (g ∘ f) l (𝓝 (g y)) := hg.toEmbedding.tendsto_nhds_iff #align open_embedding.tendsto_nhds_iff OpenEmbedding.tendsto_nhds_iff -theorem OpenEmbedding.tendsto_nhds_iff' {f : α → β} (hf : OpenEmbedding f) {g : β → γ} - {l : Filter γ} {a : α} : Tendsto (g ∘ f) (𝓝 a) l ↔ Tendsto g (𝓝 (f a)) l := by +theorem OpenEmbedding.tendsto_nhds_iff' (hf : OpenEmbedding f) {l : Filter Z} {x : X} : + Tendsto (g ∘ f) (𝓝 x) l ↔ Tendsto g (𝓝 (f x)) l := by rw [Tendsto, ← map_map, hf.map_nhds_eq]; rfl -theorem OpenEmbedding.continuousAt_iff {f : α → β} (hf : OpenEmbedding f) {g : β → γ} {x : α} : +theorem OpenEmbedding.continuousAt_iff (hf : OpenEmbedding f) {x : X} : ContinuousAt (g ∘ f) x ↔ ContinuousAt g (f x) := hf.tendsto_nhds_iff' #align open_embedding.continuous_at_iff OpenEmbedding.continuousAt_iff -theorem OpenEmbedding.continuous {f : α → β} (hf : OpenEmbedding f) : Continuous f := +theorem OpenEmbedding.continuous (hf : OpenEmbedding f) : Continuous f := hf.toEmbedding.continuous #align open_embedding.continuous OpenEmbedding.continuous -theorem OpenEmbedding.open_iff_preimage_open {f : α → β} (hf : OpenEmbedding f) {s : Set β} +theorem OpenEmbedding.open_iff_preimage_open (hf : OpenEmbedding f) {s : Set Y} (hs : s ⊆ range f) : IsOpen s ↔ IsOpen (f ⁻¹' s) := by rw [hf.open_iff_image_open, image_preimage_eq_inter_range, inter_eq_self_of_subset_left hs] #align open_embedding.open_iff_preimage_open OpenEmbedding.open_iff_preimage_open -theorem openEmbedding_of_embedding_open {f : α → β} (h₁ : Embedding f) (h₂ : IsOpenMap f) : +theorem openEmbedding_of_embedding_open (h₁ : Embedding f) (h₂ : IsOpenMap f) : OpenEmbedding f := ⟨h₁, h₂.isOpen_range⟩ #align open_embedding_of_embedding_open openEmbedding_of_embedding_open /-- A surjective embedding is an `OpenEmbedding`. -/ -theorem _root_.Embedding.toOpenEmbedding_of_surjective {f : α → β} - (hf : Embedding f) (hsurj: f.Surjective) : OpenEmbedding f := +theorem _root_.Embedding.toOpenEmbedding_of_surjective (hf : Embedding f) (hsurj: f.Surjective) : + OpenEmbedding f := ⟨hf, hsurj.range_eq ▸ isOpen_univ⟩ -theorem openEmbedding_iff_embedding_open {f : α → β} : +theorem openEmbedding_iff_embedding_open : OpenEmbedding f ↔ Embedding f ∧ IsOpenMap f := ⟨fun h => ⟨h.1, h.isOpenMap⟩, fun h => openEmbedding_of_embedding_open h.1 h.2⟩ #align open_embedding_iff_embedding_open openEmbedding_iff_embedding_open -theorem openEmbedding_of_continuous_injective_open {f : α → β} (h₁ : Continuous f) - (h₂ : Injective f) (h₃ : IsOpenMap f) : OpenEmbedding f := by +theorem openEmbedding_of_continuous_injective_open + (h₁ : Continuous f) (h₂ : Injective f) (h₃ : IsOpenMap f) : OpenEmbedding f := by simp only [openEmbedding_iff_embedding_open, embedding_iff, inducing_iff_nhds, *, and_true_iff] - exact fun a => - le_antisymm (h₁.tendsto _).le_comap (@comap_map _ _ (𝓝 a) _ h₂ ▸ comap_mono (h₃.nhds_le _)) + exact fun x => + le_antisymm (h₁.tendsto _).le_comap (@comap_map _ _ (𝓝 x) _ h₂ ▸ comap_mono (h₃.nhds_le _)) #align open_embedding_of_continuous_injective_open openEmbedding_of_continuous_injective_open -theorem openEmbedding_iff_continuous_injective_open {f : α → β} : +theorem openEmbedding_iff_continuous_injective_open : OpenEmbedding f ↔ Continuous f ∧ Injective f ∧ IsOpenMap f := ⟨fun h => ⟨h.continuous, h.inj, h.isOpenMap⟩, fun h => openEmbedding_of_continuous_injective_open h.1 h.2.1 h.2.2⟩ #align open_embedding_iff_continuous_injective_open openEmbedding_iff_continuous_injective_open -theorem openEmbedding_id : OpenEmbedding (@id α) := +theorem openEmbedding_id : OpenEmbedding (@id X) := ⟨embedding_id, IsOpenMap.id.isOpen_range⟩ #align open_embedding_id openEmbedding_id -protected theorem OpenEmbedding.comp {g : β → γ} {f : α → β} (hg : OpenEmbedding g) +namespace OpenEmbedding + +protected theorem comp (hg : OpenEmbedding g) (hf : OpenEmbedding f) : OpenEmbedding (g ∘ f) := ⟨hg.1.comp hf.1, (hg.isOpenMap.comp hf.isOpenMap).isOpen_range⟩ #align open_embedding.comp OpenEmbedding.comp -theorem OpenEmbedding.isOpenMap_iff {g : β → γ} {f : α → β} (hg : OpenEmbedding g) : +theorem isOpenMap_iff (hg : OpenEmbedding g) : IsOpenMap f ↔ IsOpenMap (g ∘ f) := by simp_rw [isOpenMap_iff_nhds_le, ← map_map, comp, ← hg.map_nhds_eq, Filter.map_le_map_iff hg.inj] #align open_embedding.is_open_map_iff OpenEmbedding.isOpenMap_iff -theorem OpenEmbedding.of_comp_iff (f : α → β) {g : β → γ} (hg : OpenEmbedding g) : +theorem of_comp_iff (f : X → Y) (hg : OpenEmbedding g) : OpenEmbedding (g ∘ f) ↔ OpenEmbedding f := by simp only [openEmbedding_iff_continuous_injective_open, ← hg.isOpenMap_iff, ← hg.1.continuous_iff, hg.inj.of_comp_iff] #align open_embedding.of_comp_iff OpenEmbedding.of_comp_iff -theorem OpenEmbedding.of_comp (f : α → β) {g : β → γ} (hg : OpenEmbedding g) +theorem of_comp (f : X → Y) (hg : OpenEmbedding g) (h : OpenEmbedding (g ∘ f)) : OpenEmbedding f := (OpenEmbedding.of_comp_iff f hg).1 h #align open_embedding.of_comp OpenEmbedding.of_comp end OpenEmbedding +end OpenEmbedding + section ClosedEmbedding -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] /-- A closed embedding is an embedding with closed image. -/ @[mk_iff] -structure ClosedEmbedding (f : α → β) extends Embedding f : Prop where +structure ClosedEmbedding (f : X → Y) extends Embedding f : Prop where /-- The range of a closed embedding is a closed set. -/ closed_range : IsClosed <| range f #align closed_embedding ClosedEmbedding #align closed_embedding_iff closedEmbedding_iff -variable {f : α → β} +namespace ClosedEmbedding -theorem ClosedEmbedding.tendsto_nhds_iff {ι : Type*} {g : ι → α} {a : Filter ι} {b : α} - (hf : ClosedEmbedding f) : Tendsto g a (𝓝 b) ↔ Tendsto (f ∘ g) a (𝓝 (f b)) := +theorem tendsto_nhds_iff {g : ι → X} {l : Filter ι} {x : X} (hf : ClosedEmbedding f) : + Tendsto g l (𝓝 x) ↔ Tendsto (f ∘ g) l (𝓝 (f x)) := hf.toEmbedding.tendsto_nhds_iff #align closed_embedding.tendsto_nhds_iff ClosedEmbedding.tendsto_nhds_iff -theorem ClosedEmbedding.continuous (hf : ClosedEmbedding f) : Continuous f := +theorem continuous (hf : ClosedEmbedding f) : Continuous f := hf.toEmbedding.continuous #align closed_embedding.continuous ClosedEmbedding.continuous -theorem ClosedEmbedding.isClosedMap (hf : ClosedEmbedding f) : IsClosedMap f := +theorem isClosedMap (hf : ClosedEmbedding f) : IsClosedMap f := hf.toEmbedding.toInducing.isClosedMap hf.closed_range #align closed_embedding.is_closed_map ClosedEmbedding.isClosedMap -theorem ClosedEmbedding.closed_iff_image_closed (hf : ClosedEmbedding f) {s : Set α} : +theorem closed_iff_image_closed (hf : ClosedEmbedding f) {s : Set X} : IsClosed s ↔ IsClosed (f '' s) := ⟨hf.isClosedMap s, fun h => by rw [← preimage_image_eq s hf.inj] exact h.preimage hf.continuous⟩ #align closed_embedding.closed_iff_image_closed ClosedEmbedding.closed_iff_image_closed -theorem ClosedEmbedding.closed_iff_preimage_closed (hf : ClosedEmbedding f) {s : Set β} +theorem closed_iff_preimage_closed (hf : ClosedEmbedding f) {s : Set Y} (hs : s ⊆ range f) : IsClosed s ↔ IsClosed (f ⁻¹' s) := by rw [hf.closed_iff_image_closed, image_preimage_eq_of_subset hs] #align closed_embedding.closed_iff_preimage_closed ClosedEmbedding.closed_iff_preimage_closed -theorem closedEmbedding_of_embedding_closed (h₁ : Embedding f) (h₂ : IsClosedMap f) : +theorem _root_.closedEmbedding_of_embedding_closed (h₁ : Embedding f) (h₂ : IsClosedMap f) : ClosedEmbedding f := ⟨h₁, image_univ (f := f) ▸ h₂ univ isClosed_univ⟩ #align closed_embedding_of_embedding_closed closedEmbedding_of_embedding_closed -theorem closedEmbedding_of_continuous_injective_closed (h₁ : Continuous f) (h₂ : Injective f) +theorem _root_.closedEmbedding_of_continuous_injective_closed (h₁ : Continuous f) (h₂ : Injective f) (h₃ : IsClosedMap f) : ClosedEmbedding f := by refine closedEmbedding_of_embedding_closed ⟨⟨?_⟩, h₂⟩ h₃ refine h₁.le_induced.antisymm fun s hs => ?_ @@ -724,18 +727,20 @@ theorem closedEmbedding_of_continuous_injective_closed (h₁ : Continuous f) (h rw [preimage_compl, preimage_image_eq _ h₂, compl_compl] #align closed_embedding_of_continuous_injective_closed closedEmbedding_of_continuous_injective_closed -theorem closedEmbedding_id : ClosedEmbedding (@id α) := +theorem _root_.closedEmbedding_id : ClosedEmbedding (@id X) := ⟨embedding_id, IsClosedMap.id.closed_range⟩ #align closed_embedding_id closedEmbedding_id -theorem ClosedEmbedding.comp {g : β → γ} {f : α → β} (hg : ClosedEmbedding g) - (hf : ClosedEmbedding f) : ClosedEmbedding (g ∘ f) := +theorem comp (hg : ClosedEmbedding g) (hf : ClosedEmbedding f) : + ClosedEmbedding (g ∘ f) := ⟨hg.toEmbedding.comp hf.toEmbedding, (hg.isClosedMap.comp hf.isClosedMap).closed_range⟩ #align closed_embedding.comp ClosedEmbedding.comp -theorem ClosedEmbedding.closure_image_eq {f : α → β} (hf : ClosedEmbedding f) (s : Set α) : +theorem closure_image_eq (hf : ClosedEmbedding f) (s : Set X) : closure (f '' s) = f '' closure s := hf.isClosedMap.closure_image_eq_of_continuous hf.continuous s #align closed_embedding.closure_image_eq ClosedEmbedding.closure_image_eq end ClosedEmbedding + +end ClosedEmbedding diff --git a/Mathlib/Topology/MetricSpace/Antilipschitz.lean b/Mathlib/Topology/MetricSpace/Antilipschitz.lean index 21ce3b0c00709..f037df1ab2a24 100644 --- a/Mathlib/Topology/MetricSpace/Antilipschitz.lean +++ b/Mathlib/Topology/MetricSpace/Antilipschitz.lean @@ -3,8 +3,10 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Topology.MetricSpace.Lipschitz import Mathlib.Topology.UniformSpace.CompleteSeparated +import Mathlib.Topology.EMetricSpace.Lipschitz +import Mathlib.Topology.MetricSpace.Basic +import Mathlib.Topology.MetricSpace.Bounded #align_import topology.metric_space.antilipschitz from "leanprover-community/mathlib"@"c8f305514e0d47dfaa710f5a52f0d21b588e6328" diff --git a/Mathlib/Topology/MetricSpace/Baire.lean b/Mathlib/Topology/MetricSpace/Baire.lean index 4df164b42b20e..3dde7607a0491 100644 --- a/Mathlib/Topology/MetricSpace/Baire.lean +++ b/Mathlib/Topology/MetricSpace/Baire.lean @@ -7,7 +7,6 @@ import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.Order.Filter.CountableInter import Mathlib.Topology.GDelta import Mathlib.Topology.Sets.Compacts -import Mathlib.Order.Filter.CountableInter #align_import topology.metric_space.baire from "leanprover-community/mathlib"@"b9e46fe101fc897fb2e7edaf0bf1f09ea49eb81a" @@ -226,7 +225,7 @@ theorem dense_iInter_of_isOpen [Encodable β] {f : β → Set α} (ho : ∀ s, I #align dense_Inter_of_open dense_iInter_of_isOpen /-- A set is residual (comeagre) if and only if it includes a dense `Gδ` set. -/ -theorem mem_residual {s : Set α} : s ∈ residual α ↔ ∃ (t : _) (_ : t ⊆ s), IsGδ t ∧ Dense t := by +theorem mem_residual {s : Set α} : s ∈ residual α ↔ ∃ t ⊆ s, IsGδ t ∧ Dense t := by constructor · rw [mem_residual_iff] rintro ⟨S, hSo, hSd, Sct, Ss⟩ @@ -239,10 +238,8 @@ theorem mem_residual {s : Set α} : s ∈ residual α ↔ ∃ (t : _) (_ : t ⊆ /-- A property holds on a residual (comeagre) set if and only if it holds on some dense `Gδ` set. -/ theorem eventually_residual {p : α → Prop} : (∀ᶠ x in residual α, p x) ↔ ∃ t : Set α, IsGδ t ∧ Dense t ∧ ∀ x : α, x ∈ t → p x := by - -- this can probably be improved... - convert@mem_residual _ _ _ p - simp_rw [exists_prop, @and_comm ((_ : Set α) ⊆ p), and_assoc] - rfl + simp only [Filter.Eventually, mem_residual, subset_def, mem_setOf_eq] + tauto #align eventually_residual eventually_residual theorem dense_of_mem_residual {s : Set α} (hs : s ∈ residual α) : Dense s := diff --git a/Mathlib/Topology/MetricSpace/Basic.lean b/Mathlib/Topology/MetricSpace/Basic.lean index 91f5349d05d4f..4dc7d8e5ad701 100644 --- a/Mathlib/Topology/MetricSpace/Basic.lean +++ b/Mathlib/Topology/MetricSpace/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2015, 2017 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Robert Y. Lewis, Johannes Hölzl, Mario Carneiro, Sébastien Gouëzel -/ -import Mathlib.Topology.MetricSpace.PseudoMetric +import Mathlib.Topology.MetricSpace.ProperSpace #align_import topology.metric_space.basic from "leanprover-community/mathlib"@"c8f305514e0d47dfaa710f5a52f0d21b588e6328" diff --git a/Mathlib/Topology/MetricSpace/Bounded.lean b/Mathlib/Topology/MetricSpace/Bounded.lean index 4497428539aca..270c53fd3260a 100644 --- a/Mathlib/Topology/MetricSpace/Bounded.lean +++ b/Mathlib/Topology/MetricSpace/Bounded.lean @@ -3,7 +3,7 @@ Copyright (c) 2015, 2017 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Robert Y. Lewis, Johannes Hölzl, Mario Carneiro, Sébastien Gouëzel -/ -import Mathlib.Topology.MetricSpace.PseudoMetric +import Mathlib.Topology.MetricSpace.ProperSpace import Mathlib.Topology.MetricSpace.Cauchy /-! @@ -28,7 +28,7 @@ diameter of a subset, and its relation to boundedness metric, pseudo_metric, bounded, diameter, Heine-Borel theorem -/ -open Set Filter Bornology +open Set Filter Bornology open scoped ENNReal Uniformity Topology Pointwise universe u v w diff --git a/Mathlib/Topology/MetricSpace/Cauchy.lean b/Mathlib/Topology/MetricSpace/Cauchy.lean index d1eedad5cd402..463bad9bb79f7 100644 --- a/Mathlib/Topology/MetricSpace/Cauchy.lean +++ b/Mathlib/Topology/MetricSpace/Cauchy.lean @@ -3,7 +3,7 @@ Copyright (c) 2015, 2017 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Robert Y. Lewis, Johannes Hölzl, Mario Carneiro, Sébastien Gouëzel -/ -import Mathlib.Topology.MetricSpace.Basic +import Mathlib.Topology.MetricSpace.PseudoMetric /-! ## Cauchy sequences in (pseudo-)metric spaces diff --git a/Mathlib/Topology/MetricSpace/Completion.lean b/Mathlib/Topology/MetricSpace/Completion.lean index 12e4a37dd028b..7f4e51a3e4583 100644 --- a/Mathlib/Topology/MetricSpace/Completion.lean +++ b/Mathlib/Topology/MetricSpace/Completion.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Topology.UniformSpace.Completion import Mathlib.Topology.MetricSpace.Isometry +import Mathlib.Topology.MetricSpace.Lipschitz import Mathlib.Topology.Instances.Real #align_import topology.metric_space.completion from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Topology/MetricSpace/Contracting.lean b/Mathlib/Topology/MetricSpace/Contracting.lean index 3e50323ef770c..b463a4c580a82 100644 --- a/Mathlib/Topology/MetricSpace/Contracting.lean +++ b/Mathlib/Topology/MetricSpace/Contracting.lean @@ -6,6 +6,7 @@ Authors: Rohan Mitta, Kevin Buzzard, Alistair Tucker, Johannes Hölzl, Yury Kudr import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.Data.Setoid.Basic import Mathlib.Dynamics.FixedPoints.Topology +import Mathlib.Topology.MetricSpace.Lipschitz #align_import topology.metric_space.contracting from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Topology/MetricSpace/Dilation.lean b/Mathlib/Topology/MetricSpace/Dilation.lean index c6efdd98a0c7f..ac384132ec0f7 100644 --- a/Mathlib/Topology/MetricSpace/Dilation.lean +++ b/Mathlib/Topology/MetricSpace/Dilation.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Dilations of emetric and metric spaces Authors: Hanting Zhang -/ +import Mathlib.Topology.MetricSpace.Lipschitz import Mathlib.Topology.MetricSpace.Antilipschitz import Mathlib.Data.FunLike.Basic @@ -71,7 +72,7 @@ infixl:25 " →ᵈ " => Dilation /-- `DilationClass F α β r` states that `F` is a type of `r`-dilations. You should extend this typeclass when you extend `Dilation`. -/ class DilationClass (F : Type*) (α β : outParam <| Type*) [PseudoEMetricSpace α] - [PseudoEMetricSpace β] extends FunLike F α fun _ => β where + [PseudoEMetricSpace β] extends DFunLike F α fun _ => β where edist_eq' : ∀ f : F, ∃ r : ℝ≥0, r ≠ 0 ∧ ∀ x y : α, edist (f x) (f y) = r * edist x y #align dilation_class DilationClass @@ -92,7 +93,7 @@ instance toDilationClass : DilationClass (α →ᵈ β) α β where #align dilation.to_dilation_class Dilation.toDilationClass instance : CoeFun (α →ᵈ β) fun _ => α → β := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[simp] theorem toFun_eq_coe {f : α →ᵈ β} : f.toFun = (f : α → β) := @@ -105,20 +106,20 @@ theorem coe_mk (f : α → β) (h) : ⇑(⟨f, h⟩ : α →ᵈ β) = f := #align dilation.coe_mk Dilation.coe_mk theorem congr_fun {f g : α →ᵈ β} (h : f = g) (x : α) : f x = g x := - FunLike.congr_fun h x + DFunLike.congr_fun h x #align dilation.congr_fun Dilation.congr_fun theorem congr_arg (f : α →ᵈ β) {x y : α} (h : x = y) : f x = f y := - FunLike.congr_arg f h + DFunLike.congr_arg f h #align dilation.congr_arg Dilation.congr_arg @[ext] theorem ext {f g : α →ᵈ β} (h : ∀ x, f x = g x) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align dilation.ext Dilation.ext theorem ext_iff {f g : α →ᵈ β} : f = g ↔ ∀ x, f x = g x := - FunLike.ext_iff + DFunLike.ext_iff #align dilation.ext_iff Dilation.ext_iff @[simp] @@ -135,7 +136,7 @@ protected def copy (f : α →ᵈ β) (f' : α → β) (h : f' = ⇑f) : α → #align dilation.copy Dilation.copy theorem copy_eq_self (f : α →ᵈ β) {f' : α → β} (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align dilation.copy_eq_self Dilation.copy_eq_self /-- The ratio of a dilation `f`. If the ratio is undefined (i.e., the distance between any two diff --git a/Mathlib/Topology/MetricSpace/DilationEquiv.lean b/Mathlib/Topology/MetricSpace/DilationEquiv.lean index b2401d76d0f76..59a5c956f4b20 100644 --- a/Mathlib/Topology/MetricSpace/DilationEquiv.lean +++ b/Mathlib/Topology/MetricSpace/DilationEquiv.lean @@ -33,7 +33,7 @@ class DilationEquivClass extends EquivLike F X Y where edist_eq' : ∀ f : F, ∃ r : ℝ≥0, r ≠ 0 ∧ ∀ x y : X, edist (f x) (f y) = r * edist x y instance (priority := 100) [DilationEquivClass F X Y] : DilationClass F X Y := - { inferInstanceAs (FunLike F X fun _ ↦ Y), ‹DilationEquivClass F X Y› with } + { inferInstanceAs (FunLike F X Y), ‹DilationEquivClass F X Y› with } end Class @@ -55,7 +55,7 @@ instance : DilationEquivClass (X ≃ᵈ Y) X Y where inv f := f.1.symm left_inv f := f.left_inv' right_inv f := f.right_inv' - coe_injective' := by rintro ⟨⟩ ⟨⟩ h -; congr; exact FunLike.ext' h + coe_injective' := by rintro ⟨⟩ ⟨⟩ h -; congr; exact DFunLike.ext' h edist_eq' f := f.edist_eq' instance : CoeFun (X ≃ᵈ Y) fun _ ↦ (X → Y) where @@ -65,7 +65,7 @@ instance : CoeFun (X ≃ᵈ Y) fun _ ↦ (X → Y) where @[ext] protected theorem ext {e e' : X ≃ᵈ Y} (h : ∀ x, e x = e' x) : e = e' := - FunLike.ext _ _ h + DFunLike.ext _ _ h /-- Inverse `DilationEquiv`. -/ def symm (e : X ≃ᵈ Y) : Y ≃ᵈ X where diff --git a/Mathlib/Topology/MetricSpace/Gluing.lean b/Mathlib/Topology/MetricSpace/Gluing.lean index ebdc0ba77d187..49de41f345305 100644 --- a/Mathlib/Topology/MetricSpace/Gluing.lean +++ b/Mathlib/Topology/MetricSpace/Gluing.lean @@ -48,9 +48,6 @@ isometrically and in a way compatible with `f n`. -/ -set_option autoImplicit true - - noncomputable section universe u v w @@ -628,6 +625,7 @@ def InductiveLimit (I : ∀ n, Isometry (f n)) : Type _ := @UniformSpace.SeparationQuotient _ (inductivePremetric I).toUniformSpace #align metric.inductive_limit Metric.InductiveLimit +set_option autoImplicit true in instance : MetricSpace (InductiveLimit (f := f) I) := inferInstanceAs <| MetricSpace <| @UniformSpace.SeparationQuotient _ (inductivePremetric I).toUniformSpace @@ -659,7 +657,7 @@ theorem toInductiveLimit_commute (I : ∀ n, Isometry (f n)) (n : ℕ) : show inductiveLimitDist f ⟨n.succ, f n x⟩ ⟨n, x⟩ = 0 rw [inductiveLimitDist_eq_dist I ⟨n.succ, f n x⟩ ⟨n, x⟩ n.succ, leRecOn_self, leRecOn_succ, leRecOn_self, dist_self] - exacts [le_rfl, le_succ _, le_rfl] + exact le_succ _ #align metric.to_inductive_limit_commute Metric.toInductiveLimit_commute end InductiveLimit diff --git a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean index b9925100f71eb..3e5bee23d381b 100644 --- a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean +++ b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Analysis.Calculus.ContDiff.Basic +import Mathlib.Analysis.Calculus.ContDiff.IsROrC import Mathlib.MeasureTheory.Measure.Hausdorff #align_import topology.metric_space.hausdorff_dimension from "leanprover-community/mathlib"@"8f9fea08977f7e450770933ee6abb20733b47c92" diff --git a/Mathlib/Topology/MetricSpace/HausdorffDistance.lean b/Mathlib/Topology/MetricSpace/HausdorffDistance.lean index 13fdb18b576a5..8c14400addc73 100644 --- a/Mathlib/Topology/MetricSpace/HausdorffDistance.lean +++ b/Mathlib/Topology/MetricSpace/HausdorffDistance.lean @@ -263,14 +263,14 @@ section HausdorffEdist variable [PseudoEMetricSpace α] [PseudoEMetricSpace β] {x y : α} {s t u : Set α} {Φ : α → β} -/-- The Hausdorff edistance of a set to itself vanishes -/ +/-- The Hausdorff edistance of a set to itself vanishes. -/ @[simp] theorem hausdorffEdist_self : hausdorffEdist s s = 0 := by simp only [hausdorffEdist_def, sup_idem, ENNReal.iSup_eq_zero] exact fun x hx => infEdist_zero_of_mem hx #align emetric.Hausdorff_edist_self EMetric.hausdorffEdist_self -/-- The Haudorff edistances of `s` to `t` and of `t` to `s` coincide -/ +/-- The Haudorff edistances of `s` to `t` and of `t` to `s` coincide. -/ theorem hausdorffEdist_comm : hausdorffEdist s t = hausdorffEdist t s := by simp only [hausdorffEdist_def]; apply sup_comm set_option linter.uppercaseLean3 false in @@ -295,7 +295,7 @@ theorem hausdorffEdist_le_of_mem_edist {r : ℝ≥0∞} (H1 : ∀ x ∈ s, ∃ y exact le_trans (infEdist_le_edist_of_mem ys) hy #align emetric.Hausdorff_edist_le_of_mem_edist EMetric.hausdorffEdist_le_of_mem_edist -/-- The distance to a set is controlled by the Hausdorff distance -/ +/-- The distance to a set is controlled by the Hausdorff distance. -/ theorem infEdist_le_hausdorffEdist_of_mem (h : x ∈ s) : infEdist x t ≤ hausdorffEdist s t := by rw [hausdorffEdist_def] refine le_trans ?_ le_sup_left @@ -303,7 +303,7 @@ theorem infEdist_le_hausdorffEdist_of_mem (h : x ∈ s) : infEdist x t ≤ hausd #align emetric.inf_edist_le_Hausdorff_edist_of_mem EMetric.infEdist_le_hausdorffEdist_of_mem /-- If the Hausdorff distance is `< r`, then any point in one of the sets has -a corresponding point at distance `< r` in the other set -/ +a corresponding point at distance `< r` in the other set. -/ theorem exists_edist_lt_of_hausdorffEdist_lt {r : ℝ≥0∞} (h : x ∈ s) (H : hausdorffEdist s t < r) : ∃ y ∈ t, edist x y < r := infEdist_lt_iff.mp <| @@ -313,7 +313,7 @@ theorem exists_edist_lt_of_hausdorffEdist_lt {r : ℝ≥0∞} (h : x ∈ s) (H : #align emetric.exists_edist_lt_of_Hausdorff_edist_lt EMetric.exists_edist_lt_of_hausdorffEdist_lt /-- The distance from `x` to `s` or `t` is controlled in terms of the Hausdorff distance -between `s` and `t` -/ +between `s` and `t`. -/ theorem infEdist_le_infEdist_add_hausdorffEdist : infEdist x t ≤ infEdist x s + hausdorffEdist s t := ENNReal.le_of_forall_pos_le_add fun ε εpos h => by @@ -334,13 +334,13 @@ theorem infEdist_le_infEdist_add_hausdorffEdist : simp [ENNReal.add_halves, add_comm, add_left_comm] #align emetric.inf_edist_le_inf_edist_add_Hausdorff_edist EMetric.infEdist_le_infEdist_add_hausdorffEdist -/-- The Hausdorff edistance is invariant under eisometries -/ +/-- The Hausdorff edistance is invariant under isometries. -/ theorem hausdorffEdist_image (h : Isometry Φ) : hausdorffEdist (Φ '' s) (Φ '' t) = hausdorffEdist s t := by simp only [hausdorffEdist_def, iSup_image, infEdist_image h] #align emetric.Hausdorff_edist_image EMetric.hausdorffEdist_image -/-- The Hausdorff distance is controlled by the diameter of the union -/ +/-- The Hausdorff distance is controlled by the diameter of the union. -/ theorem hausdorffEdist_le_ediam (hs : s.Nonempty) (ht : t.Nonempty) : hausdorffEdist s t ≤ diam (s ∪ t) := by rcases hs with ⟨x, xs⟩ @@ -352,7 +352,7 @@ theorem hausdorffEdist_le_ediam (hs : s.Nonempty) (ht : t.Nonempty) : exact ⟨x, xs, edist_le_diam_of_mem (subset_union_right _ _ hz) (subset_union_left _ _ xs)⟩ #align emetric.Hausdorff_edist_le_ediam EMetric.hausdorffEdist_le_ediam -/-- The Hausdorff distance satisfies the triangular inequality -/ +/-- The Hausdorff distance satisfies the triangle inequality. -/ theorem hausdorffEdist_triangle : hausdorffEdist s u ≤ hausdorffEdist s t + hausdorffEdist t u := by rw [hausdorffEdist_def] simp only [sup_le_iff, iSup_le_iff] @@ -374,14 +374,14 @@ theorem hausdorffEdist_triangle : hausdorffEdist s u ≤ hausdorffEdist s t + ha _ = hausdorffEdist s t + hausdorffEdist t u := by simp [hausdorffEdist_comm, add_comm] #align emetric.Hausdorff_edist_triangle EMetric.hausdorffEdist_triangle -/-- Two sets are at zero Hausdorff edistance if and only if they have the same closure -/ +/-- Two sets are at zero Hausdorff edistance if and only if they have the same closure. -/ theorem hausdorffEdist_zero_iff_closure_eq_closure : hausdorffEdist s t = 0 ↔ closure s = closure t := by simp only [hausdorffEdist_def, ENNReal.sup_eq_zero, ENNReal.iSup_eq_zero, ← subset_def, ← mem_closure_iff_infEdist_zero, subset_antisymm_iff, isClosed_closure.closure_subset_iff] #align emetric.Hausdorff_edist_zero_iff_closure_eq_closure EMetric.hausdorffEdist_zero_iff_closure_eq_closure -/-- The Hausdorff edistance between a set and its closure vanishes -/ +/-- The Hausdorff edistance between a set and its closure vanishes. -/ @[simp] theorem hausdorffEdist_self_closure : hausdorffEdist s (closure s) = 0 := by rw [hausdorffEdist_zero_iff_closure_eq_closure, closure_closure] @@ -405,26 +405,26 @@ theorem hausdorffEdist_closure₂ : hausdorffEdist s (closure t) = hausdorffEdis simp [@hausdorffEdist_comm _ _ s _] #align emetric.Hausdorff_edist_closure₂ EMetric.hausdorffEdist_closure₂ -/-- The Hausdorff edistance between sets or their closures is the same -/ +/-- The Hausdorff edistance between sets or their closures is the same. -/ -- @[simp] -- Porting note: simp can prove this theorem hausdorffEdist_closure : hausdorffEdist (closure s) (closure t) = hausdorffEdist s t := by simp #align emetric.Hausdorff_edist_closure EMetric.hausdorffEdist_closure -/-- Two closed sets are at zero Hausdorff edistance if and only if they coincide -/ +/-- Two closed sets are at zero Hausdorff edistance if and only if they coincide. -/ theorem hausdorffEdist_zero_iff_eq_of_closed (hs : IsClosed s) (ht : IsClosed t) : hausdorffEdist s t = 0 ↔ s = t := by rw [hausdorffEdist_zero_iff_closure_eq_closure, hs.closure_eq, ht.closure_eq] #align emetric.Hausdorff_edist_zero_iff_eq_of_closed EMetric.hausdorffEdist_zero_iff_eq_of_closed -/-- The Haudorff edistance to the empty set is infinite -/ +/-- The Haudorff edistance to the empty set is infinite. -/ theorem hausdorffEdist_empty (ne : s.Nonempty) : hausdorffEdist s ∅ = ∞ := by rcases ne with ⟨x, xs⟩ have : infEdist x ∅ ≤ hausdorffEdist s ∅ := infEdist_le_hausdorffEdist_of_mem xs simpa using this #align emetric.Hausdorff_edist_empty EMetric.hausdorffEdist_empty -/-- If a set is at finite Hausdorff edistance of a nonempty set, it is nonempty -/ +/-- If a set is at finite Hausdorff edistance of a nonempty set, it is nonempty. -/ theorem nonempty_of_hausdorffEdist_ne_top (hs : s.Nonempty) (fin : hausdorffEdist s t ≠ ⊤) : t.Nonempty := t.eq_empty_or_nonempty.resolve_left fun ht ↦ fin (ht.symm ▸ hausdorffEdist_empty hs) @@ -493,35 +493,35 @@ theorem infEdist_ne_top (h : s.Nonempty) : infEdist x s ≠ ⊤ := by theorem infEdist_eq_top_iff : infEdist x s = ∞ ↔ s = ∅ := by rcases s.eq_empty_or_nonempty with rfl | hs <;> simp [*, Nonempty.ne_empty, infEdist_ne_top] -/-- The minimal distance of a point to a set containing it vanishes -/ +/-- The minimal distance of a point to a set containing it vanishes. -/ theorem infDist_zero_of_mem (h : x ∈ s) : infDist x s = 0 := by simp [infEdist_zero_of_mem h, infDist] #align metric.inf_dist_zero_of_mem Metric.infDist_zero_of_mem -/-- The minimal distance to a singleton is the distance to the unique point in this singleton -/ +/-- The minimal distance to a singleton is the distance to the unique point in this singleton. -/ @[simp] theorem infDist_singleton : infDist x {y} = dist x y := by simp [infDist, dist_edist] #align metric.inf_dist_singleton Metric.infDist_singleton -/-- The minimal distance to a set is bounded by the distance to any point in this set -/ +/-- The minimal distance to a set is bounded by the distance to any point in this set. -/ theorem infDist_le_dist_of_mem (h : y ∈ s) : infDist x s ≤ dist x y := by rw [dist_edist, infDist] exact ENNReal.toReal_mono (edist_ne_top _ _) (infEdist_le_edist_of_mem h) #align metric.inf_dist_le_dist_of_mem Metric.infDist_le_dist_of_mem -/-- The minimal distance is monotonous with respect to inclusion -/ +/-- The minimal distance is monotone with respect to inclusion. -/ theorem infDist_le_infDist_of_subset (h : s ⊆ t) (hs : s.Nonempty) : infDist x t ≤ infDist x s := ENNReal.toReal_mono (infEdist_ne_top hs) (infEdist_anti h) #align metric.inf_dist_le_inf_dist_of_subset Metric.infDist_le_infDist_of_subset -/-- The minimal distance to a set is `< r` iff there exists a point in this set at distance `< r` -/ +/-- The minimal distance to a set `s` is `< r` iff there exists a point in `s` at distance `< r`. -/ theorem infDist_lt_iff {r : ℝ} (hs : s.Nonempty) : infDist x s < r ↔ ∃ y ∈ s, dist x y < r := by simp_rw [infDist, ← ENNReal.lt_ofReal_iff_toReal_lt (infEdist_ne_top hs), infEdist_lt_iff, ENNReal.lt_ofReal_iff_toReal_lt (edist_ne_top _ _), ← dist_edist] #align metric.inf_dist_lt_iff Metric.infDist_lt_iff /-- The minimal distance from `x` to `s` is bounded by the distance from `y` to `s`, modulo -the distance between `x` and `y` -/ +the distance between `x` and `y`. -/ theorem infDist_le_infDist_add_dist : infDist x s ≤ infDist y s + dist x y := by rw [infDist, infDist, dist_edist] refine ENNReal.toReal_le_add' infEdist_le_infEdist_add_edist ?_ (flip absurd (edist_ne_top _ _)) @@ -575,7 +575,7 @@ theorem continuous_infDist_pt : Continuous (infDist · s) := variable {s} -/-- The minimal distance to a set and its closure coincide -/ +/-- The minimal distances to a set and its closure coincide. -/ theorem infDist_closure : infDist x (closure s) = infDist x s := by simp [infDist, infEdist_closure] #align metric.inf_dist_eq_closure Metric.infDist_closure @@ -587,7 +587,7 @@ theorem infDist_zero_of_mem_closure (hx : x ∈ closure s) : infDist x s = 0 := exact infDist_zero_of_mem hx #align metric.inf_dist_zero_of_mem_closure Metric.infDist_zero_of_mem_closure -/-- A point belongs to the closure of `s` iff its infimum distance to this set vanishes -/ +/-- A point belongs to the closure of `s` iff its infimum distance to this set vanishes. -/ theorem mem_closure_iff_infDist_zero (h : s.Nonempty) : x ∈ closure s ↔ infDist x s = 0 := by simp [mem_closure_iff_infEdist_zero, infDist, ENNReal.toReal_eq_zero_iff, infEdist_ne_top h] #align metric.mem_closure_iff_inf_dist_zero Metric.mem_closure_iff_infDist_zero @@ -597,7 +597,7 @@ theorem _root_.IsClosed.mem_iff_infDist_zero (h : IsClosed s) (hs : s.Nonempty) x ∈ s ↔ infDist x s = 0 := by rw [← mem_closure_iff_infDist_zero hs, h.closure_eq] #align is_closed.mem_iff_inf_dist_zero IsClosed.mem_iff_infDist_zero -/-- Given a closed set `s`, a point belongs to `s` iff its infimum distance to this set vanishes -/ +/-- Given a closed set `s`, a point belongs to `s` iff its infimum distance to this set vanishes. -/ theorem _root_.IsClosed.not_mem_iff_infDist_pos (h : IsClosed s) (hs : s.Nonempty) : x ∉ s ↔ 0 < infDist x s := by simp [h.mem_iff_infDist_zero hs, infDist_nonneg.gt_iff_ne] @@ -611,7 +611,7 @@ theorem continuousAt_inv_infDist_pt (h : x ∉ closure s) : · refine (continuous_infDist_pt s).continuousAt.inv₀ ?_ rwa [Ne.def, ← mem_closure_iff_infDist_zero hs] -/-- The infimum distance is invariant under isometries -/ +/-- The infimum distance is invariant under isometries. -/ theorem infDist_image (hΦ : Isometry Φ) : infDist (Φ x) (Φ '' t) = infDist x t := by simp [infDist, infEdist_image hΦ] #align metric.inf_dist_image Metric.infDist_image @@ -681,12 +681,12 @@ theorem continuous_infNndist_pt (s : Set α) : Continuous fun x => infNndist x s /-- The Hausdorff distance between two sets is the smallest nonnegative `r` such that each set is included in the `r`-neighborhood of the other. If there is no such `r`, it is defined to -be `0`, arbitrarily -/ +be `0`, arbitrarily. -/ def hausdorffDist (s t : Set α) : ℝ := ENNReal.toReal (hausdorffEdist s t) #align metric.Hausdorff_dist Metric.hausdorffDist -/-- The Hausdorff distance is nonnegative -/ +/-- The Hausdorff distance is nonnegative. -/ theorem hausdorffDist_nonneg : 0 ≤ hausdorffDist s t := by simp [hausdorffDist] #align metric.Hausdorff_dist_nonneg Metric.hausdorffDist_nonneg @@ -713,18 +713,18 @@ theorem hausdorffEdist_ne_top_of_nonempty_of_bounded (hs : s.Nonempty) (ht : t.N exact ne_top_of_le_ne_top ENNReal.ofReal_ne_top this #align metric.Hausdorff_edist_ne_top_of_nonempty_of_bounded Metric.hausdorffEdist_ne_top_of_nonempty_of_bounded -/-- The Hausdorff distance between a set and itself is zero -/ +/-- The Hausdorff distance between a set and itself is zero. -/ @[simp] theorem hausdorffDist_self_zero : hausdorffDist s s = 0 := by simp [hausdorffDist] #align metric.Hausdorff_dist_self_zero Metric.hausdorffDist_self_zero -/-- The Hausdorff distance from `s` to `t` and from `t` to `s` coincide -/ +/-- The Hausdorff distances from `s` to `t` and from `t` to `s` coincide. -/ theorem hausdorffDist_comm : hausdorffDist s t = hausdorffDist t s := by simp [hausdorffDist, hausdorffEdist_comm] #align metric.Hausdorff_dist_comm Metric.hausdorffDist_comm /-- The Hausdorff distance to the empty set vanishes (if you want to have the more reasonable -value ∞ instead, use `EMetric.hausdorffEdist`, which takes values in ℝ≥0∞) -/ +value `∞` instead, use `EMetric.hausdorffEdist`, which takes values in `ℝ≥0∞`). -/ @[simp] theorem hausdorffDist_empty : hausdorffDist s ∅ = 0 := by rcases s.eq_empty_or_nonempty with h | h @@ -733,7 +733,7 @@ theorem hausdorffDist_empty : hausdorffDist s ∅ = 0 := by #align metric.Hausdorff_dist_empty Metric.hausdorffDist_empty /-- The Hausdorff distance to the empty set vanishes (if you want to have the more reasonable -value `∞` instead, use `EMetric.hausdorffEdist`, which takes values in `ℝ≥0∞`) -/ +value `∞` instead, use `EMetric.hausdorffEdist`, which takes values in `ℝ≥0∞`). -/ @[simp] theorem hausdorffDist_empty' : hausdorffDist ∅ s = 0 := by simp [hausdorffDist_comm] #align metric.Hausdorff_dist_empty' Metric.hausdorffDist_empty' @@ -775,7 +775,7 @@ theorem hausdorffDist_le_of_mem_dist {r : ℝ} (hr : 0 ≤ r) (H1 : ∀ x ∈ s, exact le_trans (infDist_le_dist_of_mem ys) hy #align metric.Hausdorff_dist_le_of_mem_dist Metric.hausdorffDist_le_of_mem_dist -/-- The Hausdorff distance is controlled by the diameter of the union -/ +/-- The Hausdorff distance is controlled by the diameter of the union. -/ theorem hausdorffDist_le_diam (hs : s.Nonempty) (bs : IsBounded s) (ht : t.Nonempty) (bt : IsBounded t) : hausdorffDist s t ≤ diam (s ∪ t) := by rcases hs with ⟨x, xs⟩ @@ -787,14 +787,14 @@ theorem hausdorffDist_le_diam (hs : s.Nonempty) (bs : IsBounded s) (ht : t.Nonem (subset_union_left _ _ xs)⟩ #align metric.Hausdorff_dist_le_diam Metric.hausdorffDist_le_diam -/-- The distance to a set is controlled by the Hausdorff distance -/ +/-- The distance to a set is controlled by the Hausdorff distance. -/ theorem infDist_le_hausdorffDist_of_mem (hx : x ∈ s) (fin : hausdorffEdist s t ≠ ⊤) : infDist x t ≤ hausdorffDist s t := toReal_mono fin (infEdist_le_hausdorffEdist_of_mem hx) #align metric.inf_dist_le_Hausdorff_dist_of_mem Metric.infDist_le_hausdorffDist_of_mem -/-- If the Hausdorff distance is `< r`, then any point in one of the sets is at distance -`< r` of a point in the other set -/ +/-- If the Hausdorff distance is `< r`, any point in one of the sets is at distance +`< r` of a point in the other set. -/ theorem exists_dist_lt_of_hausdorffDist_lt {r : ℝ} (h : x ∈ s) (H : hausdorffDist s t < r) (fin : hausdorffEdist s t ≠ ⊤) : ∃ y ∈ t, dist x y < r := by have r0 : 0 < r := lt_of_le_of_lt hausdorffDist_nonneg H @@ -806,8 +806,8 @@ theorem exists_dist_lt_of_hausdorffDist_lt {r : ℝ} (h : x ∈ s) (H : hausdorf exact ⟨y, hy, yr⟩ #align metric.exists_dist_lt_of_Hausdorff_dist_lt Metric.exists_dist_lt_of_hausdorffDist_lt -/-- If the Hausdorff distance is `< r`, then any point in one of the sets is at distance -`< r` of a point in the other set -/ +/-- If the Hausdorff distance is `< r`, any point in one of the sets is at distance +`< r` of a point in the other set. -/ theorem exists_dist_lt_of_hausdorffDist_lt' {r : ℝ} (h : y ∈ t) (H : hausdorffDist s t < r) (fin : hausdorffEdist s t ≠ ⊤) : ∃ x ∈ s, dist x y < r := by rw [hausdorffDist_comm] at H @@ -825,13 +825,13 @@ theorem infDist_le_infDist_add_hausdorffDist (fin : hausdorffEdist s t ≠ ⊤) exact mt (nonempty_of_hausdorffEdist_ne_top · fin) h #align metric.inf_dist_le_inf_dist_add_Hausdorff_dist Metric.infDist_le_infDist_add_hausdorffDist -/-- The Hausdorff distance is invariant under isometries -/ +/-- The Hausdorff distance is invariant under isometries. -/ theorem hausdorffDist_image (h : Isometry Φ) : hausdorffDist (Φ '' s) (Φ '' t) = hausdorffDist s t := by simp [hausdorffDist, hausdorffEdist_image h] #align metric.Hausdorff_dist_image Metric.hausdorffDist_image -/-- The Hausdorff distance satisfies the triangular inequality -/ +/-- The Hausdorff distance satisfies the triangle inequality. -/ theorem hausdorffDist_triangle (fin : hausdorffEdist s t ≠ ⊤) : hausdorffDist s u ≤ hausdorffDist s t + hausdorffDist t u := by refine toReal_le_add' hausdorffEdist_triangle (flip absurd fin) (not_imp_not.1 fun h ↦ ?_) @@ -839,7 +839,7 @@ theorem hausdorffDist_triangle (fin : hausdorffEdist s t ≠ ⊤) : exact ne_top_of_le_ne_top (add_ne_top.2 ⟨fin, h⟩) hausdorffEdist_triangle #align metric.Hausdorff_dist_triangle Metric.hausdorffDist_triangle -/-- The Hausdorff distance satisfies the triangular inequality -/ +/-- The Hausdorff distance satisfies the triangle inequality. -/ theorem hausdorffDist_triangle' (fin : hausdorffEdist t u ≠ ⊤) : hausdorffDist s u ≤ hausdorffDist s t + hausdorffDist t u := by rw [hausdorffEdist_comm] at fin @@ -848,7 +848,7 @@ theorem hausdorffDist_triangle' (fin : hausdorffEdist t u ≠ ⊤) : simpa [add_comm, hausdorffDist_comm] using I #align metric.Hausdorff_dist_triangle' Metric.hausdorffDist_triangle' -/-- The Hausdorff distance between a set and its closure vanish -/ +/-- The Hausdorff distance between a set and its closure vanishes. -/ @[simp] theorem hausdorffDist_self_closure : hausdorffDist s (closure s) = 0 := by simp [hausdorffDist] #align metric.Hausdorff_dist_self_closure Metric.hausdorffDist_self_closure @@ -865,20 +865,20 @@ theorem hausdorffDist_closure₂ : hausdorffDist s (closure t) = hausdorffDist s simp [hausdorffDist] #align metric.Hausdorff_dist_closure₂ Metric.hausdorffDist_closure₂ -/-- The Hausdorff distance between two sets and their closures coincide -/ +/-- The Hausdorff distances between two sets and their closures coincide. -/ -- @[simp] -- Porting note: simp can prove this theorem hausdorffDist_closure : hausdorffDist (closure s) (closure t) = hausdorffDist s t := by simp [hausdorffDist] #align metric.Hausdorff_dist_closure Metric.hausdorffDist_closure -/-- Two sets are at zero Hausdorff distance if and only if they have the same closures -/ +/-- Two sets are at zero Hausdorff distance if and only if they have the same closures. -/ theorem hausdorffDist_zero_iff_closure_eq_closure (fin : hausdorffEdist s t ≠ ⊤) : hausdorffDist s t = 0 ↔ closure s = closure t := by simp [← hausdorffEdist_zero_iff_closure_eq_closure, hausdorffDist, ENNReal.toReal_eq_zero_iff, fin] #align metric.Hausdorff_dist_zero_iff_closure_eq_closure Metric.hausdorffDist_zero_iff_closure_eq_closure -/-- Two closed sets are at zero Hausdorff distance if and only if they coincide -/ +/-- Two closed sets are at zero Hausdorff distance if and only if they coincide. -/ theorem _root_.IsClosed.hausdorffDist_zero_iff_eq (hs : IsClosed s) (ht : IsClosed t) (fin : hausdorffEdist s t ≠ ⊤) : hausdorffDist s t = 0 ↔ s = t := by simp [← hausdorffEdist_zero_iff_eq_of_closed hs ht, hausdorffDist, ENNReal.toReal_eq_zero_iff, diff --git a/Mathlib/Topology/MetricSpace/IsometricSMul.lean b/Mathlib/Topology/MetricSpace/IsometricSMul.lean index 6051a91aa17dc..ae59b018e4413 100644 --- a/Mathlib/Topology/MetricSpace/IsometricSMul.lean +++ b/Mathlib/Topology/MetricSpace/IsometricSMul.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Topology.MetricSpace.Isometry +import Mathlib.Topology.MetricSpace.Lipschitz #align_import topology.metric_space.isometric_smul from "leanprover-community/mathlib"@"bc91ed7093bf098d253401e69df601fc33dde156" diff --git a/Mathlib/Topology/MetricSpace/Isometry.lean b/Mathlib/Topology/MetricSpace/Isometry.lean index bf96d3fb0d64b..af6c3bd297c9c 100644 --- a/Mathlib/Topology/MetricSpace/Isometry.lean +++ b/Mathlib/Topology/MetricSpace/Isometry.lean @@ -317,7 +317,7 @@ instance : EquivLike (α ≃ᵢ β) α β where inv e := e.toEquiv.symm left_inv e := e.left_inv right_inv e := e.right_inv - coe_injective' _ _ h _ := toEquiv_injective <| FunLike.ext' h + coe_injective' _ _ h _ := toEquiv_injective <| DFunLike.ext' h theorem coe_eq_toEquiv (h : α ≃ᵢ β) (a : α) : h a = h.toEquiv a := rfl #align isometry_equiv.coe_eq_to_equiv IsometryEquiv.coe_eq_toEquiv @@ -368,7 +368,7 @@ theorem ediam_image (h : α ≃ᵢ β) (s : Set α) : EMetric.diam (h '' s) = EM @[ext] theorem ext ⦃h₁ h₂ : α ≃ᵢ β⦄ (H : ∀ x, h₁ x = h₂ x) : h₁ = h₂ := - FunLike.ext _ _ H + DFunLike.ext _ _ H #align isometry_equiv.ext IsometryEquiv.ext /-- Alternative constructor for isometric bijections, diff --git a/Mathlib/Topology/MetricSpace/Kuratowski.lean b/Mathlib/Topology/MetricSpace/Kuratowski.lean index 26abf589eb0a9..4fe66766abe17 100644 --- a/Mathlib/Topology/MetricSpace/Kuratowski.lean +++ b/Mathlib/Topology/MetricSpace/Kuratowski.lean @@ -16,9 +16,6 @@ Any partially defined Lipschitz map into `ℓ^∞` can be extended to the whole -/ -set_option autoImplicit true - - noncomputable section set_option linter.uppercaseLean3 false @@ -140,19 +137,19 @@ Theorem 2.2 of [Assaf Naor, *Metric Embeddings and Lipschitz Extensions*][Naor-2 The same result for the case of a finite type `ι` is implemented in `LipschitzOnWith.extend_pi`. -/ -theorem LipschitzOnWith.extend_lp_infty [PseudoMetricSpace α] {s : Set α} {f : α → ℓ^∞(ι)} - {K : ℝ≥0} (hfl : LipschitzOnWith K f s): ∃ g : α → ℓ^∞(ι), LipschitzWith K g ∧ EqOn f g s := by +theorem LipschitzOnWith.extend_lp_infty [PseudoMetricSpace α] {s : Set α} {ι : Type*} + {f : α → ℓ^∞(ι)} {K : ℝ≥0} (hfl : LipschitzOnWith K f s) : + ∃ g : α → ℓ^∞(ι), LipschitzWith K g ∧ EqOn f g s := by -- Construct the coordinate-wise extensions rw [LipschitzOnWith.coordinate] at hfl - have : ∀ i : ι, ∃ g : α → ℝ, LipschitzWith K g ∧ EqOn (fun x => f x i) g s - · intro i - exact LipschitzOnWith.extend_real (hfl i) -- use the nonlinear Hahn-Banach theorem here! + have (i: ι) : ∃ g : α → ℝ, LipschitzWith K g ∧ EqOn (fun x => f x i) g s := + LipschitzOnWith.extend_real (hfl i) -- use the nonlinear Hahn-Banach theorem here! choose g hgl hgeq using this rcases s.eq_empty_or_nonempty with rfl | ⟨a₀, ha₀_in_s⟩ · exact ⟨0, LipschitzWith.const' 0, by simp⟩ · -- Show that the extensions are uniformly bounded - have hf_extb : ∀ a : α, Memℓp (swap g a) ∞ - · apply LipschitzWith.uniformly_bounded (swap g) hgl a₀ + have hf_extb : ∀ a : α, Memℓp (swap g a) ∞ := by + apply LipschitzWith.uniformly_bounded (swap g) hgl a₀ use ‖f a₀‖ rintro - ⟨i, rfl⟩ simp_rw [← hgeq i ha₀_in_s] diff --git a/Mathlib/Topology/MetricSpace/Lipschitz.lean b/Mathlib/Topology/MetricSpace/Lipschitz.lean index ca99ee300e274..91c9ce2282419 100644 --- a/Mathlib/Topology/MetricSpace/Lipschitz.lean +++ b/Mathlib/Topology/MetricSpace/Lipschitz.lean @@ -32,8 +32,6 @@ coercions both to `ℝ` and `ℝ≥0∞`. Constructors whose names end with `'` argument, and return `LipschitzWith (Real.toNNReal K) f`. -/ -set_option autoImplicit true - universe u v w x open Filter Function Set Topology NNReal ENNReal Bornology diff --git a/Mathlib/Topology/MetricSpace/PartitionOfUnity.lean b/Mathlib/Topology/MetricSpace/PartitionOfUnity.lean index d982a2b76207a..6e6455ce7afb3 100644 --- a/Mathlib/Topology/MetricSpace/PartitionOfUnity.lean +++ b/Mathlib/Topology/MetricSpace/PartitionOfUnity.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Topology.EMetricSpace.Paracompact +import Mathlib.Topology.Instances.ENNReal import Mathlib.Analysis.Convex.PartitionOfUnity #align_import topology.metric_space.partition_of_unity from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Topology/MetricSpace/Polish.lean b/Mathlib/Topology/MetricSpace/Polish.lean index a4df6bfea158c..232d2b160fe09 100644 --- a/Mathlib/Topology/MetricSpace/Polish.lean +++ b/Mathlib/Topology/MetricSpace/Polish.lean @@ -406,8 +406,7 @@ theorem _root_.IsClosed.isClopenable [TopologicalSpace α] [PolishSpace α] {s : · rw [← f.induced_symm] exact f.symm.polishSpace_induced · rw [isOpen_coinduced, isOpen_sum_iff] - convert And.intro (isOpen_univ (α := s)) (isOpen_empty (α := (sᶜ : Set α))) - <;> ext ⟨x, hx⟩ <;> simpa using hx + simp [preimage_preimage] #align is_closed.is_clopenable IsClosed.isClopenable theorem IsClopenable.compl [TopologicalSpace α] {s : Set α} (hs : IsClopenable s) : diff --git a/Mathlib/Topology/MetricSpace/ProperSpace.lean b/Mathlib/Topology/MetricSpace/ProperSpace.lean new file mode 100644 index 0000000000000..7136ec2d231e6 --- /dev/null +++ b/Mathlib/Topology/MetricSpace/ProperSpace.lean @@ -0,0 +1,153 @@ +/- +Copyright (c) 2018 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 Mathlib.Topology.MetricSpace.PseudoMetric + +/-! ## Proper spaces + +## Main definitions and results +* `ProperSpace α`: a `PseudoMetricSpace` where all closed balls are compact + +* `isCompact_sphere`: any sphere in a proper space is compact. +* `proper_of_compact`: compact spaces are proper. +* `secondCountable_of_proper`: proper spaces are sigma-compact, hence second countable. +* `locally_compact_of_proper`: proper spaces are locally compact. +* `pi_properSpace`: finite products of proper spaces are proper. + +-/ + +open Set Filter + +universe u v w + +variable {α : Type u} {β : Type v} {X ι : Type*} + +section ProperSpace + +open Metric + +/-- A pseudometric space is proper if all closed balls are compact. -/ +class ProperSpace (α : Type u) [PseudoMetricSpace α] : Prop where + isCompact_closedBall : ∀ x : α, ∀ r, IsCompact (closedBall x r) +#align proper_space ProperSpace + +export ProperSpace (isCompact_closedBall) + +/-- In a proper pseudometric space, all spheres are compact. -/ +theorem isCompact_sphere {α : Type*} [PseudoMetricSpace α] [ProperSpace α] (x : α) (r : ℝ) : + IsCompact (sphere x r) := + (isCompact_closedBall x r).of_isClosed_subset isClosed_sphere sphere_subset_closedBall +#align is_compact_sphere isCompact_sphere + +/-- In a proper pseudometric space, any sphere is a `CompactSpace` when considered as a subtype. -/ +instance Metric.sphere.compactSpace {α : Type*} [PseudoMetricSpace α] [ProperSpace α] + (x : α) (r : ℝ) : CompactSpace (sphere x r) := + isCompact_iff_compactSpace.mp (isCompact_sphere _ _) + +variable [PseudoMetricSpace α] + +-- see Note [lower instance priority] +/-- A proper pseudo metric space is sigma compact, and therefore second countable. -/ +instance (priority := 100) secondCountable_of_proper [ProperSpace α] : + SecondCountableTopology α := by + -- We already have `sigmaCompactSpace_of_locallyCompact_secondCountable`, so we don't + -- add an instance for `SigmaCompactSpace`. + suffices SigmaCompactSpace α from EMetric.secondCountable_of_sigmaCompact α + rcases em (Nonempty α) with (⟨⟨x⟩⟩ | hn) + · exact ⟨⟨fun n => closedBall x n, fun n => isCompact_closedBall _ _, iUnion_closedBall_nat _⟩⟩ + · exact ⟨⟨fun _ => ∅, fun _ => isCompact_empty, iUnion_eq_univ_iff.2 fun x => (hn ⟨x⟩).elim⟩⟩ +#align second_countable_of_proper secondCountable_of_proper + +/-- If all closed balls of large enough radius are compact, then the space is proper. Especially +useful when the lower bound for the radius is 0. -/ +theorem properSpace_of_compact_closedBall_of_le (R : ℝ) + (h : ∀ x : α, ∀ r, R ≤ r → IsCompact (closedBall x r)) : ProperSpace α := + ⟨fun x r => IsCompact.of_isClosed_subset (h x (max r R) (le_max_right _ _)) isClosed_ball + (closedBall_subset_closedBall <| le_max_left _ _)⟩ +#align proper_space_of_compact_closed_ball_of_le properSpace_of_compact_closedBall_of_le + +-- A compact pseudometric space is proper +-- see Note [lower instance priority] +instance (priority := 100) proper_of_compact [CompactSpace α] : ProperSpace α := + ⟨fun _ _ => isClosed_ball.isCompact⟩ +#align proper_of_compact proper_of_compact + +-- see Note [lower instance priority] +/-- A proper space is locally compact -/ +instance (priority := 100) locally_compact_of_proper [ProperSpace α] : LocallyCompactSpace α := + .of_hasBasis (fun _ => nhds_basis_closedBall) fun _ _ _ => + isCompact_closedBall _ _ +#align locally_compact_of_proper locally_compact_of_proper + +-- see Note [lower instance priority] +/-- A proper space is complete -/ +instance (priority := 100) complete_of_proper [ProperSpace α] : CompleteSpace α := + ⟨fun {f} hf => by + /- We want to show that the Cauchy filter `f` is converging. It suffices to find a closed + ball (therefore compact by properness) where it is nontrivial. -/ + obtain ⟨t, t_fset, ht⟩ : ∃ t ∈ f, ∀ x ∈ t, ∀ y ∈ t, dist x y < 1 := + (Metric.cauchy_iff.1 hf).2 1 zero_lt_one + rcases hf.1.nonempty_of_mem t_fset with ⟨x, xt⟩ + have : closedBall x 1 ∈ f := mem_of_superset t_fset fun y yt => (ht y yt x xt).le + rcases (isCompact_iff_totallyBounded_isComplete.1 (isCompact_closedBall x 1)).2 f hf + (le_principal_iff.2 this) with + ⟨y, -, hy⟩ + exact ⟨y, hy⟩⟩ +#align complete_of_proper complete_of_proper + +/-- A binary product of proper spaces is proper. -/ +instance prod_properSpace {α : Type*} {β : Type*} [PseudoMetricSpace α] [PseudoMetricSpace β] + [ProperSpace α] [ProperSpace β] : ProperSpace (α × β) where + isCompact_closedBall := by + rintro ⟨x, y⟩ r + rw [← closedBall_prod_same x y] + exact (isCompact_closedBall x r).prod (isCompact_closedBall y r) +#align prod_proper_space prod_properSpace + +/-- A finite product of proper spaces is proper. -/ +instance pi_properSpace {π : β → Type*} [Fintype β] [∀ b, PseudoMetricSpace (π b)] + [h : ∀ b, ProperSpace (π b)] : ProperSpace (∀ b, π b) := by + refine' properSpace_of_compact_closedBall_of_le 0 fun x r hr => _ + rw [closedBall_pi _ hr] + exact isCompact_univ_pi fun _ => isCompact_closedBall _ _ +#align pi_proper_space pi_properSpace + +variable [ProperSpace α] {x : α} {r : ℝ} {s : Set α} + +/-- If a nonempty ball in a proper space includes a closed set `s`, then there exists a nonempty +ball with the same center and a strictly smaller radius that includes `s`. -/ +theorem exists_pos_lt_subset_ball (hr : 0 < r) (hs : IsClosed s) (h : s ⊆ ball x r) : + ∃ r' ∈ Ioo 0 r, s ⊆ ball x r' := by + rcases eq_empty_or_nonempty s with (rfl | hne) + · exact ⟨r / 2, ⟨half_pos hr, half_lt_self hr⟩, empty_subset _⟩ + have : IsCompact s := + (isCompact_closedBall x r).of_isClosed_subset hs (h.trans ball_subset_closedBall) + obtain ⟨y, hys, hy⟩ : ∃ y ∈ s, s ⊆ closedBall x (dist y x) := + this.exists_forall_ge hne (continuous_id.dist continuous_const).continuousOn + have hyr : dist y x < r := h hys + rcases exists_between hyr with ⟨r', hyr', hrr'⟩ + exact ⟨r', ⟨dist_nonneg.trans_lt hyr', hrr'⟩, hy.trans <| closedBall_subset_ball hyr'⟩ +#align exists_pos_lt_subset_ball exists_pos_lt_subset_ball + +/-- If a ball in a proper space includes a closed set `s`, then there exists a ball with the same +center and a strictly smaller radius that includes `s`. -/ +theorem exists_lt_subset_ball (hs : IsClosed s) (h : s ⊆ ball x r) : ∃ r' < r, s ⊆ ball x r' := by + rcases le_or_lt r 0 with hr | hr + · rw [ball_eq_empty.2 hr, subset_empty_iff] at h + subst s + exact (exists_lt r).imp fun r' hr' => ⟨hr', empty_subset _⟩ + · exact (exists_pos_lt_subset_ball hr hs h).imp fun r' hr' => ⟨hr'.1.2, hr'.2⟩ +#align exists_lt_subset_ball exists_lt_subset_ball + +end ProperSpace + +theorem Metric.exists_isLocalMin_mem_ball [PseudoMetricSpace α] [ProperSpace α] [TopologicalSpace β] + [ConditionallyCompleteLinearOrder β] [OrderTopology β] {f : α → β} {a z : α} {r : ℝ} + (hf : ContinuousOn f (closedBall a r)) (hz : z ∈ closedBall a r) + (hf1 : ∀ z' ∈ sphere a r, f z < f z') : ∃ z ∈ ball a r, IsLocalMin f z := by + simp_rw [← closedBall_diff_ball] at hf1 + exact (isCompact_closedBall a r).exists_isLocalMin_mem_open ball_subset_closedBall hf hz hf1 + isOpen_ball +#align metric.exists_local_min_mem_ball Metric.exists_isLocalMin_mem_ball diff --git a/Mathlib/Topology/MetricSpace/PseudoMetric.lean b/Mathlib/Topology/MetricSpace/PseudoMetric.lean index ac9ed4e043fd0..2bedb18114b67 100644 --- a/Mathlib/Topology/MetricSpace/PseudoMetric.lean +++ b/Mathlib/Topology/MetricSpace/PseudoMetric.lean @@ -3,10 +3,10 @@ Copyright (c) 2015, 2017 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Robert Y. Lewis, Johannes Hölzl, Mario Carneiro, Sébastien Gouëzel -/ -import Mathlib.Tactic.Positivity import Mathlib.Topology.Algebra.Order.Compact import Mathlib.Topology.EMetricSpace.Basic import Mathlib.Topology.Bornology.Constructions +import Mathlib.Data.Set.Pointwise.Interval /-! ## Pseudo-metric spaces @@ -31,7 +31,6 @@ Additional useful definitions: * `nndist a b`: `dist` as a function to the non-negative reals. * `Metric.closedBall x ε`: The set of all points `y` with `dist y x ≤ ε`. * `Metric.sphere x ε`: The set of all points `y` with `dist y x = ε`. -* `ProperSpace α`: A `PseudoMetricSpace` where all closed balls are compact. TODO (anyone): Add "Main results" section. @@ -1864,6 +1863,12 @@ theorem _root_.ContinuousOn.isSeparable_image [TopologicalSpace β] {f : α → end Metric +/-- A compact set is separable. -/ +theorem IsCompact.isSeparable {s : Set α} (hs : IsCompact s) : IsSeparable s := + haveI : CompactSpace s := isCompact_iff_compactSpace.mp hs + isSeparable_of_separableSpace_subtype s +#align is_compact.is_separable IsCompact.isSeparable + section Pi open Finset @@ -2058,128 +2063,6 @@ alias IsCompact.finite_cover_balls := finite_cover_balls_of_compact end Compact -section ProperSpace - -open Metric - -/-- A pseudometric space is proper if all closed balls are compact. -/ -class ProperSpace (α : Type u) [PseudoMetricSpace α] : Prop where - isCompact_closedBall : ∀ x : α, ∀ r, IsCompact (closedBall x r) -#align proper_space ProperSpace - -export ProperSpace (isCompact_closedBall) - -/-- In a proper pseudometric space, all spheres are compact. -/ -theorem isCompact_sphere {α : Type*} [PseudoMetricSpace α] [ProperSpace α] (x : α) (r : ℝ) : - IsCompact (sphere x r) := - (isCompact_closedBall x r).of_isClosed_subset isClosed_sphere sphere_subset_closedBall -#align is_compact_sphere isCompact_sphere - -/-- In a proper pseudometric space, any sphere is a `CompactSpace` when considered as a subtype. -/ -instance Metric.sphere.compactSpace {α : Type*} [PseudoMetricSpace α] [ProperSpace α] - (x : α) (r : ℝ) : CompactSpace (sphere x r) := - isCompact_iff_compactSpace.mp (isCompact_sphere _ _) - --- see Note [lower instance priority] -/-- A proper pseudo metric space is sigma compact, and therefore second countable. -/ -instance (priority := 100) secondCountable_of_proper [ProperSpace α] : - SecondCountableTopology α := by - -- We already have `sigmaCompactSpace_of_locallyCompact_secondCountable`, so we don't - -- add an instance for `SigmaCompactSpace`. - suffices SigmaCompactSpace α from EMetric.secondCountable_of_sigmaCompact α - rcases em (Nonempty α) with (⟨⟨x⟩⟩ | hn) - · exact ⟨⟨fun n => closedBall x n, fun n => isCompact_closedBall _ _, iUnion_closedBall_nat _⟩⟩ - · exact ⟨⟨fun _ => ∅, fun _ => isCompact_empty, iUnion_eq_univ_iff.2 fun x => (hn ⟨x⟩).elim⟩⟩ -#align second_countable_of_proper secondCountable_of_proper - -/-- If all closed balls of large enough radius are compact, then the space is proper. Especially -useful when the lower bound for the radius is 0. -/ -theorem properSpace_of_compact_closedBall_of_le (R : ℝ) - (h : ∀ x : α, ∀ r, R ≤ r → IsCompact (closedBall x r)) : ProperSpace α := - ⟨fun x r => IsCompact.of_isClosed_subset (h x (max r R) (le_max_right _ _)) isClosed_ball - (closedBall_subset_closedBall <| le_max_left _ _)⟩ -#align proper_space_of_compact_closed_ball_of_le properSpace_of_compact_closedBall_of_le - --- A compact pseudometric space is proper --- see Note [lower instance priority] -instance (priority := 100) proper_of_compact [CompactSpace α] : ProperSpace α := - ⟨fun _ _ => isClosed_ball.isCompact⟩ -#align proper_of_compact proper_of_compact - --- see Note [lower instance priority] -/-- A proper space is locally compact -/ -instance (priority := 100) locally_compact_of_proper [ProperSpace α] : LocallyCompactSpace α := - locallyCompactSpace_of_hasBasis (fun _ => nhds_basis_closedBall) fun _ _ _ => - isCompact_closedBall _ _ -#align locally_compact_of_proper locally_compact_of_proper - --- see Note [lower instance priority] -/-- A proper space is complete -/ -instance (priority := 100) complete_of_proper [ProperSpace α] : CompleteSpace α := - ⟨fun {f} hf => by - /- We want to show that the Cauchy filter `f` is converging. It suffices to find a closed - ball (therefore compact by properness) where it is nontrivial. -/ - obtain ⟨t, t_fset, ht⟩ : ∃ t ∈ f, ∀ x ∈ t, ∀ y ∈ t, dist x y < 1 := - (Metric.cauchy_iff.1 hf).2 1 zero_lt_one - rcases hf.1.nonempty_of_mem t_fset with ⟨x, xt⟩ - have : closedBall x 1 ∈ f := mem_of_superset t_fset fun y yt => (ht y yt x xt).le - rcases (isCompact_iff_totallyBounded_isComplete.1 (isCompact_closedBall x 1)).2 f hf - (le_principal_iff.2 this) with - ⟨y, -, hy⟩ - exact ⟨y, hy⟩⟩ -#align complete_of_proper complete_of_proper - -/-- A binary product of proper spaces is proper. -/ -instance prod_properSpace {α : Type*} {β : Type*} [PseudoMetricSpace α] [PseudoMetricSpace β] - [ProperSpace α] [ProperSpace β] : ProperSpace (α × β) where - isCompact_closedBall := by - rintro ⟨x, y⟩ r - rw [← closedBall_prod_same x y] - exact (isCompact_closedBall x r).prod (isCompact_closedBall y r) -#align prod_proper_space prod_properSpace - -/-- A finite product of proper spaces is proper. -/ -instance pi_properSpace {π : β → Type*} [Fintype β] [∀ b, PseudoMetricSpace (π b)] - [h : ∀ b, ProperSpace (π b)] : ProperSpace (∀ b, π b) := by - refine' properSpace_of_compact_closedBall_of_le 0 fun x r hr => _ - rw [closedBall_pi _ hr] - exact isCompact_univ_pi fun _ => isCompact_closedBall _ _ -#align pi_proper_space pi_properSpace - -variable [ProperSpace α] {x : α} {r : ℝ} {s : Set α} - -/-- If a nonempty ball in a proper space includes a closed set `s`, then there exists a nonempty -ball with the same center and a strictly smaller radius that includes `s`. -/ -theorem exists_pos_lt_subset_ball (hr : 0 < r) (hs : IsClosed s) (h : s ⊆ ball x r) : - ∃ r' ∈ Ioo 0 r, s ⊆ ball x r' := by - rcases eq_empty_or_nonempty s with (rfl | hne) - · exact ⟨r / 2, ⟨half_pos hr, half_lt_self hr⟩, empty_subset _⟩ - have : IsCompact s := - (isCompact_closedBall x r).of_isClosed_subset hs (h.trans ball_subset_closedBall) - obtain ⟨y, hys, hy⟩ : ∃ y ∈ s, s ⊆ closedBall x (dist y x) := - this.exists_forall_ge hne (continuous_id.dist continuous_const).continuousOn - have hyr : dist y x < r := h hys - rcases exists_between hyr with ⟨r', hyr', hrr'⟩ - exact ⟨r', ⟨dist_nonneg.trans_lt hyr', hrr'⟩, hy.trans <| closedBall_subset_ball hyr'⟩ -#align exists_pos_lt_subset_ball exists_pos_lt_subset_ball - -/-- If a ball in a proper space includes a closed set `s`, then there exists a ball with the same -center and a strictly smaller radius that includes `s`. -/ -theorem exists_lt_subset_ball (hs : IsClosed s) (h : s ⊆ ball x r) : ∃ r' < r, s ⊆ ball x r' := by - rcases le_or_lt r 0 with hr | hr - · rw [ball_eq_empty.2 hr, subset_empty_iff] at h - subst s - exact (exists_lt r).imp fun r' hr' => ⟨hr', empty_subset _⟩ - · exact (exists_pos_lt_subset_ball hr hs h).imp fun r' hr' => ⟨hr'.1.2, hr'.2⟩ -#align exists_lt_subset_ball exists_lt_subset_ball - -end ProperSpace - -theorem IsCompact.isSeparable {s : Set α} (hs : IsCompact s) : IsSeparable s := - haveI : CompactSpace s := isCompact_iff_compactSpace.mp hs - isSeparable_of_separableSpace_subtype s -#align is_compact.is_separable IsCompact.isSeparable - namespace Metric section SecondCountable @@ -2213,15 +2096,3 @@ theorem lebesgue_number_lemma_of_metric_sUnion {s : Set α} {c : Set (Set α)} ( (hc₁ : ∀ t ∈ c, IsOpen t) (hc₂ : s ⊆ ⋃₀ c) : ∃ δ > 0, ∀ x ∈ s, ∃ t ∈ c, ball x δ ⊆ t := by rw [sUnion_eq_iUnion] at hc₂; simpa using lebesgue_number_lemma_of_metric hs (by simpa) hc₂ #align lebesgue_number_lemma_of_metric_sUnion lebesgue_number_lemma_of_metric_sUnion - -namespace Metric -theorem exists_isLocalMin_mem_ball [ProperSpace α] [TopologicalSpace β] - [ConditionallyCompleteLinearOrder β] [OrderTopology β] {f : α → β} {a z : α} {r : ℝ} - (hf : ContinuousOn f (closedBall a r)) (hz : z ∈ closedBall a r) - (hf1 : ∀ z' ∈ sphere a r, f z < f z') : ∃ z ∈ ball a r, IsLocalMin f z := by - simp_rw [← closedBall_diff_ball] at hf1 - exact (isCompact_closedBall a r).exists_isLocalMin_mem_open ball_subset_closedBall hf hz hf1 - isOpen_ball -#align metric.exists_local_min_mem_ball Metric.exists_isLocalMin_mem_ball - -end Metric diff --git a/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean b/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean index 49193fec78031..b0aefb090041f 100644 --- a/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean +++ b/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean @@ -3,10 +3,9 @@ Copyright (c) 2022 Kalle Kytölä. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kalle Kytölä -/ -import Mathlib.Data.Real.ENNReal +import Mathlib.Data.ENNReal.Basic import Mathlib.Topology.ContinuousFunction.Bounded import Mathlib.Topology.MetricSpace.HausdorffDistance -import Mathlib.Order.Filter.IndicatorFunction #align_import topology.metric_space.thickened_indicator from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Topology/NhdsSet.lean b/Mathlib/Topology/NhdsSet.lean index 919f394686387..a618c15a2968a 100644 --- a/Mathlib/Topology/NhdsSet.lean +++ b/Mathlib/Topology/NhdsSet.lean @@ -17,8 +17,8 @@ In this file we define the filter `𝓝ˢ s` or `nhdsSet s` consisting of all ne There are a couple different notions equivalent to `s ∈ 𝓝ˢ t`: * `s ⊆ interior t` using `subset_interior_iff_mem_nhdsSet` -* `∀ x : α, x ∈ t → s ∈ 𝓝 x` using `mem_nhdsSet_iff_forall` -* `∃ U : Set α, IsOpen U ∧ t ⊆ U ∧ U ⊆ s` using `mem_nhdsSet_iff_exists` +* `∀ x : X, x ∈ t → s ∈ 𝓝 x` using `mem_nhdsSet_iff_forall` +* `∃ U : Set X, IsOpen U ∧ t ⊆ U ∧ U ⊆ s` using `mem_nhdsSet_iff_exists` Furthermore, we have the following results: * `monotone_nhdsSet`: `𝓝ˢ` is monotone @@ -29,29 +29,29 @@ Furthermore, we have the following results: open Set Filter Topology -variable {α β : Type*} [TopologicalSpace α] [TopologicalSpace β] {f : Filter α} - {s t s₁ s₂ t₁ t₂ : Set α} {x : α} +variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] {f : Filter X} + {s t s₁ s₂ t₁ t₂ : Set X} {x : X} /-- The filter of neighborhoods of a set in a topological space. -/ -def nhdsSet (s : Set α) : Filter α := +def nhdsSet (s : Set X) : Filter X := sSup (nhds '' s) #align nhds_set nhdsSet @[inherit_doc] scoped[Topology] notation "𝓝ˢ" => nhdsSet -theorem nhdsSet_diagonal (α) [TopologicalSpace (α × α)] : - 𝓝ˢ (diagonal α) = ⨆ (x : α), 𝓝 (x, x) := by +theorem nhdsSet_diagonal (X) [TopologicalSpace (X × X)] : + 𝓝ˢ (diagonal X) = ⨆ (x : X), 𝓝 (x, x) := by rw [nhdsSet, ← range_diag, ← range_comp] rfl #align nhds_set_diagonal nhdsSet_diagonal -theorem mem_nhdsSet_iff_forall : s ∈ 𝓝ˢ t ↔ ∀ x : α, x ∈ t → s ∈ 𝓝 x := by +theorem mem_nhdsSet_iff_forall : s ∈ 𝓝ˢ t ↔ ∀ x : X, x ∈ t → s ∈ 𝓝 x := by simp_rw [nhdsSet, Filter.mem_sSup, ball_image_iff] #align mem_nhds_set_iff_forall mem_nhdsSet_iff_forall -lemma nhdsSet_le : 𝓝ˢ s ≤ f ↔ ∀ a ∈ s, 𝓝 a ≤ f := by simp [nhdsSet] +lemma nhdsSet_le : 𝓝ˢ s ≤ f ↔ ∀ x ∈ s, 𝓝 x ≤ f := by simp [nhdsSet] -theorem bUnion_mem_nhdsSet {t : α → Set α} (h : ∀ x ∈ s, t x ∈ 𝓝 x) : (⋃ x ∈ s, t x) ∈ 𝓝ˢ s := +theorem bUnion_mem_nhdsSet {t : X → Set X} (h : ∀ x ∈ s, t x ∈ 𝓝 x) : (⋃ x ∈ s, t x) ∈ 𝓝ˢ s := mem_nhdsSet_iff_forall.2 fun x hx => mem_of_superset (h x hx) <| subset_iUnion₂ (s := fun x _ => t x) x hx -- porting note: fails to find `s` #align bUnion_mem_nhds_set bUnion_mem_nhdsSet @@ -67,22 +67,22 @@ theorem disjoint_principal_nhdsSet : Disjoint (𝓟 s) (𝓝ˢ t) ↔ Disjoint ( theorem disjoint_nhdsSet_principal : Disjoint (𝓝ˢ s) (𝓟 t) ↔ Disjoint s (closure t) := by rw [disjoint_comm, disjoint_principal_nhdsSet, disjoint_comm] -theorem mem_nhdsSet_iff_exists : s ∈ 𝓝ˢ t ↔ ∃ U : Set α, IsOpen U ∧ t ⊆ U ∧ U ⊆ s := by +theorem mem_nhdsSet_iff_exists : s ∈ 𝓝ˢ t ↔ ∃ U : Set X, IsOpen U ∧ t ⊆ U ∧ U ⊆ s := by rw [← subset_interior_iff_mem_nhdsSet, subset_interior_iff] #align mem_nhds_set_iff_exists mem_nhdsSet_iff_exists /-- A proposition is true on a set neighborhood of `s` iff it is true on a larger open set -/ -theorem eventually_nhdsSet_iff_exists {p : α → Prop} : +theorem eventually_nhdsSet_iff_exists {p : X → Prop} : (∀ᶠ x in 𝓝ˢ s, p x) ↔ ∃ t, IsOpen t ∧ s ⊆ t ∧ ∀ x, x ∈ t → p x := mem_nhdsSet_iff_exists /-- A proposition is true on a set neighborhood of `s` iff it is eventually true near each point in the set. -/ -theorem eventually_nhdsSet_iff_forall {p : α → Prop} : +theorem eventually_nhdsSet_iff_forall {p : X → Prop} : (∀ᶠ x in 𝓝ˢ s, p x) ↔ ∀ x, x ∈ s → ∀ᶠ y in 𝓝 x, p y := mem_nhdsSet_iff_forall -theorem hasBasis_nhdsSet (s : Set α) : (𝓝ˢ s).HasBasis (fun U => IsOpen U ∧ s ⊆ U) fun U => U := +theorem hasBasis_nhdsSet (s : Set X) : (𝓝ˢ s).HasBasis (fun U => IsOpen U ∧ s ⊆ U) fun U => U := ⟨fun t => by simp [mem_nhdsSet_iff_exists, and_assoc]⟩ #align has_basis_nhds_set hasBasis_nhdsSet @@ -99,10 +99,10 @@ theorem principal_le_nhdsSet : 𝓟 s ≤ 𝓝ˢ s := fun _s hs => theorem subset_of_mem_nhdsSet (h : t ∈ 𝓝ˢ s) : s ⊆ t := principal_le_nhdsSet h -theorem Filter.Eventually.self_of_nhdsSet {p : α → Prop} (h : ∀ᶠ x in 𝓝ˢ s, p x) : ∀ x ∈ s, p x := +theorem Filter.Eventually.self_of_nhdsSet {p : X → Prop} (h : ∀ᶠ x in 𝓝ˢ s, p x) : ∀ x ∈ s, p x := principal_le_nhdsSet h -nonrec theorem Filter.EventuallyEq.self_of_nhdsSet {f g : α → β} (h : f =ᶠ[𝓝ˢ s] g) : EqOn f g s := +nonrec theorem Filter.EventuallyEq.self_of_nhdsSet {f g : X → Y} (h : f =ᶠ[𝓝ˢ s] g) : EqOn f g s := h.self_of_nhdsSet @[simp] @@ -128,14 +128,14 @@ theorem mem_nhdsSet_interior : s ∈ 𝓝ˢ (interior s) := #align mem_nhds_set_interior mem_nhdsSet_interior @[simp] -theorem nhdsSet_empty : 𝓝ˢ (∅ : Set α) = ⊥ := by rw [isOpen_empty.nhdsSet_eq, principal_empty] +theorem nhdsSet_empty : 𝓝ˢ (∅ : Set X) = ⊥ := by rw [isOpen_empty.nhdsSet_eq, principal_empty] #align nhds_set_empty nhdsSet_empty -theorem mem_nhdsSet_empty : s ∈ 𝓝ˢ (∅ : Set α) := by simp +theorem mem_nhdsSet_empty : s ∈ 𝓝ˢ (∅ : Set X) := by simp #align mem_nhds_set_empty mem_nhdsSet_empty @[simp] -theorem nhdsSet_univ : 𝓝ˢ (univ : Set α) = ⊤ := by rw [isOpen_univ.nhdsSet_eq, principal_univ] +theorem nhdsSet_univ : 𝓝ˢ (univ : Set X) = ⊤ := by rw [isOpen_univ.nhdsSet_eq, principal_univ] #align nhds_set_univ nhdsSet_univ @[mono] @@ -143,7 +143,7 @@ theorem nhdsSet_mono (h : s ⊆ t) : 𝓝ˢ s ≤ 𝓝ˢ t := sSup_le_sSup <| image_subset _ h #align nhds_set_mono nhdsSet_mono -theorem monotone_nhdsSet : Monotone (𝓝ˢ : Set α → Filter α) := fun _ _ => nhdsSet_mono +theorem monotone_nhdsSet : Monotone (𝓝ˢ : Set X → Filter X) := fun _ _ => nhdsSet_mono #align monotone_nhds_set monotone_nhdsSet theorem nhds_le_nhdsSet (h : x ∈ s) : 𝓝 x ≤ 𝓝ˢ s := @@ -151,7 +151,7 @@ theorem nhds_le_nhdsSet (h : x ∈ s) : 𝓝 x ≤ 𝓝ˢ s := #align nhds_le_nhds_set nhds_le_nhdsSet @[simp] -theorem nhdsSet_union (s t : Set α) : 𝓝ˢ (s ∪ t) = 𝓝ˢ s ⊔ 𝓝ˢ t := by +theorem nhdsSet_union (s t : Set X) : 𝓝ˢ (s ∪ t) = 𝓝ˢ s ⊔ 𝓝ˢ t := by simp only [nhdsSet, image_union, sSup_union] #align nhds_set_union nhdsSet_union @@ -161,19 +161,61 @@ theorem union_mem_nhdsSet (h₁ : s₁ ∈ 𝓝ˢ t₁) (h₂ : s₂ ∈ 𝓝ˢ #align union_mem_nhds_set union_mem_nhdsSet @[simp] -theorem nhdsSet_insert (x : α) (s : Set α) : 𝓝ˢ (insert x s) = 𝓝 x ⊔ 𝓝ˢ s := by +theorem nhdsSet_insert (x : X) (s : Set X) : 𝓝ˢ (insert x s) = 𝓝 x ⊔ 𝓝ˢ s := by rw [insert_eq, nhdsSet_union, nhdsSet_singleton] /-- Preimage of a set neighborhood of `t` under a continuous map `f` is a set neighborhood of `s` provided that `f` maps `s` to `t`. -/ -theorem Continuous.tendsto_nhdsSet {f : α → β} {t : Set β} (hf : Continuous f) +theorem Continuous.tendsto_nhdsSet {f : X → Y} {t : Set Y} (hf : Continuous f) (hst : MapsTo f s t) : Tendsto f (𝓝ˢ s) (𝓝ˢ t) := ((hasBasis_nhdsSet s).tendsto_iff (hasBasis_nhdsSet t)).mpr fun U hU => ⟨f ⁻¹' U, ⟨hU.1.preimage hf, hst.mono Subset.rfl hU.2⟩, fun _ => id⟩ #align continuous.tendsto_nhds_set Continuous.tendsto_nhdsSet -lemma Continuous.tendsto_nhdsSet_nhds {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] - {s : Set X} {y : Y} {f : X → Y} (h : Continuous f) (h' : EqOn f (fun _ ↦ y) s) : +lemma Continuous.tendsto_nhdsSet_nhds + {y : Y} {f : X → Y} (h : Continuous f) (h' : EqOn f (fun _ ↦ y) s) : Tendsto f (𝓝ˢ s) (𝓝 y) := by rw [← nhdsSet_singleton] exact h.tendsto_nhdsSet h' + +/- This inequality cannot be improved to an equality. For instance, +if `X` has two elements and the coarse topology and `s` and `t` are distinct singletons then +`𝓝ˢ (s ∩ t) = ⊥` while `𝓝ˢ s ⊓ 𝓝ˢ t = ⊤` and those are different. -/ +theorem nhdsSet_inter_le (s t : Set X) : 𝓝ˢ (s ∩ t) ≤ 𝓝ˢ s ⊓ 𝓝ˢ t := + (monotone_nhdsSet (X := X)).map_inf_le s t + +variable (s) in +theorem IsClosed.nhdsSet_le_sup (h : IsClosed t) : 𝓝ˢ s ≤ 𝓝ˢ (s ∩ t) ⊔ 𝓟 (tᶜ) := + calc + 𝓝ˢ s = 𝓝ˢ (s ∩ t ∪ s ∩ tᶜ) := by rw [Set.inter_union_compl s t] + _ = 𝓝ˢ (s ∩ t) ⊔ 𝓝ˢ (s ∩ tᶜ) := by rw [nhdsSet_union] + _ ≤ 𝓝ˢ (s ∩ t) ⊔ 𝓝ˢ (tᶜ) := (sup_le_sup_left (monotone_nhdsSet (s.inter_subset_right (tᶜ))) _) + _ = 𝓝ˢ (s ∩ t) ⊔ 𝓟 (tᶜ) := by rw [h.isOpen_compl.nhdsSet_eq] + +variable (s) in +theorem IsClosed.nhdsSet_le_sup' (h : IsClosed t) : + 𝓝ˢ s ≤ 𝓝ˢ (t ∩ s) ⊔ 𝓟 (tᶜ) := by rw [Set.inter_comm]; exact h.nhdsSet_le_sup s + +theorem Filter.Eventually.eventually_nhdsSet {p : X → Prop} (h : ∀ᶠ y in 𝓝ˢ s, p y) : + ∀ᶠ y in 𝓝ˢ s, ∀ᶠ x in 𝓝 y, p x := + eventually_nhdsSet_iff_forall.mpr fun x x_in ↦ + (eventually_nhdsSet_iff_forall.mp h x x_in).eventually_nhds + +theorem Filter.Eventually.union_nhdsSet {p : X → Prop} : + (∀ᶠ x in 𝓝ˢ (s ∪ t), p x) ↔ (∀ᶠ x in 𝓝ˢ s, p x) ∧ ∀ᶠ x in 𝓝ˢ t, p x := by + rw [nhdsSet_union, eventually_sup] + +theorem Filter.Eventually.union {p : X → Prop} (hs : ∀ᶠ x in 𝓝ˢ s, p x) (ht : ∀ᶠ x in 𝓝ˢ t, p x) : + ∀ᶠ x in 𝓝ˢ (s ∪ t), p x := + Filter.Eventually.union_nhdsSet.mpr ⟨hs, ht⟩ + +theorem nhdsSet_iUnion {ι : Sort*} (s : ι → Set X) : 𝓝ˢ (⋃ i, s i) = ⨆ i, 𝓝ˢ (s i) := by + simp only [nhdsSet, image_iUnion, sSup_iUnion (β := Filter X)] + +theorem eventually_nhdsSet_iUnion₂ {ι : Sort*} {p : ι → Prop} {s : ι → Set X} {P : X → Prop} : + (∀ᶠ x in 𝓝ˢ (⋃ (i) (_ : p i), s i), P x) ↔ ∀ i, p i → ∀ᶠ x in 𝓝ˢ (s i), P x := by + simp only [nhdsSet_iUnion, eventually_iSup] + +theorem eventually_nhdsSet_iUnion {ι : Sort*} {s : ι → Set X} {P : X → Prop} : + (∀ᶠ x in 𝓝ˢ (⋃ i, s i), P x) ↔ ∀ i, ∀ᶠ x in 𝓝ˢ (s i), P x := by + simp only [nhdsSet_iUnion, eventually_iSup] diff --git a/Mathlib/Topology/NoetherianSpace.lean b/Mathlib/Topology/NoetherianSpace.lean index 9bc598546cb29..cde20c7d92d57 100644 --- a/Mathlib/Topology/NoetherianSpace.lean +++ b/Mathlib/Topology/NoetherianSpace.lean @@ -121,7 +121,7 @@ instance {α} : NoetherianSpace (CofiniteTopology α) := by theorem noetherianSpace_of_surjective [NoetherianSpace α] (f : α → β) (hf : Continuous f) (hf' : Function.Surjective f) : NoetherianSpace β := - noetherianSpace_iff_isCompact.2 $ (Set.image_surjective.mpr hf').forall.2 fun s => + noetherianSpace_iff_isCompact.2 <| (Set.image_surjective.mpr hf').forall.2 fun s => (NoetherianSpace.isCompact s).image hf #align topological_space.noetherian_space_of_surjective TopologicalSpace.noetherianSpace_of_surjective @@ -240,11 +240,11 @@ theorem NoetherianSpace.exists_open_ne_empty_le_irreducibleComponent [Noetherian rw [Set.diff_eq_empty] at r exact r) simp only [Set.Finite.mem_toFinset, Set.mem_diff, Set.mem_singleton_iff] at hZ' - exact hZ'.1.2 $ le_antisymm (H.2 hZ'.1.1.1 hZ'.2) hZ'.2 + exact hZ'.1.2 <| le_antisymm (H.2 hZ'.1.1.1 hZ'.2) hZ'.2 have hU1 : U = (⋃ (x : ι), x.1) ᶜ · rw [Set.compl_eq_univ_diff] - refine le_antisymm (Set.diff_subset_diff le_top $ subset_refl _) ?_ + refine le_antisymm (Set.diff_subset_diff le_top <| subset_refl _) ?_ rw [← Set.compl_eq_univ_diff] refine Set.compl_subset_iff_union.mpr (le_antisymm le_top ?_) rw [Set.union_comm, ← Set.sUnion_eq_iUnion, ← Set.sUnion_insert] diff --git a/Mathlib/Topology/Order/Basic.lean b/Mathlib/Topology/Order/Basic.lean index 9b2facc704b4e..98a24d9f0fb91 100644 --- a/Mathlib/Topology/Order/Basic.lean +++ b/Mathlib/Topology/Order/Basic.lean @@ -4,10 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Yury Kudryashov -/ import Mathlib.Data.Set.Intervals.Pi -import Mathlib.Data.Set.Pointwise.Interval +import Mathlib.Data.Set.Pointwise.Basic import Mathlib.Order.Filter.Interval import Mathlib.Tactic.TFAE -import Mathlib.Topology.Support +import Mathlib.Tactic.NormNum +import Mathlib.Topology.Separation import Mathlib.Topology.Algebra.Order.LeftRight #align_import topology.order.basic from "leanprover-community/mathlib"@"3efd324a3a31eaa40c9d5bfc669c4fafee5f9423" @@ -137,6 +138,10 @@ theorem closure_Iic (a : α) : closure (Iic a) = Iic a := isClosed_Iic.closure_eq #align closure_Iic closure_Iic +theorem le_of_tendsto_of_frequently {f : β → α} {a b : α} {x : Filter β} (lim : Tendsto f x (𝓝 a)) + (h : ∃ᶠ c in x, f c ≤ b) : a ≤ b := + (isClosed_le' b).mem_of_frequently_of_tendsto h lim + theorem le_of_tendsto {f : β → α} {a b : α} {x : Filter β} [NeBot x] (lim : Tendsto f x (𝓝 a)) (h : ∀ᶠ c in x, f c ≤ b) : a ≤ b := (isClosed_le' b).mem_of_tendsto lim h @@ -165,6 +170,10 @@ theorem closure_Ici (a : α) : closure (Ici a) = Ici a := isClosed_Ici.closure_eq #align closure_Ici closure_Ici +lemma ge_of_tendsto_of_frequently {f : β → α} {a b : α} {x : Filter β} (lim : Tendsto f x (𝓝 a)) + (h : ∃ᶠ c in x, b ≤ f c) : b ≤ a := + (isClosed_ge' b).mem_of_frequently_of_tendsto h lim + theorem ge_of_tendsto {f : β → α} {a b : α} {x : Filter β} [NeBot x] (lim : Tendsto f x (𝓝 a)) (h : ∀ᶠ c in x, b ≤ f c) : b ≤ a := (isClosed_ge' b).mem_of_tendsto lim h @@ -414,7 +423,7 @@ theorem Ioo_mem_nhdsWithin_Ioi {a b c : α} (H : b ∈ Ico a c) : Ioo a c ∈ theorem Ioo_mem_nhdsWithin_Ioi' {a b : α} (H : a < b) : Ioo a b ∈ 𝓝[>] a := Ioo_mem_nhdsWithin_Ioi ⟨le_rfl, H⟩ -theorem Covby.nhdsWithin_Ioi {a b : α} (h : a ⋖ b) : 𝓝[>] a = ⊥ := +theorem CovBy.nhdsWithin_Ioi {a b : α} (h : a ⋖ b) : 𝓝[>] a = ⊥ := empty_mem_iff_bot.mp <| h.Ioo_eq ▸ Ioo_mem_nhdsWithin_Ioi' h.1 theorem Ioc_mem_nhdsWithin_Ioi {a b c : α} (H : b ∈ Ico a c) : Ioc a c ∈ 𝓝[>] b := @@ -476,7 +485,7 @@ theorem Ioo_mem_nhdsWithin_Iio {a b c : α} (H : b ∈ Ioc a c) : Ioo a c ∈ theorem Ioo_mem_nhdsWithin_Iio' {a b : α} (H : a < b) : Ioo a b ∈ 𝓝[<] b := Ioo_mem_nhdsWithin_Iio ⟨H, le_rfl⟩ -theorem Covby.nhdsWithin_Iio {a b : α} (h : a ⋖ b) : 𝓝[<] b = ⊥ := +theorem CovBy.nhdsWithin_Iio {a b : α} (h : a ⋖ b) : 𝓝[<] b = ⊥ := empty_mem_iff_bot.mp <| h.Ioo_eq ▸ Ioo_mem_nhdsWithin_Iio' h.1 theorem Ico_mem_nhdsWithin_Iio {a b c : α} (H : b ∈ Ioc a c) : Ico a c ∈ 𝓝[<] b := @@ -1043,7 +1052,7 @@ theorem StrictMono.embedding_of_ordConnected {α β : Type*} [LinearOrder α] [L order is the same as the restriction to the subset of the order topology. -/ instance orderTopology_of_ordConnected {α : Type u} [TopologicalSpace α] [LinearOrder α] [OrderTopology α] {t : Set α} [ht : OrdConnected t] : OrderTopology t := - ⟨(Subtype.strictMono_coe t).induced_topology_eq_preorder $ by + ⟨(Subtype.strictMono_coe t).induced_topology_eq_preorder <| by rwa [← @Subtype.range_val _ t] at ht⟩ #align order_topology_of_ord_connected orderTopology_of_ordConnected @@ -1337,7 +1346,7 @@ variable {α} -- porting note: new lemma /-- The set of points which are isolated on the right is countable when the space is second-countable. -/ -theorem countable_setOf_covby_right [SecondCountableTopology α] : +theorem countable_setOf_covBy_right [SecondCountableTopology α] : Set.Countable { x : α | ∃ y, x ⋖ y } := by nontriviality α let s := { x : α | ∃ y, x ⋖ y } @@ -1379,24 +1388,24 @@ theorem countable_setOf_covby_right [SecondCountableTopology α] : /-- The set of points which are isolated on the right is countable when the space is second-countable. -/ -@[deprecated countable_setOf_covby_right] +@[deprecated countable_setOf_covBy_right] theorem countable_of_isolated_right' [SecondCountableTopology α] : Set.Countable { x : α | ∃ y, x < y ∧ Ioo x y = ∅ } := by - simpa only [← covby_iff_Ioo_eq] using countable_setOf_covby_right + simpa only [← covBy_iff_Ioo_eq] using countable_setOf_covBy_right #align countable_of_isolated_right countable_of_isolated_right' /-- The set of points which are isolated on the left is countable when the space is second-countable. -/ -theorem countable_setOf_covby_left [SecondCountableTopology α] : +theorem countable_setOf_covBy_left [SecondCountableTopology α] : Set.Countable { x : α | ∃ y, y ⋖ x } := by - convert countable_setOf_covby_right (α := αᵒᵈ) using 5 - exact toDual_covby_toDual_iff.symm + convert countable_setOf_covBy_right (α := αᵒᵈ) using 5 + exact toDual_covBy_toDual_iff.symm /-- The set of points which are isolated on the left is countable when the space is second-countable. -/ theorem countable_of_isolated_left' [SecondCountableTopology α] : Set.Countable { x : α | ∃ y, y < x ∧ Ioo y x = ∅ } := by - simpa only [← covby_iff_Ioo_eq] using countable_setOf_covby_left + simpa only [← covBy_iff_Ioo_eq] using countable_setOf_covBy_left #align countable_of_isolated_left countable_of_isolated_left' /-- Consider a disjoint family of intervals `(x, y)` with `x < y` in a second-countable space. @@ -1408,7 +1417,7 @@ theorem Set.PairwiseDisjoint.countable_of_Ioo [SecondCountableTopology α] {y : have : (s \ { x | ∃ y, x ⋖ y }).Countable := (h.subset (diff_subset _ _)).countable_of_isOpen (fun _ _ => isOpen_Ioo) fun x hx => (h' _ hx.1).exists_lt_lt (mt (Exists.intro (y x)) hx.2) - this.of_diff countable_setOf_covby_right + this.of_diff countable_setOf_covBy_right #align set.pairwise_disjoint.countable_of_Ioo Set.PairwiseDisjoint.countable_of_Ioo /-- For a function taking values in a second countable space, the set of points `x` for @@ -1689,7 +1698,7 @@ theorem nhdsWithin_Ioi_eq_bot_iff {a : α} : 𝓝[>] a = ⊥ ↔ IsTop a ∨ ∃ · simp [ha, ha.isMax.Ioi_eq] · simp only [ha, false_or] rw [isTop_iff_isMax, not_isMax_iff] at ha - simp only [(nhdsWithin_Ioi_basis' ha).eq_bot_iff, covby_iff_Ioo_eq] + simp only [(nhdsWithin_Ioi_basis' ha).eq_bot_iff, covBy_iff_Ioo_eq] /-- A set is a neighborhood of `a` within `(a, +∞)` if and only if it contains an interval `(a, u)` with `a < u`. -/ @@ -1704,7 +1713,7 @@ second-countable. -/ theorem countable_setOf_isolated_right [SecondCountableTopology α] : { x : α | 𝓝[>] x = ⊥ }.Countable := by simp only [nhdsWithin_Ioi_eq_bot_iff, setOf_or] - exact (subsingleton_isTop α).countable.union countable_setOf_covby_right + exact (subsingleton_isTop α).countable.union countable_setOf_covBy_right /-- The set of points which are isolated on the left is countable when the space is second-countable. -/ @@ -1778,7 +1787,7 @@ theorem nhdsWithin_Iio_basis' {a : α} (h : ∃ b, b < a) : (𝓝[<] a).HasBasis theorem nhdsWithin_Iio_eq_bot_iff {a : α} : 𝓝[<] a = ⊥ ↔ IsBot a ∨ ∃ b, b ⋖ a := by convert (config := {preTransparency := .default}) nhdsWithin_Ioi_eq_bot_iff (a := OrderDual.toDual a) using 4 - exact ofDual_covby_ofDual_iff + exact ofDual_covBy_ofDual_iff open List in /-- The following statements are equivalent: @@ -1836,17 +1845,18 @@ theorem nhdsWithin_Ici_basis_Ico [NoMaxOrder α] (a : α) : ⟨fun _ => mem_nhdsWithin_Ici_iff_exists_Ico_subset⟩ #align nhds_within_Ici_basis_Ico nhdsWithin_Ici_basis_Ico +/-- The filter of right neighborhoods has a basis of closed intervals. -/ +theorem nhdsWithin_Ici_basis_Icc [NoMaxOrder α] [DenselyOrdered α] {a : α} : + (𝓝[≥] a).HasBasis (a < ·) (Icc a) := + (nhdsWithin_Ici_basis _).to_hasBasis + (fun _u hu ↦ (exists_between hu).imp fun _v hv ↦ hv.imp_right Icc_subset_Ico_right) + fun u hu ↦ ⟨u, hu, Ico_subset_Icc_self⟩ + /-- A set is a neighborhood of `a` within `[a, +∞)` if and only if it contains an interval `[a, u]` with `a < u`. -/ theorem mem_nhdsWithin_Ici_iff_exists_Icc_subset [NoMaxOrder α] [DenselyOrdered α] {a : α} - {s : Set α} : s ∈ 𝓝[≥] a ↔ ∃ u, a < u ∧ Icc a u ⊆ s := by - rw [mem_nhdsWithin_Ici_iff_exists_Ico_subset] - constructor - · rintro ⟨u, au, as⟩ - rcases exists_between au with ⟨v, hv⟩ - exact ⟨v, hv.1, fun x hx => as ⟨hx.1, lt_of_le_of_lt hx.2 hv.2⟩⟩ - · rintro ⟨u, au, as⟩ - exact ⟨u, au, Subset.trans Ico_subset_Icc_self as⟩ + {s : Set α} : s ∈ 𝓝[≥] a ↔ ∃ u, a < u ∧ Icc a u ⊆ s := + nhdsWithin_Ici_basis_Icc.mem_iff #align mem_nhds_within_Ici_iff_exists_Icc_subset mem_nhdsWithin_Ici_iff_exists_Icc_subset open List in @@ -1897,6 +1907,11 @@ theorem mem_nhdsWithin_Iic_iff_exists_Icc_subset [NoMinOrder α] [DenselyOrdered _ ↔ ∃ l, l < a ∧ Icc l a ⊆ s := by simp only [dual_Icc]; rfl #align mem_nhds_within_Iic_iff_exists_Icc_subset mem_nhdsWithin_Iic_iff_exists_Icc_subset +/-- The filter of left neighborhoods has a basis of closed intervals. -/ +theorem nhdsWithin_Iic_basis_Icc [NoMinOrder α] [DenselyOrdered α] {a : α} : + (𝓝[≤] a).HasBasis (· < a) (Icc · a) := + ⟨fun _ ↦ mem_nhdsWithin_Iic_iff_exists_Icc_subset⟩ + end OrderTopology end LinearOrder @@ -2937,7 +2952,7 @@ theorem Monotone.tendsto_nhdsWithin_Iio {α β : Type*} [LinearOrder α] [Topolo refine' tendsto_order.2 ⟨fun l hl => _, fun m hm => _⟩ · obtain ⟨z, zx, lz⟩ : ∃ a : α, a < x ∧ l < f a := by simpa only [mem_image, exists_prop, exists_exists_and_eq_and] using - exists_lt_of_lt_csSup (nonempty_image_iff.2 h) hl + exists_lt_of_lt_csSup (h.image _) hl exact mem_of_superset (Ioo_mem_nhdsWithin_Iio' zx) fun y hy => lz.trans_le (Mf hy.1.le) · refine mem_of_superset self_mem_nhdsWithin fun _ hy => lt_of_le_of_lt ?_ hm exact le_csSup (Mf.map_bddAbove bddAbove_Iio) (mem_image_of_mem _ hy) diff --git a/Mathlib/Topology/Order/Category/AlexDisc.lean b/Mathlib/Topology/Order/Category/AlexDisc.lean index 7a66425207877..5bd646c682fe2 100644 --- a/Mathlib/Topology/Order/Category/AlexDisc.lean +++ b/Mathlib/Topology/Order/Category/AlexDisc.lean @@ -50,8 +50,8 @@ def of (α : Type*) [TopologicalSpace α] [AlexandrovDiscrete α] : AlexDisc := def Iso.mk {α β : AlexDisc} (e : α ≃ₜ β) : α ≅ β where hom := (e : ContinuousMap α β) inv := (e.symm : ContinuousMap β α) - hom_inv_id := FunLike.ext _ _ e.symm_apply_apply - inv_hom_id := FunLike.ext _ _ e.apply_symm_apply + hom_inv_id := DFunLike.ext _ _ e.symm_apply_apply + inv_hom_id := DFunLike.ext _ _ e.apply_symm_apply end AlexDisc @@ -60,7 +60,7 @@ end AlexDisc def alexDiscEquivPreord : AlexDisc ≌ Preord where functor := forget₂ _ _ ⋙ topToPreord inverse := { obj := λ X ↦ AlexDisc.of (WithUpperSet X), map := WithUpperSet.map } - unitIso := NatIso.ofComponents λ X ↦ AlexDisc.Iso.mk $ by + unitIso := NatIso.ofComponents λ X ↦ AlexDisc.Iso.mk <| by dsimp; exact homeoWithUpperSetTopologyorderIso X - counitIso := NatIso.ofComponents λ X ↦ Preord.Iso.mk $ by + counitIso := NatIso.ofComponents λ X ↦ Preord.Iso.mk <| by dsimp; exact (orderIsoSpecializationWithUpperSetTopology X).symm diff --git a/Mathlib/Topology/Order/Hom/Basic.lean b/Mathlib/Topology/Order/Hom/Basic.lean index cb88e0cfaf760..0ec9633a0adf4 100644 --- a/Mathlib/Topology/Order/Hom/Basic.lean +++ b/Mathlib/Topology/Order/Hom/Basic.lean @@ -15,7 +15,7 @@ This file defines continuous order homomorphisms, that is maps which are both co monotone. They are also called Priestley homomorphisms because they are the morphisms of the category of Priestley spaces. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -115,7 +115,7 @@ theorem toFun_eq_coe {f : α →Co β} : f.toFun = (f : α → β) := rfl @[ext] theorem ext {f g : α →Co β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align continuous_order_hom.ext ContinuousOrderHom.ext /-- Copy of a `ContinuousOrderHom` with a new `ContinuousMap` equal to the old one. Useful to fix @@ -130,7 +130,7 @@ theorem coe_copy (f : α →Co β) (f' : α → β) (h : f' = f) : ⇑(f.copy f' #align continuous_order_hom.coe_copy ContinuousOrderHom.coe_copy theorem copy_eq (f : α →Co β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align continuous_order_hom.copy_eq ContinuousOrderHom.copy_eq variable (α) @@ -189,7 +189,7 @@ theorem id_comp (f : α →Co β) : (ContinuousOrderHom.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : β →Co γ} {f : α →Co β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun h => congr_arg₂ _ h rfl⟩ #align continuous_order_hom.cancel_right ContinuousOrderHom.cancel_right @[simp] @@ -204,6 +204,6 @@ instance : Preorder (α →Co β) := end Preorder instance [PartialOrder β] : PartialOrder (α →Co β) := - PartialOrder.lift ((↑) : (α →Co β) → α → β) FunLike.coe_injective + PartialOrder.lift ((↑) : (α →Co β) → α → β) DFunLike.coe_injective end ContinuousOrderHom diff --git a/Mathlib/Topology/Order/Hom/Esakia.lean b/Mathlib/Topology/Order/Hom/Esakia.lean index 6907fd11591dc..4aaade5689cd9 100644 --- a/Mathlib/Topology/Order/Hom/Esakia.lean +++ b/Mathlib/Topology/Order/Hom/Esakia.lean @@ -13,7 +13,7 @@ import Mathlib.Topology.Order.Hom.Basic This file defines pseudo-epimorphisms and Esakia morphisms. -We use the `FunLike` design, so each type of morphisms has a companion typeclass which is meant to +We use the `DFunLike` design, so each type of morphisms has a companion typeclass which is meant to be satisfied by itself and all stricter types. ## Types of morphisms @@ -116,10 +116,10 @@ instance : PseudoEpimorphismClass (PseudoEpimorphism α β) α β where map_rel f _ _ h := f.monotone' h exists_map_eq_of_map_le := PseudoEpimorphism.exists_map_eq_of_map_le' -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (PseudoEpimorphism α β) fun _ => α → β := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun @[simp] theorem toOrderHom_eq_coe (f : PseudoEpimorphism α β) : ⇑f.toOrderHom = f := rfl @@ -129,7 +129,7 @@ theorem toFun_eq_coe {f : PseudoEpimorphism α β} : f.toFun = (f : α → β) : @[ext] theorem ext {f g : PseudoEpimorphism α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align pseudo_epimorphism.ext PseudoEpimorphism.ext /-- Copy of a `PseudoEpimorphism` with a new `toFun` equal to the old one. Useful to fix @@ -143,7 +143,7 @@ theorem coe_copy (f : PseudoEpimorphism α β) (f' : α → β) (h : f' = f) : #align pseudo_epimorphism.coe_copy PseudoEpimorphism.coe_copy theorem copy_eq (f : PseudoEpimorphism α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align pseudo_epimorphism.copy_eq PseudoEpimorphism.copy_eq variable (α) @@ -211,7 +211,7 @@ theorem id_comp (f : PseudoEpimorphism α β) : (PseudoEpimorphism.id β).comp f @[simp] theorem cancel_right {g₁ g₂ : PseudoEpimorphism β γ} {f : PseudoEpimorphism α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (comp · f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (comp · f)⟩ #align pseudo_epimorphism.cancel_right PseudoEpimorphism.cancel_right @[simp] @@ -244,10 +244,10 @@ instance : EsakiaHomClass (EsakiaHom α β) α β where map_continuous f := f.continuous_toFun exists_map_eq_of_map_le f := f.exists_map_eq_of_map_le' -/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` directly. -/ instance : CoeFun (EsakiaHom α β) fun _ => α → β := - FunLike.hasCoeToFun + DFunLike.hasCoeToFun -- Porting note: introduced this to appease simpNF linter with `toFun_eq_coe` @[simp] @@ -260,7 +260,7 @@ theorem toFun_eq_coe {f : EsakiaHom α β} : f.toFun = (f : α → β) := rfl @[ext] theorem ext {f g : EsakiaHom α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align esakia_hom.ext EsakiaHom.ext /-- Copy of an `EsakiaHom` with a new `toFun` equal to the old one. Useful to fix definitional @@ -275,7 +275,7 @@ theorem coe_copy (f : EsakiaHom α β) (f' : α → β) (h : f' = f) : ⇑(f.cop #align esakia_hom.coe_copy EsakiaHom.coe_copy theorem copy_eq (f : EsakiaHom α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align esakia_hom.copy_eq EsakiaHom.copy_eq variable (α) @@ -351,7 +351,7 @@ theorem id_comp (f : EsakiaHom α β) : (EsakiaHom.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : EsakiaHom β γ} {f : EsakiaHom α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg (comp · f)⟩ + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, congr_arg (comp · f)⟩ #align esakia_hom.cancel_right EsakiaHom.cancel_right @[simp] diff --git a/Mathlib/Topology/Order/Lattice.lean b/Mathlib/Topology/Order/Lattice.lean index d83c889d90701..e714bffb16368 100644 --- a/Mathlib/Topology/Order/Lattice.lean +++ b/Mathlib/Topology/Order/Lattice.lean @@ -24,8 +24,6 @@ class `TopologicalLattice` as a topological space and lattice `L` extending `Con topological, lattice -/ -set_option autoImplicit true - open Filter open Topology @@ -79,7 +77,7 @@ instance (priority := 100) LinearOrder.topologicalLattice {L : Type*} [Topologic continuous_sup := continuous_max #align linear_order.topological_lattice LinearOrder.topologicalLattice -variable [TopologicalSpace L] [TopologicalSpace X] +variable {L X : Type*} [TopologicalSpace L] [TopologicalSpace X] @[continuity] theorem continuous_inf [Inf L] [ContinuousInf L] : Continuous fun p : L × L => p.1 ⊓ p.2 := @@ -133,7 +131,7 @@ end SupInf open Finset -variable {ι : Type*} {s : Finset ι} {f : ι → α → L} {g : ι → L} +variable {ι α : Type*} {s : Finset ι} {f : ι → α → L} {l : Filter α} {g : ι → L} lemma finset_sup'_nhds [SemilatticeSup L] [ContinuousSup L] (hne : s.Nonempty) (hs : ∀ i ∈ s, Tendsto (f i) l (𝓝 (g i))) : diff --git a/Mathlib/Topology/Order/ScottTopology.lean b/Mathlib/Topology/Order/ScottTopology.lean index 46c6b4df47967..b61769148e99b 100644 --- a/Mathlib/Topology/Order/ScottTopology.lean +++ b/Mathlib/Topology/Order/ScottTopology.lean @@ -90,14 +90,14 @@ alias ⟨DirSupInacc.of_compl, DirSupClosed.compl⟩ := dirSupInacc_compl alias ⟨DirSupClosed.of_compl, DirSupInacc.compl⟩ := dirSupClosed_compl lemma DirSupClosed.inter (hs : DirSupClosed s) (ht : DirSupClosed t) : DirSupClosed (s ∩ t) := - fun _d hd hd' _a ha hds ↦ ⟨hs hd hd' ha $ hds.trans $ inter_subset_left _ _, - ht hd hd' ha $ hds.trans $ inter_subset_right _ _⟩ + fun _d hd hd' _a ha hds ↦ ⟨hs hd hd' ha <| hds.trans <| inter_subset_left _ _, + ht hd hd' ha <| hds.trans <| inter_subset_right _ _⟩ lemma DirSupInacc.union (hs : DirSupInacc s) (ht : DirSupInacc t) : DirSupInacc (s ∪ t) := by rw [← dirSupClosed_compl, compl_union]; exact hs.compl.inter ht.compl lemma IsUpperSet.dirSupClosed (hs : IsUpperSet s) : DirSupClosed s := - fun _d ⟨_b, hb⟩ _ _a ha hds ↦ hs (ha.1 hb) $ hds hb + fun _d ⟨_b, hb⟩ _ _a ha hds ↦ hs (ha.1 hb) <| hds hb lemma IsLowerSet.dirSupInacc (hs : IsLowerSet s) : DirSupInacc s := hs.compl.dirSupClosed.of_compl @@ -168,7 +168,7 @@ lemma isOpen_of_isLowerSet (h : IsLowerSet s) : IsOpen s := isOpen_iff.2 fun _d ⟨b, hb⟩ _ _ hda ha ↦ ⟨b, hb, fun _ hc ↦ h (mem_upperBounds.1 hda.1 _ hc.2) ha⟩ lemma isClosed_of_isUpperSet (h : IsUpperSet s) : IsClosed s := - isOpen_compl_iff.1 $ isOpen_of_isLowerSet h.compl + isOpen_compl_iff.1 <| isOpen_of_isLowerSet h.compl lemma dirSupInacc_of_isOpen (h : IsOpen s) : DirSupInacc s := fun d hd₁ hd₂ a hda hd₃ ↦ by @@ -248,7 +248,7 @@ The closure of a singleton `{a}` in the Scott topology is the right-closed left- `(-∞,a]`. -/ @[simp] lemma closure_singleton : closure {a} = Iic a := le_antisymm - (closure_minimal (by rw [singleton_subset_iff, mem_Iic]) isClosed_Iic) $ by + (closure_minimal (by rw [singleton_subset_iff, mem_Iic]) isClosed_Iic) <| by rw [← LowerSet.coe_Iic, ← lowerClosure_singleton] apply lowerClosure_subset_closure @@ -263,7 +263,7 @@ lemma monotone_of_continuous (hf : Continuous f) : Monotone f := fun _ b hab ↦ refine ⟨fun h ↦ continuous_def.2 fun u hu ↦ ?_, ?_⟩ · rw [isOpen_iff_isUpperSet_and_dirSupInacc] exact ⟨(isUpperSet_of_isOpen hu).preimage h.monotone, fun _ hd₁ hd₂ _ hd₃ ha ↦ - image_inter_nonempty_iff.mp $ (isOpen_iff_isUpperSet_and_dirSupInacc.mp hu).2 (hd₁.image f) + image_inter_nonempty_iff.mp <| (isOpen_iff_isUpperSet_and_dirSupInacc.mp hu).2 (hd₁.image f) (directedOn_image.mpr (hd₂.mono @(h.monotone))) (h hd₁ hd₂ hd₃) ha⟩ · refine fun hf _ d₁ d₂ _ d₃ ↦ ⟨(monotone_of_continuous hf).mem_upperBounds_image d₃.1, fun b hb ↦ ?_⟩ @@ -273,7 +273,7 @@ lemma monotone_of_continuous (hf : Continuous f) : Monotone f := fun _ b hab ↦ rw [isOpen_iff_isUpperSet_and_dirSupInacc] at hu obtain ⟨c, hcd, hfcb⟩ := hu.2 d₁ d₂ d₃ h simp [upperBounds] at hb - exact hfcb $ hb _ hcd + exact hfcb <| hb _ hcd end Preorder @@ -285,8 +285,8 @@ The Scott topology on a partial order is T₀. -/ -- see Note [lower instance priority] instance (priority := 90) : T0Space α := - (t0Space_iff_inseparable α).2 fun x y h ↦ Iic_injective $ - by simpa only [inseparable_iff_closure_eq, IsScott.closure_singleton] using h + (t0Space_iff_inseparable α).2 fun x y h ↦ Iic_injective <| by + simpa only [inseparable_iff_closure_eq, IsScott.closure_singleton] using h end PartialOrder end IsScott @@ -346,6 +346,6 @@ lemma IsScott.scottHausdorff_le [IsScott α] : scottHausdorff ≤ ‹Topological lemma IsLower.scottHausdorff_le [IsLower α] : scottHausdorff ≤ ‹TopologicalSpace α› := fun _ h ↦ - @IsScottHausdorff.isOpen_of_isLowerSet _ _ scottHausdorff _ _ $ IsLower.isLowerSet_of_isOpen h + @IsScottHausdorff.isOpen_of_isLowerSet _ _ scottHausdorff _ _ <| IsLower.isLowerSet_of_isOpen h end Topology diff --git a/Mathlib/Topology/Partial.lean b/Mathlib/Topology/Partial.lean index 8bc1cb8c39229..de5798162b3ec 100644 --- a/Mathlib/Topology/Partial.lean +++ b/Mathlib/Topology/Partial.lean @@ -20,45 +20,45 @@ open Filter open Topology -variable {α β : Type*} [TopologicalSpace α] +variable {X Y : Type*} [TopologicalSpace X] -theorem rtendsto_nhds {r : Rel β α} {l : Filter β} {a : α} : - RTendsto r l (𝓝 a) ↔ ∀ s, IsOpen s → a ∈ s → r.core s ∈ l := +theorem rtendsto_nhds {r : Rel Y X} {l : Filter Y} {x : X} : + RTendsto r l (𝓝 x) ↔ ∀ s, IsOpen s → x ∈ s → r.core s ∈ l := all_mem_nhds_filter _ _ (fun _s _t => id) _ #align rtendsto_nhds rtendsto_nhds -theorem rtendsto'_nhds {r : Rel β α} {l : Filter β} {a : α} : - RTendsto' r l (𝓝 a) ↔ ∀ s, IsOpen s → a ∈ s → r.preimage s ∈ l := by +theorem rtendsto'_nhds {r : Rel Y X} {l : Filter Y} {x : X} : + RTendsto' r l (𝓝 x) ↔ ∀ s, IsOpen s → x ∈ s → r.preimage s ∈ l := by rw [rtendsto'_def] apply all_mem_nhds_filter apply Rel.preimage_mono #align rtendsto'_nhds rtendsto'_nhds -theorem ptendsto_nhds {f : β →. α} {l : Filter β} {a : α} : - PTendsto f l (𝓝 a) ↔ ∀ s, IsOpen s → a ∈ s → f.core s ∈ l := +theorem ptendsto_nhds {f : Y →. X} {l : Filter Y} {x : X} : + PTendsto f l (𝓝 x) ↔ ∀ s, IsOpen s → x ∈ s → f.core s ∈ l := rtendsto_nhds #align ptendsto_nhds ptendsto_nhds -theorem ptendsto'_nhds {f : β →. α} {l : Filter β} {a : α} : - PTendsto' f l (𝓝 a) ↔ ∀ s, IsOpen s → a ∈ s → f.preimage s ∈ l := +theorem ptendsto'_nhds {f : Y →. X} {l : Filter Y} {x : X} : + PTendsto' f l (𝓝 x) ↔ ∀ s, IsOpen s → x ∈ s → f.preimage s ∈ l := rtendsto'_nhds #align ptendsto'_nhds ptendsto'_nhds /-! ### Continuity and partial functions -/ -variable [TopologicalSpace β] +variable [TopologicalSpace Y] /-- Continuity of a partial function -/ -def PContinuous (f : α →. β) := +def PContinuous (f : X →. Y) := ∀ s, IsOpen s → IsOpen (f.preimage s) #align pcontinuous PContinuous -theorem open_dom_of_pcontinuous {f : α →. β} (h : PContinuous f) : IsOpen f.Dom := by +theorem open_dom_of_pcontinuous {f : X →. Y} (h : PContinuous f) : IsOpen f.Dom := by rw [← PFun.preimage_univ]; exact h _ isOpen_univ #align open_dom_of_pcontinuous open_dom_of_pcontinuous -theorem pcontinuous_iff' {f : α →. β} : +theorem pcontinuous_iff' {f : X →. Y} : PContinuous f ↔ ∀ {x y} (h : y ∈ f x), PTendsto' f (𝓝 x) (𝓝 y) := by constructor · intro h x y h' @@ -83,7 +83,7 @@ theorem pcontinuous_iff' {f : α →. β} : exact ⟨s, Set.Subset.refl _, os, ys⟩ #align pcontinuous_iff' pcontinuous_iff' -theorem continuousWithinAt_iff_ptendsto_res (f : α → β) {x : α} {s : Set α} : +theorem continuousWithinAt_iff_ptendsto_res (f : X → Y) {x : X} {s : Set X} : ContinuousWithinAt f s x ↔ PTendsto (PFun.res f s) (𝓝 x) (𝓝 (f x)) := tendsto_iff_ptendsto _ _ _ _ #align continuous_within_at_iff_ptendsto_res continuousWithinAt_iff_ptendsto_res diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index c290c93085038..928b98cd88dc3 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -10,7 +10,6 @@ import Mathlib.Topology.Sets.Opens /-! # Partial homeomorphisms -# Partial homeomorphisms This file defines homeomorphisms between open subsets of topological spaces. An element `e` of `PartialHomeomorph α β` is an extension of `PartialEquiv α β`, i.e., it is a pair of functions @@ -45,7 +44,6 @@ If a lemma deals with the intersection of a set with either source or target of then it should use `e.source ∩ s` or `e.target ∩ t`, not `s ∩ e.source` or `t ∩ e.target`. -/ - open Function Set Filter Topology variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} [TopologicalSpace α] @@ -63,7 +61,10 @@ structure PartialHomeomorph (α : Type*) (β : Type*) [TopologicalSpace α] namespace PartialHomeomorph -variable (e : PartialHomeomorph α β) (e' : PartialHomeomorph β γ) +variable (e : PartialHomeomorph α β) + +/- Basic properties; inverse (symm instance) -/ +section Basic /-- Coercion of a partial homeomorphisms to a function. We don't use `e.toFun` because it is actually `e.toPartialEquiv.toFun`, so `simp` will apply lemmas about `toPartialEquiv`. @@ -71,7 +72,7 @@ While we may want to switch to this behavior later, doing it mid-port will break @[coe] def toFun' : α → β := e.toFun /-- Coercion of a `PartialHomeomorph` to function. -Note that a `PartialHomeomorph` is not `FunLike`. -/ +Note that a `PartialHomeomorph` is not `DFunLike`. -/ instance : CoeFun (PartialHomeomorph α β) fun _ => α → β := ⟨fun e => e.toFun'⟩ @@ -200,6 +201,8 @@ protected theorem surjOn : SurjOn e e.source e.target := e.bijOn.surjOn #align local_homeomorph.surj_on PartialHomeomorph.surjOn +end Basic + /-- Interpret a `Homeomorph` as a `PartialHomeomorph` by restricting it to an open set `s` in the domain and to `t` in the codomain. -/ @[simps! (config := .asFn) apply symm_apply toPartialEquiv, @@ -228,7 +231,7 @@ def replaceEquiv (e : PartialHomeomorph α β) (e' : PartialEquiv α β) (h : e. continuousOn_invFun := h ▸ e.continuousOn_invFun #align local_homeomorph.replace_equiv PartialHomeomorph.replaceEquiv -theorem replaceEquiv_eq_self (e : PartialHomeomorph α β) (e' : PartialEquiv α β) +theorem replaceEquiv_eq_self (e' : PartialEquiv α β) (h : e.toPartialEquiv = e') : e.replaceEquiv e' h = e := by cases e subst e' @@ -240,32 +243,32 @@ theorem source_preimage_target : e.source ⊆ e ⁻¹' e.target := #align local_homeomorph.source_preimage_target PartialHomeomorph.source_preimage_target @[deprecated toPartialEquiv_injective] -theorem eq_of_localEquiv_eq {e e' : PartialHomeomorph α β} +theorem eq_of_partialEquiv_eq {e e' : PartialHomeomorph α β} (h : e.toPartialEquiv = e'.toPartialEquiv) : e = e' := toPartialEquiv_injective h -#align local_homeomorph.eq_of_local_equiv_eq PartialHomeomorph.eq_of_localEquiv_eq +#align local_homeomorph.eq_of_local_equiv_eq PartialHomeomorph.eq_of_partialEquiv_eq -theorem eventually_left_inverse (e : PartialHomeomorph α β) {x} (hx : x ∈ e.source) : +theorem eventually_left_inverse {x} (hx : x ∈ e.source) : ∀ᶠ y in 𝓝 x, e.symm (e y) = y := (e.open_source.eventually_mem hx).mono e.left_inv' #align local_homeomorph.eventually_left_inverse PartialHomeomorph.eventually_left_inverse -theorem eventually_left_inverse' (e : PartialHomeomorph α β) {x} (hx : x ∈ e.target) : +theorem eventually_left_inverse' {x} (hx : x ∈ e.target) : ∀ᶠ y in 𝓝 (e.symm x), e.symm (e y) = y := e.eventually_left_inverse (e.map_target hx) #align local_homeomorph.eventually_left_inverse' PartialHomeomorph.eventually_left_inverse' -theorem eventually_right_inverse (e : PartialHomeomorph α β) {x} (hx : x ∈ e.target) : +theorem eventually_right_inverse {x} (hx : x ∈ e.target) : ∀ᶠ y in 𝓝 x, e (e.symm y) = y := (e.open_target.eventually_mem hx).mono e.right_inv' #align local_homeomorph.eventually_right_inverse PartialHomeomorph.eventually_right_inverse -theorem eventually_right_inverse' (e : PartialHomeomorph α β) {x} (hx : x ∈ e.source) : +theorem eventually_right_inverse' {x} (hx : x ∈ e.source) : ∀ᶠ y in 𝓝 (e x), e (e.symm y) = y := e.eventually_right_inverse (e.map_source hx) #align local_homeomorph.eventually_right_inverse' PartialHomeomorph.eventually_right_inverse' -theorem eventually_ne_nhdsWithin (e : PartialHomeomorph α β) {x} (hx : x ∈ e.source) : +theorem eventually_ne_nhdsWithin {x} (hx : x ∈ e.source) : ∀ᶠ x' in 𝓝[≠] x, e x' ≠ e x := eventually_nhdsWithin_iff.2 <| (e.eventually_left_inverse hx).mono fun x' hx' => @@ -319,11 +322,11 @@ theorem source_inter_preimage_target_inter (s : Set β) : e.toPartialEquiv.source_inter_preimage_target_inter s #align local_homeomorph.source_inter_preimage_target_inter PartialHomeomorph.source_inter_preimage_target_inter -theorem image_source_eq_target (e : PartialHomeomorph α β) : e '' e.source = e.target := +theorem image_source_eq_target : e '' e.source = e.target := e.toPartialEquiv.image_source_eq_target #align local_homeomorph.image_source_eq_target PartialHomeomorph.image_source_eq_target -theorem symm_image_target_eq_source (e : PartialHomeomorph α β) : e.symm '' e.target = e.source := +theorem symm_image_target_eq_source : e.symm '' e.target = e.source := e.symm.image_source_eq_target #align local_homeomorph.symm_image_target_eq_source PartialHomeomorph.symm_image_target_eq_source @@ -392,7 +395,7 @@ theorem image_mem_nhds {x} (hx : x ∈ e.source) {s : Set α} (hs : s ∈ 𝓝 x e.map_nhds_eq hx ▸ Filter.image_mem_map hs #align local_homeomorph.image_mem_nhds PartialHomeomorph.image_mem_nhds -theorem map_nhdsWithin_eq (e : PartialHomeomorph α β) {x} (hx : x ∈ e.source) (s : Set α) : +theorem map_nhdsWithin_eq {x} (hx : x ∈ e.source) (s : Set α) : map e (𝓝[s] x) = 𝓝[e '' (e.source ∩ s)] e x := calc map e (𝓝[s] x) = map e (𝓝[e.source ∩ s] x) := @@ -403,31 +406,31 @@ theorem map_nhdsWithin_eq (e : PartialHomeomorph α β) {x} (hx : x ∈ e.source (e.continuousAt hx).continuousWithinAt #align local_homeomorph.map_nhds_within_eq PartialHomeomorph.map_nhdsWithin_eq -theorem map_nhdsWithin_preimage_eq (e : PartialHomeomorph α β) {x} (hx : x ∈ e.source) (s : Set β) : +theorem map_nhdsWithin_preimage_eq {x} (hx : x ∈ e.source) (s : Set β) : map e (𝓝[e ⁻¹' s] x) = 𝓝[s] e x := by rw [e.map_nhdsWithin_eq hx, e.image_source_inter_eq', e.target_inter_inv_preimage_preimage, e.nhdsWithin_target_inter (e.map_source hx)] #align local_homeomorph.map_nhds_within_preimage_eq PartialHomeomorph.map_nhdsWithin_preimage_eq -theorem eventually_nhds (e : PartialHomeomorph α β) {x : α} (p : β → Prop) (hx : x ∈ e.source) : +theorem eventually_nhds {x : α} (p : β → Prop) (hx : x ∈ e.source) : (∀ᶠ y in 𝓝 (e x), p y) ↔ ∀ᶠ x in 𝓝 x, p (e x) := Iff.trans (by rw [e.map_nhds_eq hx]) eventually_map #align local_homeomorph.eventually_nhds PartialHomeomorph.eventually_nhds -theorem eventually_nhds' (e : PartialHomeomorph α β) {x : α} (p : α → Prop) (hx : x ∈ e.source) : +theorem eventually_nhds' {x : α} (p : α → Prop) (hx : x ∈ e.source) : (∀ᶠ y in 𝓝 (e x), p (e.symm y)) ↔ ∀ᶠ x in 𝓝 x, p x := by rw [e.eventually_nhds _ hx] refine' eventually_congr ((e.eventually_left_inverse hx).mono fun y hy => _) rw [hy] #align local_homeomorph.eventually_nhds' PartialHomeomorph.eventually_nhds' -theorem eventually_nhdsWithin (e : PartialHomeomorph α β) {x : α} (p : β → Prop) {s : Set α} +theorem eventually_nhdsWithin {x : α} (p : β → Prop) {s : Set α} (hx : x ∈ e.source) : (∀ᶠ y in 𝓝[e.symm ⁻¹' s] e x, p y) ↔ ∀ᶠ x in 𝓝[s] x, p (e x) := by refine' Iff.trans _ eventually_map rw [e.map_nhdsWithin_eq hx, e.image_source_inter_eq', e.nhdsWithin_target_inter (e.mapsTo hx)] #align local_homeomorph.eventually_nhds_within PartialHomeomorph.eventually_nhdsWithin -theorem eventually_nhdsWithin' (e : PartialHomeomorph α β) {x : α} (p : α → Prop) {s : Set α} +theorem eventually_nhdsWithin' {x : α} (p : α → Prop) {s : Set α} (hx : x ∈ e.source) : (∀ᶠ y in 𝓝[e.symm ⁻¹' s] e x, p (e.symm y)) ↔ ∀ᶠ x in 𝓝[s] x, p x := by rw [e.eventually_nhdsWithin _ hx] refine eventually_congr <| @@ -454,17 +457,44 @@ theorem isOpen_inter_preimage {s : Set β} (hs : IsOpen s) : IsOpen (e.source e.continuousOn.isOpen_inter_preimage e.open_source hs #align local_homeomorph.preimage_open_of_open PartialHomeomorph.isOpen_inter_preimage -/-- A partial homeomorphism is an open map on its source. -/ +theorem isOpen_inter_preimage_symm {s : Set α} (hs : IsOpen s) : IsOpen (e.target ∩ e.symm ⁻¹' s) := + e.symm.continuousOn.isOpen_inter_preimage e.open_target hs +#align local_homeomorph.preimage_open_of_open_symm PartialHomeomorph.isOpen_inter_preimage_symm + +/-- A partial homeomorphism is an open map on its source: + the image of an open subset of the source is open. -/ lemma isOpen_image_of_subset_source {s : Set α} (hs : IsOpen s) (hse : s ⊆ e.source) : IsOpen (e '' s) := by rw [(image_eq_target_inter_inv_preimage (e := e) hse)] exact e.continuousOn_invFun.isOpen_inter_preimage e.open_target hs +#align local_homeomorph.image_open_of_open PartialHomeomorph.isOpen_image_of_subset_source + +/-- The image of the restriction of an open set to the source is open. -/ +theorem isOpen_image_source_inter {s : Set α} (hs : IsOpen s) : + IsOpen (e '' (e.source ∩ s)) := + e.isOpen_image_of_subset_source (e.open_source.inter hs) (inter_subset_left _ _) +#align local_homeomorph.image_open_of_open' PartialHomeomorph.isOpen_image_source_inter /-- The inverse of a partial homeomorphism `e` is an open map on `e.target`. -/ lemma isOpen_image_symm_of_subset_target {t : Set β} (ht : IsOpen t) (hte : t ⊆ e.target) : IsOpen (e.symm '' t) := isOpen_image_of_subset_source e.symm ht (e.symm_source ▸ hte) +lemma isOpen_symm_image_iff_of_subset_target {t : Set β} (hs : t ⊆ e.target) : + IsOpen (e.symm '' t) ↔ IsOpen t := by + refine ⟨fun h ↦ ?_, fun h ↦ e.symm.isOpen_image_of_subset_source h hs⟩ + have hs' : e.symm '' t ⊆ e.source := by + rw [e.symm_image_eq_source_inter_preimage hs] + apply Set.inter_subset_left + rw [← e.image_symm_image_of_subset_target hs] + exact e.isOpen_image_of_subset_source h hs' + +theorem isOpen_image_iff_of_subset_source {s : Set α} (hs : s ⊆ e.source) : + IsOpen (e '' s) ↔ IsOpen s := by + rw [← e.symm.isOpen_symm_image_iff_of_subset_target hs, e.symm_symm] + +section IsImage + /-! ### `PartialHomeomorph.IsImage` relation @@ -666,22 +696,7 @@ theorem preimage_frontier (s : Set β) : (IsImage.of_preimage_eq rfl).frontier.preimage_eq #align local_homeomorph.preimage_frontier PartialHomeomorph.preimage_frontier -theorem isOpen_inter_preimage_symm {s : Set α} (hs : IsOpen s) : IsOpen (e.target ∩ e.symm ⁻¹' s) := - e.symm.continuousOn.isOpen_inter_preimage e.open_target hs -#align local_homeomorph.preimage_open_of_open_symm PartialHomeomorph.isOpen_inter_preimage_symm - -/-- The image of an open set in the source is open. -/ -theorem image_isOpen_of_isOpen {s : Set α} (hs : IsOpen s) (h : s ⊆ e.source) : - IsOpen (e '' s) := by - have : e '' s = e.target ∩ e.symm ⁻¹' s := e.toPartialEquiv.image_eq_target_inter_inv_preimage h - rw [this] - exact e.continuousOn_symm.isOpen_inter_preimage e.open_target hs -#align local_homeomorph.image_open_of_open PartialHomeomorph.image_isOpen_of_isOpen - -/-- The image of the restriction of an open set to the source is open. -/ -theorem image_isOpen_of_isOpen' {s : Set α} (hs : IsOpen s) : IsOpen (e '' (e.source ∩ s)) := - image_isOpen_of_isOpen _ (IsOpen.inter e.open_source hs) (inter_subset_left _ _) -#align local_homeomorph.image_open_of_open' PartialHomeomorph.image_isOpen_of_isOpen' +end IsImage /-- A `PartialEquiv` with continuous open forward map and open source is a `PartialHomeomorph`. -/ def ofContinuousOpenRestrict (e : PartialEquiv α β) (hc : ContinuousOn e e.source) @@ -765,16 +780,17 @@ protected def refl (α : Type*) [TopologicalSpace α] : PartialHomeomorph α α #align local_homeomorph.refl PartialHomeomorph.refl @[simp, mfld_simps] -theorem refl_localEquiv : (PartialHomeomorph.refl α).toPartialEquiv = PartialEquiv.refl α := +theorem refl_partialEquiv : (PartialHomeomorph.refl α).toPartialEquiv = PartialEquiv.refl α := rfl -#align local_homeomorph.refl_local_equiv PartialHomeomorph.refl_localEquiv +#align local_homeomorph.refl_local_equiv PartialHomeomorph.refl_partialEquiv @[simp, mfld_simps] theorem refl_symm : (PartialHomeomorph.refl α).symm = PartialHomeomorph.refl α := rfl #align local_homeomorph.refl_symm PartialHomeomorph.refl_symm -section +/- ofSet: the identity on a set `s` -/ +section ofSet variable {s : Set α} (hs : IsOpen s) @@ -802,7 +818,12 @@ theorem ofSet_symm : (ofSet s hs).symm = ofSet s hs := theorem ofSet_univ_eq_refl : ofSet univ isOpen_univ = PartialHomeomorph.refl α := by ext <;> simp #align local_homeomorph.of_set_univ_eq_refl PartialHomeomorph.ofSet_univ_eq_refl -end +end ofSet + +/- `trans`: composition of two partial homeomorphisms -/ +section trans + +variable (e' : PartialHomeomorph β γ) /-- Composition of two partial homeomorphisms when the target of the first and the source of the second coincide. -/ @@ -811,7 +832,7 @@ protected def trans' (h : e.target = e'.source) : PartialHomeomorph α γ where toPartialEquiv := PartialEquiv.trans' e.toPartialEquiv e'.toPartialEquiv h open_source := e.open_source open_target := e'.open_target - continuousOn_toFun := e'.continuousOn.comp e.continuousOn <| h ▸ e.mapsTo + continuousOn_toFun := e'.continuousOn.comp e.continuousOn <| h ▸ e.mapsTo continuousOn_invFun := e.continuousOn_symm.comp e'.continuousOn_symm <| h.symm ▸ e'.symm_mapsTo #align local_homeomorph.trans' PartialHomeomorph.trans' @@ -925,37 +946,10 @@ theorem restr_trans (s : Set α) : (e.restr s).trans e' = (e.trans e').restr s : PartialEquiv.restr_trans e.toPartialEquiv e'.toPartialEquiv (interior s) #align local_homeomorph.restr_trans PartialHomeomorph.restr_trans -/-- Postcompose a partial homeomorphism with a homeomorphism. -We modify the source and target to have better definitional behavior. -/ -@[simps! (config := .asFn)] -def transHomeomorph (e' : β ≃ₜ γ) : PartialHomeomorph α γ where - toPartialEquiv := e.toPartialEquiv.transEquiv e'.toEquiv - open_source := e.open_source - open_target := e.open_target.preimage e'.symm.continuous - continuousOn_toFun := e'.continuous.comp_continuousOn e.continuousOn - continuousOn_invFun := e.symm.continuousOn.comp e'.symm.continuous.continuousOn fun _ => id -#align local_homeomorph.trans_homeomorph PartialHomeomorph.transHomeomorph - -theorem transHomeomorph_eq_trans (e' : β ≃ₜ γ) : - e.transHomeomorph e' = e.trans e'.toPartialHomeomorph := - toPartialEquiv_injective <| PartialEquiv.transEquiv_eq_trans _ _ -#align local_homeomorph.trans_equiv_eq_trans PartialHomeomorph.transHomeomorph_eq_trans - -/-- Precompose a partial homeomorphism with a homeomorphism. -We modify the source and target to have better definitional behavior. -/ -@[simps! (config := .asFn)] -def _root_.Homeomorph.transPartialHomeomorph (e : α ≃ₜ β) : PartialHomeomorph α γ where - toPartialEquiv := e.toEquiv.transPartialEquiv e'.toPartialEquiv - open_source := e'.open_source.preimage e.continuous - open_target := e'.open_target - continuousOn_toFun := e'.continuousOn.comp e.continuous.continuousOn fun _ => id - continuousOn_invFun := e.symm.continuous.comp_continuousOn e'.symm.continuousOn -#align homeomorph.trans_local_homeomorph Homeomorph.transPartialHomeomorph +end trans -theorem _root_.Homeomorph.transPartialHomeomorph_eq_trans (e : α ≃ₜ β) : - e.transPartialHomeomorph e' = e.toPartialHomeomorph.trans e' := - toPartialEquiv_injective <| Equiv.transPartialEquiv_eq_trans _ _ -#align homeomorph.trans_local_homeomorph_eq_trans Homeomorph.transPartialHomeomorph_eq_trans +/- `EqOnSource`: equivalence on their source -/ +section EqOnSource /-- `EqOnSource e e'` means that `e` and `e'` have the same source, and coincide there. They should really be considered the same partial equivalence. -/ @@ -1039,6 +1033,9 @@ theorem eq_of_eqOnSource_univ {e e' : PartialHomeomorph α β} (h : e ≈ e') (s toPartialEquiv_injective <| PartialEquiv.eq_of_eqOnSource_univ _ _ h s t #align local_homeomorph.eq_of_eq_on_source_univ PartialHomeomorph.eq_of_eqOnSource_univ +end EqOnSource + +/- product of two partial homeomorphisms -/ section Prod /-- The product of two partial homeomorphisms, as a partial homeomorphism on the product space. -/ @@ -1091,6 +1088,27 @@ theorem prod_eq_prod_of_nonempty' {e₁ e₁' : PartialHomeomorph α β} {e₂ e end Prod +/- finite product of partial homeomorphisms -/ +section Pi + +variable {ι : Type*} [Fintype ι] {Xi Yi : ι → Type*} [∀ i, TopologicalSpace (Xi i)] + [∀ i, TopologicalSpace (Yi i)] (ei : ∀ i, PartialHomeomorph (Xi i) (Yi i)) + +/-- The product of a finite family of `PartialHomeomorph`s. -/ +@[simps toPartialEquiv] +def pi : PartialHomeomorph (∀ i, Xi i) (∀ i, Yi i) where + toPartialEquiv := PartialEquiv.pi fun i => (ei i).toPartialEquiv + open_source := isOpen_set_pi finite_univ fun i _ => (ei i).open_source + open_target := isOpen_set_pi finite_univ fun i _ => (ei i).open_target + continuousOn_toFun := continuousOn_pi.2 fun i => + (ei i).continuousOn.comp (continuous_apply _).continuousOn fun _f hf => hf i trivial + continuousOn_invFun := continuousOn_pi.2 fun i => + (ei i).continuousOn_symm.comp (continuous_apply _).continuousOn fun _f hf => hf i trivial +#align local_homeomorph.pi PartialHomeomorph.pi + +end Pi + +/- combining two partial homeomorphisms using `Set.piecewise` -/ section Piecewise /-- Combine two `PartialHomeomorph`s using `Set.piecewise`. The source of the new @@ -1147,25 +1165,6 @@ def disjointUnion (e e' : PartialHomeomorph α β) [∀ x, Decidable (x ∈ e.so end Piecewise -section Pi - -variable {ι : Type*} [Fintype ι] {Xi Yi : ι → Type*} [∀ i, TopologicalSpace (Xi i)] - [∀ i, TopologicalSpace (Yi i)] (ei : ∀ i, PartialHomeomorph (Xi i) (Yi i)) - -/-- The product of a finite family of `PartialHomeomorph`s. -/ -@[simps toPartialEquiv] -def pi : PartialHomeomorph (∀ i, Xi i) (∀ i, Yi i) where - toPartialEquiv := PartialEquiv.pi fun i => (ei i).toPartialEquiv - open_source := isOpen_set_pi finite_univ fun i _ => (ei i).open_source - open_target := isOpen_set_pi finite_univ fun i _ => (ei i).open_target - continuousOn_toFun := continuousOn_pi.2 fun i => - (ei i).continuousOn.comp (continuous_apply _).continuousOn fun _f hf => hf i trivial - continuousOn_invFun := continuousOn_pi.2 fun i => - (ei i).continuousOn_symm.comp (continuous_apply _).continuousOn fun _f hf => hf i trivial -#align local_homeomorph.pi PartialHomeomorph.pi - -end Pi - section Continuity /-- Continuity within a set at a point can be read under right composition with a local @@ -1262,7 +1261,7 @@ def toHomeomorphSourceTarget : e.source ≃ₜ e.target := e.homeomorphOfImageSubsetSource subset_rfl e.image_source_eq_target #align local_homeomorph.to_homeomorph_source_target PartialHomeomorph.toHomeomorphSourceTarget -theorem secondCountableTopology_source [SecondCountableTopology β] (e : PartialHomeomorph α β) : +theorem secondCountableTopology_source [SecondCountableTopology β] : SecondCountableTopology e.source := e.toHomeomorphSourceTarget.secondCountableTopology #align local_homeomorph.second_countable_topology_source PartialHomeomorph.secondCountableTopology_source @@ -1299,7 +1298,7 @@ theorem openEmbedding_restrict : OpenEmbedding (e.source.restrict e) := by refine openEmbedding_of_continuous_injective_open (e.continuousOn.comp_continuous continuous_subtype_val Subtype.prop) e.injOn.injective fun V hV ↦ ?_ rw [Set.restrict_eq, Set.image_comp] - exact e.image_isOpen_of_isOpen (e.open_source.isOpenMap_subtype_val V hV) + exact e.isOpen_image_of_subset_source (e.open_source.isOpenMap_subtype_val V hV) fun _ ⟨x, _, h⟩ ↦ h ▸ x.2 /-- A partial homeomorphism whose source is all of `α` defines an open embedding of `α` into `β`. @@ -1335,6 +1334,35 @@ theorem trans_toPartialHomeomorph : PartialHomeomorph.toPartialEquiv_injective <| Equiv.trans_toPartialEquiv _ _ #align homeomorph.trans_to_local_homeomorph Homeomorph.trans_toPartialHomeomorph +/-- Precompose a partial homeomorphism with a homeomorphism. +We modify the source and target to have better definitional behavior. -/ +@[simps! (config := .asFn)] +def transPartialHomeomorph (e : α ≃ₜ β) (f' : PartialHomeomorph β γ) : PartialHomeomorph α γ where + toPartialEquiv := e.toEquiv.transPartialEquiv f'.toPartialEquiv + open_source := f'.open_source.preimage e.continuous + open_target := f'.open_target + continuousOn_toFun := f'.continuousOn.comp e.continuous.continuousOn fun _ => id + continuousOn_invFun := e.symm.continuous.comp_continuousOn f'.symm.continuousOn +#align homeomorph.trans_local_homeomorph Homeomorph.transPartialHomeomorph + +theorem transPartialHomeomorph_eq_trans (e : α ≃ₜ β) (f' : PartialHomeomorph β γ) : + e.transPartialHomeomorph f' = e.toPartialHomeomorph.trans f' := + PartialHomeomorph.toPartialEquiv_injective <| Equiv.transPartialEquiv_eq_trans _ _ +#align homeomorph.trans_local_homeomorph_eq_trans Homeomorph.transPartialHomeomorph_eq_trans + +@[simp, mfld_simps] +theorem transPartialHomeomorph_trans (e : α ≃ₜ β) (f : PartialHomeomorph β γ) + (f' : PartialHomeomorph γ δ) : + (e.transPartialHomeomorph f).trans f' = e.transPartialHomeomorph (f.trans f') := by + simp only [transPartialHomeomorph_eq_trans, PartialHomeomorph.trans_assoc] + +@[simp, mfld_simps] +theorem trans_transPartialHomeomorph (e : α ≃ₜ β) (e' : β ≃ₜ γ) (f'' : PartialHomeomorph γ δ) : + (e.trans e').transPartialHomeomorph f'' = + e.transPartialHomeomorph (e'.transPartialHomeomorph f'') := by + simp only [transPartialHomeomorph_eq_trans, PartialHomeomorph.trans_assoc, + trans_toPartialHomeomorph] + end Homeomorph namespace OpenEmbedding @@ -1362,38 +1390,71 @@ lemma toPartialHomeomorph_right_inv {x : β} (hx : x ∈ Set.range f) : end OpenEmbedding +/- inclusion of an open set in a topological space -/ namespace TopologicalSpace.Opens -open TopologicalSpace - variable (s : Opens α) [Nonempty s] /-- The inclusion of an open subset `s` of a space `α` into `α` is a partial homeomorphism from the subtype `s` to `α`. -/ -noncomputable def localHomeomorphSubtypeCoe : PartialHomeomorph s α := +noncomputable def partialHomeomorphSubtypeCoe : PartialHomeomorph s α := OpenEmbedding.toPartialHomeomorph _ s.2.openEmbedding_subtype_val -#align topological_space.opens.local_homeomorph_subtype_coe TopologicalSpace.Opens.localHomeomorphSubtypeCoe +#align topological_space.opens.local_homeomorph_subtype_coe TopologicalSpace.Opens.partialHomeomorphSubtypeCoe @[simp, mfld_simps] -theorem localHomeomorphSubtypeCoe_coe : (s.localHomeomorphSubtypeCoe : s → α) = (↑) := +theorem partialHomeomorphSubtypeCoe_coe : (s.partialHomeomorphSubtypeCoe : s → α) = (↑) := rfl -#align topological_space.opens.local_homeomorph_subtype_coe_coe TopologicalSpace.Opens.localHomeomorphSubtypeCoe_coe +#align topological_space.opens.local_homeomorph_subtype_coe_coe TopologicalSpace.Opens.partialHomeomorphSubtypeCoe_coe @[simp, mfld_simps] -theorem localHomeomorphSubtypeCoe_source : s.localHomeomorphSubtypeCoe.source = Set.univ := +theorem partialHomeomorphSubtypeCoe_source : s.partialHomeomorphSubtypeCoe.source = Set.univ := rfl -#align topological_space.opens.local_homeomorph_subtype_coe_source TopologicalSpace.Opens.localHomeomorphSubtypeCoe_source +#align topological_space.opens.local_homeomorph_subtype_coe_source TopologicalSpace.Opens.partialHomeomorphSubtypeCoe_source @[simp, mfld_simps] -theorem localHomeomorphSubtypeCoe_target : s.localHomeomorphSubtypeCoe.target = s := by - simp only [localHomeomorphSubtypeCoe, Subtype.range_coe_subtype, mfld_simps] +theorem partialHomeomorphSubtypeCoe_target : s.partialHomeomorphSubtypeCoe.target = s := by + simp only [partialHomeomorphSubtypeCoe, Subtype.range_coe_subtype, mfld_simps] rfl -#align topological_space.opens.local_homeomorph_subtype_coe_target TopologicalSpace.Opens.localHomeomorphSubtypeCoe_target +#align topological_space.opens.local_homeomorph_subtype_coe_target TopologicalSpace.Opens.partialHomeomorphSubtypeCoe_target end TopologicalSpace.Opens namespace PartialHomeomorph +/- post-compose with a partial homeomorphism -/ +section transHomeomorph + +/-- Postcompose a partial homeomorphism with a homeomorphism. +We modify the source and target to have better definitional behavior. -/ +@[simps! (config := .asFn)] +def transHomeomorph (e : PartialHomeomorph α β) (f' : β ≃ₜ γ) : PartialHomeomorph α γ where + toPartialEquiv := e.toPartialEquiv.transEquiv f'.toEquiv + open_source := e.open_source + open_target := e.open_target.preimage f'.symm.continuous + continuousOn_toFun := f'.continuous.comp_continuousOn e.continuousOn + continuousOn_invFun := e.symm.continuousOn.comp f'.symm.continuous.continuousOn fun _ => id +#align local_homeomorph.trans_homeomorph PartialHomeomorph.transHomeomorph + +theorem transHomeomorph_eq_trans (e : PartialHomeomorph α β) (f' : β ≃ₜ γ) : + e.transHomeomorph f' = e.trans f'.toPartialHomeomorph := + toPartialEquiv_injective <| PartialEquiv.transEquiv_eq_trans _ _ +#align local_homeomorph.trans_equiv_eq_trans PartialHomeomorph.transHomeomorph_eq_trans + +@[simp, mfld_simps] +theorem transHomeomorph_transHomeomorph (e : PartialHomeomorph α β) (f' : β ≃ₜ γ) (f'' : γ ≃ₜ δ) : + (e.transHomeomorph f').transHomeomorph f'' = e.transHomeomorph (f'.trans f'') := by + simp only [transHomeomorph_eq_trans, trans_assoc, Homeomorph.trans_toPartialHomeomorph] + +@[simp, mfld_simps] +theorem trans_transHomeomorph (e : PartialHomeomorph α β) (e' : PartialHomeomorph β γ) + (f'' : γ ≃ₜ δ) : + (e.trans e').transHomeomorph f'' = e.trans (e'.transHomeomorph f'') := by + simp only [transHomeomorph_eq_trans, trans_assoc, Homeomorph.trans_toPartialHomeomorph] + +end transHomeomorph + +/- `subtypeRestr`: restriction to a subtype -/ +section subtypeRestr open TopologicalSpace variable (e : PartialHomeomorph α β) @@ -1403,10 +1464,10 @@ variable (s : Opens α) [Nonempty s] /-- The restriction of a partial homeomorphism `e` to an open subset `s` of the domain type produces a partial homeomorphism whose domain is the subtype `s`. -/ noncomputable def subtypeRestr : PartialHomeomorph s β := - s.localHomeomorphSubtypeCoe.trans e + s.partialHomeomorphSubtypeCoe.trans e #align local_homeomorph.subtype_restr PartialHomeomorph.subtypeRestr -theorem subtypeRestr_def : e.subtypeRestr s = s.localHomeomorphSubtypeCoe.trans e := +theorem subtypeRestr_def : e.subtypeRestr s = s.partialHomeomorphSubtypeCoe.trans e := rfl #align local_homeomorph.subtype_restr_def PartialHomeomorph.subtypeRestr_def @@ -1421,16 +1482,13 @@ theorem subtypeRestr_source : (e.subtypeRestr s).source = (↑) ⁻¹' e.source simp only [subtypeRestr_def, mfld_simps] #align local_homeomorph.subtype_restr_source PartialHomeomorph.subtypeRestr_source -variable {s} - +variable {s} in theorem map_subtype_source {x : s} (hxe : (x : α) ∈ e.source): e x ∈ (e.subtypeRestr s).target := by refine' ⟨e.map_source hxe, _⟩ - rw [s.localHomeomorphSubtypeCoe_target, mem_preimage, e.leftInvOn hxe] + rw [s.partialHomeomorphSubtypeCoe_target, mem_preimage, e.leftInvOn hxe] exact x.prop #align local_homeomorph.map_subtype_source PartialHomeomorph.map_subtype_source -variable (s) - /- This lemma characterizes the transition functions of an open subset in terms of the transition functions of the original space. -/ theorem subtypeRestr_symm_trans_subtypeRestr (f f' : PartialHomeomorph α β) : @@ -1447,7 +1505,7 @@ theorem subtypeRestr_symm_trans_subtypeRestr (f f' : PartialHomeomorph α β) : rw [ofSet_trans', sets_identity, ← trans_of_set' _ openness₂, trans_assoc] refine' EqOnSource.trans' (eqOnSource_refl _) _ -- f has been eliminated !!! - refine' Setoid.trans (symm_trans_self s.localHomeomorphSubtypeCoe) _ + refine' Setoid.trans (symm_trans_self s.partialHomeomorphSubtypeCoe) _ simp only [mfld_simps, Setoid.refl] #align local_homeomorph.subtype_restr_symm_trans_subtype_restr PartialHomeomorph.subtypeRestr_symm_trans_subtypeRestr @@ -1465,17 +1523,19 @@ theorem subtypeRestr_symm_eqOn_of_le {U V : Opens α} [Nonempty U] [Nonempty V] set i := Set.inclusion hUV intro y hy dsimp [PartialHomeomorph.subtypeRestr_def] at hy ⊢ - have hyV : e.symm y ∈ V.localHomeomorphSubtypeCoe.target := by - rw [Opens.localHomeomorphSubtypeCoe_target] at hy ⊢ + have hyV : e.symm y ∈ V.partialHomeomorphSubtypeCoe.target := by + rw [Opens.partialHomeomorphSubtypeCoe_target] at hy ⊢ exact hUV hy.2 - refine' V.localHomeomorphSubtypeCoe.injOn _ trivial _ + refine' V.partialHomeomorphSubtypeCoe.injOn _ trivial _ · rw [← PartialHomeomorph.symm_target] apply PartialHomeomorph.map_source rw [PartialHomeomorph.symm_source] exact hyV - · rw [V.localHomeomorphSubtypeCoe.right_inv hyV] - show _ = U.localHomeomorphSubtypeCoe _ - rw [U.localHomeomorphSubtypeCoe.right_inv hy.2] + · rw [V.partialHomeomorphSubtypeCoe.right_inv hyV] + show _ = U.partialHomeomorphSubtypeCoe _ + rw [U.partialHomeomorphSubtypeCoe.right_inv hy.2] #align local_homeomorph.subtype_restr_symm_eq_on_of_le PartialHomeomorph.subtypeRestr_symm_eqOn_of_le +end subtypeRestr + end PartialHomeomorph diff --git a/Mathlib/Topology/PartitionOfUnity.lean b/Mathlib/Topology/PartitionOfUnity.lean index 0db4ce7f6f92b..3289109acb78d 100644 --- a/Mathlib/Topology/PartitionOfUnity.lean +++ b/Mathlib/Topology/PartitionOfUnity.lean @@ -16,8 +16,9 @@ import Mathlib.Topology.UrysohnsLemma # Continuous partition of unity In this file we define `PartitionOfUnity (ι X : Type*) [TopologicalSpace X] (s : Set X := univ)` -to be a continuous partition of unity on `s` indexed by `ι`. More precisely, `f : PartitionOfUnity -ι X s` is a collection of continuous functions `f i : C(X, ℝ)`, `i : ι`, such that +to be a continuous partition of unity on `s` indexed by `ι`. More precisely, +`f : PartitionOfUnity ι X s` is a collection of continuous functions `f i : C(X, ℝ)`, `i : ι`, +such that * the supports of `f i` form a locally finite family of sets; * each `f i` is nonnegative; @@ -134,7 +135,7 @@ namespace PartitionOfUnity variable {E : Type*} [AddCommMonoid E] [SMulWithZero ℝ E] [TopologicalSpace E] [ContinuousSMul ℝ E] {s : Set X} (f : PartitionOfUnity ι X s) -instance : FunLike (PartitionOfUnity ι X s) ι fun _ ↦ C(X, ℝ) where +instance : FunLike (PartitionOfUnity ι X s) ι C(X, ℝ) where coe := toFun coe_injective' := fun f g h ↦ by cases f; cases g; congr @@ -174,6 +175,51 @@ theorem le_one (i : ι) (x : X) : f i x ≤ 1 := (single_le_finsum i (f.locallyFinite.point_finite x) fun j => f.nonneg j x).trans (f.sum_le_one x) #align partition_of_unity.le_one PartitionOfUnity.le_one +section finsupport + +variable {s : Set X} (ρ : PartitionOfUnity ι X s) (x₀ : X) + +/-- The support of a partition of unity at a point `x₀` as a `Finset`. + This is the set of `i : ι` such that `f i` doesn't vanish at `x₀`. -/ +def finsupport : Finset ι := (ρ.locallyFinite.point_finite x₀).toFinset + +@[simp] +theorem mem_finsupport (x₀ : X) {i} : + i ∈ ρ.finsupport x₀ ↔ i ∈ support fun i ↦ ρ i x₀ := by + simp only [finsupport, mem_support, Finite.mem_toFinset, mem_setOf_eq] + +@[simp] +theorem coe_finsupport (x₀ : X) : + (ρ.finsupport x₀ : Set ι) = support fun i ↦ ρ i x₀ := by + ext + rw [Finset.mem_coe, mem_finsupport] + +variable {x₀ : X} + +theorem sum_finsupport (hx₀ : x₀ ∈ s) : ∑ i in ρ.finsupport x₀, ρ i x₀ = 1 := by + rw [← ρ.sum_eq_one hx₀, finsum_eq_sum_of_support_subset _ (ρ.coe_finsupport x₀).superset] + +theorem sum_finsupport' (hx₀ : x₀ ∈ s) {I : Finset ι} (hI : ρ.finsupport x₀ ⊆ I) : + ∑ i in I, ρ i x₀ = 1 := by + classical + rw [← Finset.sum_sdiff hI, ρ.sum_finsupport hx₀] + suffices ∑ i in I \ ρ.finsupport x₀, (ρ i) x₀ = ∑ i in I \ ρ.finsupport x₀, 0 by + rw [this, add_left_eq_self, Finset.sum_const_zero] + apply Finset.sum_congr rfl + rintro x hx + simp only [Finset.mem_sdiff, ρ.mem_finsupport, mem_support, Classical.not_not] at hx + exact hx.2 + +theorem sum_finsupport_smul_eq_finsum {M : Type _} [AddCommGroup M] [Module ℝ M] (φ : ι → X → M) : + ∑ i in ρ.finsupport x₀, ρ i x₀ • φ i x₀ = ∑ᶠ i, ρ i x₀ • φ i x₀ := by + apply (finsum_eq_sum_of_support_subset _ _).symm + have : (fun i ↦ (ρ i) x₀ • φ i x₀) = (fun i ↦ (ρ i) x₀) • (fun i ↦ φ i x₀) := + funext fun _ => (Pi.smul_apply' _ _ _).symm + rw [ρ.coe_finsupport x₀, this, support_smul] + exact inter_subset_left _ _ + +end finsupport + /-- If `f` is a partition of unity on `s : Set X` and `g : X → E` is continuous at every point of the topological support of some `f i`, then `fun x ↦ f i x • g x` is continuous on the whole space. -/ @@ -201,6 +247,20 @@ def IsSubordinate (U : ι → Set X) : Prop := variable {f} +theorem exists_finset_nhd' {s : Set X} (ρ : PartitionOfUnity ι X s) (x₀ : X) : + ∃ I : Finset ι, (∀ᶠ x in 𝓝[s] x₀, ∑ i in I, ρ i x = 1) ∧ + ∀ᶠ x in 𝓝 x₀, support (ρ · x) ⊆ I := by + rcases ρ.locallyFinite.exists_finset_support x₀ with ⟨I, hI⟩ + refine ⟨I, eventually_nhdsWithin_iff.mpr (hI.mono fun x hx x_in ↦ ?_), hI⟩ + have : ∑ᶠ i : ι, ρ i x = ∑ i : ι in I, ρ i x := finsum_eq_sum_of_support_subset _ hx + rwa [eq_comm, ρ.sum_eq_one x_in] at this + +theorem exists_finset_nhd (ρ : PartitionOfUnity ι X univ) (x₀ : X) : + ∃ I : Finset ι, ∀ᶠ x in 𝓝 x₀, ∑ i in I, ρ i x = 1 ∧ support (ρ · x) ⊆ I := by + rcases ρ.exists_finset_nhd' x₀ with ⟨I, H⟩ + use I + rwa [nhdsWithin_univ, ← eventually_and] at H + theorem exists_finset_nhd_support_subset {U : ι → Set X} (hso : f.IsSubordinate U) (ho : ∀ i, IsOpen (U i)) (x : X) : ∃ (is : Finset ι), ∃ n ∈ 𝓝 x, n ⊆ ⋂ i ∈ is, U i ∧ ∀ z ∈ n, (support (f · z)) ⊆ is := @@ -222,7 +282,7 @@ namespace BumpCovering variable {s : Set X} (f : BumpCovering ι X s) -instance : FunLike (BumpCovering ι X s) ι fun _ ↦ C(X, ℝ) where +instance : FunLike (BumpCovering ι X s) ι C(X, ℝ) where coe := toFun coe_injective' := fun f g h ↦ by cases f; cases g; congr diff --git a/Mathlib/Topology/Separation.lean b/Mathlib/Topology/Separation.lean index f48b19e899032..592769941c51f 100644 --- a/Mathlib/Topology/Separation.lean +++ b/Mathlib/Topology/Separation.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Topology.Compactness.SigmaCompact -import Mathlib.Topology.Connected.LocallyConnected import Mathlib.Topology.Connected.TotallyDisconnected import Mathlib.Topology.Inseparable @@ -59,7 +58,7 @@ This file defines the predicate `SeparatedNhds`, and common separation axioms * `t2_iff_nhds`: A space is T₂ iff the neighbourhoods of distinct points generate the bottom filter. * `t2_iff_isClosed_diagonal`: A space is T₂ iff the `diagonal` of `X` (that is, the set of all points of the form `(a, a) : X × X`) is closed under the product topology. -* `finset_disjoint_finset_opens_of_t2`: Any two disjoint finsets are `SeparatedNhds`. +* `separatedNhds_of_finset_finset`: Any two disjoint finsets are `SeparatedNhds`. * Most topological constructions preserve Hausdorffness; these results are part of the typeclass inference system (e.g. `Embedding.t2Space`) * `Set.EqOn.closure`: If two functions are equal on some set `s`, they are equal on its closure. @@ -149,11 +148,11 @@ theorem disjoint_closure_right (h : SeparatedNhds s t) : Disjoint s (closure t) h.symm.disjoint_closure_left.symm #align separated_nhds.disjoint_closure_right SeparatedNhds.disjoint_closure_right -theorem empty_right (s : Set X) : SeparatedNhds s ∅ := +@[simp] theorem empty_right (s : Set X) : SeparatedNhds s ∅ := ⟨_, _, isOpen_univ, isOpen_empty, fun a _ => mem_univ a, Subset.rfl, disjoint_empty _⟩ #align separated_nhds.empty_right SeparatedNhds.empty_right -theorem empty_left (s : Set X) : SeparatedNhds ∅ s := +@[simp] theorem empty_left (s : Set X) : SeparatedNhds ∅ s := (empty_right _).symm #align separated_nhds.empty_left SeparatedNhds.empty_left @@ -237,7 +236,7 @@ theorem inseparable_eq_eq [T0Space X] : Inseparable = @Eq X := theorem TopologicalSpace.IsTopologicalBasis.inseparable_iff {b : Set (Set X)} (hb : IsTopologicalBasis b) {x y : X} : Inseparable x y ↔ ∀ s ∈ b, (x ∈ s ↔ y ∈ s) := ⟨fun h s hs ↦ inseparable_iff_forall_open.1 h _ (hb.isOpen hs), - fun h ↦ hb.nhds_hasBasis.eq_of_same_basis $ by + fun h ↦ hb.nhds_hasBasis.eq_of_same_basis <| by convert hb.nhds_hasBasis using 2 exact and_congr_right (h _)⟩ @@ -842,7 +841,7 @@ theorem ConnectedSpace.infinite [ConnectedSpace X] [Nontrivial X] [T1Space X] : #align connected_space.infinite ConnectedSpace.infinite /-- A non-trivial connected T1 space has no isolated points. -/ -instance ConnectedSpace.neBot_nhdsWithin_compl_of_nontrivial_of_t1space +instance (priority := 100) ConnectedSpace.neBot_nhdsWithin_compl_of_nontrivial_of_t1space [ConnectedSpace X] [Nontrivial X] [T1Space X] (x : X) : NeBot (𝓝[≠] x) := by by_contra contra @@ -1336,22 +1335,23 @@ theorem Function.LeftInverse.closedEmbedding [T2Space X] {f : X → Y} {g : Y ⟨h.embedding hf hg, h.closed_range hf hg⟩ #align function.left_inverse.closed_embedding Function.LeftInverse.closedEmbedding -theorem isCompact_isCompact_separated [T2Space X] {s t : Set X} (hs : IsCompact s) +theorem separatedNhds_of_isCompact_isCompact [T2Space X] {s t : Set X} (hs : IsCompact s) (ht : IsCompact t) (hst : Disjoint s t) : SeparatedNhds s t := by simp only [SeparatedNhds, prod_subset_compl_diagonal_iff_disjoint.symm] at hst ⊢ exact generalized_tube_lemma hs ht isClosed_diagonal.isOpen_compl hst -#align is_compact_is_compact_separated isCompact_isCompact_separated +#align is_compact_is_compact_separated separatedNhds_of_isCompact_isCompact section SeparatedFinset -theorem finset_disjoint_finset_opens_of_t2 [T2Space X] (s t : Finset X) (h : Disjoint s t) : +theorem separatedNhds_of_finset_finset [T2Space X] (s t : Finset X) (h : Disjoint s t) : SeparatedNhds (s : Set X) t := - isCompact_isCompact_separated s.finite_toSet.isCompact t.finite_toSet.isCompact <| mod_cast h -#align finset_disjoint_finset_opens_of_t2 finset_disjoint_finset_opens_of_t2 + separatedNhds_of_isCompact_isCompact s.finite_toSet.isCompact t.finite_toSet.isCompact + <| mod_cast h +#align finset_disjoint_finset_opens_of_t2 separatedNhds_of_finset_finset theorem point_disjoint_finset_opens_of_t2 [T2Space X] {x : X} {s : Finset X} (h : x ∉ s) : SeparatedNhds ({x} : Set X) s := - mod_cast finset_disjoint_finset_opens_of_t2 {x} s (Finset.disjoint_singleton_left.mpr h) + mod_cast separatedNhds_of_finset_finset {x} s (Finset.disjoint_singleton_left.mpr h) #align point_disjoint_finset_opens_of_t2 point_disjoint_finset_opens_of_t2 end SeparatedFinset @@ -1360,7 +1360,7 @@ end SeparatedFinset theorem IsCompact.isClosed [T2Space X] {s : Set X} (hs : IsCompact s) : IsClosed s := isOpen_compl_iff.1 <| isOpen_iff_forall_mem_open.mpr fun x hx => let ⟨u, v, _, vo, su, xv, uv⟩ := - isCompact_isCompact_separated hs isCompact_singleton (disjoint_singleton_right.2 hx) + separatedNhds_of_isCompact_isCompact hs isCompact_singleton (disjoint_singleton_right.2 hx) ⟨v, (uv.mono_left <| show s ≤ u from su).subset_compl_left, vo, by simpa using xv⟩ #align is_compact.is_closed IsCompact.isClosed @@ -1399,36 +1399,12 @@ theorem IsCompact.inter [T2Space X] {s t : Set X} (hs : IsCompact s) (ht : IsCom hs.inter_right <| ht.isClosed #align is_compact.inter IsCompact.inter -theorem isCompact_closure_of_subset_compact [T2Space X] {s t : Set X} (ht : IsCompact t) - (h : s ⊆ t) : IsCompact (closure s) := - ht.of_isClosed_subset isClosed_closure (closure_minimal h ht.isClosed) -#align is_compact_closure_of_subset_compact isCompact_closure_of_subset_compact - -@[simp] -theorem exists_compact_superset_iff [T2Space X] {s : Set X} : - (∃ K, IsCompact K ∧ s ⊆ K) ↔ IsCompact (closure s) := - ⟨fun ⟨_K, hK, hsK⟩ => isCompact_closure_of_subset_compact hK hsK, fun h => - ⟨closure s, h, subset_closure⟩⟩ -#align exists_compact_superset_iff exists_compact_superset_iff - theorem image_closure_of_isCompact [T2Space Y] {s : Set X} (hs : IsCompact (closure s)) {f : X → Y} (hf : ContinuousOn f (closure s)) : f '' closure s = closure (f '' s) := Subset.antisymm hf.image_closure <| closure_minimal (image_subset f subset_closure) (hs.image_of_continuousOn hf).isClosed #align image_closure_of_is_compact image_closure_of_isCompact -/-- If a compact set is covered by two open sets, then we can cover it by two compact subsets. -/ -theorem IsCompact.binary_compact_cover [T2Space X] {K U V : Set X} (hK : IsCompact K) - (hU : IsOpen U) (hV : IsOpen V) (h2K : K ⊆ U ∪ V) : - ∃ K₁ K₂ : Set X, IsCompact K₁ ∧ IsCompact K₂ ∧ K₁ ⊆ U ∧ K₂ ⊆ V ∧ K = K₁ ∪ K₂ := by - obtain ⟨O₁, O₂, h1O₁, h1O₂, h2O₁, h2O₂, hO⟩ := - isCompact_isCompact_separated (hK.diff hU) (hK.diff hV) - (by rwa [disjoint_iff_inter_eq_empty, diff_inter_diff, diff_eq_empty]) - exact - ⟨_, _, hK.diff h1O₁, hK.diff h1O₂, by rwa [diff_subset_comm], by rwa [diff_subset_comm], by - rw [← diff_inter, hO.inter_eq, diff_empty]⟩ -#align is_compact.binary_compact_cover IsCompact.binary_compact_cover - /-- A continuous map from a compact space to a Hausdorff space is a closed map. -/ protected theorem Continuous.isClosedMap [CompactSpace X] [T2Space Y] {f : X → Y} (h : Continuous f) : IsClosedMap f := fun _s hs => (hs.isCompact.image h).isClosed @@ -1446,37 +1422,6 @@ theorem QuotientMap.of_surjective_continuous [CompactSpace X] [T2Space Y] {f : X hcont.isClosedMap.to_quotientMap hcont hsurj #align quotient_map.of_surjective_continuous QuotientMap.of_surjective_continuous -section - -open Finset Function - -/-- For every finite open cover `Uᵢ` of a compact set, there exists a compact cover `Kᵢ ⊆ Uᵢ`. -/ -theorem IsCompact.finite_compact_cover [T2Space X] {s : Set X} (hs : IsCompact s) {ι} (t : Finset ι) - (U : ι → Set X) (hU : ∀ i ∈ t, IsOpen (U i)) (hsC : s ⊆ ⋃ i ∈ t, U i) : - ∃ K : ι → Set X, (∀ i, IsCompact (K i)) ∧ (∀ i, K i ⊆ U i) ∧ s = ⋃ i ∈ t, K i := by - induction' t using Finset.induction with x t hx ih generalizing U s - · refine' ⟨fun _ => ∅, fun _ => isCompact_empty, fun i => empty_subset _, _⟩ - simpa only [subset_empty_iff, Finset.not_mem_empty, iUnion_false, iUnion_empty] using hsC - simp only [Finset.set_biUnion_insert] at hsC - simp only [Finset.forall_mem_insert] at hU - have hU' : ∀ i ∈ t, IsOpen (U i) := fun i hi => hU.2 i hi - rcases hs.binary_compact_cover hU.1 (isOpen_biUnion hU') hsC with - ⟨K₁, K₂, h1K₁, h1K₂, h2K₁, h2K₂, hK⟩ - rcases ih h1K₂ U hU' h2K₂ with ⟨K, h1K, h2K, h3K⟩ - refine' ⟨update K x K₁, _, _, _⟩ - · intro i - rcases eq_or_ne i x with rfl | hi - · simp only [update_same, h1K₁] - · simp only [update_noteq hi, h1K] - · intro i - rcases eq_or_ne i x with rfl | hi - · simp only [update_same, h2K₁] - · simp only [update_noteq hi, h2K] - · simp only [set_biUnion_insert_update _ hx, hK, h3K] -#align is_compact.finite_compact_cover IsCompact.finite_compact_cover - -end - instance (priority := 900) [WeaklyLocallyCompactSpace X] [T2Space Y] : LocallyCompactPair X Y where exists_mem_nhds_isCompact_mapsTo := by intro f x s hf hs @@ -1484,7 +1429,7 @@ instance (priority := 900) [WeaklyLocallyCompactSpace X] [T2Space Y] : LocallyCo have hc : IsCompact (f '' K \ interior s) := (hKc.image hf).diff isOpen_interior have hd : Disjoint {f x} (f '' K \ interior s) := disjoint_singleton_left.2 fun h ↦ h.2 <| mem_interior_iff_mem_nhds.2 hs - rcases isCompact_isCompact_separated isCompact_singleton hc hd + rcases separatedNhds_of_isCompact_isCompact isCompact_singleton hc hd with ⟨U, V, Uo, Vo, hxU, hV, hd⟩ refine ⟨K \ f ⁻¹' V, diff_mem hKx ?_, hKc.diff <| Vo.preimage hf, fun y hy ↦ ?_⟩ · filter_upwards [hf.continuousAt <| Uo.mem_nhds (hxU rfl)] with x hx @@ -1492,50 +1437,6 @@ instance (priority := 900) [WeaklyLocallyCompactSpace X] [T2Space Y] : LocallyCo · by_contra hys exact hy.2 (hV ⟨mem_image_of_mem _ hy.1, not_mem_subset interior_subset hys⟩) --- see Note [lower instance priority] -/-- A weakly locally compact Hausdorff space is locally compact. -/ -instance WeaklyLocallyCompactSpace.locallyCompactSpace [WeaklyLocallyCompactSpace X] [T2Space X] : - LocallyCompactSpace X := - ⟨fun _ _ h => - let ⟨K, hKx, hKc, hKs⟩ := exists_mem_nhds_isCompact_mapsTo continuous_id h - ⟨K, hKx, hKs, hKc⟩⟩ -#align locally_compact_of_compact_nhds WeaklyLocallyCompactSpace.locallyCompactSpace - -@[deprecated WeaklyLocallyCompactSpace.locallyCompactSpace] -theorem locally_compact_of_compact [T2Space X] [CompactSpace X] : - LocallyCompactSpace X := - inferInstance -#align locally_compact_of_compact locally_compact_of_compact - -/-- In a weakly locally compact T₂ space, -every compact set has an open neighborhood with compact closure. -/ -theorem exists_open_superset_and_isCompact_closure [WeaklyLocallyCompactSpace X] [T2Space X] - {K : Set X} (hK : IsCompact K) : ∃ V, IsOpen V ∧ K ⊆ V ∧ IsCompact (closure V) := by - rcases exists_compact_superset hK with ⟨K', hK', hKK'⟩ - exact ⟨interior K', isOpen_interior, hKK', - isCompact_closure_of_subset_compact hK' interior_subset⟩ -#align exists_open_superset_and_is_compact_closure exists_open_superset_and_isCompact_closure - -/-- In a weakly locally compact T₂ space, -every point has an open neighborhood with compact closure. -/ -theorem exists_open_with_compact_closure [WeaklyLocallyCompactSpace X] [T2Space X] (x : X) : - ∃ U : Set X, IsOpen U ∧ x ∈ U ∧ IsCompact (closure U) := by - simpa only [singleton_subset_iff] - using exists_open_superset_and_isCompact_closure isCompact_singleton -#align exists_open_with_compact_closure exists_open_with_compact_closure - -/-- In a locally compact T₂ space, given a compact set `K` inside an open set `U`, we can find an -open set `V` between these sets with compact closure: `K ⊆ V` and the closure of `V` is inside `U`. --/ -theorem exists_open_between_and_isCompact_closure [LocallyCompactSpace X] [T2Space X] {K U : Set X} - (hK : IsCompact K) (hU : IsOpen U) (hKU : K ⊆ U) : - ∃ V, IsOpen V ∧ K ⊆ V ∧ closure V ⊆ U ∧ IsCompact (closure V) := by - rcases exists_compact_between hK hU hKU with ⟨V, hV, hKV, hVU⟩ - exact - ⟨interior V, isOpen_interior, hKV, (closure_minimal interior_subset hV.isClosed).trans hVU, - isCompact_closure_of_subset_compact hV interior_subset⟩ -#align exists_open_between_and_is_compact_closure exists_open_between_and_isCompact_closure - theorem isPreirreducible_iff_subsingleton [T2Space X] {S : Set X} : IsPreirreducible S ↔ S.Subsingleton := by refine' ⟨fun h x hx y hy => _, Set.Subsingleton.isPreirreducible⟩ @@ -1625,7 +1526,7 @@ theorem RegularSpace.ofExistsMemNhdsIsClosedSubset #align regular_space.of_exists_mem_nhds_is_closed_subset RegularSpace.ofExistsMemNhdsIsClosedSubset /-- A locally compact T2 space is regular. -/ -instance [LocallyCompactSpace X] [T2Space X] : RegularSpace X := by +instance (priority := 100) [LocallyCompactSpace X] [T2Space X] : RegularSpace X := by apply RegularSpace.ofExistsMemNhdsIsClosedSubset (fun x s hx ↦ ?_) rcases local_compact_nhds hx with ⟨k, kx, ks, hk⟩ exact ⟨k, kx, hk.isClosed, ks⟩ @@ -1751,29 +1652,50 @@ instance {ι : Type*} {X : ι → Type*} [∀ i, TopologicalSpace (X i)] [∀ i, RegularSpace (∀ i, X i) := regularSpace_iInf fun _ => regularSpace_induced _ +/-- In a regular space, if a compact set and a closed set are disjoint, then they have disjoint +neighborhoods. -/ +lemma separatedNhds_of_isCompact_isClosed [RegularSpace X] {s t : Set X} + (hs : IsCompact s) (ht : IsClosed t) (hst : Disjoint s t) : SeparatedNhds s t := by + apply hs.induction_on (p := fun u ↦ SeparatedNhds u t) + · simp + · intro s u su hu + exact hu.mono su Subset.rfl + · intro u v hu hv + exact hu.union_left hv + · intro x hx + have : tᶜ ∈ 𝓝 x := ht.isOpen_compl.mem_nhds (disjoint_left.1 hst hx) + rcases exists_mem_nhds_isClosed_subset this with ⟨u, u_mem, u_closed, hu⟩ + refine ⟨interior u, mem_nhdsWithin_of_mem_nhds (interior_mem_nhds.2 u_mem), ?_⟩ + exact ⟨interior u, uᶜ, isOpen_interior, u_closed.isOpen_compl, Subset.rfl, + subset_compl_comm.mp hu, disjoint_compl_right.mono_left (interior_subset)⟩ + end RegularSpace -section ClosableCompactSubsetOpenSpace +section T2OrLocallyCompactRegularSpace -/-- A class of topological spaces in which, given a compact set included inside an open set, then -the closure of the compact set is also included in the open set. -Satisfied notably for T2 spaces and regular spaces, and useful when discussing classes of -regular measures. Equivalent to regularity among locally compact spaces. -/ -class ClosableCompactSubsetOpenSpace (X : Type*) [TopologicalSpace X] : Prop := - closure_subset_of_isOpen : ∀ (K U : Set X), IsCompact K → IsOpen U → K ⊆ U → closure K ⊆ U +/-- A topological space which is either T2 or locally compact regular. Equivalent to regularity +among locally compact spaces. These two classes share the properties that are needed to develop a +lot of measure theory, so it's worth defining a single class to avoid developing things twice. -/ +class T2OrLocallyCompactRegularSpace (X : Type*) [TopologicalSpace X] : Prop := + out : T2Space X ∨ (LocallyCompactSpace X ∧ RegularSpace X) -theorem IsCompact.closure_subset_of_isOpen [ClosableCompactSubsetOpenSpace X] - {s : Set X} (hs : IsCompact s) {u : Set X} (hu : IsOpen u) (h : s ⊆ u) : - closure s ⊆ u := - ClosableCompactSubsetOpenSpace.closure_subset_of_isOpen s u hs hu h +instance (priority := 100) [h : T2Space X] : T2OrLocallyCompactRegularSpace X := ⟨Or.inl h⟩ +instance (priority := 100) [h : LocallyCompactSpace X] [h' : RegularSpace X] : + T2OrLocallyCompactRegularSpace X := ⟨Or.inr ⟨h, h'⟩⟩ -instance (priority := 150) [T2Space X] : ClosableCompactSubsetOpenSpace X := - ⟨fun K _U K_comp _U_open KU ↦ by rwa [K_comp.isClosed.closure_eq]⟩ +/-- A locally compact space which is T2 or locally comapct regular is regular. Not an instance, as +one should instead assume `LocallyCompactSpace X` and `RegularSpace X`. -/ +theorem RegularSpace.ofT2SpaceOrRegularSpace + [LocallyCompactSpace X] [h : T2OrLocallyCompactRegularSpace X] : RegularSpace X := by + rcases h.out with h'|⟨-, h'⟩ <;> infer_instance -/-- In a (possibly non-Hausdorff) regular space, if a compact set `s` is contained in an +/-- In a space which is T2 or locally compact regular, if a compact set `s` is contained in an open set `u`, then its closure is also contained in `u`. -/ -instance (priority := 150) [RegularSpace X] : ClosableCompactSubsetOpenSpace X := by - refine ⟨fun s u hs hu h ↦ ?_⟩ +theorem IsCompact.closure_subset_of_isOpen [hX : T2OrLocallyCompactRegularSpace X] + {s : Set X} (hs : IsCompact s) {u : Set X} (hu : IsOpen u) (h : s ⊆ u) : + closure s ⊆ u := by + rcases hX.out with h'|⟨-, h'⟩ + · rwa [hs.isClosed.closure_eq] obtain ⟨F, sF, F_closed, Fu⟩ : ∃ F, s ⊆ F ∧ IsClosed F ∧ F ⊆ u := by apply hs.induction_on (p := fun t ↦ ∃ F, t ⊆ F ∧ IsClosed F ∧ F ⊆ u) · exact ⟨∅, by simp⟩ @@ -1786,11 +1708,32 @@ instance (priority := 150) [RegularSpace X] : ClosableCompactSubsetOpenSpace X : exact ⟨F, nhdsWithin_le_nhds F_mem, F, Subset.rfl, F_closed, Fu⟩ exact (closure_minimal sF F_closed).trans Fu -/-- In a (possibly non-Hausdorff) locally compact space with the `ClosableCompactSubsetOpenSpace` - property (for instance regular spaces), for every containment `K ⊆ U` of a compact set `K` in an - open set `U`, there is a compact closed neighborhood `L` such that `K ⊆ L ⊆ U`: equivalently, - there is a compact closed set `L` such that `K ⊆ interior L` and `L ⊆ U`. -/ -theorem exists_compact_closed_between [LocallyCompactSpace X] [ClosableCompactSubsetOpenSpace X] +theorem separatedNhds_of_isCompact_isCompact_isClosed [hX : T2OrLocallyCompactRegularSpace X] + {s t : Set X} (hs : IsCompact s) (ht : IsCompact t) (h't : IsClosed t) + (hst : Disjoint s t) : SeparatedNhds s t := by + rcases hX.out with h'|⟨-, h'⟩ + · exact separatedNhds_of_isCompact_isCompact hs ht hst + · exact separatedNhds_of_isCompact_isClosed hs h't hst + +protected theorem IsCompact.closure [hX : T2OrLocallyCompactRegularSpace X] + {K : Set X} (hK : IsCompact K) : IsCompact (closure K) := by + rcases hX.out with h'|⟨h', -⟩ + · rwa [hK.isClosed.closure_eq] + rcases exists_compact_superset hK with ⟨L, L_comp, hL⟩ + exact L_comp.of_isClosed_subset isClosed_closure + ((hK.closure_subset_of_isOpen isOpen_interior hL).trans interior_subset) + +theorem isCompact_closure_of_subset_compact [T2OrLocallyCompactRegularSpace X] + {s t : Set X} (ht : IsCompact t) + (h : s ⊆ t) : IsCompact (closure s) := + ht.closure.of_isClosed_subset isClosed_closure (closure_mono h) +#align is_compact_closure_of_subset_compact isCompact_closure_of_subset_compact + +/-- In a (possibly non-Hausdorff) locally compact regular space, for every containment `K ⊆ U` of + a compact set `K` in an open set `U`, there is a compact closed neighborhood `L` + such that `K ⊆ L ⊆ U`: equivalently, there is a compact closed set `L` such + that `K ⊆ interior L` and `L ⊆ U`. -/ +theorem exists_compact_closed_between [LocallyCompactSpace X] [RegularSpace X] {K U : Set X} (hK : IsCompact K) (hU : IsOpen U) (h_KU : K ⊆ U) : ∃ L, IsCompact L ∧ IsClosed L ∧ K ⊆ interior L ∧ L ⊆ U := by rcases exists_compact_between hK hU h_KU with ⟨L, L_comp, KL, LU⟩ @@ -1805,23 +1748,109 @@ theorem exists_compact_closed_between [LocallyCompactSpace X] [ClosableCompactSu · apply M_comp.closure_subset_of_isOpen hU exact ML.trans (interior_subset.trans LU) -/-- A locally compact space with the `ClosableCompactSubsetOpenSpace` is `Regular`. -/ -instance (priority := 80) [LocallyCompactSpace X] [ClosableCompactSubsetOpenSpace X] : - RegularSpace X := by - apply RegularSpace.ofExistsMemNhdsIsClosedSubset (fun x s hx ↦ ?_) - rcases _root_.mem_nhds_iff.1 hx with ⟨u, us, u_open, xu⟩ - rcases exists_compact_closed_between (isCompact_singleton (x := x)) u_open (by simpa using xu) - with ⟨t, -, t_closed, xt, tu⟩ - have : interior t ∈ 𝓝 x := isOpen_interior.mem_nhds (by simpa using xt) - exact ⟨t, interior_mem_nhds.mp this, t_closed, tu.trans us⟩ +/-- In a locally compact regular space, given a compact set `K` inside an open set `U`, we can find +an open set `V` between these sets with compact closure: `K ⊆ V` and the closure of `V` is +inside `U`. -/ +theorem exists_open_between_and_isCompact_closure [LocallyCompactSpace X] [RegularSpace X] + {K U : Set X} (hK : IsCompact K) (hU : IsOpen U) (hKU : K ⊆ U) : + ∃ V, IsOpen V ∧ K ⊆ V ∧ closure V ⊆ U ∧ IsCompact (closure V) := by + rcases exists_compact_closed_between hK hU hKU with ⟨L, L_compact, L_closed, KL, LU⟩ + have A : closure (interior L) ⊆ L := by + apply (closure_mono interior_subset).trans (le_of_eq L_closed.closure_eq) + refine ⟨interior L, isOpen_interior, KL, A.trans LU, ?_⟩ + exact isCompact_closure_of_subset_compact L_compact interior_subset +#align exists_open_between_and_is_compact_closure exists_open_between_and_isCompact_closure -protected theorem IsCompact.closure [WeaklyLocallyCompactSpace X] [ClosableCompactSubsetOpenSpace X] - {K : Set X} (hK : IsCompact K) : IsCompact (closure K) := by - rcases exists_compact_superset hK with ⟨L, L_comp, hL⟩ - exact L_comp.of_isClosed_subset isClosed_closure - ((hK.closure_subset_of_isOpen isOpen_interior hL).trans interior_subset) +@[simp] +theorem exists_compact_superset_iff [T2OrLocallyCompactRegularSpace X] {s : Set X} : + (∃ K, IsCompact K ∧ s ⊆ K) ↔ IsCompact (closure s) := + ⟨fun ⟨_K, hK, hsK⟩ => isCompact_closure_of_subset_compact hK hsK, fun h => + ⟨closure s, h, subset_closure⟩⟩ +#align exists_compact_superset_iff exists_compact_superset_iff + +/-- In a weakly locally compact space which is either T₂ or locally compact regular, +every compact set has an open neighborhood with compact closure. -/ +theorem exists_open_superset_and_isCompact_closure + [WeaklyLocallyCompactSpace X] [T2OrLocallyCompactRegularSpace X] + {K : Set X} (hK : IsCompact K) : ∃ V, IsOpen V ∧ K ⊆ V ∧ IsCompact (closure V) := by + rcases exists_compact_superset hK with ⟨K', hK', hKK'⟩ + exact ⟨interior K', isOpen_interior, hKK', + isCompact_closure_of_subset_compact hK' interior_subset⟩ +#align exists_open_superset_and_is_compact_closure exists_open_superset_and_isCompact_closure + +/-- In a weakly locally compact which is either T₂ or locally compact regular, +every point has an open neighborhood with compact closure. -/ +theorem exists_open_with_compact_closure + [WeaklyLocallyCompactSpace X] [T2OrLocallyCompactRegularSpace X] (x : X) : + ∃ U : Set X, IsOpen U ∧ x ∈ U ∧ IsCompact (closure U) := by + simpa only [singleton_subset_iff] + using exists_open_superset_and_isCompact_closure isCompact_singleton +#align exists_open_with_compact_closure exists_open_with_compact_closure + +-- see Note [lower instance priority] +/-- A weakly locally compact Hausdorff space is locally compact. -/ +instance (priority := 80) WeaklyLocallyCompactSpace.locallyCompactSpace + [WeaklyLocallyCompactSpace X] [hX : T2OrLocallyCompactRegularSpace X] : + LocallyCompactSpace X := by + rcases hX.out with h'X|⟨h'X, -⟩ + · exact ⟨fun _ _ h => + let ⟨K, hKx, hKc, hKs⟩ := exists_mem_nhds_isCompact_mapsTo continuous_id h + ⟨K, hKx, hKs, hKc⟩⟩ + · exact h'X +#align locally_compact_of_compact_nhds WeaklyLocallyCompactSpace.locallyCompactSpace + +@[deprecated WeaklyLocallyCompactSpace.locallyCompactSpace] +theorem locally_compact_of_compact [T2Space X] [CompactSpace X] : + LocallyCompactSpace X := + inferInstance +#align locally_compact_of_compact locally_compact_of_compact + +/-- If a compact set is covered by two open sets, then we can cover it by two compact subsets. -/ +theorem IsCompact.binary_compact_cover [T2OrLocallyCompactRegularSpace X] {K U V : Set X} + (hK : IsCompact K) (hU : IsOpen U) (hV : IsOpen V) (h2K : K ⊆ U ∪ V) : + ∃ K₁ K₂ : Set X, IsCompact K₁ ∧ IsCompact K₂ ∧ K₁ ⊆ U ∧ K₂ ⊆ V ∧ K = K₁ ∪ K₂ := by + have hK' : IsCompact (closure K) := hK.closure + have : SeparatedNhds (closure K \ U) (closure K \ V) := by + apply separatedNhds_of_isCompact_isCompact_isClosed (hK'.diff hU) (hK'.diff hV) + (isClosed_closure.sdiff hV) + rw [disjoint_iff_inter_eq_empty, diff_inter_diff, diff_eq_empty] + exact hK.closure_subset_of_isOpen (hU.union hV) h2K + have : SeparatedNhds (K \ U) (K \ V) := + this.mono (diff_subset_diff_left (subset_closure)) (diff_subset_diff_left (subset_closure)) + rcases this with ⟨O₁, O₂, h1O₁, h1O₂, h2O₁, h2O₂, hO⟩ + exact ⟨K \ O₁, K \ O₂, hK.diff h1O₁, hK.diff h1O₂, diff_subset_comm.mp h2O₁, + diff_subset_comm.mp h2O₂, by rw [← diff_inter, hO.inter_eq, diff_empty]⟩ +#align is_compact.binary_compact_cover IsCompact.binary_compact_cover + +open Finset Function + +/-- For every finite open cover `Uᵢ` of a compact set, there exists a compact cover `Kᵢ ⊆ Uᵢ`. -/ +theorem IsCompact.finite_compact_cover [T2OrLocallyCompactRegularSpace X] + {s : Set X} (hs : IsCompact s) {ι} + (t : Finset ι) (U : ι → Set X) (hU : ∀ i ∈ t, IsOpen (U i)) (hsC : s ⊆ ⋃ i ∈ t, U i) : + ∃ K : ι → Set X, (∀ i, IsCompact (K i)) ∧ (∀ i, K i ⊆ U i) ∧ s = ⋃ i ∈ t, K i := by + induction' t using Finset.induction with x t hx ih generalizing U s + · refine' ⟨fun _ => ∅, fun _ => isCompact_empty, fun i => empty_subset _, _⟩ + simpa only [subset_empty_iff, Finset.not_mem_empty, iUnion_false, iUnion_empty] using hsC + simp only [Finset.set_biUnion_insert] at hsC + simp only [Finset.forall_mem_insert] at hU + have hU' : ∀ i ∈ t, IsOpen (U i) := fun i hi => hU.2 i hi + rcases hs.binary_compact_cover hU.1 (isOpen_biUnion hU') hsC with + ⟨K₁, K₂, h1K₁, h1K₂, h2K₁, h2K₂, hK⟩ + rcases ih h1K₂ U hU' h2K₂ with ⟨K, h1K, h2K, h3K⟩ + refine' ⟨update K x K₁, _, _, _⟩ + · intro i + rcases eq_or_ne i x with rfl | hi + · simp only [update_same, h1K₁] + · simp only [update_noteq hi, h1K] + · intro i + rcases eq_or_ne i x with rfl | hi + · simp only [update_same, h2K₁] + · simp only [update_noteq hi, h2K] + · simp only [set_biUnion_insert_update _ hx, hK, h3K] +#align is_compact.finite_compact_cover IsCompact.finite_compact_cover -end ClosableCompactSubsetOpenSpace +end T2OrLocallyCompactRegularSpace section T3 @@ -1982,7 +2011,7 @@ instance (priority := 100) T4Space.t3Space [T4Space X] : T3Space X where instance (priority := 100) T4Space.of_compactSpace_t2Space [CompactSpace X] [T2Space X] : T4Space X where - normal _s _t hs ht := isCompact_isCompact_separated hs.isCompact ht.isCompact + normal _s _t hs ht := separatedNhds_of_isCompact_isCompact hs.isCompact ht.isCompact #align normal_of_compact_t2 T4Space.of_compactSpace_t2Space /-- If the codomain of a closed embedding is a T₄ space, then so is the domain. -/ @@ -2156,7 +2185,8 @@ theorem compact_t2_tot_disc_iff_tot_sep : TotallyDisconnectedSpace X ↔ Totally variable [TotallyDisconnectedSpace X] /-- A totally disconnected compact Hausdorff space is totally separated. -/ -instance : TotallySeparatedSpace X := compact_t2_tot_disc_iff_tot_sep.mp inferInstance +instance (priority := 100) : TotallySeparatedSpace X := + compact_t2_tot_disc_iff_tot_sep.mp inferInstance theorem nhds_basis_clopen (x : X) : (𝓝 x).HasBasis (fun s : Set X => x ∈ s ∧ IsClopen s) id := ⟨fun U => by diff --git a/Mathlib/Topology/Separation/NotNormal.lean b/Mathlib/Topology/Separation/NotNormal.lean index 716dbf2c96da0..7a787e9c383f4 100644 --- a/Mathlib/Topology/Separation/NotNormal.lean +++ b/Mathlib/Topology/Separation/NotNormal.lean @@ -46,7 +46,7 @@ theorem IsClosed.mk_lt_continuum [NormalSpace X] {s : Set X} (hs : IsClosed s) exact mk_le_of_injective hfi -- Since `t` is dense, restriction `C(X, ℝ) → C(t, ℝ)` is injective, hence `#C(X, ℝ) ≤ #C(t, ℝ)` _ ≤ #C(t, ℝ) := mk_le_of_injective <| ContinuousMap.injective_restrict htd - _ ≤ #(t → ℝ) := mk_le_of_injective FunLike.coe_injective + _ ≤ #(t → ℝ) := mk_le_of_injective DFunLike.coe_injective -- Since `t` is countable, we have `#(t → ℝ) ≤ 𝔠` _ ≤ 𝔠 := by rw [mk_arrow, mk_real, lift_uzero, lift_continuum, continuum, ← power_mul] diff --git a/Mathlib/Topology/Sets/Closeds.lean b/Mathlib/Topology/Sets/Closeds.lean index 2311868fdb964..7dd2d625927c8 100644 --- a/Mathlib/Topology/Sets/Closeds.lean +++ b/Mathlib/Topology/Sets/Closeds.lean @@ -251,7 +251,7 @@ lemma Closeds.coe_eq_singleton_of_isAtom [T0Space α] {s : Closeds α} (hs : IsA ∃ a, (s : Set α) = {a} := by refine minimal_nonempty_closed_eq_singleton s.2 (coe_nonempty.2 hs.1) fun t hts ht ht' ↦ ?_ lift t to Closeds α using ht' - exact SetLike.coe_injective.eq_iff.2 $ (hs.le_iff_eq $ coe_nonempty.1 ht).1 hts + exact SetLike.coe_injective.eq_iff.2 <| (hs.le_iff_eq <| coe_nonempty.1 ht).1 hts @[simp, norm_cast] lemma Closeds.isAtom_coe [T1Space α] {s : Closeds α} : IsAtom (s : Set α) ↔ IsAtom s := diff --git a/Mathlib/Topology/Sets/Opens.lean b/Mathlib/Topology/Sets/Opens.lean index 5c83ed8468280..cd329e94d35cc 100644 --- a/Mathlib/Topology/Sets/Opens.lean +++ b/Mathlib/Topology/Sets/Opens.lean @@ -264,7 +264,7 @@ theorem openEmbedding' (U : Opens α) : OpenEmbedding (Subtype.val : U → α) : U.isOpen.openEmbedding_subtype_val theorem openEmbedding_of_le {U V : Opens α} (i : U ≤ V) : - OpenEmbedding (Set.inclusion $ SetLike.coe_subset_coe.2 i) := + OpenEmbedding (Set.inclusion <| SetLike.coe_subset_coe.2 i) := { toEmbedding := embedding_inclusion i open_range := by rw [Set.range_inclusion i] @@ -396,7 +396,7 @@ theorem comap_injective [T0Space β] : Injective (comap : C(α, β) → FrameHom ContinuousMap.ext fun a => Inseparable.eq <| inseparable_iff_forall_open.2 fun s hs => - have : comap f ⟨s, hs⟩ = comap g ⟨s, hs⟩ := FunLike.congr_fun h ⟨_, hs⟩ + have : comap f ⟨s, hs⟩ = comap g ⟨s, hs⟩ := DFunLike.congr_fun h ⟨_, hs⟩ show a ∈ f ⁻¹' s ↔ a ∈ g ⁻¹' s from Set.ext_iff.1 (coe_inj.2 this) a #align topological_space.opens.comap_injective TopologicalSpace.Opens.comap_injective diff --git a/Mathlib/Topology/Sheaves/LocalPredicate.lean b/Mathlib/Topology/Sheaves/LocalPredicate.lean index 9cbd1e3f6b1a6..189ef414e519a 100644 --- a/Mathlib/Topology/Sheaves/LocalPredicate.lean +++ b/Mathlib/Topology/Sheaves/LocalPredicate.lean @@ -5,7 +5,6 @@ Authors: Johan Commelin, Scott Morrison, Adam Topaz -/ import Mathlib.Topology.Sheaves.SheafOfFunctions import Mathlib.Topology.Sheaves.Stalks -import Mathlib.Topology.PartialHomeomorph import Mathlib.Topology.Sheaves.SheafCondition.UniqueGluing #align_import topology.sheaves.local_predicate from "leanprover-community/mathlib"@"5dc6092d09e5e489106865241986f7f2ad28d4c8" diff --git a/Mathlib/Topology/Sheaves/Presheaf.lean b/Mathlib/Topology/Sheaves/Presheaf.lean index a4831770ba571..2010d0c71f724 100644 --- a/Mathlib/Topology/Sheaves/Presheaf.lean +++ b/Mathlib/Topology/Sheaves/Presheaf.lean @@ -5,7 +5,6 @@ Authors: Scott Morrison, Mario Carneiro, Reid Barton, Andrew Yang -/ import Mathlib.CategoryTheory.Limits.KanExtension import Mathlib.Topology.Category.TopCat.Opens -import Mathlib.Algebra.Category.Ring.Basic import Mathlib.CategoryTheory.Adjunction.Opposites import Mathlib.Topology.Sheaves.Init @@ -55,6 +54,9 @@ variable {C} namespace Presheaf +@[simp] theorem comp_app {P Q R : Presheaf C X} (f : P ⟶ Q) (g : Q ⟶ R) : + (f ≫ g).app U = f.app U ≫ g.app U := rfl + -- Porting note: added an `ext` lemma, -- since `NatTrans.ext` can not see through the definition of `Presheaf`. -- See https://github.com/leanprover-community/mathlib4/issues/5229 @@ -67,7 +69,7 @@ lemma ext {P Q : Presheaf C X} {f g : P ⟶ Q} (w : ∀ U : Opens X, f.app (op U apply w attribute [local instance] CategoryTheory.ConcreteCategory.hasCoeToSort - CategoryTheory.ConcreteCategory.funLike + CategoryTheory.ConcreteCategory.instFunLike /-- attribute `sheaf_restrict` to mark lemmas related to restricting sheaves -/ macro "sheaf_restrict" : attr => @@ -79,16 +81,20 @@ attribute [sheaf_restrict] bot_le le_top le_refl inf_le_left inf_le_right /-- `restrict_tac` solves relations among subsets (copied from `aesop cat`) -/ macro (name := restrict_tac) "restrict_tac" c:Aesop.tactic_clause* : tactic => `(tactic| first | assumption | - aesop $c* (options := - { terminal := true, assumptionTransparency := .reducible }) - (simp_options := { enabled := false }) - (rule_sets [-default, -builtin, $(Lean.mkIdent `Restrict):ident])) + aesop $c* + (config := { terminal := true + assumptionTransparency := .reducible + enableSimp := false }) + (rule_sets [-default, -builtin, $(Lean.mkIdent `Restrict):ident])) /-- `restrict_tac?` passes along `Try this` from `aesop` -/ macro (name := restrict_tac?) "restrict_tac?" c:Aesop.tactic_clause* : tactic => `(tactic| - aesop? $c* (options := - { terminal := true, assumptionTransparency := .reducible, maxRuleApplications := 300 }) + aesop? $c* + (config := { terminal := true + assumptionTransparency := .reducible + enableSimp := false + maxRuleApplications := 300 }) (rule_sets [-default, -builtin, $(Lean.mkIdent `Restrict):ident])) attribute[aesop 10% (rule_sets [Restrict])] le_trans @@ -243,7 +249,7 @@ set_option linter.uppercaseLean3 false in @[simp (high)] theorem id_hom_app' (U) (p) : (id ℱ).hom.app (op ⟨U, p⟩) = ℱ.map (𝟙 (op ⟨U, p⟩)) := by dsimp [id] - simp [CategoryStruct.comp] + simp set_option linter.uppercaseLean3 false in #align Top.presheaf.pushforward.id_hom_app' TopCat.Presheaf.Pushforward.id_hom_app' @@ -474,7 +480,7 @@ theorem pushforwardToOfIso_app {X Y : TopCat} (H₁ : X ≅ Y) {ℱ : Y.Presheaf (pushforwardToOfIso H₁ H₂).app U = H₂.app (op ((Opens.map H₁.inv).obj (unop U))) ≫ 𝒢.map (eqToHom (by simp [Opens.map, Set.preimage_preimage])) := by - simp [pushforwardToOfIso, Equivalence.toAdjunction, CategoryStruct.comp] + simp [pushforwardToOfIso, Equivalence.toAdjunction] set_option linter.uppercaseLean3 false in #align Top.presheaf.pushforward_to_of_iso_app TopCat.Presheaf.pushforwardToOfIso_app diff --git a/Mathlib/Topology/Sheaves/SheafCondition/Sites.lean b/Mathlib/Topology/Sheaves/SheafCondition/Sites.lean index e25d265d83689..4d71162d5f83d 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/Sites.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/Sites.lean @@ -198,11 +198,11 @@ instance : RepresentablyFlat (Opens.map f) := by refine @IsCofiltered.mk _ _ ?_ ?_ · constructor · intro V W - exact ⟨⟨⟨PUnit.unit⟩, V.right ⊓ W.right, homOfLE $ le_inf V.hom.le W.hom.le⟩, + exact ⟨⟨⟨PUnit.unit⟩, V.right ⊓ W.right, homOfLE <| le_inf V.hom.le W.hom.le⟩, StructuredArrow.homMk (homOfLE inf_le_left), StructuredArrow.homMk (homOfLE inf_le_right), trivial⟩ · exact fun _ _ _ _ ↦ ⟨_, 𝟙 _, by simp [eq_iff_true_of_subsingleton]⟩ - · exact ⟨StructuredArrow.mk $ show U ⟶ (Opens.map f).obj ⊤ from homOfLE le_top⟩ + · exact ⟨StructuredArrow.mk <| show U ⟶ (Opens.map f).obj ⊤ from homOfLE le_top⟩ theorem compatiblePreserving_opens_map : CompatiblePreserving (Opens.grothendieckTopology X) (Opens.map f) := diff --git a/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean b/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean index 4f13510ceb9df..c43e1c18cc4c9 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean @@ -50,7 +50,7 @@ namespace Presheaf section -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike variable {X : TopCat.{x}} (F : Presheaf C X) {ι : Type x} (U : ι → Opens X) @@ -152,7 +152,7 @@ end TypeValued section -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike variable [HasLimits C] [ReflectsIsomorphisms (forget C)] [PreservesLimits (forget C)] @@ -179,7 +179,7 @@ open CategoryTheory section -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.funLike +attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike variable [HasLimits C] [ReflectsIsomorphisms (ConcreteCategory.forget (C := C))] diff --git a/Mathlib/Topology/Sheaves/Skyscraper.lean b/Mathlib/Topology/Sheaves/Skyscraper.lean index 774ed16aa8e71..91c604a1bc429 100644 --- a/Mathlib/Topology/Sheaves/Skyscraper.lean +++ b/Mathlib/Topology/Sheaves/Skyscraper.lean @@ -326,9 +326,6 @@ protected def unit : 𝟭 (Presheaf C X) ⟶ Presheaf.stalkFunctor C p₀ ⋙ sk app 𝓕 := toSkyscraperPresheaf _ <| 𝟙 _ naturality 𝓕 𝓖 f := by ext U; dsimp - -- Porting note : added the following `rw` and `dsimp` to make it compile - rw [NatTrans.comp_app, toSkyscraperPresheaf_app, NatTrans.comp_app, toSkyscraperPresheaf_app] - dsimp only [skyscraperPresheaf_obj, unop_op, Eq.ndrec, SkyscraperPresheafFunctor.map'_app] split_ifs with h · simp only [Category.id_comp, ← Category.assoc]; rw [comp_eqToHom_iff] simp only [Category.assoc, eqToHom_trans, eqToHom_refl, Category.comp_id] diff --git a/Mathlib/Topology/Specialization.lean b/Mathlib/Topology/Specialization.lean index f5620a8412d8b..0829a60314997 100644 --- a/Mathlib/Topology/Specialization.lean +++ b/Mathlib/Topology/Specialization.lean @@ -85,5 +85,5 @@ def homeoWithUpperSetTopologyorderIso (α : Type*) [TopologicalSpace α] [Alexan /-- Sends a topological space to its specialisation order. -/ @[simps] def topToPreord : TopCat ⥤ Preord where - obj X := Preord.of $ Specialization X + obj X := Preord.of <| Specialization X map := Specialization.map diff --git a/Mathlib/Topology/Spectral/Hom.lean b/Mathlib/Topology/Spectral/Hom.lean index ae274c307c122..aa3d24e6d7776 100644 --- a/Mathlib/Topology/Spectral/Hom.lean +++ b/Mathlib/Topology/Spectral/Hom.lean @@ -76,7 +76,7 @@ section You should extend this class when you extend `SpectralMap`. -/ class SpectralMapClass (F : Type*) (α β : outParam <| Type*) [TopologicalSpace α] - [TopologicalSpace β] extends FunLike F α fun _ => β where + [TopologicalSpace β] extends DFunLike F α fun _ => β where /-- statement that `F` is a type of spectral maps-/ map_spectral (f : F) : IsSpectralMap f #align spectral_map_class SpectralMapClass @@ -116,10 +116,10 @@ instance : SpectralMapClass (SpectralMap α β) α β map_spectral f := f.spectral' -- Porting note: These CoeFun instances are not desirable in Lean 4. ---/-- Helper instance for when there's too many metavariables to apply `FunLike.hasCoeToFun` +--/-- Helper instance for when there's too many metavariables to apply `DFunLike.hasCoeToFun` --directly. -/ --instance : CoeFun (SpectralMap α β) fun _ => α → β := --- FunLike.hasCoeToFun +-- DFunLike.hasCoeToFun @[simp] theorem toFun_eq_coe {f : SpectralMap α β} : f.toFun = (f : α → β) := @@ -128,7 +128,7 @@ theorem toFun_eq_coe {f : SpectralMap α β} : f.toFun = (f : α → β) := @[ext] theorem ext {f g : SpectralMap α β} (h : ∀ a, f a = g a) : f = g := - FunLike.ext f g h + DFunLike.ext f g h #align spectral_map.ext SpectralMap.ext /-- Copy of a `SpectralMap` with a new `toFun` equal to the old one. Useful to fix definitional @@ -143,7 +143,7 @@ theorem coe_copy (f : SpectralMap α β) (f' : α → β) (h : f' = f) : ⇑(f.c #align spectral_map.coe_copy SpectralMap.coe_copy theorem copy_eq (f : SpectralMap α β) (f' : α → β) (h : f' = f) : f.copy f' h = f := - FunLike.ext' h + DFunLike.ext' h #align spectral_map.copy_eq SpectralMap.copy_eq variable (α) @@ -213,7 +213,7 @@ theorem id_comp (f : SpectralMap α β) : (SpectralMap.id β).comp f = f := @[simp] theorem cancel_right {g₁ g₂ : SpectralMap β γ} {f : SpectralMap α β} (hf : Surjective f) : g₁.comp f = g₂.comp f ↔ g₁ = g₂ := - ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, + ⟨fun h => ext <| hf.forall.2 <| DFunLike.ext_iff.1 h, fun a => of_eq (congrFun (congrArg comp a) f)⟩ #align spectral_map.cancel_right SpectralMap.cancel_right diff --git a/Mathlib/Topology/Support.lean b/Mathlib/Topology/Support.lean index 238c5bc0e8d80..868b8f189ee85 100644 --- a/Mathlib/Topology/Support.lean +++ b/Mathlib/Topology/Support.lean @@ -5,6 +5,7 @@ Authors: Floris van Doorn, Patrick Massot -/ import Mathlib.Algebra.Module.Basic import Mathlib.Topology.Separation +import Mathlib.Algebra.Group.Defs #align_import topology.support from "leanprover-community/mathlib"@"d90e4e186f1d18e375dcd4e5b5f6364b01cb3e46" @@ -25,7 +26,7 @@ Furthermore, we say that `f` has compact support if the topological support of ` * We write all lemmas for multiplicative functions, and use `@[to_additive]` to get the more common additive versions. -* We do not put the definitions in the `function` namespace, following many other topological +* We do not put the definitions in the `Function` namespace, following many other topological definitions that are in the root namespace (compare `Embedding` vs `Function.Embedding`). -/ @@ -81,7 +82,7 @@ theorem range_subset_insert_image_mulTSupport (f : X → α) : @[to_additive] theorem range_eq_image_mulTSupport_or (f : X → α) : range f = f '' mulTSupport f ∨ range f = insert 1 (f '' mulTSupport f) := - (wcovby_insert _ _).eq_or_eq (image_subset_range _ _) (range_subset_insert_image_mulTSupport f) + (wcovBy_insert _ _).eq_or_eq (image_subset_range _ _) (range_subset_insert_image_mulTSupport f) #align range_eq_image_mul_tsupport_or range_eq_image_mulTSupport_or #align range_eq_image_tsupport_or range_eq_image_tsupport_or @@ -132,6 +133,16 @@ theorem continuous_of_mulTSupport [TopologicalSpace β] {f : α → β} #align continuous_of_mul_tsupport continuous_of_mulTSupport #align continuous_of_tsupport continuous_of_tsupport +end + +/-! ## Functions with compact support -/ +section CompactSupport +variable [TopologicalSpace α] [TopologicalSpace α'] + +variable [One β] [One γ] [One δ] + +variable {g : β → γ} {f : α → β} {f₂ : α → γ} {m : β → γ → δ} {x : α} + /-- A function `f` *has compact multiplicative support* or is *compactly supported* if the closure of the multiplicative support of `f` is compact. In a T₂ space this is equivalent to `f` being equal to `1` outside a compact set. -/ @@ -157,15 +168,16 @@ theorem exists_compact_iff_hasCompactMulSupport [T2Space α] : #align exists_compact_iff_has_compact_mul_support exists_compact_iff_hasCompactMulSupport #align exists_compact_iff_has_compact_support exists_compact_iff_hasCompactSupport +namespace HasCompactMulSupport @[to_additive] -theorem HasCompactMulSupport.intro [T2Space α] {K : Set α} (hK : IsCompact K) +theorem intro [T2Space α] {K : Set α} (hK : IsCompact K) (hfK : ∀ x, x ∉ K → f x = 1) : HasCompactMulSupport f := exists_compact_iff_hasCompactMulSupport.mp ⟨K, hK, hfK⟩ #align has_compact_mul_support.intro HasCompactMulSupport.intro #align has_compact_support.intro HasCompactSupport.intro @[to_additive] -theorem HasCompactMulSupport.intro' {K : Set α} (hK : IsCompact K) (h'K : IsClosed K) +theorem intro' {K : Set α} (hK : IsCompact K) (h'K : IsClosed K) (hfK : ∀ x, x ∉ K → f x = 1) : HasCompactMulSupport f := by have : mulTSupport f ⊆ K := by rw [← h'K.closure_eq] @@ -173,18 +185,18 @@ theorem HasCompactMulSupport.intro' {K : Set α} (hK : IsCompact K) (h'K : IsClo exact IsCompact.of_isClosed_subset hK ( isClosed_mulTSupport f) this @[to_additive] -theorem HasCompactMulSupport.of_mulSupport_subset_isCompact [T2Space α] {K : Set α} +theorem of_mulSupport_subset_isCompact [T2Space α] {K : Set α} (hK : IsCompact K) (h : mulSupport f ⊆ K) : HasCompactMulSupport f := isCompact_closure_of_subset_compact hK h @[to_additive] -theorem HasCompactMulSupport.isCompact (hf : HasCompactMulSupport f) : IsCompact (mulTSupport f) := +theorem isCompact (hf : HasCompactMulSupport f) : IsCompact (mulTSupport f) := hf #align has_compact_mul_support.is_compact HasCompactMulSupport.isCompact #align has_compact_support.is_compact HasCompactSupport.isCompact @[to_additive] -theorem hasCompactMulSupport_iff_eventuallyEq : +theorem _root_.hasCompactMulSupport_iff_eventuallyEq : HasCompactMulSupport f ↔ f =ᶠ[coclosedCompact α] 1 := ⟨fun h => mem_coclosedCompact.mpr ⟨mulTSupport f, isClosed_mulTSupport _, h, @@ -196,49 +208,49 @@ theorem hasCompactMulSupport_iff_eventuallyEq : #align has_compact_support_iff_eventually_eq hasCompactSupport_iff_eventuallyEq @[to_additive] -theorem isCompact_range_of_mulSupport_subset_isCompact [TopologicalSpace β] +theorem _root_.isCompact_range_of_mulSupport_subset_isCompact [TopologicalSpace β] (hf : Continuous f) {k : Set α} (hk : IsCompact k) (h'f : mulSupport f ⊆ k) : IsCompact (range f) := by cases' range_eq_image_or_of_mulSupport_subset h'f with h2 h2 <;> rw [h2] exacts [hk.image hf, (hk.image hf).insert 1] @[to_additive] -theorem HasCompactMulSupport.isCompact_range [TopologicalSpace β] (h : HasCompactMulSupport f) +theorem isCompact_range [TopologicalSpace β] (h : HasCompactMulSupport f) (hf : Continuous f) : IsCompact (range f) := isCompact_range_of_mulSupport_subset_isCompact hf h (subset_mulTSupport f) #align has_compact_mul_support.is_compact_range HasCompactMulSupport.isCompact_range #align has_compact_support.is_compact_range HasCompactSupport.isCompact_range @[to_additive] -theorem HasCompactMulSupport.mono' {f' : α → γ} (hf : HasCompactMulSupport f) +theorem mono' {f' : α → γ} (hf : HasCompactMulSupport f) (hff' : mulSupport f' ⊆ mulTSupport f) : HasCompactMulSupport f' := IsCompact.of_isClosed_subset hf isClosed_closure <| closure_minimal hff' isClosed_closure #align has_compact_mul_support.mono' HasCompactMulSupport.mono' #align has_compact_support.mono' HasCompactSupport.mono' @[to_additive] -theorem HasCompactMulSupport.mono {f' : α → γ} (hf : HasCompactMulSupport f) +theorem mono {f' : α → γ} (hf : HasCompactMulSupport f) (hff' : mulSupport f' ⊆ mulSupport f) : HasCompactMulSupport f' := hf.mono' <| hff'.trans subset_closure #align has_compact_mul_support.mono HasCompactMulSupport.mono #align has_compact_support.mono HasCompactSupport.mono @[to_additive] -theorem HasCompactMulSupport.comp_left (hf : HasCompactMulSupport f) (hg : g 1 = 1) : +theorem comp_left (hf : HasCompactMulSupport f) (hg : g 1 = 1) : HasCompactMulSupport (g ∘ f) := hf.mono <| mulSupport_comp_subset hg f #align has_compact_mul_support.comp_left HasCompactMulSupport.comp_left #align has_compact_support.comp_left HasCompactSupport.comp_left @[to_additive] -theorem hasCompactMulSupport_comp_left (hg : ∀ {x}, g x = 1 ↔ x = 1) : +theorem _root_.hasCompactMulSupport_comp_left (hg : ∀ {x}, g x = 1 ↔ x = 1) : HasCompactMulSupport (g ∘ f) ↔ HasCompactMulSupport f := by simp_rw [hasCompactMulSupport_def, mulSupport_comp_eq g (@hg) f] #align has_compact_mul_support_comp_left hasCompactMulSupport_comp_left #align has_compact_support_comp_left hasCompactSupport_comp_left @[to_additive] -theorem HasCompactMulSupport.comp_closedEmbedding (hf : HasCompactMulSupport f) {g : α' → α} +theorem comp_closedEmbedding (hf : HasCompactMulSupport f) {g : α' → α} (hg : ClosedEmbedding g) : HasCompactMulSupport (f ∘ g) := by rw [hasCompactMulSupport_def, Function.mulSupport_comp_eq_preimage] refine' IsCompact.of_isClosed_subset (hg.isCompact_preimage hf) isClosed_closure _ @@ -248,7 +260,7 @@ theorem HasCompactMulSupport.comp_closedEmbedding (hf : HasCompactMulSupport f) #align has_compact_support.comp_closed_embedding HasCompactSupport.comp_closedEmbedding @[to_additive] -theorem HasCompactMulSupport.comp₂_left (hf : HasCompactMulSupport f) +theorem comp₂_left (hf : HasCompactMulSupport f) (hf₂ : HasCompactMulSupport f₂) (hm : m 1 1 = 1) : HasCompactMulSupport fun x => m (f x) (f₂ x) := by rw [hasCompactMulSupport_iff_eventuallyEq] at hf hf₂ ⊢ @@ -256,8 +268,6 @@ theorem HasCompactMulSupport.comp₂_left (hf : HasCompactMulSupport f) #align has_compact_mul_support.comp₂_left HasCompactMulSupport.comp₂_left #align has_compact_support.comp₂_left HasCompactSupport.comp₂_left -namespace HasCompactMulSupport - variable [T2Space α'] (hf : HasCompactMulSupport f) {g : α → α'} (cont : Continuous g) @[to_additive] @@ -290,8 +300,10 @@ theorem continuous_extend_one [TopologicalSpace β] {U : Set α'} (hU : IsOpen U end HasCompactMulSupport -end +end CompactSupport +/-! ## Functions with compact support: algebraic operations -/ +section CompactSupport2 section Monoid variable [TopologicalSpace α] [Monoid β] @@ -355,9 +367,11 @@ theorem HasCompactSupport.mul_left (hf : HasCompactSupport f') : HasCompactSuppo end MulZeroClass -namespace LocallyFinite +end CompactSupport2 -variable {ι : Type*} {U : ι → Set X} [TopologicalSpace X] [One R] +section LocallyFinite + +variable {ι : Type*} [TopologicalSpace X] -- porting note: todo: reformulate for any locally finite family of sets /-- If a family of functions `f` has locally-finite multiplicative support, subordinate to a family @@ -366,7 +380,7 @@ of open sets, then for any point we can find a neighbourhood on which only finit @[to_additive " If a family of functions `f` has locally-finite support, subordinate to a family of open sets, then for any point we can find a neighbourhood on which only finitely-many members of `f` are non-zero. "] -theorem exists_finset_nhd_mulSupport_subset {f : ι → X → R} +theorem LocallyFinite.exists_finset_nhd_mulSupport_subset {U : ι → Set X} [One R] {f : ι → X → R} (hlf : LocallyFinite fun i => mulSupport (f i)) (hso : ∀ i, mulTSupport (f i) ⊆ U i) (ho : ∀ i, IsOpen (U i)) (x : X) : ∃ (is : Finset ι), ∃ n, n ∈ 𝓝 x ∧ (n ⊆ ⋂ i ∈ is, U i) ∧ @@ -397,4 +411,9 @@ theorem exists_finset_nhd_mulSupport_subset {f : ι → X → R} #align locally_finite.exists_finset_nhd_mul_support_subset LocallyFinite.exists_finset_nhd_mulSupport_subset #align locally_finite.exists_finset_nhd_support_subset LocallyFinite.exists_finset_nhd_support_subset +@[to_additive] +theorem locallyFinite_mulSupport_iff [CommMonoid M] {f : ι → X → M} : + (LocallyFinite fun i ↦ mulSupport <| f i) ↔ LocallyFinite fun i ↦ mulTSupport <| f i := + ⟨LocallyFinite.closure, fun H ↦ H.subset fun _ ↦ subset_closure⟩ + end LocallyFinite diff --git a/Mathlib/Topology/TietzeExtension.lean b/Mathlib/Topology/TietzeExtension.lean index 50ab9d32d156b..8e93d313ce85f 100644 --- a/Mathlib/Topology/TietzeExtension.lean +++ b/Mathlib/Topology/TietzeExtension.lean @@ -333,7 +333,7 @@ theorem exists_forall_mem_restrict_eq_of_closed {s : Set Y} (f : s →ᵇ ℝ) ( rcases exists_extension_forall_mem_of_closedEmbedding f hf hne (closedEmbedding_subtype_val hs) with ⟨g, hg, hgf⟩ - exact ⟨g, hg, FunLike.coe_injective hgf⟩ + exact ⟨g, hg, DFunLike.coe_injective hgf⟩ #align bounded_continuous_function.exists_forall_mem_restrict_eq_of_closed BoundedContinuousFunction.exists_forall_mem_restrict_eq_of_closed end BoundedContinuousFunction diff --git a/Mathlib/Topology/UniformSpace/Basic.lean b/Mathlib/Topology/UniformSpace/Basic.lean index 72761866eec8c..1aacf081f77e7 100644 --- a/Mathlib/Topology/UniformSpace/Basic.lean +++ b/Mathlib/Topology/UniformSpace/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Order.Filter.SmallSets import Mathlib.Tactic.Monotonicity import Mathlib.Topology.Compactness.Compact import Mathlib.Topology.NhdsSet +import Mathlib.Algebra.Group.Defs #align_import topology.uniform_space.basic from "leanprover-community/mathlib"@"195fcd60ff2bfe392543bceb0ec2adcdb472db4c" @@ -1993,7 +1994,7 @@ lemma exists_is_open_mem_uniformity_of_forall_mem_eq have B : {z | (g x, g z) ∈ t} ∈ 𝓝 x := (hg x hx).preimage_mem_nhds (mem_nhds_left (g x) ht) rcases _root_.mem_nhds_iff.1 (inter_mem A B) with ⟨u, hu, u_open, xu⟩ refine ⟨u, u_open, xu, fun y hy ↦ ?_⟩ - have I1 : (f y, f x) ∈ t := (htsymm.mk_mem_comm).2 (hu hy).1 + have I1 : (f y, f x) ∈ t := (htsymm.mk_mem_comm).2 (hu hy).1 have I2 : (g x, g y) ∈ t := (hu hy).2 rw [hfg hx] at I1 exact htr (prod_mk_mem_compRel I1 I2) diff --git a/Mathlib/Topology/UniformSpace/Equicontinuity.lean b/Mathlib/Topology/UniformSpace/Equicontinuity.lean index 286792e0404cb..ca0adfcbd2b96 100644 --- a/Mathlib/Topology/UniformSpace/Equicontinuity.lean +++ b/Mathlib/Topology/UniformSpace/Equicontinuity.lean @@ -441,7 +441,7 @@ theorem UniformInducing.uniformEquicontinuous_iff {F : ι → β → α} {u : α /-- A version of `EquicontinuousAt.closure` applicable to subsets of types which embed continuously into `X → α` with the product topology. It turns out we don't need any other condition on the -embedding than continuity, but in practice this will mostly be applied to `FunLike` types where +embedding than continuity, but in practice this will mostly be applied to `DFunLike` types where the coercion is injective. -/ theorem EquicontinuousAt.closure' {A : Set Y} {u : Y → X → α} {x₀ : X} (hA : EquicontinuousAt (u ∘ (↑) : A → X → α) x₀) (hu : Continuous u) : @@ -473,7 +473,7 @@ theorem Filter.Tendsto.continuousAt_of_equicontinuousAt {l : Filter ι} [l.NeBot /-- A version of `Equicontinuous.closure` applicable to subsets of types which embed continuously into `X → α` with the product topology. It turns out we don't need any other condition on the -embedding than continuity, but in practice this will mostly be applied to `FunLike` types where +embedding than continuity, but in practice this will mostly be applied to `DFunLike` types where the coercion is injective. -/ theorem Equicontinuous.closure' {A : Set Y} {u : Y → X → α} (hA : Equicontinuous (u ∘ (↑) : A → X → α)) (hu : Continuous u) : @@ -495,7 +495,7 @@ theorem Filter.Tendsto.continuous_of_equicontinuousAt {l : Filter ι} [l.NeBot] /-- A version of `UniformEquicontinuous.closure` applicable to subsets of types which embed continuously into `β → α` with the product topology. It turns out we don't need any other condition -on the embedding than continuity, but in practice this will mostly be applied to `FunLike` types +on the embedding than continuity, but in practice this will mostly be applied to `DFunLike` types where the coercion is injective. -/ theorem UniformEquicontinuous.closure' {A : Set Y} {u : Y → β → α} (hA : UniformEquicontinuous (u ∘ (↑) : A → β → α)) (hu : Continuous u) : diff --git a/Mathlib/Topology/UniformSpace/Equiv.lean b/Mathlib/Topology/UniformSpace/Equiv.lean index b4a2710337e48..f2adb7db74879 100644 --- a/Mathlib/Topology/UniformSpace/Equiv.lean +++ b/Mathlib/Topology/UniformSpace/Equiv.lean @@ -57,7 +57,7 @@ instance : EquivLike (α ≃ᵤ β) α β where inv := fun h => h.toEquiv.symm left_inv := fun h => h.left_inv right_inv := fun h => h.right_inv - coe_injective' := fun _ _ H _ => toEquiv_injective <| FunLike.ext' H + coe_injective' := fun _ _ H _ => toEquiv_injective <| DFunLike.ext' H @[simp] theorem uniformEquiv_mk_coe (a : Equiv α β) (b c) : (UniformEquiv.mk a b c : α → β) = a := diff --git a/Mathlib/Topology/UniformSpace/Matrix.lean b/Mathlib/Topology/UniformSpace/Matrix.lean index d9ae28180f385..136d62d275b50 100644 --- a/Mathlib/Topology/UniformSpace/Matrix.lean +++ b/Mathlib/Topology/UniformSpace/Matrix.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser, Heather Macbeth -/ +import Mathlib.Topology.Algebra.UniformGroup import Mathlib.Topology.UniformSpace.Pi import Mathlib.Data.Matrix.Basic @@ -22,6 +23,10 @@ namespace Matrix instance : UniformSpace (Matrix m n 𝕜) := (by infer_instance : UniformSpace (m → n → 𝕜)) +instance instUniformAddGroup [AddGroup 𝕜] [UniformAddGroup 𝕜] : + UniformAddGroup (Matrix m n 𝕜) := + inferInstanceAs <| UniformAddGroup (m → n → 𝕜) + theorem uniformity : 𝓤 (Matrix m n 𝕜) = ⨅ (i : m) (j : n), (𝓤 𝕜).comap fun a => (a.1 i j, a.2 i j) := by erw [Pi.uniformity, Pi.uniformity] diff --git a/Mathlib/Topology/UniformSpace/Separation.lean b/Mathlib/Topology/UniformSpace/Separation.lean index 807a31e430cfe..81c097934d8ab 100644 --- a/Mathlib/Topology/UniformSpace/Separation.lean +++ b/Mathlib/Topology/UniformSpace/Separation.lean @@ -176,7 +176,7 @@ theorem separationRel_comap {f : α → β} 𝓢 α = Prod.map f f ⁻¹' 𝓢 β := by subst h dsimp [separationRel] - simp_rw [uniformity_comap, ((𝓤 β).comap_hasBasis $ Prod.map f f).ker, ker_def, preimage_iInter] + simp_rw [uniformity_comap, ((𝓤 β).comap_hasBasis <| Prod.map f f).ker, ker_def, preimage_iInter] #align separation_rel_comap separationRel_comap protected theorem Filter.HasBasis.separationRel {ι : Sort*} {p : ι → Prop} {s : ι → Set (α × α)} diff --git a/Mathlib/Topology/UniformSpace/UniformConvergenceTopology.lean b/Mathlib/Topology/UniformSpace/UniformConvergenceTopology.lean index c5f184f3f8286..bf8f898480622 100644 --- a/Mathlib/Topology/UniformSpace/UniformConvergenceTopology.lean +++ b/Mathlib/Topology/UniformSpace/UniformConvergenceTopology.lean @@ -167,9 +167,9 @@ open UniformConvergence variable {α β : Type*} {𝔖 : Set (Set α)} -instance [Nonempty β] : Nonempty (α →ᵤ β) := Pi.Nonempty +instance [Nonempty β] : Nonempty (α →ᵤ β) := Pi.instNonempty -instance [Nonempty β] : Nonempty (α →ᵤ[𝔖] β) := Pi.Nonempty +instance [Nonempty β] : Nonempty (α →ᵤ[𝔖] β) := Pi.instNonempty /-- Reinterpret `f : α → β` as an element of `α →ᵤ β`. -/ def UniformFun.ofFun : (α → β) ≃ (α →ᵤ β) := @@ -515,7 +515,7 @@ protected def uniformEquivPiComm : UniformEquiv (α →ᵤ ∀ i, δ i) (∀ i, -- that some square commutes. @Equiv.toUniformEquivOfUniformInducing _ _ 𝒰(α, ∀ i, δ i, Pi.uniformSpace δ) - (@Pi.uniformSpace ι (fun i => α → δ i) fun i => 𝒰(α, δ i, _)) (Equiv.piComm _) $ by + (@Pi.uniformSpace ι (fun i => α → δ i) fun i => 𝒰(α, δ i, _)) (Equiv.piComm _) <| by refine @UniformInducing.mk ?_ ?_ ?_ ?_ ?_ ?_ change comap (Prod.map Function.swap Function.swap) _ = _ rw [← uniformity_comap] @@ -860,7 +860,7 @@ protected def uniformEquivProdArrow [UniformSpace γ] : -- but it turns out to be more annoying. ((UniformOnFun.ofFun 𝔖).symm.trans <| (Equiv.arrowProdEquivProdArrow _ _ _).trans <| - (UniformOnFun.ofFun 𝔖).prodCongr (UniformOnFun.ofFun 𝔖)).toUniformEquivOfUniformInducing $ by + (UniformOnFun.ofFun 𝔖).prodCongr (UniformOnFun.ofFun 𝔖)).toUniformEquivOfUniformInducing <| by constructor rw [uniformity_prod, comap_inf, comap_comap, comap_comap] have H := @UniformOnFun.inf_eq α (β × γ) 𝔖 @@ -887,7 +887,7 @@ protected def uniformEquivPiComm : (α →ᵤ[𝔖] ((i:ι) → δ i)) ≃ᵤ (( -- We could also deduce this from `UniformFun.uniformEquivPiComm`, but it turns out -- to be more annoying. @Equiv.toUniformEquivOfUniformInducing (α →ᵤ[𝔖] ((i:ι) → δ i)) ((i:ι) → α →ᵤ[𝔖] δ i) - _ _ (Equiv.piComm _) $ by + _ _ (Equiv.piComm _) <| by constructor change comap (Prod.map Function.swap Function.swap) _ = _ erw [← uniformity_comap] diff --git a/Mathlib/Topology/UnitInterval.lean b/Mathlib/Topology/UnitInterval.lean index 44797fad16522..bb074cd7dd6cc 100644 --- a/Mathlib/Topology/UnitInterval.lean +++ b/Mathlib/Topology/UnitInterval.lean @@ -48,7 +48,7 @@ theorem one_mem : (1 : ℝ) ∈ I := #align unit_interval.one_mem unitInterval.one_mem theorem mul_mem {x y : ℝ} (hx : x ∈ I) (hy : y ∈ I) : x * y ∈ I := - ⟨mul_nonneg hx.1 hy.1, (mul_le_mul hx.2 hy.2 hy.1 zero_le_one).trans_eq <| one_mul 1⟩ + ⟨mul_nonneg hx.1 hy.1, mul_le_one hx.2 hy.1 hy.2⟩ #align unit_interval.mul_mem unitInterval.mul_mem theorem div_mem {x y : ℝ} (hx : 0 ≤ x) (hy : 0 ≤ y) (hxy : x ≤ y) : x / y ∈ I := @@ -94,11 +94,11 @@ instance : Mul I := -- todo: we could set up a `LinearOrderedCommMonoidWithZero I` instance theorem mul_le_left {x y : I} : x * y ≤ x := - Subtype.coe_le_coe.mp <| (mul_le_mul_of_nonneg_left y.2.2 x.2.1).trans_eq <| mul_one x.1 + Subtype.coe_le_coe.mp <| mul_le_of_le_one_right x.2.1 y.2.2 #align unit_interval.mul_le_left unitInterval.mul_le_left theorem mul_le_right {x y : I} : x * y ≤ y := - Subtype.coe_le_coe.mp <| (mul_le_mul_of_nonneg_right x.2.2 y.2.1).trans_eq <| one_mul y.1 + Subtype.coe_le_coe.mp <| mul_le_of_le_one_left y.2.1 x.2.2 #align unit_interval.mul_le_right unitInterval.mul_le_right /-- Unit interval central symmetry. -/ diff --git a/Mathlib/Topology/UrysohnsLemma.lean b/Mathlib/Topology/UrysohnsLemma.lean index 05125f0cb1965..7b01dbf31d9bc 100644 --- a/Mathlib/Topology/UrysohnsLemma.lean +++ b/Mathlib/Topology/UrysohnsLemma.lean @@ -6,6 +6,7 @@ Authors: Yury G. Kudryashov import Mathlib.Analysis.NormedSpace.AddTorsor import Mathlib.LinearAlgebra.AffineSpace.Ordered import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Algebra.Order.Support #align_import topology.urysohns_lemma from "leanprover-community/mathlib"@"f2ce6086713c78a7f880485f7917ea547a215982" diff --git a/Mathlib/Topology/VectorBundle/Basic.lean b/Mathlib/Topology/VectorBundle/Basic.lean index e06149db52d56..aa1f7619400a8 100644 --- a/Mathlib/Topology/VectorBundle/Basic.lean +++ b/Mathlib/Topology/VectorBundle/Basic.lean @@ -54,8 +54,6 @@ notes" section of `Mathlib.Topology.FiberBundle.Basic`. Vector bundle -/ -set_option autoImplicit true - noncomputable section open Bundle Set Classical @@ -680,7 +678,7 @@ def localTriv (i : ι) : Trivialization F (π F Z.Fiber) := -- porting note: moved from below to fix the next instance @[simp, mfld_simps] -theorem localTriv_apply (p : Z.TotalSpace) : +theorem localTriv_apply {i : ι} (p : Z.TotalSpace) : (Z.localTriv i) p = ⟨p.1, Z.coordChange (Z.indexAt p.1) i p.1 p.2⟩ := rfl #align vector_bundle_core.local_triv_apply VectorBundleCore.localTriv_apply diff --git a/Mathlib/Topology/VectorBundle/Hom.lean b/Mathlib/Topology/VectorBundle/Hom.lean index 1a6b649526806..9039c54882cb6 100644 --- a/Mathlib/Topology/VectorBundle/Hom.lean +++ b/Mathlib/Topology/VectorBundle/Hom.lean @@ -61,7 +61,7 @@ Porting note: after the port is done, we may want to remove this definition. -/ @[reducible] protected def Bundle.ContinuousLinearMap [∀ x, TopologicalSpace (E₁ x)] - [∀ x, TopologicalSpace (E₂ x)] : ∀ _ : B, Type _ := fun x => E₁ x →SL[σ] E₂ x + [∀ x, TopologicalSpace (E₂ x)] : B → Type _ := fun x => E₁ x →SL[σ] E₂ x #align bundle.continuous_linear_map Bundle.ContinuousLinearMap -- Porting note: possibly remove after the port diff --git a/Mathlib/Util/AddRelatedDecl.lean b/Mathlib/Util/AddRelatedDecl.lean index f56e8668c5b8b..22625a2347426 100644 --- a/Mathlib/Util/AddRelatedDecl.lean +++ b/Mathlib/Util/AddRelatedDecl.lean @@ -3,7 +3,8 @@ Copyright (c) 2023 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Floris van Doorn -/ -import Lean +import Lean.Elab.DeclarationRange +import Lean.Elab.Term /-! # `addRelatedDecl` @@ -44,7 +45,7 @@ def addRelatedDecl (src : Name) (suffix : String) (ref : Syntax) (construct : Expr → Expr → List Name → MetaM (Expr × List Name)) : MetaM Unit := do let tgt := match src with - | Name.str n s => Name.mkStr n $ s ++ suffix + | Name.str n s => Name.mkStr n <| s ++ suffix | x => x addDeclarationRanges tgt { range := ← getDeclarationRange (← getRef) @@ -66,7 +67,7 @@ def addRelatedDecl (src : Name) (suffix : String) (ref : Syntax) { info with levelParams := newLevels, type := newType, name := tgt, value := newValue } | _ => throwError "Constant {src} is not a theorem or definition." if isProtected (← getEnv) src then - setEnv $ addProtected (← getEnv) tgt + setEnv <| addProtected (← getEnv) tgt let attrs := match attrs? with | some attrs => attrs | none => #[] _ ← Term.TermElabM.run' <| do let attrs ← elabAttrs attrs diff --git a/Mathlib/Util/AssertExists.lean b/Mathlib/Util/AssertExists.lean index 41691c9dad605..093c438785aab 100644 --- a/Mathlib/Util/AssertExists.lean +++ b/Mathlib/Util/AssertExists.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Scott Morrison -/ -import Lean +import Lean.Elab.Command /-! # User commands for assert the (non-)existence of declaration or instances. diff --git a/Mathlib/Util/AtomM.lean b/Mathlib/Util/AtomM.lean index a396f30706ef4..3887182a2b19f 100644 --- a/Mathlib/Util/AtomM.lean +++ b/Mathlib/Util/AtomM.lean @@ -45,7 +45,6 @@ put it in the list of atoms and return the new index, otherwise. -/ def AtomM.addAtom (e : Expr) : AtomM Nat := do let c ← get for h : i in [:c.atoms.size] do - have : i < c.atoms.size := h.2 if ← withTransparency (← read).red <| isDefEq e c.atoms[i] then return i modifyGet fun c ↦ (c.atoms.size, { c with atoms := c.atoms.push e }) diff --git a/Mathlib/Util/CompileInductive.lean b/Mathlib/Util/CompileInductive.lean index 6653452c5879e..15b4ef01da861 100644 --- a/Mathlib/Util/CompileInductive.lean +++ b/Mathlib/Util/CompileInductive.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Parth Shastri, Gabriel Ebner, Mario Carneiro -/ import Lean.Compiler.CSimpAttr -import Lean.Elab.PreDefinition +import Lean.Meta.RecursorInfo +import Lean.Meta.Tactic.Subst import Mathlib.Tactic.RunCmd /-! diff --git a/Mathlib/Util/DischargerAsTactic.lean b/Mathlib/Util/DischargerAsTactic.lean index 0334142d33047..1af2581cffddc 100644 --- a/Mathlib/Util/DischargerAsTactic.lean +++ b/Mathlib/Util/DischargerAsTactic.lean @@ -22,5 +22,7 @@ This is inverse to `mkDischargeWrapper`. -/ def wrapSimpDischarger (dis : Simp.Discharge) : TacticM Unit := do let eS : Lean.Meta.Simp.State := {} let eC : Lean.Meta.Simp.Context := {} - let (some a, _) ← liftM <| StateRefT'.run (ReaderT.run (dis <| ← getMainTarget) eC) eS | failure + let eM : Lean.Meta.Simp.Methods := {} + let (some a, _) ← liftM <| StateRefT'.run (ReaderT.run (ReaderT.run (dis <| ← getMainTarget) + eM.toMethodsRef) eC) eS | failure (← getMainGoal).assignIfDefeq a diff --git a/Mathlib/Util/Export.lean b/Mathlib/Util/Export.lean index a119623b40873..41a2f086819ea 100644 --- a/Mathlib/Util/Export.lean +++ b/Mathlib/Util/Export.lean @@ -3,7 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Lean +import Lean.CoreM +import Lean.Util.FoldConsts /-! A rudimentary export format, adapted from @@ -72,7 +73,7 @@ namespace Export def alloc {α} [BEq α] [Hashable α] [OfState α] (a : α) : ExportM Nat := do let n := (OfState.get (α := α) (← get)).next - modify $ OfState.modify (α := α) fun s ↦ {map := s.map.insert a n, next := n+1} + modify <| OfState.modify (α := α) fun s ↦ {map := s.map.insert a n, next := n+1} pure n def exportName (n : Name) : ExportM Nat := do diff --git a/Mathlib/Util/Imports.lean b/Mathlib/Util/Imports.lean deleted file mode 100644 index bd46a73ce3214..0000000000000 --- a/Mathlib/Util/Imports.lean +++ /dev/null @@ -1,261 +0,0 @@ -/- -Copyright (c) 2023 Scott Morrison. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison --/ -import Mathlib.Lean.Expr.Basic -import Std.Lean.NameMap - - -/-! -# Tools for analyzing imports. - -Provides the commands - -* `#redundant_imports` which lists any transitively redundant imports in the current module. -* `#minimize_imports` which attempts to construct a minimal set of imports for the declarations - in the current file. - (Must be run at the end of the file. Tactics and macros may result in incorrect output.) -* `#find_home decl` suggests files higher up the import hierarchy to which `decl` could be moved. --/ - -open Lean - -namespace Lean.Environment - -/-- -Find the imports of a given module. --/ -def importsOf (env : Environment) (n : Name) : Array Name := - if n = env.header.mainModule then - env.header.imports.map Import.module - else match env.getModuleIdx? n with - | .some idx => env.header.moduleData[idx.toNat]!.imports.map Import.module |>.erase `Init - | .none => #[] - -/-- -Construct the import graph of the current file. --/ -partial def importGraph (env : Environment) : NameMap (Array Name) := - let main := env.header.mainModule - let imports := env.header.imports.map Import.module - imports.foldl (fun m i => process env i m) (({} : NameMap _).insert main imports) - |>.erase Name.anonymous -where - process (env) (i) (m) : NameMap (Array Name) := - if m.contains i then - m - else - let imports := env.importsOf i - imports.foldr (fun i m => process env i m) (m.insert i imports) - -/-- -Return the redundant imports (i.e. those transitively implied by another import) -amongst a candidate list of imports. --/ -partial def findRedundantImports (env : Environment) (imports : Array Name) : NameSet := - let run := visit env.importGraph imports - let (_, seen) := imports.foldl (fun ⟨v, s⟩ n => run v s n) ({}, {}) - seen -where - visit (Γ) (targets) (visited) (seen) (n) : NameSet × NameSet := - if visited.contains n then - (visited, seen) - else - let imports := (Γ.find? n).getD #[] - let (visited', seen') := imports.foldl (fun ⟨v, s⟩ t => visit Γ targets v s t) (visited, seen) - (visited'.insert n, - imports.foldl (fun s t => if targets.contains t then s.insert t else s) seen') - -end Lean.Environment - -namespace Lean.NameMap - -/-- -Compute the transitive closure of an import graph. --/ -partial def transitiveClosure (m : NameMap (Array Name)) : NameMap NameSet := - m.fold (fun r n i => process r n i) {} -where - process (r : NameMap NameSet) (n : Name) (i : Array Name) : NameMap NameSet := - if r.contains n then - r - else - let r' := i.foldr (fun i r => process r i ((m.find? i).getD #[])) r - let t := i.foldr - (fun j s => ((r'.find? j).getD {}).fold NameSet.insert s) - (RBTree.ofList i.toList) - r'.insert n t - -/-- -Compute the transitive reduction of an import graph. - -Typical usage is `transitiveReduction (← importGraph)`. --/ -def transitiveReduction (m : NameMap (Array Name)) : NameMap (Array Name) := - let c := transitiveClosure m - m.fold (fun r n a => - r.insert n (a.foldr (fun i b => b.filter (fun j => ! ((c.find? i).getD {}).contains j)) a)) {} - -/-- Restrict an import graph to only the downstream dependencies of some set of modules. -/ -def downstreamOf (m : NameMap (Array Name)) (targets : NameSet) : NameMap (Array Name) := - let tc := transitiveClosure m - let P (n : Name) := targets.contains n || ((tc.find? n).getD {}).any fun j => targets.contains j - m.fold (init := {}) fun r n i => - if P n then - r.insert n (i.filter P) - else - r - -/-- Restrict an import graph to only the transitive imports of some set of modules. -/ -def upstreamOf (m : NameMap (Array Name)) (targets : NameSet) : NameMap (Array Name) := - let tc := transitiveClosure m - let P (n : Name) := targets.contains n || targets.any fun t => ((tc.find? t).getD {}).contains n - m.fold (init := {}) fun r n i => - if P n then - r.insert n (i.filter P) - else - r - -/-- -Filter the list of edges `… → node` inside `graph` by the function `filter`. - -Any such upstream node `source` where `filter source` returns true will be replaced -by all its upstream nodes. This results in a list of all unfiltered nodes -in the `graph` that either had an edge to `node` -or had an indirect edge to `node` going through filtered nodes. - -Will panic if the `node` is not in the `graph`. --/ -partial -def transitiveFilteredUpstream (node : Name) (graph : NameMap (Array Name)) - (filter : Name → Bool) (replacement : Option Name := none): - List Name := - (graph.find! node).toList.bind fun source => - ( if filter source then - -- Add the transitive edges going through the filtered node `source`. - -- If there is a replacement node, add an additional edge `repl → node`. - match replacement with - | none => transitiveFilteredUpstream source graph filter - | some repl => .cons repl <| transitiveFilteredUpstream source graph filter - -- If the node is not filtered, we leave the edge `source → node` intact. - else [source]).eraseDup - -/-- -Filters the `graph` removing all nodes where `filter n` returns false. Additionally, -replace edges from removed nodes by all the transitive edges. - -This means there is a path between two nodes in the filtered graph iff there exists -such a path in the original graph. - -If the optional `(replacement : Name)` is provided, a corresponding node will be -added together with edges to all nodes which had an incoming edge from any -filtered node. --/ -def filterGraph (graph : NameMap (Array Name)) (filter : Name → Bool) - (replacement : Option Name := none) : NameMap (Array Name) := - -- Create a list of all files imported by any of the filtered files - -- and remove all imports starting with `Mathlib` to avoid loops. - let replImports := graph.toList.bind - (fun ⟨n, i⟩ => if filter n then i.toList else []) - |>.eraseDup |>.filter (¬ Name.isPrefixOf `Mathlib ·) |>.toArray - let graph := graph.filterMap (fun node edges => if filter node then none else some <| - -- If the node `node` is not filtered, modify the `edges` going into `node`. - edges.toList.bind (fun source => - if filter source then - transitiveFilteredUpstream source graph filter (replacement := replacement) - else [source]) |>.eraseDup.toArray) - -- Add a replacement node if provided. - match replacement with - | none => graph - | some repl => graph.insert repl replImports - -end Lean.NameMap - -/-- -Return the redundant imports (i.e. those transitively implied by another import) -of a specified module (or the current module if `none` is specified). --/ -def redundantImports (n? : Option Name := none) : CoreM NameSet := do - let env ← getEnv - let imports := env.importsOf (n?.getD (env.header.mainModule)) - return env.findRedundantImports imports - -/-- -List the imports in this file which can be removed -because they are transitively implied by another import. --/ -elab "#redundant_imports" : command => do - let redundant := (← Elab.Command.liftCoreM do redundantImports) - if redundant.isEmpty then - logInfo "No transitively redundant imports found." - else - logInfo m!"Found the following transitively redundant imports:\n\ - {Format.joinSep redundant.toList "\n"}" - -/-- -Return the names of the modules in which constants used in the current file were defined, -with modules already transitively imported removed. - -Note that this will *not* account for tactics and syntax used in the file, -so the results may not suffice as imports. --/ -def Lean.Environment.minimalRequiredModules (env : Environment) : Array Name := - let required := env.requiredModules.toArray.erase env.header.mainModule - let redundant := findRedundantImports env required - required.filter fun n => ¬ redundant.contains n - -/-- -Try to compute a minimal set of imports for this file, -by analyzing the declarations. - -This must be run at the end of the file, -and is not aware of syntax and tactics, -so the results will likely need to be adjusted by hand. --/ -elab "#minimize_imports" : command => do - let imports := (← getEnv).minimalRequiredModules.qsort Name.lt - |>.toList.map (fun n => "import " ++ n.toString) - logInfo <| Format.joinSep imports "\n" - -/-- -Find locations as high as possible in the import hierarchy -where the named declaration could live. --/ -def Lean.Name.findHome (n : Name) (env : Option Environment) : CoreM NameSet := do - let current? := match env with | some env => env.header.mainModule | _ => default - let required := (← n.requiredModules).toArray.erase current? - let imports := (← getEnv).importGraph.transitiveClosure - let mut candidates : NameSet := {} - for (n, i) in imports do - if required.all fun r => n == r || i.contains r then - candidates := candidates.insert n - for c in candidates do - for i in candidates do - if imports.find? i |>.getD {} |>.contains c then - candidates := candidates.erase i - return candidates - -open Elab in -/-- -Find locations as high as possible in the import hierarchy -where the named declaration could live. -Using `#find_home!` will forcefully remove the current file. -Note that this works best if used in a file with `import Mathlib`. - -The current file could still be the only suggestion, even using `#find_home! lemma`. -The reason is that `#find_home!` scans the import graph below the current file, -selects all the files containing declarations appearing in `lemma`, excluding -the current file itself and looks for all least upper bounds of such files. - -For a simple example, if `lemma` is in a file importing only `A.lean` and `B.lean` and -uses one lemma from each, then `#find_home! lemma` returns the current file. --/ -elab "#find_home" bang:"!"? n:ident : command => do - let stx ← getRef - let mut homes := #[] - let n ← resolveGlobalConstNoOverloadWithInfo n - let env := if bang.isSome then some (← getEnv) else none - for i in (← Elab.Command.liftCoreM do n.findHome env) do - homes := homes.push i - logInfoAt stx[0] m!"{homes}" diff --git a/Mathlib/Util/LongNames.lean b/Mathlib/Util/LongNames.lean index a4f61d290fa8a..c13b3f976f07b 100644 --- a/Mathlib/Util/LongNames.lean +++ b/Mathlib/Util/LongNames.lean @@ -19,7 +19,7 @@ open Lean Meta Elab def printNameHashMap (h : Std.HashMap Name (Array Name)) : IO Unit := for (m, names) in h.toList do IO.println "----" - IO.println $ m.toString ++ ":" + IO.println <| m.toString ++ ":" for n in names do IO.println n diff --git a/Mathlib/Util/MemoFix.lean b/Mathlib/Util/MemoFix.lean index f3076273a8100..cd9eb99dfb518 100644 --- a/Mathlib/Util/MemoFix.lean +++ b/Mathlib/Util/MemoFix.lean @@ -25,7 +25,7 @@ private unsafe def memoFixImplObj (f : (Object → Object) → (Object → Objec let b := f fix a cache.modify (·.insert a b) pure b - pure $ fix a + pure <| fix a private unsafe def memoFixImpl {α : Type u} {β : Type v} [Nonempty β] : (f : (α → β) → (α → β)) → (a : α) → β := diff --git a/Mathlib/Util/SleepHeartbeats.lean b/Mathlib/Util/SleepHeartbeats.lean index 1c163f71710c4..2fdfdeb4238a3 100644 --- a/Mathlib/Util/SleepHeartbeats.lean +++ b/Mathlib/Util/SleepHeartbeats.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Alex J. Best. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Alex J. Best -/ -import Lean +import Lean.Elab.Tactic.Basic /-! # Defines `sleep_heartbeats` tactic. diff --git a/Mathlib/Util/Superscript.lean b/Mathlib/Util/Superscript.lean index f215e717ed4b4..9fdb254afe754 100644 --- a/Mathlib/Util/Superscript.lean +++ b/Mathlib/Util/Superscript.lean @@ -3,8 +3,7 @@ Copyright (c) 2023 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Lean -import Std +import Std.Tactic.Lint /-! # A parser for superscripts and subscripts diff --git a/Mathlib/Util/Syntax.lean b/Mathlib/Util/Syntax.lean index c38d360c258d1..05e43fe6b6b63 100644 --- a/Mathlib/Util/Syntax.lean +++ b/Mathlib/Util/Syntax.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Gabriel Ebner -/ -import Lean +import Lean.Syntax /-! # Helper functions for working with typed syntaxes. diff --git a/Mathlib/Util/SynthesizeUsing.lean b/Mathlib/Util/SynthesizeUsing.lean index bf98baaf8cfbb..3056d155e5aca 100644 --- a/Mathlib/Util/SynthesizeUsing.lean +++ b/Mathlib/Util/SynthesizeUsing.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Lean +import Lean.Elab.Tactic.Basic /-! # `SynthesizeUsing` diff --git a/Mathlib/Util/Tactic.lean b/Mathlib/Util/Tactic.lean index cbd6091551edf..2b3f7f9437871 100644 --- a/Mathlib/Util/Tactic.lean +++ b/Mathlib/Util/Tactic.lean @@ -3,8 +3,7 @@ Copyright (c) 2022 Arthur Paulino. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino, Jannis Limperg -/ - -import Mathlib.Lean.Expr.Basic +import Lean.MetavarContext /-! # Miscellaneous helper functions for tactics. @@ -16,7 +15,7 @@ set_option autoImplicit true namespace Mathlib.Tactic -open Lean Meta Elab Tactic +open Lean Meta Tactic variable [Monad m] diff --git a/Mathlib/Util/TermBeta.lean b/Mathlib/Util/TermBeta.lean index 69bae70c757aa..2cd8f8d0ccca8 100644 --- a/Mathlib/Util/TermBeta.lean +++ b/Mathlib/Util/TermBeta.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Lean +import Lean.Elab.Term /-! `beta%` term elaborator diff --git a/Mathlib/Util/WhatsNew.lean b/Mathlib/Util/WhatsNew.lean index 3225231d1ad34..4372b6ade6579 100644 --- a/Mathlib/Util/WhatsNew.lean +++ b/Mathlib/Util/WhatsNew.lean @@ -107,7 +107,7 @@ def whatsNew (old new : Environment) : CoreM MessageData := do if diffs.isEmpty then return "no new constants" - pure $ MessageData.joinSep diffs.toList "\n\n" + pure <| MessageData.joinSep diffs.toList "\n\n" /-- `whatsnew in $command` executes the command and then prints the declarations that were added to the environment. -/ diff --git a/Shake/Main.lean b/Shake/Main.lean new file mode 100644 index 0000000000000..86fdbe1aba238 --- /dev/null +++ b/Shake/Main.lean @@ -0,0 +1,456 @@ +/- +Copyright (c) 2023 Mario Carneiro. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro +-/ +import Lean.Util.FoldConsts +import Lean + +/-! # `lake exe shake` command + +This command will check mathlib (or the specified modules) and all their dependency for unused +imports. This works by looking at generated `.olean` files to deduce required imports and ensuring +that every import is used to contribute some constant. Because recompilation is not needed this +is quite fast (about 8 seconds to check `Mathlib` and all dependencies), but it has some known +limitations: + +* Tactics that are used during elaboration generally leave no trace in the proof term, so + they will be incorrectly marked as unused. +* Similarly, files that contribute only notations will not be detected. +* Conversely, files that define tactics and notations are also likely to have false positives + because the notation itself does not depend on the referenced constant (it elaborates to a + name literal rather than an actual reference to the target constant). + +To mitigate this, the `scripts/noshake.json` file is used to suppress known false positives. See +`ShakeCfg` for information regarding the file format. + +-/ + +def help : String := "Mathlib4 tree shaking tool +Usage: lake exe shake [OPTIONS] .. + +Arguments: + + A module path like `Mathlib`. All files transitively reachable from the + provided module(s) will be checked. + +Options: + --fix + Apply the suggested fixes directly. Make sure you have a clean checkout + before running this, so you can review the changes. + + --cfg (default: scripts/noshake.json) + Use FILE to specify which imports we should ignore. + + --update + Assume that all issues we find are false positives and update the config + file to include them. + + --no-downstream + Unless disabled, shake will check downstream files that were transitively + depending on the import we want to remove and re-add the import to these + downstream files. + +# The noshake.json file + +The file passed in the --cfg argument is a JSON file with the following +structure: + + { + \"ignoreAll\": [NAME], + \"ignoreImport\": [NAME], + \"ignore\": {NAME: [NAME]} + } + +The fields can be omitted if empty. They have the following interpretation: + +* ignoreAll: + All imports in these files should be treated as necessary +* ignore[X]: + All imports in the list should be treated as necessary when processing X +* ignoreImport: + These files should be treated as necessary when imported into any other file. +" + +open Lean + +/-- We use `Nat` as a bitset for doing efficient set operations. +The bit indexes will usually be a module index. -/ +abbrev Bitset := Nat + +/-- The main state of the checker, containing information on all loaded modules. -/ +structure State where + /-- Maps a module name to its index in the module list. -/ + toIdx : HashMap Name USize := {} + /-- Maps a module index to the module name. -/ + modNames : Array Name := #[] + /-- Maps a module index to the module data. -/ + mods : Array ModuleData := #[] + /-- `j ∈ deps[i]` if module `j` is a direct dependency of module `i` -/ + deps : Array Bitset := #[] + /-- `j ∈ transDeps[i]` is the reflexive transitive closure of `deps` -/ + transDeps : Array Bitset := #[] + /-- `j ∈ needs[i]` if module `i` uses a constant declared in module `j`. + Note: this is left empty if `args.downstream` is false, we calculate `needs` on demand -/ + needs : Array Bitset := #[] + /-- Maps a constant name to the module index containing it. -/ + constToIdx : HashMap Name USize := {} + +/-- Calculates the value of the `needs[i]` bitset for a given module `mod`. +Bit `j` is set in the result if some constant from module `j` is used in this module. -/ +def calcNeeds (constToIdx : HashMap Name USize) (mod : ModuleData) : Bitset := + mod.constants.foldl (init := 0) fun deps ci => + let deps := visitExpr ci.type deps + match ci.value? with + | some e => visitExpr e deps + | none => deps +where + /-- Accumulate the results from expression `e` into `deps`. -/ + visitExpr e deps := + Lean.Expr.foldConsts e deps fun c deps => match constToIdx.find? c with + | some i => deps ||| (1 <<< i.toNat) + | none => deps + +/-- Load all the modules in `imports` into the `State`, as well as their transitive dependencies. +Returns a pair `(imps, transImps)` where: + +* `j ∈ imps` if `j` is one of the module indexes in `imports` +* `j ∈ transImps` if module `j` is transitively reachable from `imports` + -/ +partial def loadModules (imports : Array Import) : StateT State IO (Bitset × Bitset) := do + let mut imps := 0 + let mut transImps := 0 + for imp in imports do + let s ← get + if let some i := s.toIdx.find? imp.module then + imps := imps ||| (1 <<< i.toNat) + transImps := transImps ||| s.transDeps[i]! + else + let mFile ← findOLean imp.module + unless (← mFile.pathExists) do + throw <| IO.userError s!"object file '{mFile}' of module {imp.module} does not exist" + let (mod, _) ← readModuleData mFile + let (deps, transDeps) ← loadModules mod.imports + let s ← get + let n := s.mods.size.toUSize + let transDeps := transDeps ||| (1 <<< n.toNat) + imps := imps ||| (1 <<< n.toNat) + transImps := transImps ||| transDeps + set (σ := State) { + toIdx := s.toIdx.insert imp.module n + modNames := s.modNames.push imp.module + mods := s.mods.push mod + deps := s.deps.push deps + transDeps := s.transDeps.push transDeps + needs := s.needs + constToIdx := mod.constNames.foldl (·.insert · n) s.constToIdx + } + return (imps, transImps) + +/-- The list of edits that will be applied in `--fix`. `edits[i] = (removed, added)` where: + +* If `j ∈ removed` then we want to delete module named `j` from the imports of `i` +* If `j ∈ added` then we want to add module index `j` to the imports of `i`. + We keep this as a bitset because we will do transitive reduction before applying it +-/ +def Edits := HashMap Name (NameSet × Bitset) + +/-- Register that we want to remove `tgt` from the imports of `src`. -/ +def Edits.remove (ed : Edits) (src tgt : Name) : Edits := + match ed.find? src with + | none => ed.insert src (RBTree.insert ∅ tgt, 0) + | some (a, b) => ed.insert src (a.insert tgt, b) + +/-- Register that we want to add `tgt` to the imports of `src`. -/ +def Edits.add (ed : Edits) (src : Name) (tgt : Nat) : Edits := + match ed.find? src with + | none => ed.insert src (∅, 1 <<< tgt) + | some (a, b) => ed.insert src (a, b ||| (1 <<< tgt)) + +/-- Analyze and report issues from module `i`. Arguments: + +* `s`: The main state (contains all the modules and dependency information) +* `srcSearchPath`: Used to find the path for error reporting purposes +* `ignoreImps`: if `j ∈ ignoreImps` then it will be treated as used +* `i`: the module index +* `needs`: this is the same as `s.needs[i]`, except that this array may not + be initialized if `downstream` mode is disabled so we pass it in here +* `edits`: accumulates the list of edits to apply if `--fix` is true +* `downstream`: if true, then we report downstream files that need to be fixed too + -/ +def visitModule (s : State) (srcSearchPath : SearchPath) (ignoreImps : Bitset) + (i : Nat) (needs : Bitset) (edits : Edits) (downstream := true) : IO Edits := do + -- Do transitive reduction of `needs` in `deps` and transitive closure in `transDeps`. + -- Include the `ignoreImps` in `transDeps` + let mut deps := needs + let mut transDeps := needs ||| ignoreImps + for i in [0:s.mods.size] do + if deps &&& (1 <<< i) != 0 then + let deps2 := s.transDeps[i]! + deps := deps ^^^ (deps &&& deps2) ^^^ (1 <<< i) + transDeps := transDeps ||| deps2 + + -- Any import which is not in `transDeps` was unused. + -- Also accumulate `newDeps` which is the transitive closure of the remaining imports + let mut toRemove := #[] + let mut newDeps := 0 + for imp in s.mods[i]!.imports do + let i := s.toIdx.find! imp.module + if transDeps &&& (1 <<< i.toNat) == 0 then + toRemove := toRemove.push i + else + newDeps := newDeps ||| s.transDeps[i]! + + if toRemove.isEmpty then return edits -- nothing to do + + -- If `newDeps` does not cover `needs`, then we have to add back some imports until it does. + -- To minimize new imports we pick only new imports which are not transitively implied by + -- another new import + let mut toAdd := #[] + for i in [0:s.mods.size] do + if deps &&& (1 <<< i) != 0 && newDeps &&& (1 <<< i) == 0 then + toAdd := toAdd.push i + newDeps := newDeps ||| s.transDeps[i]! + + -- mark and report the removals + let mut edits := toRemove.foldl (init := edits) fun edits n => + edits.remove s.modNames[i]! s.modNames[n]! + if let some path ← srcSearchPath.findModuleWithExt "lean" s.modNames[i]! then + println! "{path}:" + else + println! "{s.modNames[i]!}:" + println! " remove {toRemove.map (s.modNames[·]!)}" + + -- mark and report the additions + if !toAdd.isEmpty then + edits := toAdd.foldl (init := edits) fun edits n => + edits.add s.modNames[i]! n + println! " add {toAdd.map (s.modNames[·]!)}" + + if downstream then + -- In `downstream` mode, we should also check all the other modules to find out if + -- we have a situation like `A -/> B -> C`, where we are removing the `A -> B` import + -- but `C` depends on `A` and only directly imports `B`. + -- This situation occurs when `A ∈ needs[C]` and `B ∈ transDeps[C]`. + for r in toRemove do + let mut toFix := 0 + for j in [0:s.mods.size] do + if j != i && s.needs[j]! &&& (1 <<< r.toNat) != 0 && s.transDeps[j]! &&& (1 <<< i) != 0 then + toFix := toFix ||| (1 <<< j) + if toFix != 0 then + -- `toFix` is the list of all files that need to have the import of `A` added back in, + -- but some of them might be importing others, for example if `A -/> B -> C -> D` where + -- `A ∈ needs[C]` and `A ∈ needs[D]`, adding the `A` import to `C` fixes the issue with `D` + -- for free. So we take only the minimal elements of `toFix` to actually fix. + let mut toFixArr := #[] + for j in [0:s.mods.size] do + if toFix &&& s.transDeps[j]! == 1 <<< j then + toFixArr := toFixArr.push j + edits := toFixArr.foldl (init := edits) fun edits n => + edits.add s.modNames[n]! r.toNat + println! " fix {s.modNames[r]!}: {toFixArr.map (s.modNames[·]!)}" + return edits + +/-- Convert a list of module names to a bitset of module indexes -/ +def toBitset (s : State) (ns : List Name) : Bitset := + ns.foldl (init := 0) fun c name => + match s.toIdx.find? name with + | some i => c ||| (1 <<< i.toNat) + | none => c + +/-- The parsed CLI arguments. See `help` for more information -/ +structure Args where + /-- `--help`: shows the help -/ + help : Bool := false + /-- `--no-downstream`: disables downstream mode -/ + downstream : Bool := true + /-- `--fix`: apply the fixes directly -/ + fix : Bool := false + /-- `--update`: update the config file -/ + update : Bool := false + /-- `--global`: with `--update`, add imports to `ignoreImport` instead of `ignore` -/ + global : Bool := false + /-- `--cfg FILE`: choose a custom location for the config file -/ + cfg : Option String := none + /-- `..`: the list of root modules to check -/ + mods : Array Name := #[] + +instance {α} [FromJson α] : FromJson (NameMap α) where + fromJson? j := do + (← j.getObj?).foldM (init := mkNameMap _) fun m a b => do + m.insert a.toName <$> fromJson? b +instance {α} [ToJson α] : ToJson (NameMap α) where + toJson m := Json.obj <| m.fold (init := ∅) fun m a b => + m.insert compare (toString a) (toJson b) + +/-- The config file format, which we both read and write. -/ +structure ShakeCfg where + /-- All imports from modules in this list will be ignored -/ + ignoreAll? : Option (List Name) := none + /-- The modules in this list will be ignored as imports of any other file -/ + ignoreImport? : Option (List Name) := [`Init, `Lean] + /-- If `X` maps to `Y` then an import of `Y` in module `X` will be ignored -/ + ignore? : Option (NameMap (Array Name)) := none + deriving FromJson, ToJson + +/-- The main entry point. See `help` for more information on arguments. -/ +def main (args : List String) : IO Unit := do + initSearchPath (← findSysroot) + -- Parse the arguments + let rec parseArgs (args : Args) : List String → Args + | [] => args + | "--help" :: rest => parseArgs { args with help := true } rest + | "--no-downstream" :: rest => parseArgs { args with downstream := false } rest + | "--fix" :: rest => parseArgs { args with fix := true } rest + | "--update" :: rest => parseArgs { args with update := true } rest + | "--global" :: rest => parseArgs { args with global := true } rest + | "--cfg" :: cfg :: rest => parseArgs { args with cfg := cfg } rest + | "--" :: rest => { args with mods := args.mods ++ rest.map (·.toName) } + | other :: rest => parseArgs { args with mods := args.mods.push other.toName } rest + let args := parseArgs {} args + + -- Bail if `--help` is passed + if args.help then + IO.println help + IO.Process.exit 0 + + -- Parse the `--cfg` argument + let srcSearchPath ← initSrcSearchPath + let cfgFile ← if let some cfg := args.cfg then + pure (some ⟨cfg⟩) + else if let some path ← srcSearchPath.findModuleWithExt "lean" `Mathlib then + pure (some (path.parent.get! / "scripts" / "noshake.json")) + else pure none + + -- Read the config file + let cfg ← if let some file := cfgFile then + try + IO.ofExcept (Json.parse (← IO.FS.readFile file) >>= fromJson? (α := ShakeCfg)) + catch e => + println! "{e.toString}" + pure {} + else pure {} + + -- the list of root modules + let mods := if args.mods.isEmpty then #[`Mathlib] else args.mods + -- Only submodules of `pkg` will be edited or have info reported on them + let pkg := mods[0]!.components.head! + + -- Load all the modules + let mut (_, s) ← (loadModules (mods.map ({module := ·}))).run {} + + -- Parse the config file + let ignoreMods := toBitset s (cfg.ignoreAll?.getD []) + let ignoreImps := toBitset s (cfg.ignoreImport?.getD []) + let ignore := (cfg.ignore?.getD {}).fold (init := mkHashMap) fun m a v => + m.insert a (toBitset s v.toList) + + let noIgnore (i : Nat) := + !s.mods[i]!.constNames.isEmpty && -- skip import-only mods + ignoreMods &&& (1 <<< i) == 0 && + pkg.isPrefixOf s.modNames[i]! + + -- Run the calculation of the `needs` array in parallel + let needs := s.mods.mapIdx fun i mod => + if args.downstream || noIgnore i then + some <| Task.spawn fun _ => + -- remove the module from its own `needs` + (calcNeeds s.constToIdx mod ||| (1 <<< i.1)) ^^^ (1 <<< i.1) + else + none + if args.downstream then + s := { s with needs := needs.map (·.get!.get) } + + -- Check all selected modules + let mut edits : Edits := mkHashMap + for i in [0:s.mods.size], t in needs do + if let some t := t then + if noIgnore i then + let ignoreImps := ignoreImps ||| ignore.findD s.modNames[i]! 0 + edits ← visitModule s srcSearchPath ignoreImps i t.get edits args.downstream + + -- Write the config file + if args.update then + if let some cfgFile := cfgFile then + let mut ignore := cfg.ignore?.getD {} + let ignoreImport := cfg.ignoreImport?.getD {} + let mut ignoreImportSet : NameSet := ignoreImport.foldl .insert {} + -- if `args.fix` is true then we assume the errors will be fixed after, + -- so it's just reformatting the existing file + if !args.fix then + if args.global then + -- in global mode all the edits are added to `ignoreImport` + ignoreImportSet := edits.fold (init := ignoreImportSet) + (fun ignore _ (remove, _) => ignore.union remove) + else + -- in local mode all the edits are added to `ignore` + ignore := edits.fold (init := ignore) fun ignore mod (remove, _) => + let ns := (ignore.findD mod #[]).foldl (init := remove) (·.insert ·) + if ns.isEmpty then ignore.erase mod else + ignore.insert mod ns.toArray + -- If an entry is in `ignoreAll`, the `ignore` key is redundant + for i in cfg.ignoreAll?.getD {} do + if ignore.contains i then + ignore := ignore.erase i + -- If an entry is in `ignoreImport`, the `ignore` value is redundant + ignore := ignore.fold (init := {}) fun ignore mod ns => + let ns := ns.filter (!ignoreImportSet.contains ·) + if ns.isEmpty then ignore else ignore.insert mod (ns.qsort (·.toString < ·.toString)) + -- Sort the lists alphabetically + let ignoreImport := (ignoreImportSet.toArray.qsort (·.toString < ·.toString)).toList + let cfg : ShakeCfg := { + ignoreAll? := cfg.ignoreAll?.filter (!·.isEmpty) + ignoreImport? := (some ignoreImport).filter (!·.isEmpty) + ignore? := (some ignore).filter (!·.isEmpty) + } + IO.FS.writeFile cfgFile <| toJson cfg |>.pretty + + -- Apply the edits to existing files + if !args.fix then return + edits.forM fun mod (remove, add) => do + -- Only edit files in the current package + if pkg.isPrefixOf mod then + -- Compute the transitive reduction of `add` and convert to a list of names + let add := if add == 0 then #[] else Id.run do + let mut val := add + for i in [0:s.mods.size] do + if val &&& (1 <<< i) != 0 then + val := val ^^^ (val &&& s.transDeps[i]!) ^^^ (1 <<< i) + let mut out := #[] + for i in [0:s.mods.size] do + if val &&& (1 <<< i) != 0 then + out := out.push s.modNames[i]! + out.qsort Name.lt + + -- Parse the input file + let some path ← srcSearchPath.findModuleWithExt "lean" mod + | println! "error: failed to find source file for {mod}" + let text ← IO.FS.readFile path + let inputCtx := Parser.mkInputContext text path.toString + let (header, parserState, msgs) ← Parser.parseHeader inputCtx + if !msgs.isEmpty then -- skip this file if there are parse errors + msgs.forM fun msg => msg.toString >>= IO.println + return + + -- Calculate the edit result + let mut pos : String.Pos := 0 + let mut out : String := "" + let mut seen : NameSet := {} + for stx in header[1].getArgs do + let mod := stx[2].getId + if remove.contains mod || seen.contains mod then + out := out ++ text.extract pos stx.getPos?.get! + -- We use the end position of the syntax, but include whitespace up to the first newline + pos := text.findAux (· == '\n') text.endPos stx.getTailPos?.get! + ⟨1⟩ + seen := seen.insert mod + -- the insertion point for `add` is the first newline after the imports + let insertion := header.getTailPos?.getD parserState.pos + let insertion := text.findAux (· == '\n') text.endPos insertion + ⟨1⟩ + out := out ++ text.extract pos insertion + for mod in add do + if !seen.contains mod then + seen := seen.insert mod + out := out ++ s!"import {mod}\n" + out := out ++ text.extract insertion text.endPos + + IO.FS.writeFile path out diff --git a/docs/references.bib b/docs/references.bib index 579d89c03a7e6..a43362e2bc891 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -939,6 +939,18 @@ @Book{ Elephant publisher = {Oxford University Press} } +@Article{ elliott2006binomial, + author = {Elliott, Jesse}, + title = {Binomial rings, integer-valued polynomials, and λ-rings}, + journal = {Journal of Pure and Applied Algebra}, + number = {1}, + year = {2006}, + pages = {165–185}, + volume = {207}, + publisher = {Elsevier}, + doi = {10.1016/j.jpaa.2005.09.003} +} + @Book{ engel1997, title = {Sperner theory}, author = {Engel, Konrad}, diff --git a/lake-manifest.json b/lake-manifest.json index 5ef737b829a59..5a53c7f8b6add 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -4,7 +4,7 @@ [{"url": "https://github.com/leanprover/std4", "type": "git", "subDir": null, - "rev": "0410d2762ab42a57fd8d7c98b73b87b7082dd65b", + "rev": "1d17268685714381c10b6389cca0a9e380742731", "name": "std", "manifestFile": "lake-manifest.json", "inputRev": "nightly-testing", @@ -22,19 +22,19 @@ {"url": "https://github.com/leanprover-community/aesop", "type": "git", "subDir": null, - "rev": "48375eac3aa5e3be2869d718e1f5c38b83787243", + "rev": "7a0082b8286da58fb63d0abfe2a78b3c164bd62a", "name": "aesop", "manifestFile": "lake-manifest.json", - "inputRev": "bump/v4.6.0", + "inputRev": "nightly-testing", "inherited": false, "configFile": "lakefile.lean"}, {"url": "https://github.com/leanprover-community/ProofWidgets4", "type": "git", "subDir": null, - "rev": "8dd18350791c85c0fc9adbd6254c94a81d260d35", + "rev": "9466e2c665dd81f8c9bdd2e27b67c1cac0145571", "name": "proofwidgets", "manifestFile": "lake-manifest.json", - "inputRev": "v0.0.25", + "inputRev": "v0.0.26-pre", "inherited": false, "configFile": "lakefile.lean"}, {"url": "https://github.com/leanprover/lean4-cli", @@ -45,6 +45,15 @@ "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": false, + "configFile": "lakefile.lean"}, + {"url": "https://github.com/leanprover-community/import-graph.git", + "type": "git", + "subDir": null, + "rev": "7d051a52c49ac25ee5a04c7a2a70148cc95ddab3", + "name": "importGraph", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": false, "configFile": "lakefile.lean"}], "name": "mathlib", "lakeDir": ".lake"} diff --git a/lakefile.lean b/lakefile.lean index 3d8d080cdaea8..f7373cbbf2be4 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -28,9 +28,10 @@ require «doc-gen4» from git "https://github.com/leanprover/doc-gen4" @ "main" require std from git "https://github.com/leanprover/std4" @ "nightly-testing" require Qq from git "https://github.com/leanprover-community/quote4" @ "master" -require aesop from git "https://github.com/leanprover-community/aesop" @ "bump/v4.6.0" -require proofwidgets from git "https://github.com/leanprover-community/ProofWidgets4" @ "v0.0.25" +require aesop from git "https://github.com/leanprover-community/aesop" @ "nightly-testing" +require proofwidgets from git "https://github.com/leanprover-community/ProofWidgets4" @ "v0.0.26-pre" require Cli from git "https://github.com/leanprover/lean4-cli" @ "main" +require importGraph from git "https://github.com/leanprover-community/import-graph.git" @ "main" /-! ## Mathlib libraries @@ -43,7 +44,6 @@ lean_lib Cache lean_lib MathlibExtras lean_lib Archive lean_lib Counterexamples -lean_lib ImportGraph /-- Additional documentation in the form of modules that only contain module docstrings. -/ lean_lib docs where roots := #[`docs] @@ -61,9 +61,9 @@ lean_exe checkYaml where srcDir := "scripts" supportInterpreter := true -/-- `lake exe graph` constructs import graphs in `.dot` or graphical formats. -/ -lean_exe graph where - root := `ImportGraph.Main +/-- `lake exe shake` checks files for unnecessary imports. -/ +lean_exe shake where + root := `Shake.Main supportInterpreter := true /-! diff --git a/scripts/bench/fake-root/bin/lean b/scripts/bench/fake-root/bin/lean index b0a53ca119798..248444b934b1c 100755 --- a/scripts/bench/fake-root/bin/lean +++ b/scripts/bench/fake-root/bin/lean @@ -11,4 +11,5 @@ for arg in "$@"; do fi done -perf stat -e instructions -x ';' lean --profile -Dprofiler.threshold=10000 "$@" |& sed -E "s/([0-9]+);;instructions;.*/~$mod| \\1s/" +# measure userspace instructions per file as almost-deterministic time-like metric +perf stat -e instructions:u -x ';' lean --profile -Dprofiler.threshold=10000 "$@" |& sed -E "s/([0-9]+);;instructions:u;.*/~$mod| \\1s/" diff --git a/scripts/bench/run b/scripts/bench/run index 1995762847bb9..5a2903e9d2228 100755 --- a/scripts/bench/run +++ b/scripts/bench/run @@ -4,5 +4,7 @@ set -euxo pipefail temci exec --config ./scripts/bench/temci-config.yml >2 temci report --reporter codespeed2 |\ + sed 's/instructions:u/instructions/g' |\ jq '(.build | to_entries | group_by(.key | test("~")) | map(from_entries)) as $groups | .build = $groups[0] | . + ($groups[1] | map_values({instructions: .}))' - # move file metrics starting with "~" from "build" to toplevel and assign them the "instructions" metric + # sed: preserve old metric names + # jq: move file metrics starting with "~" from "build" to toplevel and assign them the "instructions" metric diff --git a/scripts/bench/temci-config.run.yml b/scripts/bench/temci-config.run.yml index e0872f2798a78..94da59c4ae3e9 100644 --- a/scripts/bench/temci-config.run.yml +++ b/scripts/bench/temci-config.run.yml @@ -3,7 +3,7 @@ run_config: runner: perf_stat perf_stat: - properties: ['wall-clock', 'task-clock', 'instructions', 'branches', 'branch-misses'] + properties: ['wall-clock', 'task-clock', 'instructions:u', 'branches', 'branch-misses'] rusage_properties: ['maxrss'] cmd: | bash -c 'set -eo pipefail; lake clean && LEAN_PATH=$(lean --print-libdir) lake build -v --lean ./scripts/bench/fake-root/bin/lean | ./scripts/bench/accumulate_profile.py | grep -v took' @@ -14,7 +14,7 @@ run_config: runner: perf_stat perf_stat: - properties: ['wall-clock', 'instructions'] + properties: ['wall-clock', 'instructions:u'] cmd: | make lint runs: 1 @@ -23,7 +23,7 @@ run_config: runner: perf_stat perf_stat: - properties: ['wall-clock', 'task-clock', 'instructions'] + properties: ['wall-clock', 'task-clock', 'instructions:u'] rusage_properties: ['maxrss'] cmd: | # run lake+lean like the file worker would diff --git a/scripts/install_debian.sh b/scripts/install_debian.sh index cc46455f1acaf..d2085be2d8cfb 100755 --- a/scripts/install_debian.sh +++ b/scripts/install_debian.sh @@ -12,7 +12,7 @@ rm elan-init.sh # The following test is needed in case VScode or VSCodium was installed by other # means (e.g. using Ubuntu snap) -vsc="$(which code 2>/dev/null || which codium 2>/dev/null)" +vsc="$(which code 2>/dev/null || which codium 2>/dev/null || true)" if [ -z "$vsc" ]; then wget -O code.deb https://go.microsoft.com/fwlink/?LinkID=760868 sudo apt install -y ./code.deb diff --git a/scripts/lean-pr-testing-comments.sh b/scripts/lean-pr-testing-comments.sh index 854c7d6f25a72..397fb18a9fce5 100755 --- a/scripts/lean-pr-testing-comments.sh +++ b/scripts/lean-pr-testing-comments.sh @@ -1,6 +1,9 @@ ## Create comments and labels on a Lean 4 PR after CI has finished on a `lean-pr-testing-NNNN` branch. +## +## See https://leanprover-community.github.io/contribute/tags_and_branches.html set -e + # TODO: The whole script ought to be rewritten in javascript, to avoid having to use curl for API calls. # # This is not meant to be run from the command line, only from CI. @@ -9,9 +12,12 @@ set -e # TOKEN: ${{ secrets.LEAN_PR_TESTING }} # GITHUB_CONTEXT: ${{ toJson(github) }} # WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }} +# BUILD_OUTCOME: ${{ steps.build.outcome }} +# NOISY_OUTCOME: ${{ steps.noisy.outcome }} +# ARCHIVE_OUTCOME: ${{ steps.archive.outcome }} +# COUNTEREXAMPLES_OUTCOME: ${{ steps.counterexamples.outcome }} # LINT_OUTCOME: ${{ steps.lint.outcome }} # TEST_OUTCOME: ${{ steps.test.outcome }} -# BUILD_OUTCOME: ${{ steps.build.outcome }} # CHECK_OUTCOME: ${{ steps.lean4checker.outcome }} # Extract branch name and check if it matches the pattern. @@ -45,7 +51,7 @@ if [[ "$branch_name" =~ ^lean-pr-testing-([0-9]+)$ ]]; then -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/leanprover/lean4/issues/$pr_number/labels \ -d '{"labels":["builds-mathlib"]}' - elif [ "$CHECK_OUTCOME" == "failure" ] || [ "$LINT_OUTCOME" == "failure" ] || [ "$TEST_OUTCOME" == "failure" ] || [ "$BUILD_OUTCOME" == "failure" ]; then + elif [ "$CHECK_OUTCOME" == "failure" ] || [ "$LINT_OUTCOME" == "failure" ] || [ "$TEST_OUTCOME" == "failure" ] || [ "$COUNTEREXAMPLES_OUTCOME" == "failure" ] || [ "$ARCHIVE_OUTCOME" == "failure" ] || [ "$NOISY_OUTCOME" == "failure" ] || [ "$BUILD_OUTCOME" == "failure" ]; then echo "Removing label builds-mathlib" curl -L -s \ -X DELETE \ @@ -53,37 +59,44 @@ if [[ "$branch_name" =~ ^lean-pr-testing-([0-9]+)$ ]]; then -H "Authorization: Bearer $TOKEN" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/leanprover/lean4/issues/$pr_number/labels/builds-mathlib - echo "Adding label breaks-mathlib" + echo "Adding labels breaks-mathlib and full-ci" + # We also add the 'full-ci' label, as fixing a Mathlib breakage may require toolchains for all OSes curl -L -s \ -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer $TOKEN" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/leanprover/lean4/issues/$pr_number/labels \ - -d '{"labels":["breaks-mathlib"]}' + -d '{"labels":["breaks-mathlib", "full-ci"]}' fi # Use GitHub API to check if a comment already exists existing_comment=$(curl -L -s -H "Authorization: token $TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/leanprover/lean4/issues/$pr_number/comments" \ - | jq '.[] | select(.body | test("^- . Mathlib")) | select(.user.login == "leanprover-community-mathlib4-bot")') + | jq 'first(.[] | select(.body | test("^- . Mathlib") or startswith("Mathlib CI status")) | select(.user.login == "leanprover-community-mathlib4-bot"))') existing_comment_id=$(echo "$existing_comment" | jq -r .id) existing_comment_body=$(echo "$existing_comment" | jq -r .body) branch="[lean-pr-testing-$pr_number](https://github.com/leanprover-community/mathlib4/compare/nightly-testing...lean-pr-testing-$pr_number)" # Depending on the success/failure, set the appropriate message - if [ "$LINT_OUTCOME" == "cancelled" ] || [ "$TEST_OUTCOME" == "cancelled" ] || [ "$BUILD_OUTCOME" == "cancelled" ] || [ "$CHECK_OUTCOME" == "cancelled" ]; then + if [ "$LINT_OUTCOME" == "cancelled" ] || [ "$TEST_OUTCOME" == "cancelled" ] || [ "$COUNTEREXAMPLES_OUTCOME" == "cancelled" ] || [ "$ARCHIVE_OUTCOME" == "cancelled" ] || [ "$NOISY_OUTCOME" == "cancelled" ] || [ "$BUILD_OUTCOME" == "cancelled" ] || [ "$CHECK_OUTCOME" == "cancelled" ]; then message="- 🟡 Mathlib branch $branch build against this PR was cancelled. ($current_time) [View Log]($WORKFLOW_URL)" elif [ "$CHECK_OUTCOME" == "success" ]; then message="- ✅ Mathlib branch $branch has successfully built against this PR. ($current_time) [View Log]($WORKFLOW_URL)" - elif [ "$LINT_OUTCOME" == "success" ]; then + elif [ "$CHECK_OUTCOME" == "failure" ]; then message="- ❌ Mathlib branch $branch built against this PR, but lean4checker failed. ($current_time) [View Log]($WORKFLOW_URL)" - elif [ "$TEST_OUTCOME" == "success" ]; then + elif [ "$LINT_OUTCOME" == "failure" ]; then message="- ❌ Mathlib branch $branch built against this PR, but linting failed. ($current_time) [View Log]($WORKFLOW_URL)" - elif [ "$BUILD_OUTCOME" == "success" ]; then + elif [ "$COUNTEREXAMPLES_OUTCOME" == "failure" ]; then + message="- ❌ Mathlib branch $branch built against this PR, but the counterexamples library failed. ($current_time) [View Log]($WORKFLOW_URL)" + elif [ "$ARCHIVE_OUTCOME" == "failure" ]; then + message="- ❌ Mathlib branch $branch built against this PR, but the archive failed. ($current_time) [View Log]($WORKFLOW_URL)" + elif [ "$NOISY_OUTCOME" == "failure" ]; then + message="- ❌ Mathlib branch $branch built against this PR, but was unexpectedly noisy. ($current_time) [View Log]($WORKFLOW_URL)" + elif [ "$TEST_OUTCOME" == "failure" ]; then message="- ❌ Mathlib branch $branch built against this PR, but testing failed. ($current_time) [View Log]($WORKFLOW_URL)" - elif [ "$CHECK_OUTCOME" == "failure" ] || [ "$LINT_OUTCOME" == "failure" ] || [ "$TEST_OUTCOME" == "failure" ] || [ "$BUILD_OUTCOME" == "failure" ]; then + elif [ "$BUILD_OUTCOME" == "failure" ] ; then message="- 💥 Mathlib branch $branch build failed against this PR. ($current_time) [View Log]($WORKFLOW_URL)" else message="- 🟡 Mathlib branch $branch build this PR didn't complete normally. ($current_time) [View Log]($WORKFLOW_URL)" @@ -94,12 +107,14 @@ if [[ "$branch_name" =~ ^lean-pr-testing-([0-9]+)$ ]]; then # Append new result to the existing comment or post a new comment if [ -z "$existing_comment_id" ]; then # Post new comment with a bullet point + # Keep message in sync with https://github.com/leanprover/lean4/blob/master/.github/workflows/pr-release.yml + intro="Mathlib CI status ([docs](https://leanprover-community.github.io/contribute/tags_and_branches.html)):" echo "Posting as new comment at leanprover/lean4/issues/$pr_number/comments" curl -L -s \ -X POST \ -H "Authorization: token $TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ - -d "$(jq --null-input --arg val "$message" '{"body": $val}')" \ + -d "$(jq --null-input --arg intro "$intro" --arg val "$message" '{"body": ($intro + "\n" + $val)}')" \ "https://api.github.com/repos/leanprover/lean4/issues/$pr_number/comments" else # Append new result to the existing comment diff --git a/scripts/lint-style.py b/scripts/lint-style.py index 5fa3dbb87d0ec..b19209bd3758f 100755 --- a/scripts/lint-style.py +++ b/scripts/lint-style.py @@ -51,6 +51,7 @@ ERR_CLN = 16 # line starts with a colon ERR_IND = 17 # second line not correctly indented ERR_ARR = 18 # space after "←" +ERR_NUM_LIN = 19 # file is too large exceptions = [] @@ -60,20 +61,22 @@ with SCRIPTS_DIR.joinpath("style-exceptions.txt").open(encoding="utf-8") as f: for exline in f: - filename, _, _, _, _, errno, *_ = exline.split() + filename, _, _, _, _, errno, *extra = exline.split() path = ROOT_DIR / filename if errno == "ERR_COP": - exceptions += [(ERR_COP, path)] + exceptions += [(ERR_COP, path, None)] if errno == "ERR_MOD": - exceptions += [(ERR_MOD, path)] + exceptions += [(ERR_MOD, path, None)] if errno == "ERR_LIN": - exceptions += [(ERR_LIN, path)] + exceptions += [(ERR_LIN, path, None)] if errno == "ERR_OPT": - exceptions += [(ERR_OPT, path)] + exceptions += [(ERR_OPT, path, None)] if errno == "ERR_AUT": - exceptions += [(ERR_AUT, path)] + exceptions += [(ERR_AUT, path, None)] if errno == "ERR_TAC": - exceptions += [(ERR_TAC, path)] + exceptions += [(ERR_TAC, path, None)] + if errno == "ERR_NUM_LIN": + exceptions += [(ERR_NUM_LIN, path, extra[1])] new_exceptions = False @@ -328,7 +331,7 @@ def output_message(path, line_nr, code, msg): def format_errors(errors): global new_exceptions for errno, line_nr, path in errors: - if (errno, path.resolve()) in exceptions: + if (errno, path.resolve(), None) in exceptions: continue new_exceptions = True if errno == ERR_COP: @@ -377,6 +380,21 @@ def lint(path, fix=False): format_errors(errs) if not import_only_check(newlines, path): + # Check for too long files: either longer than 1500 lines, or not covered by an exception. + # Each exception contains a "watermark". If the file is longer than that, we also complain. + if len(lines) > 1500: + ex = [e for e in exceptions if e[1] == path.resolve()] + if ex: + (_ERR_NUM, _path, watermark) = list(ex)[0] + assert int(watermark) > 500 # protect against parse error + is_too_long = len(lines) > int(watermark) + else: + is_too_long = True + if is_too_long: + new_exceptions = True + # add up to 200 lines of slack, so simple PRs don't trigger this right away + watermark = len(lines) // 100 * 100 + 200 + output_message(path, 1, "ERR_NUM_LIN", f"{watermark} file contains {len(lines)} lines, try to split it up") errs, newlines = regular_check(newlines, path) format_errors(errs) errs, newlines = banned_import_check(newlines, path) diff --git a/scripts/nolints.json b/scripts/nolints.json index 21ee2657fed9f..5b4bc92b5ff7a 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -38,11 +38,9 @@ ["docBlame", "RightInverse"], ["docBlame", "Ring"], ["docBlame", "Semiring"], - ["docBlame", "Set"], ["docBlame", "UFModel"], ["docBlame", "UFNode"], ["docBlame", "UnionFind"], - ["docBlame", "UpperLowerSet_toOrderDualHomeomorph"], ["docBlame", "Writer"], ["docBlame", "WriterT"], ["docBlame", "Xor'"], @@ -61,12 +59,8 @@ ["docBlame", "joinM"], ["docBlame", "measurability!"], ["docBlame", "measurability!?"], - ["docBlame", "setOf"], ["docBlame", "tacticCancel_denoms_"], ["docBlame", "tacticUse_finite_instance"], - ["docBlame", "termCexp"], - ["docBlame", "«termLine[_,_,_]»"], - ["docBlame", "termRexp"], ["docBlame", "«term_+ᵥ_»"], ["docBlame", "«term_-ᵥ_»"], ["docBlame", "«term_[Λ^_]→L[_]_»"], @@ -81,7 +75,6 @@ ["docBlame", "«term_→ₗᵢ[_]_»"], ["docBlame", "«term_→ₗᵢ⋆[_]_»"], ["docBlame", "«term_→ₛₗᵢ[_]_»"], - ["docBlame", "«term_≃_»"], ["docBlame", "«term_≃ᵃ[_]_»"], ["docBlame", "«term_≃ᵃⁱ[_]_»"], ["docBlame", "«term_≃ᵈ_»"], @@ -91,10 +84,8 @@ ["docBlame", "«term_≡_[SMOD_]»"], ["docBlame", "«term_⊻_»"], ["docBlame", "«term_⊼_»"], - ["docBlame", "«termΩ[_⁄_]»"], ["docBlame", "termℂ"], ["docBlame", "termℕ"], - ["docBlame", "termℙ"], ["docBlame", "termℤ"], ["docBlame", "«termℤ√_»"], ["docBlame", "«term∃!_,_»"], @@ -104,90 +95,43 @@ ["docBlame", "«term∯_InT(_,_),_»"], ["docBlame", "«term⨍_In_.._,_»"], ["docBlame", "timeCmd"], - ["docBlame", "toOrderDualHomeomorph"], ["docBlame", "when"], ["docBlame", "whenM"], ["docBlame", "Action.V"], ["docBlame", "Action.ρ"], - ["docBlame", "AddCancelMonoid.add_right_cancel"], - ["docBlame", "AddChar.toFun"], ["docBlame", "AddCommGroup.«term_≡_[PMOD_]»"], - ["docBlame", "AddGroup.add_left_neg"], - ["docBlame", "AddGroupFilterBasis.add'"], - ["docBlame", "AddGroupFilterBasis.conj'"], - ["docBlame", "AddGroupFilterBasis.neg'"], - ["docBlame", "AddGroupFilterBasis.zero'"], - ["docBlame", "AddGroupWithOne.add_left_neg"], - ["docBlame", "AddGroupWithOne.sub_eq_add_neg"], ["docBlame", "AddGroupWithOne.zsmul"], - ["docBlame", "AddGroupWithOne.zsmul_neg'"], - ["docBlame", "AddGroupWithOne.zsmul_succ'"], - ["docBlame", "AddGroupWithOne.zsmul_zero'"], - ["docBlame", "AddLeftCancelSemigroup.add_left_cancel"], ["docBlame", "AddMagmaCat.forget_obj_eq_coe"], ["docBlame", "AddMonoidAlgebra.mapDomain"], ["docBlame", "AddMonoidAlgebra.single"], - ["docBlame", "AddRightCancelSemigroup.add_right_cancel"], ["docBlame", "AddSemigroupCat.forget_obj_eq_coe"], ["docBlame", "Affine.termAffineSpace"], - ["docBlame", "Affine.«term_∥_»"], - ["docBlame", "AffineBasis.ind'"], ["docBlame", "AffineBasis.toFun"], - ["docBlame", "AffineBasis.tot'"], ["docBlame", "AffineEquiv.linear"], - ["docBlame", "AffineEquiv.map_vadd'"], - ["docBlame", "AffineIsometry.norm_map"], - ["docBlame", "AffineIsometryEquiv.norm_map"], ["docBlame", "AffineMap.linear"], - ["docBlame", "AffineMap.map_vadd'"], ["docBlame", "AffineMap.toFun"], - ["docBlame", "AffineSubspace.carrier"], - ["docBlame", "AffineSubspace.smul_vsub_vadd_mem"], - ["docBlame", "AlgHom.commutes'"], ["docBlame", "AlgHom.toAddMonoidHom'"], ["docBlame", "AlgHom.toMonoidHom'"], - ["docBlame", "AlgHomClass.commutes"], - ["docBlame", "Algebra.commutes'"], - ["docBlame", "Algebra.smul_def'"], ["docBlame", "AlgebraCat.carrier"], ["docBlame", "AlgebraicGeometry.«termProj|_»"], ["docBlame", "AndThen'.andthen"], ["docBlame", "Asymptotics.«term_=Θ[_]_»"], ["docBlame", "Asymptotics.«term_~[_]_»"], - ["docBlame", "BaireSpace.baire_property"], ["docBlame", "BddDistLat.toDistLat"], ["docBlame", "BddLat.toLat"], ["docBlame", "Bifunctor.bimap"], ["docBlame", "BilinForm.bilin"], - ["docBlame", "BilinForm.bilin_add_left"], - ["docBlame", "BilinForm.bilin_add_right"], - ["docBlame", "BilinForm.bilin_smul_left"], - ["docBlame", "BilinForm.bilin_smul_right"], ["docBlame", "Bimod.X"], ["docBlame", "Bimod.actLeft"], ["docBlame", "Bimod.actRight"], - ["docBlame", "Bimod.actRight_one"], - ["docBlame", "Bimod.left_assoc"], - ["docBlame", "Bimod.middle_assoc"], - ["docBlame", "Bimod.one_actLeft"], - ["docBlame", "Bimod.right_assoc"], ["docBlame", "BinaryHeap.arr"], ["docBlame", "Bipointed.X"], ["docBlame", "Bipointed.toProd"], ["docBlame", "Bitraversable.bitraverse"], - ["docBlame", "BorelSpace.measurable_eq"], - ["docBlame", "BoundedContinuousFunction.map_bounded'"], ["docBlame", "BoundedContinuousFunction.«term_→ᵇ_»"], - ["docBlame", "BoundedContinuousMapClass.map_bounded"], ["docBlame", "BoundedRandom.randomR"], - ["docBlame", "BoundedSMul.dist_pair_smul'"], - ["docBlame", "BoundedSMul.dist_smul_pair'"], ["docBlame", "BoxIntegral.«term_→ᵇᵃ[_]_»"], ["docBlame", "BoxIntegral.«term_→ᵇᵃ_»"], - ["docBlame", "BumpCovering.eventuallyEq_one'"], - ["docBlame", "BumpCovering.le_one'"], - ["docBlame", "BumpCovering.locallyFinite'"], - ["docBlame", "BumpCovering.nonneg'"], ["docBlame", "BumpCovering.toFun"], ["docBlame", "ByteSlice.arr"], ["docBlame", "ByteSlice.len"], @@ -196,14 +140,9 @@ ["docBlame", "ByteSliceT.off"], ["docBlame", "CFilter.f"], ["docBlame", "CFilter.inf"], - ["docBlame", "CFilter.inf_le_left"], - ["docBlame", "CFilter.inf_le_right"], ["docBlame", "CFilter.pt"], ["docBlame", "CancelDenoms.synthesizeUsingNormNum"], - ["docBlame", "CancelMonoid.mul_right_cancel"], - ["docBlame", "CanonicalEmbedding.termE"], ["docBlame", "Cardinal.term𝔠"], - ["docBlame", "CategoryTheory.projectiveResolution"], ["docBlame", "CategoryTheory.«term_ᘁ»"], ["docBlame", "CategoryTheory.«term_ᘁ_1»"], ["docBlame", "CategoryTheory.«term_⟶[_]_»"], @@ -211,114 +150,48 @@ ["docBlame", "CategoryTheory.«termᘁ_»"], ["docBlame", "CategoryTheory.«termᘁ__1»"], ["docBlame", "ChangeOfRings.«term_⊗ₜ[_,_]_»"], - ["docBlame", "CharP.cast_eq_zero_iff'"], ["docBlame", "ChartedSpace.atlas"], ["docBlame", "ChartedSpace.chartAt"], - ["docBlame", "ChartedSpace.chart_mem_atlas"], - ["docBlame", "ChartedSpace.mem_chart_source"], ["docBlame", "ChartedSpaceCore.atlas"], ["docBlame", "ChartedSpaceCore.chartAt"], - ["docBlame", "ChartedSpaceCore.chart_mem_atlas"], - ["docBlame", "ChartedSpaceCore.continuous_toFun"], - ["docBlame", "ChartedSpaceCore.mem_chart_source"], - ["docBlame", "ChartedSpaceCore.open_source"], - ["docBlame", "CircleDeg1Lift.map_add_one'"], - ["docBlame", "ClopenUpperSet.upper'"], - ["docBlame", "ClosedUnderRestriction.closedUnderRestriction"], ["docBlame", "Combinator.I"], ["docBlame", "Combinator.K"], ["docBlame", "Combinator.S"], - ["docBlame", "CommMon_.mul_comm"], ["docBlame", "CommRingCat.forget_obj_eq_coe"], ["docBlame", "CommSemiRingCat.forget_obj_eq_coe"], - ["docBlame", "CompletableTopField.nice"], ["docBlame", "CompleteBooleanAlgebra.toCompleteAtomicBooleanAlgebra"], - ["docBlame", "CompletelyDistribLattice.iInf_iSup_eq"], ["docBlame", "Complex.im"], ["docBlame", "Complex.re"], - ["docBlame", "Complex.termCexp"], ["docBlame", "Complex.«term_×ℂ_»"], - ["docBlame", "ComplexStarModule.termℑ"], - ["docBlame", "ComplexStarModule.termℜ"], ["docBlame", "CompositionSeries.length"], ["docBlame", "CompositionSeries.series"], - ["docBlame", "CompositionSeries.step'"], ["docBlame", "Computability.«term_∗»"], ["docBlame", "Computation.parallelRec"], ["docBlame", "Congr!.elabConfig"], ["docBlame", "ContDiffBump.rIn"], - ["docBlame", "ContDiffBump.rIn_lt_rOut"], - ["docBlame", "ContDiffBump.rIn_pos"], ["docBlame", "ContDiffBump.rOut"], - ["docBlame", "ContDiffBumpBase.eq_one"], - ["docBlame", "ContDiffBumpBase.mem_Icc"], - ["docBlame", "ContDiffBumpBase.smooth"], - ["docBlame", "ContDiffBumpBase.support"], - ["docBlame", "ContDiffBumpBase.symmetric"], ["docBlame", "ContDiffBumpBase.toFun"], - ["docBlame", "ContMDiffSection.contMDiff_toFun"], ["docBlame", "ContMDiffSection.toFun"], ["docBlame", "ContT.map"], ["docBlame", "ContT.monadLift"], ["docBlame", "ContT.run"], ["docBlame", "ContT.withContT"], - ["docBlame", "ContinuousAdd.continuous_add"], - ["docBlame", "ContinuousAffineMap.cont"], - ["docBlame", "ContinuousDiv.continuous_div'"], - ["docBlame", "ContinuousInv.continuous_inv"], - ["docBlame", - "ContinuousLinearMap.instNormedSpaceContinuousLinearMapToSemiringToDivisionSemiringToSemifieldToFieldToNormedFieldIdToNonAssocSemiringContinuousLinearMapToTopologicalSpaceToUniformSpaceToPseudoMetricSpaceToAddCommMonoidToAddCommGroupToTopologicalSpaceToUniformSpaceToPseudoMetricSpaceToAddCommMonoidToAddCommGroupToModuleToModuleTopologicalSpaceToTopologicalAddGroupAddCommMonoidToContinuousAddToAddGroupToSeminormedAddGroupContinuousLinearMapToTopologicalSpaceToUniformSpaceToPseudoMetricSpaceToAddCommMonoidToAddCommGroupToModuleTopologicalSpaceToTopologicalAddGroupAddCommMonoidToContinuousAddToAddGroupToSeminormedAddGroupModuleSmulCommClass_selfToCommMonoidToCommRingToEuclideanDomainToMulActionToMonoidWithZeroToZeroToNegZeroClassToSubNegZeroMonoidToSubtractionMonoidToDivisionAddCommMonoidToMulActionWithZeroContinuousConstSMulToTopologicalSpaceToUniformSpaceToPseudoMetricSpaceToSeminormedRingToSeminormedCommRingToNormedCommRingToSMulToZeroToAddMonoidToSMulZeroClassToZeroToSMulWithZeroContinuousSMulToZeroToCommMonoidWithZeroToCommGroupWithZeroBoundedSMulModuleSmulCommClass_selfToMulActionToZeroToNegZeroClassToSubNegZeroMonoidToSubtractionMonoidToDivisionAddCommMonoidToMulActionWithZeroContinuousConstSMulToSMulToZeroToAddMonoidToSMulZeroClassToSMulWithZeroContinuousSMulBoundedSMulInstSeminormedAddCommGroupContinuousLinearMapToSemiringToDivisionSemiringToSemifieldToFieldToNormedFieldIdToNonAssocSemiringContinuousLinearMapToTopologicalSpaceToUniformSpaceToPseudoMetricSpaceToAddCommMonoidToAddCommGroupToTopologicalSpaceToUniformSpaceToPseudoMetricSpaceToAddCommMonoidToAddCommGroupToModuleToModuleTopologicalSpaceToTopologicalAddGroupAddCommMonoidToContinuousAddToAddGroupToSeminormedAddGroupContinuousLinearMapToTopologicalSpaceToUniformSpaceToPseudoMetricSpaceToAddCommMonoidToAddCommGroupToModuleTopologicalSpaceToTopologicalAddGroupAddCommMonoidToContinuousAddToAddGroupToSeminormedAddGroupModuleSmulCommClass_selfToCommMonoidToCommRingToEuclideanDomainToMulActionToMonoidWithZeroToZeroToNegZeroClassToSubNegZeroMonoidToSubtractionMonoidToDivisionAddCommMonoidToMulActionWithZeroContinuousConstSMulToTopologicalSpaceToUniformSpaceToPseudoMetricSpaceToSeminormedRingToSeminormedCommRingToNormedCommRingToSMulToZeroToAddMonoidToSMulZeroClassToZeroToSMulWithZeroContinuousSMulToZeroToCommMonoidWithZeroToCommGroupWithZeroBoundedSMulModuleSmulCommClass_selfToMulActionToZeroToNegZeroClassToSubNegZeroMonoidToSubtractionMonoidToDivisionAddCommMonoidToMulActionWithZeroContinuousConstSMulToSMulToZeroToAddMonoidToSMulZeroClassToSMulWithZeroContinuousSMulBoundedSMul"], ["docBlame", "ContinuousMap.«term_≃ₕ_»"], - ["docBlame", "ContinuousMul.continuous_mul"], - ["docBlame", "ContinuousNeg.continuous_neg"], - ["docBlame", "ContinuousOpenMap.map_open'"], - ["docBlame", "ContinuousOpenMapClass.map_open"], - ["docBlame", "ContinuousOrderHom.continuous_toFun"], - ["docBlame", "ContinuousOrderHomClass.map_monotone"], - ["docBlame", "ContinuousOrderHomClass.toContinuousOrderHom"], - ["docBlame", "ContinuousSub.continuous_sub"], - ["docBlame", "ContractibleSpace.hequiv_unit'"], ["docBlame", "Convex.«term[_-[_]_]»"], ["docBlame", "ConvexBody.carrier"], - ["docBlame", "ConvexBody.convex'"], - ["docBlame", "ConvexBody.isCompact'"], - ["docBlame", "ConvexBody.nonempty'"], - ["docBlame", "ConvexCone.add_mem'"], ["docBlame", "ConvexCone.carrier"], - ["docBlame", "ConvexCone.smul_mem'"], - ["docBlame", "Convolution.«term_⋆[_,_]_»"], - ["docBlame", "Convolution.«term_⋆[_]_»"], - ["docBlame", "Convolution.«term_⋆_»"], - ["docBlame", "CstarRing.norm_star_mul_self"], ["docBlame", "Ctop.f"], ["docBlame", "Ctop.inter"], - ["docBlame", "Ctop.inter_mem"], - ["docBlame", "Ctop.inter_sub"], ["docBlame", "Ctop.top"], - ["docBlame", "Ctop.top_mem"], ["docBlame", "Cubic.a"], ["docBlame", "Cubic.b"], ["docBlame", "Cubic.c"], ["docBlame", "Cubic.d"], - ["docBlame", "CuspForm.holo'"], - ["docBlame", "CuspForm.zero_at_infty'"], - ["docBlame", "CuspFormClass.holo"], - ["docBlame", "CuspFormClass.zero_at_infty"], ["docBlame", "Decidable.recOn_false"], ["docBlame", "Decidable.recOn_true"], - ["docBlame", "Derivation.leibniz'"], - ["docBlame", "Derivation.map_one_eq_zero'"], ["docBlame", "Derivation.«termC^_⟮_,_;_⟯⟨_⟩»"], - ["docBlame", "DiffContOnCl.continuousOn"], - ["docBlame", "DiffContOnCl.differentiableOn"], - ["docBlame", "Diffeomorph.contMDiff_invFun"], - ["docBlame", "Diffeomorph.contMDiff_toFun"], - ["docBlame", "Dilation.edist_eq'"], ["docBlame", "Dilation.toFun"], - ["docBlame", "DilationClass.edist_eq'"], - ["docBlame", "DilationEquiv.edist_eq'"], ["docBlame", "DilationEquiv.toDilation"], - ["docBlame", "DilationEquivClass.edist_eq'"], ["docBlame", "Dioph.«term&_»"], ["docBlame", "Dioph.«termD&_»"], ["docBlame", "Dioph.«termD._»"], @@ -336,35 +209,16 @@ ["docBlame", "Dioph.«term_D∨_»"], ["docBlame", "Dioph.«term_D≠_»"], ["docBlame", "Dioph.«term_D≤_»"], - ["docBlame", "DirectedSystem.map_map'"], - ["docBlame", "DirectedSystem.map_self'"], - ["docBlame", "DiscreteValuationRing.not_a_field'"], ["docBlame", "Dist.dist"], - ["docBlame", "DivInvOneMonoid.inv_one"], ["docBlame", "DivisibleBy.div"], - ["docBlame", "DivisibleBy.div_cancel"], - ["docBlame", "DivisibleBy.div_zero"], - ["docBlame", "DivisionMonoid.inv_eq_of_mul"], - ["docBlame", "DivisionMonoid.inv_inv"], - ["docBlame", "DivisionMonoid.mul_inv_rev"], ["docBlame", "DoldKan.«termK[_]»"], ["docBlame", "DoldKan.«termN[_]»"], - ["docBlame", "DualNumber.«term_[ε]»"], - ["docBlame", "DualNumber.termε"], ["docBlame", "EDist.edist"], - ["docBlame", "EMetricSpace.eq_of_edist_eq_zero"], - ["docBlame", "ENorm.eq_zero'"], - ["docBlame", "ENorm.map_add_le'"], - ["docBlame", "ENorm.map_smul_le'"], ["docBlame", "ENorm.toFun"], ["docBlame", "EqualCharZero.pnatCast"], ["docBlame", "Equiv.invFun"], - ["docBlame", "Equiv.left_inv"], - ["docBlame", "Equiv.right_inv"], ["docBlame", "Equiv.toFun"], - ["docBlame", "EsakiaHom.exists_map_eq_of_map_le'"], ["docBlame", "EsakiaHom.toPseudoEpimorphism"], - ["docBlame", "EsakiaHomClass.exists_map_eq_of_map_le"], ["docBlame", "EuclideanDomain.wellFoundedRelation"], ["docBlame", "EuclideanGeometry.o"], ["docBlame", "EuclideanGeometry.«term∠»"], @@ -372,25 +226,13 @@ ["docBlame", "ExceptT.callCC"], ["docBlame", "ExceptT.mkLabel"], ["docBlame", "FBinopElab.elabBinOp"], - ["docBlame", "FiberBundle.mem_baseSet_trivializationAt'"], - ["docBlame", "FiberBundle.totalSpaceMk_inducing'"], ["docBlame", "FiberBundle.trivializationAt'"], ["docBlame", "FiberBundle.trivializationAtlas'"], - ["docBlame", "FiberBundle.trivialization_mem_atlas'"], ["docBlame", "FiberBundleCore.baseSet"], - ["docBlame", "FiberBundleCore.continuousOn_coordChange"], ["docBlame", "FiberBundleCore.coordChange"], - ["docBlame", "FiberBundleCore.coordChange_comp"], - ["docBlame", "FiberBundleCore.coordChange_self"], ["docBlame", "FiberBundleCore.indexAt"], - ["docBlame", "FiberBundleCore.isOpen_baseSet"], - ["docBlame", "FiberBundleCore.mem_baseSet_at"], - ["docBlame", "FiberPrebundle.continuous_trivChange"], - ["docBlame", "FiberPrebundle.mem_base_pretrivializationAt"], ["docBlame", "FiberPrebundle.pretrivializationAt"], ["docBlame", "FiberPrebundle.pretrivializationAtlas"], - ["docBlame", "FiberPrebundle.pretrivialization_mem_atlas"], - ["docBlame", "FiberPrebundle.totalSpaceMk_inducing"], ["docBlame", "FinBddDistLat.toBddDistLat"], ["docBlame", "FinBoolAlg.toBoolAlg"], ["docBlame", "FinPartOrd.toPartOrd"], @@ -401,13 +243,9 @@ ["docBlame", "FirstOrder.«term∀'_»"], ["docBlame", "FirstOrder.«term∃'_»"], ["docBlame", "FirstOrder.«term∼_»"], - ["docBlame", "Flow.cont'"], - ["docBlame", "Flow.map_add'"], - ["docBlame", "Flow.map_zero'"], ["docBlame", "Flow.toFun"], ["docBlame", "FourierTransform.«term_[_]»"], ["docBlame", "FourierTransform.term𝓕"], - ["docBlame", "FrechetUrysohnSpace.closure_subset_seqClosure"], ["docBlame", "Function.app"], ["docBlame", "Function.compLeft"], ["docBlame", "Function.compRight"], @@ -417,183 +255,41 @@ ["docBlame", "FundamentalGroupoid.termπ"], ["docBlame", "FundamentalGroupoid.termπₓ"], ["docBlame", "FundamentalGroupoid.termπₘ"], - ["docBlame", "Group.mul_left_inv"], - ["docBlame", "GroupFilterBasis.conj'"], - ["docBlame", "GroupFilterBasis.inv'"], - ["docBlame", "GroupFilterBasis.mul'"], - ["docBlame", "GroupFilterBasis.one'"], ["docBlame", "HSpace.e"], ["docBlame", "HSpace.eHmul"], ["docBlame", "HSpace.hmul"], ["docBlame", "HSpace.hmulE"], - ["docBlame", "HSpace.hmul_e_e"], ["docBlame", "HSpaces.«term_⋀_»"], ["docBlame", "HahnSeries.coeff"], - ["docBlame", "HahnSeries.isPwo_support'"], - ["docBlame", "HasBesicovitchCovering.no_satelliteConfig"], - ["docBlame", "HasContDiffBump.out"], - ["docBlame", "HasCountableSeparatingOn.exists_countable_separating"], - ["docBlame", "HasFPowerSeriesOnBall.hasSum"], - ["docBlame", "HasFPowerSeriesOnBall.r_le"], - ["docBlame", "HasFPowerSeriesOnBall.r_pos"], - ["docBlame", "HasFTaylorSeriesUpTo.cont"], - ["docBlame", "HasFTaylorSeriesUpTo.fderiv"], - ["docBlame", "HasFTaylorSeriesUpTo.zero_eq"], - ["docBlame", "HasFTaylorSeriesUpToOn.cont"], - ["docBlame", "HasFTaylorSeriesUpToOn.fderivWithin"], - ["docBlame", "HasFTaylorSeriesUpToOn.zero_eq"], - ["docBlame", "HasGroupoid.compatible"], ["docBlame", "HasInfs.infs"], - ["docBlame", "HasOrthogonalProjection.exists_orthogonal"], - ["docBlame", "HasSolidNorm.solid"], ["docBlame", "HasSups.sups"], - ["docBlame", "HasUpperLowerClosure.isLowerSet_closure"], - ["docBlame", "HasUpperLowerClosure.isOpen_lowerClosure"], - ["docBlame", "HasUpperLowerClosure.isOpen_upperClosure"], - ["docBlame", "HasUpperLowerClosure.isUpperSet_closure"], - ["docBlame", "HenselianLocalRing.is_henselian"], - ["docBlame", "HenselianRing.is_henselian"], - ["docBlame", "HenselianRing.jac"], ["docBlame", "Holor.assocLeft"], ["docBlame", "Holor.assocRight"], ["docBlame", "HolorIndex.assocLeft"], ["docBlame", "HolorIndex.assocRight"], ["docBlame", "HolorIndex.drop"], ["docBlame", "HolorIndex.take"], - ["docBlame", "HomogeneousIdeal.is_homogeneous'"], ["docBlame", "HomologicalComplex.X"], ["docBlame", "HomologicalComplex.d"], - ["docBlame", "HomologicalComplex.d_comp_d'"], - ["docBlame", "HomologicalComplex.shape"], - ["docBlame", "Homotopy.comm"], ["docBlame", "Homotopy.hom"], - ["docBlame", "Homotopy.zero"], ["docBlame", "HomotopyEquiv.hom"], ["docBlame", "HomotopyEquiv.homotopyHomInvId"], ["docBlame", "HomotopyEquiv.homotopyInvHomId"], ["docBlame", "HomotopyEquiv.inv"], ["docBlame", "IO.runRandWith"], - ["docBlame", "IdemCommSemiring.add_eq_sup"], ["docBlame", "IdemCommSemiring.bot"], - ["docBlame", "IdemCommSemiring.bot_le"], - ["docBlame", "IdemSemiring.add_eq_sup"], ["docBlame", "IdemSemiring.bot"], - ["docBlame", "IdemSemiring.bot_le"], - ["docBlame", "ImplicitFunctionData.isCompl_ker"], ["docBlame", "ImplicitFunctionData.leftDeriv"], ["docBlame", "ImplicitFunctionData.leftFun"], - ["docBlame", "ImplicitFunctionData.left_has_deriv"], - ["docBlame", "ImplicitFunctionData.left_range"], ["docBlame", "ImplicitFunctionData.pt"], ["docBlame", "ImplicitFunctionData.rightDeriv"], ["docBlame", "ImplicitFunctionData.rightFun"], - ["docBlame", "ImplicitFunctionData.right_has_deriv"], - ["docBlame", "ImplicitFunctionData.right_range"], ["docBlame", "InnerProduct.«term_†»"], - ["docBlame", "InnerProductSpaceable.parallelogram_identity"], ["docBlame", "Int.decNonneg"], ["docBlame", "IntermediateField.delabAdjoinNotation"], - ["docBlame", "IntermediateField.inv_mem'"], - ["docBlame", "IntermediateField.neg_mem'"], - ["docBlame", "InvOneClass.inv_one"], - ["docBlame", "InvolutiveInv.inv_inv"], - ["docBlame", "InvolutiveNeg.neg_neg"], - ["docBlame", "IsAddCyclic.exists_generator"], - ["docBlame", "IsAdjoinRoot.algebraMap_eq"], - ["docBlame", "IsAdjoinRoot.ker_map"], ["docBlame", "IsAdjoinRoot.map"], - ["docBlame", "IsAdjoinRoot.map_surjective"], - ["docBlame", "IsAdjoinRootMonic.Monic"], - ["docBlame", "IsAlgClosed.splits"], - ["docBlame", "IsAlgClosure.alg_closed"], - ["docBlame", "IsAlgClosure.algebraic"], - ["docBlame", "IsAntisymm.antisymm"], - ["docBlame", "IsArtinian.wellFounded_submodule_lt'"], - ["docBlame", "IsAssociative.assoc"], - ["docBlame", "IsAsymm.asymm"], - ["docBlame", "IsBoundedBilinearMap.add_left"], - ["docBlame", "IsBoundedBilinearMap.add_right"], - ["docBlame", "IsBoundedBilinearMap.bound"], - ["docBlame", "IsBoundedBilinearMap.smul_left"], - ["docBlame", "IsBoundedBilinearMap.smul_right"], - ["docBlame", "IsBoundedLinearMap.bound"], - ["docBlame", "IsCHSHTuple.A₀B₀_commutes"], - ["docBlame", "IsCHSHTuple.A₀B₁_commutes"], - ["docBlame", "IsCHSHTuple.A₀_inv"], - ["docBlame", "IsCHSHTuple.A₀_sa"], - ["docBlame", "IsCHSHTuple.A₁B₀_commutes"], - ["docBlame", "IsCHSHTuple.A₁B₁_commutes"], - ["docBlame", "IsCHSHTuple.A₁_inv"], - ["docBlame", "IsCHSHTuple.A₁_sa"], - ["docBlame", "IsCHSHTuple.B₀_inv"], - ["docBlame", "IsCHSHTuple.B₀_sa"], - ["docBlame", "IsCHSHTuple.B₁_inv"], - ["docBlame", "IsCHSHTuple.B₁_sa"], - ["docBlame", "IsCommJordan.lmul_comm_rmul_rmul"], - ["docBlame", "IsCommJordan.mul_comm"], - ["docBlame", "IsCommutative.comm"], - ["docBlame", "IsCyclic.exists_generator"], - ["docBlame", "IsDedekindDomainDvr.isNoetherianRing"], - ["docBlame", "IsDedekindDomainDvr.is_dvr_at_nonzero_prime"], - ["docBlame", "IsEmpty.false"], - ["docBlame", "IsHausdorff.haus'"], - ["docBlame", "IsIdempotent.idempotent"], - ["docBlame", "IsIncompTrans.incomp_trans"], - ["docBlame", "IsIntegralClosure.algebraMap_injective'"], - ["docBlame", "IsIntegralClosure.isIntegral_iff"], - ["docBlame", "IsInvariantSubfield.smul_mem"], - ["docBlame", "IsInvariantSubring.smul_mem"], - ["docBlame", "IsIrrefl.irrefl"], - ["docBlame", "IsJordan.lmul_comm_rmul"], - ["docBlame", "IsJordan.lmul_comm_rmul_rmul"], - ["docBlame", "IsJordan.lmul_lmul_comm_lmul"], - ["docBlame", "IsJordan.lmul_lmul_comm_rmul"], - ["docBlame", "IsJordan.rmul_comm_rmul_rmul"], - ["docBlame", "IsLeftCancel.left_cancel"], - ["docBlame", "IsLeftId.left_id"], - ["docBlame", "IsLprojection.Lnorm"], - ["docBlame", "IsLprojection.proj"], - ["docBlame", "IsMprojection.Mnorm"], - ["docBlame", "IsMprojection.proj"], - ["docBlame", "IsPicardLindelof.C_mul_le_R"], - ["docBlame", "IsPicardLindelof.cont"], - ["docBlame", "IsPicardLindelof.hR"], - ["docBlame", "IsPicardLindelof.ht₀"], - ["docBlame", "IsPicardLindelof.lipschitz"], - ["docBlame", "IsPicardLindelof.norm_le"], - ["docBlame", "IsPrecomplete.prec'"], - ["docBlame", "IsPrimitiveRoot.dvd_of_pow_eq_one"], - ["docBlame", "IsPrimitiveRoot.pow_eq_one"], - ["docBlame", "IsROrC.I_mul_I_ax"], - ["docBlame", "IsROrC.I_re_ax"], - ["docBlame", "IsROrC.conj_I_ax"], - ["docBlame", "IsROrC.conj_im_ax"], - ["docBlame", "IsROrC.conj_re_ax"], ["docBlame", "IsROrC.im"], - ["docBlame", "IsROrC.le_iff_re_im"], - ["docBlame", "IsROrC.mul_im_I_ax"], - ["docBlame", "IsROrC.mul_im_ax"], - ["docBlame", "IsROrC.mul_re_ax"], - ["docBlame", "IsROrC.norm_sq_eq_def_ax"], - ["docBlame", "IsROrC.ofReal_im_ax"], - ["docBlame", "IsROrC.ofReal_re_ax"], ["docBlame", "IsROrC.re"], - ["docBlame", "IsROrC.re_add_im_ax"], - ["docBlame", "IsRefl.refl"], - ["docBlame", "IsRightCancel.right_cancel"], - ["docBlame", "IsRightId.right_id"], - ["docBlame", "IsSeparable.isIntegral'"], - ["docBlame", "IsSeparable.separable'"], - ["docBlame", "IsSepClosed.splits_of_separable"], - ["docBlame", "IsSepClosure.sep_closed"], - ["docBlame", "IsSepClosure.separable"], - ["docBlame", "IsSubfield.inv_mem"], - ["docBlame", "IsSymm.symm"], - ["docBlame", "IsSymmOp.symm_op"], - ["docBlame", "IsTotal.total"], - ["docBlame", "IsTrans.trans"], - ["docBlame", "IsTrichotomous.trichotomous"], - ["docBlame", "IsUnifLocDoublingMeasure.exists_measure_closedBall_le_mul''"], ["docBlame", "Isocrystal.«termK(_,_)»"], ["docBlame", "Isocrystal.«term_→ᶠˡ[_,_]_»"], ["docBlame", "Isocrystal.«term_→ᶠⁱ[_,_]_»"], @@ -601,53 +297,18 @@ ["docBlame", "Isocrystal.«term_≃ᶠⁱ[_,_]_»"], ["docBlame", "Isocrystal.«termΦ(_,_)»"], ["docBlame", "Isocrystal.«termφ(_,_)»"], - ["docBlame", "IsometricSMul.isometry_smul"], - ["docBlame", "IsometricVAdd.isometry_vadd"], - ["docBlame", "IsometryEquiv.isometry_toFun"], ["docBlame", "JordanHolderLattice.IsMaximal"], ["docBlame", "JordanHolderLattice.Iso"], - ["docBlame", "JordanHolderLattice.isMaximal_inf_left_of_isMaximal_sup"], - ["docBlame", "JordanHolderLattice.iso_symm"], - ["docBlame", "JordanHolderLattice.iso_trans"], - ["docBlame", "JordanHolderLattice.lt_of_isMaximal"], - ["docBlame", "JordanHolderLattice.second_iso"], - ["docBlame", "JordanHolderLattice.sup_eq_of_isMaximal"], ["docBlame", "KStar.kstar"], - ["docBlame", "KleeneAlgebra.kstar_mul_le_kstar"], - ["docBlame", "KleeneAlgebra.kstar_mul_le_self"], - ["docBlame", "KleeneAlgebra.mul_kstar_le_kstar"], - ["docBlame", "KleeneAlgebra.mul_kstar_le_self"], - ["docBlame", "KleeneAlgebra.one_le_kstar"], ["docBlame", "Kronecker.«term_⊗ₖ_»"], ["docBlame", "Kronecker.«term_⊗ₖₜ[_]_»"], ["docBlame", "Kronecker.«term_⊗ₖₜ_»"], ["docBlame", "LaurentSeries.instMonoidWithZeroHahnSeriesIntToPartialOrderToStrictOrderedRingToLinearOrderedRingLinearOrderedCommRingToZeroToCommMonoidWithZeroToCommGroupWithZeroToSemifield"], - ["docBlame", "LawfulBifunctor.bimap_bimap"], - ["docBlame", "LawfulBifunctor.id_bimap"], - ["docBlame", "LawfulBitraversable.binaturality"], - ["docBlame", "LawfulBitraversable.bitraverse_eq_bimap_id"], - ["docBlame", "LawfulBitraversable.comp_bitraverse"], - ["docBlame", "LawfulBitraversable.id_bitraverse"], - ["docBlame", "LawfulFix.fix_eq"], - ["docBlame", "LawfulMonadCont.callCC_bind_left"], - ["docBlame", "LawfulMonadCont.callCC_bind_right"], - ["docBlame", "LawfulMonadCont.callCC_dummy"], ["docBlame", "Lean.ExportM"], - ["docBlame", "LeftCancelSemigroup.mul_left_cancel"], - ["docBlame", "LeftInvariantDerivation.left_invariant''"], ["docBlame", "LieGroup.«term𝑳»"], ["docBlame", "LieGroup.«term𝑹»"], - ["docBlame", "LieSubmodule.lie_mem"], - ["docBlame", "LinearIsometry.norm_map'"], - ["docBlame", "LinearIsometryEquiv.norm_map'"], - ["docBlame", "LinearOrderedAddCommGroupWithTop.add_neg_cancel"], - ["docBlame", "LinearOrderedAddCommGroupWithTop.neg_top"], - ["docBlame", "LinearOrderedAddCommGroupWithTop.sub_eq_add_neg"], ["docBlame", "LinearOrderedAddCommGroupWithTop.zsmul"], - ["docBlame", "LinearOrderedAddCommGroupWithTop.zsmul_neg'"], - ["docBlame", "LinearOrderedAddCommGroupWithTop.zsmul_succ'"], - ["docBlame", "LinearOrderedAddCommGroupWithTop.zsmul_zero'"], ["docBlame", "LinearPMap.domain"], ["docBlame", "LinearPMap.sSup"], ["docBlame", "LinearPMap.«term_†»"], @@ -655,19 +316,10 @@ ["docBlame", "LinearPMap.toFun'"], ["docBlame", "LinearRecurrence.coeffs"], ["docBlame", "LinearRecurrence.order"], - ["docBlame", "LipschitzAdd.lipschitz_add"], - ["docBlame", "LipschitzMul.lipschitz_mul"], ["docBlame", "List.card"], ["docBlame", "List.equiv"], ["docBlame", "List.inj_on"], ["docBlame", "List.remove"], - ["docBlame", "PartialHomeomorph.continuousOn_invFun"], - ["docBlame", "PartialHomeomorph.continuousOn_toFun"], - ["docBlame", "PartialHomeomorph.open_source"], - ["docBlame", "PartialHomeomorph.open_target"], - ["docBlame", "LocallyConvexSpace.convex_basis"], - ["docBlame", "LowerSetTopology.topology_eq_lowerSetTopology"], - ["docBlame", "LowerTopology.topology_eq_lowerTopology"], ["docBlame", "MagmaCat.forget_obj_eq_coe"], ["docBlame", "Manifold.«termC^_⟮_,_;_,_⟯»"], ["docBlame", "Manifold.«termC^_⟮_,_;_⟯»"], @@ -692,33 +344,6 @@ ["docBlame", "Matrix.«term_⊙_»"], ["docBlame", "MatrixGroups.«termSL(_,_)»"], ["docBlame", "MaximalSpectrum.asIdeal"], - ["docBlame", "MeasurableAdd.measurable_add_const"], - ["docBlame", "MeasurableAdd.measurable_const_add"], - ["docBlame", "MeasurableAdd₂.measurable_add"], - ["docBlame", "MeasurableDiv.measurable_const_div"], - ["docBlame", "MeasurableDiv.measurable_div_const"], - ["docBlame", "MeasurableDiv₂.measurable_div"], - ["docBlame", "MeasurableInf.measurable_const_inf"], - ["docBlame", "MeasurableInf.measurable_inf_const"], - ["docBlame", "MeasurableInf₂.measurable_inf"], - ["docBlame", "MeasurableInv.measurable_inv"], - ["docBlame", "MeasurableMul.measurable_const_mul"], - ["docBlame", "MeasurableMul.measurable_mul_const"], - ["docBlame", "MeasurableMul₂.measurable_mul"], - ["docBlame", "MeasurableNeg.measurable_neg"], - ["docBlame", "MeasurablePow.measurable_pow"], - ["docBlame", "MeasurableSMul.measurable_const_smul"], - ["docBlame", "MeasurableSMul.measurable_smul_const"], - ["docBlame", "MeasurableSMul₂.measurable_smul"], - ["docBlame", "MeasurableSub.measurable_const_sub"], - ["docBlame", "MeasurableSub.measurable_sub_const"], - ["docBlame", "MeasurableSub₂.measurable_sub"], - ["docBlame", "MeasurableSup.measurable_const_sup"], - ["docBlame", "MeasurableSup.measurable_sup_const"], - ["docBlame", "MeasurableSup₂.measurable_sup"], - ["docBlame", "MeasurableVAdd.measurable_const_vadd"], - ["docBlame", "MeasurableVAdd.measurable_vadd_const"], - ["docBlame", "MeasurableVAdd₂.measurable_vadd"], ["docBlame", "MeasureTheory.«term_=ᵐ[_]_»"], ["docBlame", "MeasureTheory.«term_[_|_]»"], ["docBlame", "MeasureTheory.«term_→₁[_]_»"], @@ -734,33 +359,13 @@ ["docBlame", "MeasureTheory.«term⨍⁻_,_∂_»"], ["docBlame", "MeasureTheory.«term⨍⁻_In_,_»"], ["docBlame", "MeasureTheory.«term⨍⁻_In_,_∂_»"], - ["docBlame", "MemTrivializationAtlas.out"], - ["docBlame", "MetricSpace.eq_of_dist_eq_zero"], - ["docBlame", "MixedCharZero.charP_quotient"], - ["docBlame", "MixedCharZero.toCharZero"], ["docBlame", "Mod_.X"], ["docBlame", "Mod_.act"], - ["docBlame", "Mod_.assoc"], - ["docBlame", "Mod_.one_act"], - ["docBlame", "ModelWithCorners.continuous_invFun"], - ["docBlame", "ModelWithCorners.continuous_toFun"], - ["docBlame", "ModelWithCorners.source_eq"], - ["docBlame", "ModelWithCorners.unique_diff'"], - ["docBlame", "ModularForm.bdd_at_infty'"], - ["docBlame", "ModularForm.holo'"], ["docBlame", "ModularForm.«term_∣[_;_]_»"], ["docBlame", "ModularForm.«term_∣[_]_»"], - ["docBlame", "ModularFormClass.bdd_at_infty"], - ["docBlame", "ModularFormClass.holo"], - ["docBlame", "ModuleFilterBasis.smul'"], - ["docBlame", "ModuleFilterBasis.smul_left'"], - ["docBlame", "ModuleFilterBasis.smul_right'"], ["docBlame", "Mon_.X"], ["docBlame", "Mon_.mul"], - ["docBlame", "Mon_.mul_assoc"], - ["docBlame", "Mon_.mul_one"], ["docBlame", "Mon_.one"], - ["docBlame", "Mon_.one_mul"], ["docBlame", "Monad.cond"], ["docBlame", "Monad.filter"], ["docBlame", "Monad.foldl"], @@ -783,13 +388,9 @@ ["docBlame", "Monoid.foldrM"], ["docBlame", "MonoidAlgebra.mapDomain"], ["docBlame", "MonoidAlgebra.single"], - ["docBlame", "MulChar.map_nonunit'"], - ["docBlame", "MulCharClass.map_nonunit"], ["docBlame", "MvPFunctor.wpRec"], ["docBlame", "MvQPF.P"], ["docBlame", "MvQPF.abs"], - ["docBlame", "MvQPF.abs_map"], - ["docBlame", "MvQPF.abs_repr"], ["docBlame", "MvQPF.repr"], ["docBlame", "NFA.accept"], ["docBlame", "NFA.start"], @@ -800,93 +401,45 @@ ["docBlame", "Nat.Partrec"], ["docBlame", "Nat.discriminate"], ["docBlame", "Nat.findX"], - ["docBlame", "Nat.iterate"], ["docBlame", "Nat.ltByCases"], ["docBlame", "Nat.ltGeByCases"], ["docBlame", "Nat.prio"], ["docBlame", "Nat.rfind"], ["docBlame", "Nat.rfindOpt"], ["docBlame", "Nat.rfindX"], - ["docBlame", "Nat.strongRecOn"], ["docBlame", "Nat.subInduction"], ["docBlame", "Nat.«termOrd_compl[_]_»"], ["docBlame", "Nat.«termOrd_proj[_]_»"], - ["docBlame", "Nat.«term_^[_]»"], ["docBlame", "Nat.«term_‼»"], ["docBlame", "Nat.termπ"], ["docBlame", "Nat.termπ'"], ["docBlame", "Nat.twoStepInduction"], - ["docBlame", "NegZeroClass.neg_zero"], - ["docBlame", "NonUnitalSubsemiringClass.mul_mem"], - ["docBlame", "NonarchimedeanAddGroup.is_nonarchimedean"], - ["docBlame", "NonarchimedeanGroup.is_nonarchimedean"], - ["docBlame", "NonarchimedeanRing.is_nonarchimedean"], - ["docBlame", "Normal.isAlgebraic'"], - ["docBlame", "Normal.splits'"], - ["docBlame", "NormedAddTorsor.dist_eq_norm'"], - ["docBlame", "NormedLatticeAddCommGroup.add_le_add_left"], - ["docBlame", "NormedStarGroup.norm_star"], ["docBlame", "NumberField.term𝓞"], ["docBlame", "NumberTheorySymbols.«termJ(_|_)»"], ["docBlame", "One.one"], - ["docBlame", "OpenAddSubgroup.isOpen'"], - ["docBlame", "OpenSubgroup.isOpen'"], - ["docBlame", "OpensMeasurableSpace.borel_le"], ["docBlame", "Option.getDM'"], ["docBlame", "OptionT.callCC"], ["docBlame", "OptionT.mkLabel"], ["docBlame", "OrthonormalBasis.repr"], - ["docBlame", "PartialOrder.le_antisymm"], - ["docBlame", "PartitionOfUnity.locallyFinite'"], - ["docBlame", "PartitionOfUnity.nonneg'"], - ["docBlame", "PartitionOfUnity.sum_eq_one'"], - ["docBlame", "PartitionOfUnity.sum_le_one'"], ["docBlame", "PartitionOfUnity.toFun"], - ["docBlame", "Perfect.acc"], - ["docBlame", "Perfect.closed"], - ["docBlame", "PerfectRing.frobenius_pthRoot'"], - ["docBlame", "PerfectRing.pthRoot'"], - ["docBlame", "PerfectRing.pthRoot_frobenius'"], - ["docBlame", "PerfectionMap.injective"], - ["docBlame", "PerfectionMap.surjective"], ["docBlame", "PicardLindelof.C"], ["docBlame", "PicardLindelof.L"], ["docBlame", "PicardLindelof.R"], - ["docBlame", "PicardLindelof.isPicardLindelof"], ["docBlame", "PicardLindelof.tMax"], ["docBlame", "PicardLindelof.tMin"], ["docBlame", "PicardLindelof.toFun"], ["docBlame", "PicardLindelof.t₀"], ["docBlame", "PicardLindelof.x₀"], - ["docBlame", "PolishSpace.complete"], - ["docBlame", "PolishSpace.secondCountableTopology"], ["docBlame", "Polynomial.quotientSpanXSubCAlgEquivAux1"], ["docBlame", "Polynomial.quotientSpanXSubCAlgEquivAux2"], ["docBlame", "Polynomial.«term_[X]»"], ["docBlame", "Polynomial.toFinsupp"], ["docBlame", "PowerBasis.basis"], - ["docBlame", "PowerBasis.basis_eq_pow"], ["docBlame", "PowerBasis.dim"], ["docBlame", "PowerBasis.gen"], - ["docBlame", "PreErgodic.ae_empty_or_univ"], - ["docBlame", "Pregroupoid.comp"], - ["docBlame", "Pregroupoid.congr"], - ["docBlame", "Pregroupoid.id_mem"], - ["docBlame", "Pregroupoid.locality"], ["docBlame", "Pregroupoid.property"], - ["docBlame", "Preorder.le_refl"], - ["docBlame", "Preorder.le_trans"], - ["docBlame", "Preorder.lt_iff_le_not_le"], - ["docBlame", "PresheafOfModules.map_smul"], ["docBlame", "PresheafOfModules.presheaf"], ["docBlame", "Pretrivialization.baseSet"], - ["docBlame", "Pretrivialization.open_baseSet"], - ["docBlame", "Pretrivialization.open_target"], - ["docBlame", "Pretrivialization.proj_toFun"], - ["docBlame", "Pretrivialization.source_eq"], - ["docBlame", "Pretrivialization.target_eq"], - ["docBlame", "PriestleySpace.priestley"], - ["docBlame", "Primcodable.prim"], ["docBlame", "PrimeSpectrum.asIdeal"], ["docBlame", "ProbabilityTheory.«termEVar[_]»"], ["docBlame", "ProbabilityTheory.«termVar[_]»"], @@ -904,32 +457,11 @@ ["docBlame", "ProbabilityTheory.«term𝔼[_]»"], ["docBlame", "ProbabilityTheory.«term𝔼[_|_]»"], ["docBlame", "ProjectiveSpectrum.asHomogeneousIdeal"], - ["docBlame", "ProjectiveSpectrum.not_irrelevant_le"], - ["docBlame", "ProperCone.is_closed'"], - ["docBlame", "ProperCone.nonempty'"], - ["docBlame", "ProperSpace.isCompact_closedBall"], - ["docBlame", "PseudoEMetricSpace.edist_comm"], - ["docBlame", "PseudoEMetricSpace.edist_self"], - ["docBlame", "PseudoEMetricSpace.edist_triangle"], - ["docBlame", "PseudoEMetricSpace.uniformity_edist"], - ["docBlame", "PseudoEpimorphism.exists_map_eq_of_map_le'"], - ["docBlame", "PseudoEpimorphismClass.exists_map_eq_of_map_le"], - ["docBlame", "PseudoMetricSpace.cobounded_sets"], - ["docBlame", "PseudoMetricSpace.dist_comm"], - ["docBlame", "PseudoMetricSpace.dist_self"], - ["docBlame", "PseudoMetricSpace.dist_triangle"], ["docBlame", "PseudoMetricSpace.edist"], - ["docBlame", "PseudoMetricSpace.edist_dist"], - ["docBlame", "PseudoMetricSpace.uniformity_dist"], ["docBlame", "QPF.P"], ["docBlame", "QPF.abs"], - ["docBlame", "QPF.abs_map"], - ["docBlame", "QPF.abs_repr"], ["docBlame", "QPF.repr"], - ["docBlame", "QuadraticForm.exists_companion'"], ["docBlame", "QuadraticForm.toFun"], - ["docBlame", "QuadraticForm.toFun_smul"], - ["docBlame", "QuasiSober.sober"], ["docBlame", "Quaternion.termℍ"], ["docBlame", "Quaternion.«termℍ[_]»"], ["docBlame", "QuaternionAlgebra.imI"], @@ -942,37 +474,19 @@ ["docBlame", "ReaderT.callCC"], ["docBlame", "ReaderT.mk"], ["docBlame", "ReaderT.mkLabel"], - ["docBlame", "RightCancelSemigroup.mul_right_cancel"], - ["docBlame", "Ring.add_left_neg"], - ["docBlame", "Ring.sub_eq_add_neg"], ["docBlame", "Ring.zsmul"], - ["docBlame", "Ring.zsmul_neg'"], - ["docBlame", "Ring.zsmul_succ'"], - ["docBlame", "Ring.zsmul_zero'"], ["docBlame", "RingCat.forget_obj_eq_coe"], - ["docBlame", "RingFilterBasis.mul'"], - ["docBlame", "RingFilterBasis.mul_left'"], - ["docBlame", "RingFilterBasis.mul_right'"], - ["docBlame", "RingHomId.eq_id"], ["docBlame", "RingQuot.preLift"], ["docBlame", "RingQuot.preLiftAlgHom"], ["docBlame", "RingQuot.toQuot"], ["docBlame", "RootableBy.root"], - ["docBlame", "RootableBy.root_cancel"], - ["docBlame", "RootableBy.root_zero"], ["docBlame", "SMul.smul"], - ["docBlame", "SchwartzMap.decay'"], - ["docBlame", "SchwartzMap.smooth'"], ["docBlame", "SchwartzMap.toFun"], ["docBlame", "SchwartzSpace.«term𝓢(_,_)»"], ["docBlame", "SemiRingCat.forget_obj_eq_coe"], ["docBlame", "SemigroupCat.forget_obj_eq_coe"], ["docBlame", "SemilatInfCat.X"], ["docBlame", "SemilatSupCat.X"], - ["docBlame", "SemilinearIsometryClass.norm_map"], - ["docBlame", "SemilinearIsometryEquivClass.norm_map"], - ["docBlame", "SeqCompactSpace.seq_compact_univ"], - ["docBlame", "SequentialSpace.isClosed_of_seq"], ["docBlame", "Set.Subset"], ["docBlame", "Set.compl"], ["docBlame", "Set.diff"], @@ -982,48 +496,26 @@ ["docBlame", "Set.powerset"], ["docBlame", "Set.singleton"], ["docBlame", "Set.«term{_|_}»"], - ["docBlame", "Set.«term{_|_}_1»"], ["docBlame", "Set.term𝒫_"], ["docBlame", "Set.union"], ["docBlame", "Set.univ"], ["docBlame", "Shrink.rec"], ["docBlame", "SimpleGraph.Adj"], - ["docBlame", "SimpleGraph.loopless"], - ["docBlame", "SimpleGraph.symm"], - ["docBlame", "SimpleGraph.Subgraph.Connected.coe"], - ["docBlame", "SimpleGraph.Subgraph.Preconnected.coe"], ["docBlame", "SimpleGraph.«term_→g_»"], ["docBlame", "SimpleGraph.«term_↪g_»"], ["docBlame", "SimpleGraph.«term_≃g_»"], ["docBlame", "Simplicial.«termΔ[_]»"], ["docBlame", "Simplicial.«termΛ[_,_]»"], ["docBlame", "Simplicial.«term∂Δ[_]»"], - ["docBlame", "SimplyConnectedSpace.equiv_unit"], - ["docBlame", "SlashAction.add_slash"], ["docBlame", "SlashAction.map"], - ["docBlame", "SlashAction.slash_mul"], - ["docBlame", "SlashAction.slash_one"], - ["docBlame", "SlashAction.smul_slash"], - ["docBlame", "SlashAction.zero_slash"], - ["docBlame", "SlashInvariantForm.slash_action_eq'"], ["docBlame", "SlashInvariantForm.toFun"], - ["docBlame", "SlashInvariantFormClass.slash_action_eq"], ["docBlame", "SlimCheck.NamedBinder"], ["docBlame", "SlimCheck.«command#test_»"], - ["docBlame", "SmoothAdd.smooth_add"], - ["docBlame", "SmoothAddMonoidMorphism.smooth_toFun"], - ["docBlame", "SmoothBumpFunction.closedBall_subset"], - ["docBlame", "SmoothMonoidMorphism.smooth_toFun"], - ["docBlame", "SmoothMul.smooth_mul"], - ["docBlame", "SmoothRing.smooth_mul"], - ["docBlame", "SmoothVectorBundle.smoothOn_coordChangeL"], ["docBlame", "StarAlgEquiv.restrictScalars"], ["docBlame", "StarAlgHom.restrictScalars"], ["docBlame", "StateT.callCC"], ["docBlame", "StateT.mk"], ["docBlame", "StateT.mkLabel"], - ["docBlame", "StieltjesFunction.mono'"], - ["docBlame", "StieltjesFunction.right_continuous'"], ["docBlame", "StieltjesFunction.toFun"], ["docBlame", "Stream'.corec"], ["docBlame", "Stream'.corec'"], @@ -1033,29 +525,11 @@ ["docBlame", "Stream'.«term_⊛_»"], ["docBlame", "Stream'.«term_⋈_»"], ["docBlame", "Stream'.unfolds"], - ["docBlame", "StrictConvexSpace.strictConvex_closedBall"], ["docBlame", "StrictWeakOrder.Equiv"], ["docBlame", "StrictWeakOrder.«term_≈[_]_»"], - ["docBlame", "Structomorph.mem_groupoid"], - ["docBlame", "StructureGroupoid.eq_on_source'"], - ["docBlame", "StructureGroupoid.id_mem'"], - ["docBlame", "StructureGroupoid.locality'"], ["docBlame", "StructureGroupoid.members"], - ["docBlame", "StructureGroupoid.symm'"], - ["docBlame", "StructureGroupoid.trans'"], - ["docBlame", "SubNegMonoid.sub_eq_add_neg"], ["docBlame", "SubNegMonoid.zsmul"], - ["docBlame", "SubNegMonoid.zsmul_neg'"], - ["docBlame", "SubNegMonoid.zsmul_succ'"], - ["docBlame", "SubNegMonoid.zsmul_zero'"], - ["docBlame", "SubNegZeroMonoid.neg_zero"], ["docBlame", "Submodule.«term_∙_»"], - ["docBlame", "SubtractionMonoid.neg_add_rev"], - ["docBlame", "SubtractionMonoid.neg_eq_of_add"], - ["docBlame", "SubtractionMonoid.neg_neg"], - ["docBlame", "Sylow.isPGroup'"], - ["docBlame", "Sylow.is_maximal'"], - ["docBlame", "TensorProduct.addMonoid"], ["docBlame", "TensorProduct.«term_⊗[_]_»"], ["docBlame", "TensorProduct.«term_⊗_»"], ["docBlame", "TensorProduct.«term_⊗ₜ[_]_»"], @@ -1073,10 +547,6 @@ ["docBlame", "Tree.«term_△_»"], ["docBlame", "Tree.unitRecOn"], ["docBlame", "Trivialization.baseSet"], - ["docBlame", "Trivialization.open_baseSet"], - ["docBlame", "Trivialization.proj_toFun"], - ["docBlame", "Trivialization.source_eq"], - ["docBlame", "Trivialization.target_eq"], ["docBlame", "TwoP.X"], ["docBlame", "TwoP.toTwoPointing"], ["docBlame", "UFModel.Agrees"], @@ -1085,80 +555,43 @@ ["docBlame", "UFModel.parent"], ["docBlame", "UFModel.push"], ["docBlame", "UFModel.rank"], - ["docBlame", "UFModel.rank_lt"], ["docBlame", "UFModel.setParent"], ["docBlame", "UFModel.setParentBump"], ["docBlame", "UFNode.parent"], ["docBlame", "UFNode.rank"], ["docBlame", "UFNode.value"], ["docBlame", "ULiftable.congr"], - ["docBlame", "UniformAddGroup.uniformContinuous_sub"], - ["docBlame", "UniformContinuousConstSMul.uniformContinuous_const_smul"], - ["docBlame", "UniformContinuousConstVAdd.uniformContinuous_const_vadd"], ["docBlame", "UniformConvergence.«term_→ᵤ[_]_»"], ["docBlame", "UniformConvergence.«term_→ᵤ_»"], - ["docBlame", "UniformConvexSpace.uniform_convex"], ["docBlame", "UniformFun.phi"], - ["docBlame", "UniformGroup.uniformContinuous_div"], ["docBlame", "UnionFind.arr"], ["docBlame", "UnionFind.empty"], ["docBlame", "UnionFind.find"], ["docBlame", "UnionFind.findAux"], ["docBlame", "UnionFind.link"], ["docBlame", "UnionFind.mkEmpty"], - ["docBlame", "UnionFind.model"], ["docBlame", "UnionFind.push"], ["docBlame", "UnionFind.rank"], ["docBlame", "UnionFind.rankMax"], ["docBlame", "UnionFind.rankMaxAux"], ["docBlame", "UnionFind.size"], ["docBlame", "UnionFind.union"], - ["docBlame", "UniqueDiffWithinAt.dense_tangentCone"], - ["docBlame", "UniqueDiffWithinAt.mem_closure"], - ["docBlame", "UniqueFactorizationMonoid.irreducible_iff_prime"], ["docBlame", "UnitDisc.term𝔻"], - ["docBlame", "UnitalShelf.act_one"], - ["docBlame", "UnitalShelf.one_act"], ["docBlame", "UnivLE.witness"], + ["docBlame", "UpperHalfPlane.coe'"], ["docBlame", "UpperHalfPlane.termℍ"], - ["docBlame", "UpperSetTopology.topology_eq_upperSetTopology"], - ["docBlame", "UpperTopology.topology_eq_upperTopology"], ["docBlame", "VAdd.vadd"], ["docBlame", "VSub.vsub"], - ["docBlame", "ValuationRing.cond'"], - ["docBlame", - "ValuationSubring.instMulOneClassQuotientSubtypeUnitsToMonoidToMonoidWithZeroToSemiringToDivisionSemiringToSemifieldMemSubgroupInstGroupUnitsInstMembershipInstSetLikeSubgroupUnitGroupToGroupInstHasQuotientSubgroupComapSubtypePrincipalUnitGroup"], - ["docBlame", "ValuationSubring.mem_or_inv_mem'"], - ["docBlame", "Valued.is_topological_valuation"], ["docBlame", "Valued.v"], ["docBlame", "Vector3.«term_::_»"], ["docBlame", "Vector3.unexpandCons"], ["docBlame", "Vector3.unexpandNil"], - ["docBlame", "VectorBundle.continuousOn_coordChange'"], - ["docBlame", "VectorBundle.trivialization_linear'"], ["docBlame", "VectorBundleCore.baseSet"], - ["docBlame", "VectorBundleCore.continuousOn_coordChange"], ["docBlame", "VectorBundleCore.coordChange"], - ["docBlame", "VectorBundleCore.coordChange_comp"], - ["docBlame", "VectorBundleCore.coordChange_self"], ["docBlame", "VectorBundleCore.indexAt"], - ["docBlame", "VectorBundleCore.isOpen_baseSet"], - ["docBlame", "VectorBundleCore.mem_baseSet_at"], - ["docBlame", "VectorPrebundle.exists_coordChange"], - ["docBlame", "VectorPrebundle.mem_base_pretrivializationAt"], ["docBlame", "VectorPrebundle.pretrivializationAt"], ["docBlame", "VectorPrebundle.pretrivializationAtlas"], - ["docBlame", "VectorPrebundle.pretrivialization_linear'"], - ["docBlame", "VectorPrebundle.pretrivialization_mem_atlas"], - ["docBlame", "VectorPrebundle.totalSpaceMk_inducing"], - ["docBlame", "VitaliFamily.MeasurableSet'"], - ["docBlame", "VitaliFamily.Nontrivial"], - ["docBlame", "VitaliFamily.covering"], - ["docBlame", "VitaliFamily.nonempty_interior"], - ["docBlame", "VitaliFamily.setsAt"], - ["docBlame", "WfDvdMonoid.wellFounded_dvdNotUnit"], ["docBlame", "WithIdeal.i"], - ["docBlame", "WithSeminorms.topology_eq_withSeminorms"], ["docBlame", "WithZeroTopology.instHasContinuousInv₀ToZeroToLinearOrderedCommMonoidWithZeroToInvTopologicalSpace"], ["docBlame", "Witt.termW"], @@ -1185,163 +618,76 @@ ["docBlame", "εNFA.accept"], ["docBlame", "εNFA.start"], ["docBlame", "εNFA.step"], - ["docBlame", "Action.Hom.comm"], ["docBlame", "Action.Hom.hom"], - ["docBlame", "AddAction.IsMinimal.dense_orbit"], - ["docBlame", "AddCommGroup.PositiveCone.add_nonneg"], ["docBlame", "AddCommGroup.PositiveCone.nonneg"], - ["docBlame", "AddCommGroup.PositiveCone.nonneg_antisymm"], ["docBlame", "AddCommGroup.PositiveCone.pos"], - ["docBlame", "AddCommGroup.PositiveCone.pos_iff"], - ["docBlame", "AddCommGroup.PositiveCone.zero_nonneg"], - ["docBlame", "AddGroup.FG.out"], - ["docBlame", "AddMonoid.FG.out"], - ["docBlame", "Affine.Simplex.independent"], ["docBlame", "Affine.Simplex.points"], - ["docBlame", "Algebra.FiniteType.out"], - ["docBlame", "Algebra.FormallyEtale.comp_bijective"], - ["docBlame", "Algebra.FormallySmooth.comp_surjective"], - ["docBlame", "Algebra.FormallyUnramified.comp_injective"], - ["docBlame", "Algebra.IsPushout.out"], - ["docBlame", - "AlgebraicGeometry.LocallyOfFiniteType.finiteType_of_affine_subset"], ["docBlame", "AlgebraicGeometry.PresheafedSpace.carrier"], ["docBlame", "AlgebraicGeometry.PresheafedSpace.presheaf"], - ["docBlame", "AlgebraicGeometry.Scheme.local_affine"], - ["docBlame", "AlgebraicGeometry.UniversallyClosed.out"], ["docBlame", "Array.cyclicPermute!.cyclicPermuteAux"], ["docBlame", "Array.heapSort.loop"], ["docBlame", "Besicovitch.BallPackage.c"], ["docBlame", "Besicovitch.BallPackage.r"], ["docBlame", "Besicovitch.BallPackage.r_bound"], - ["docBlame", "Besicovitch.BallPackage.r_le"], - ["docBlame", "Besicovitch.BallPackage.rpos"], ["docBlame", "Besicovitch.SatelliteConfig.c"], - ["docBlame", "Besicovitch.SatelliteConfig.h"], - ["docBlame", "Besicovitch.SatelliteConfig.hlast"], - ["docBlame", "Besicovitch.SatelliteConfig.inter"], ["docBlame", "Besicovitch.SatelliteConfig.r"], - ["docBlame", "Besicovitch.SatelliteConfig.rpos"], - ["docBlame", "Besicovitch.TauPackage.one_lt_tau"], ["docBlame", "Besicovitch.TauPackage.τ"], ["docBlame", "Bimod.Hom.hom"], - ["docBlame", "Bimod.Hom.left_act_hom"], - ["docBlame", "Bimod.Hom.right_act_hom"], ["docBlame", "BinaryHeap.mkHeap.loop"], - ["docBlame", "Bipointed.Hom.map_fst"], - ["docBlame", "Bipointed.Hom.map_snd"], ["docBlame", "Bipointed.Hom.toFun"], ["docBlame", "BoxIntegral.Box.lower"], - ["docBlame", "BoxIntegral.Box.lower_lt_upper"], ["docBlame", "BoxIntegral.Box.toSet"], ["docBlame", "BoxIntegral.Box.upper"], ["docBlame", "BoxIntegral.Box.withBotToSet"], - ["docBlame", "BoxIntegral.BoxAdditiveMap.sum_partition_boxes'"], ["docBlame", "BoxIntegral.BoxAdditiveMap.toFun"], ["docBlame", "BoxIntegral.IntegrationParams.bDistortion"], ["docBlame", "BoxIntegral.IntegrationParams.bHenstock"], ["docBlame", "BoxIntegral.IntegrationParams.bRiemann"], ["docBlame", "BoxIntegral.Prepartition.boxes"], - ["docBlame", "BoxIntegral.Prepartition.le_of_mem'"], - ["docBlame", "BoxIntegral.Prepartition.pairwiseDisjoint"], ["docBlame", "BoxIntegral.TaggedPrepartition.tag"], - ["docBlame", "BoxIntegral.TaggedPrepartition.tag_mem_Icc"], ["docBlame", "Bundle.TotalSpace.mk'"], ["docBlame", "Bundle.TotalSpace.snd"], - ["docBlame", "CategoryTheory.Adhesive.van_kampen"], - ["docBlame", "CategoryTheory.ArtinianObject.subobject_lt_wellFounded'"], - ["docBlame", "CategoryTheory.Balanced.isIso_of_mono_of_epi"], ["docBlame", "CategoryTheory.Bicategory.associator"], - ["docBlame", "CategoryTheory.Bicategory.comp_whiskerLeft"], - ["docBlame", "CategoryTheory.Bicategory.comp_whiskerRight"], - ["docBlame", "CategoryTheory.Bicategory.id_whiskerLeft"], - ["docBlame", "CategoryTheory.Bicategory.id_whiskerRight"], ["docBlame", "CategoryTheory.Bicategory.leftUnitor"], - ["docBlame", "CategoryTheory.Bicategory.pentagon"], ["docBlame", "CategoryTheory.Bicategory.rightUnitor"], ["docBlame", "CategoryTheory.Bicategory.«term_▷_»"], ["docBlame", "CategoryTheory.Bicategory.«term_◁_»"], ["docBlame", "CategoryTheory.Bicategory.termα_"], ["docBlame", "CategoryTheory.Bicategory.«termλ_»"], ["docBlame", "CategoryTheory.Bicategory.termρ_"], - ["docBlame", "CategoryTheory.Bicategory.triangle"], ["docBlame", "CategoryTheory.Bicategory.whiskerLeft"], - ["docBlame", "CategoryTheory.Bicategory.whiskerLeft_comp"], - ["docBlame", "CategoryTheory.Bicategory.whiskerLeft_id"], ["docBlame", "CategoryTheory.Bicategory.whiskerRight"], - ["docBlame", "CategoryTheory.Bicategory.whiskerRight_comp"], - ["docBlame", "CategoryTheory.Bicategory.whiskerRight_id"], - ["docBlame", "CategoryTheory.Bicategory.whisker_assoc"], - ["docBlame", "CategoryTheory.Bicategory.whisker_exchange"], ["docBlame", "CategoryTheory.BraidedCategory.braiding"], - ["docBlame", "CategoryTheory.BraidedCategory.braiding_naturality"], - ["docBlame", "CategoryTheory.BraidedCategory.hexagon_forward"], - ["docBlame", "CategoryTheory.BraidedCategory.hexagon_reverse"], - ["docBlame", "CategoryTheory.BraidedFunctor.braided"], ["docBlame", "CategoryTheory.Comma.hom"], ["docBlame", "CategoryTheory.Comma.left"], ["docBlame", "CategoryTheory.Comma.right"], ["docBlame", "CategoryTheory.CommaMorphism.left"], ["docBlame", "CategoryTheory.CommaMorphism.right"], - ["docBlame", "CategoryTheory.CommaMorphism.w"], - ["docBlame", "CategoryTheory.Comonad.coassoc'"], - ["docBlame", "CategoryTheory.Comonad.left_counit'"], - ["docBlame", "CategoryTheory.Comonad.right_counit'"], ["docBlame", "CategoryTheory.Comonad.δ'"], ["docBlame", "CategoryTheory.Comonad.ε'"], - ["docBlame", "CategoryTheory.ComonadHom.app_δ"], - ["docBlame", "CategoryTheory.ComonadHom.app_ε"], - ["docBlame", "CategoryTheory.CompatiblePreserving.Compatible"], - ["docBlame", "CategoryTheory.CoverLifting.cover_lift"], - ["docBlame", "CategoryTheory.CoverPreserving.cover_preserve"], - ["docBlame", "CategoryTheory.EnoughProjectives.presentation"], ["docBlame", "CategoryTheory.EnrichedCategory.Hom"], - ["docBlame", "CategoryTheory.EnrichedCategory.assoc"], ["docBlame", "CategoryTheory.EnrichedCategory.comp"], - ["docBlame", "CategoryTheory.EnrichedCategory.comp_id"], ["docBlame", "CategoryTheory.EnrichedCategory.id"], - ["docBlame", "CategoryTheory.EnrichedCategory.id_comp"], ["docBlame", "CategoryTheory.EnrichedFunctor.map"], - ["docBlame", "CategoryTheory.EnrichedFunctor.map_comp"], - ["docBlame", "CategoryTheory.EnrichedFunctor.map_id"], ["docBlame", "CategoryTheory.EnrichedFunctor.obj"], - ["docBlame", "CategoryTheory.Exact.w"], ["docBlame", "CategoryTheory.ExactPairing.coevaluation"], ["docBlame", "CategoryTheory.ExactPairing.coevaluation'"], - ["docBlame", "CategoryTheory.ExactPairing.coevaluation_evaluation'"], ["docBlame", "CategoryTheory.ExactPairing.evaluation"], ["docBlame", "CategoryTheory.ExactPairing.evaluation'"], - ["docBlame", "CategoryTheory.ExactPairing.evaluation_coevaluation'"], ["docBlame", "CategoryTheory.ExactPairing.termε_"], ["docBlame", "CategoryTheory.ExactPairing.termη_"], ["docBlame", "CategoryTheory.GlueData.J"], ["docBlame", "CategoryTheory.GlueData.U"], ["docBlame", "CategoryTheory.GlueData.V"], - ["docBlame", "CategoryTheory.GlueData.cocycle"], ["docBlame", "CategoryTheory.GlueData.f"], ["docBlame", "CategoryTheory.GlueData.t"], ["docBlame", "CategoryTheory.GlueData.t'"], - ["docBlame", "CategoryTheory.GlueData.t_fac"], - ["docBlame", "CategoryTheory.GlueData.t_id"], ["docBlame", "CategoryTheory.GradedNatTrans.app"], - ["docBlame", "CategoryTheory.GradedNatTrans.naturality"], ["docBlame", "CategoryTheory.GrothendieckTopology.sheafificationIsoPresheafToSheafCompSheafToPreasheaf"], - ["docBlame", "CategoryTheory.HalfBraiding.monoidal"], - ["docBlame", "CategoryTheory.HalfBraiding.naturality"], ["docBlame", "CategoryTheory.HalfBraiding.β"], ["docBlame", "CategoryTheory.HasLeftDual.leftDual"], - ["docBlame", "CategoryTheory.HasProjectiveResolution.out"], ["docBlame", "CategoryTheory.HasRightDual.rightDual"], - ["docBlame", "CategoryTheory.IsCoreflexivePair.common_retraction'"], - ["docBlame", "CategoryTheory.IsReflexivePair.common_section'"], - ["docBlame", "CategoryTheory.LaxBraidedFunctor.braided"], - ["docBlame", "CategoryTheory.LaxMonoidalFunctor.left_unitality"], - ["docBlame", "CategoryTheory.LaxMonoidalFunctor.right_unitality"], - ["docBlame", "CategoryTheory.LaxMonoidalFunctor.μ_natural"], - ["docBlame", "CategoryTheory.LeftSplit.epi"], - ["docBlame", "CategoryTheory.LeftSplit.exact"], - ["docBlame", "CategoryTheory.LeftSplit.left_split"], ["docBlame", "CategoryTheory.Mat_.X"], ["docBlame", "CategoryTheory.Mat_.ι"], ["docBlame", "CategoryTheory.Monad.CreatesColimitOfIsSplitPair"], @@ -1349,154 +695,61 @@ ["docBlame", "CategoryTheory.Monad.PreservesColimitOfIsReflexivePair"], ["docBlame", "CategoryTheory.Monad.PreservesColimitOfIsSplitPair"], ["docBlame", "CategoryTheory.Monad.ReflectsColimitOfIsSplitPair"], - ["docBlame", "CategoryTheory.Monad.assoc'"], - ["docBlame", "CategoryTheory.Monad.left_unit'"], - ["docBlame", "CategoryTheory.Monad.right_unit'"], ["docBlame", "CategoryTheory.Monad.η'"], ["docBlame", "CategoryTheory.Monad.μ'"], - ["docBlame", "CategoryTheory.MonadHom.app_η"], - ["docBlame", "CategoryTheory.MonadHom.app_μ"], - ["docBlame", "CategoryTheory.MonoidalCategory.id_whiskerRight"], - ["docBlame", "CategoryTheory.MonoidalCategory.tensorHom_def"], - ["docBlame", "CategoryTheory.MonoidalCategory.whiskerLeft_id"], - ["docBlame", "CategoryTheory.MonoidalLinear.smul_tensor"], - ["docBlame", "CategoryTheory.MonoidalLinear.tensor_smul"], ["docBlame", "CategoryTheory.MonoidalOpposite.«term_ᴹᵒᵖ»"], - ["docBlame", "CategoryTheory.NoetherianObject.subobject_gt_wellFounded'"], ["docBlame", "CategoryTheory.Presieve.yonedaFamilyOfElements_fromCocone"], - ["docBlame", "CategoryTheory.Pretopology.Transitive"], ["docBlame", "CategoryTheory.Pretopology.coverings"], - ["docBlame", "CategoryTheory.Pretopology.has_isos"], - ["docBlame", "CategoryTheory.Pretopology.pullbacks"], - ["docBlame", "CategoryTheory.Projective.factors"], ["docBlame", "CategoryTheory.ProjectivePresentation.f"], ["docBlame", "CategoryTheory.ProjectivePresentation.p"], - ["docBlame", "CategoryTheory.ProjectiveResolution.complex"], - ["docBlame", "CategoryTheory.ProjectiveResolution.exact"], - ["docBlame", "CategoryTheory.ProjectiveResolution.exact₀"], - ["docBlame", "CategoryTheory.ProjectiveResolution.π"], - ["docBlame", "CategoryTheory.RightSplit.exact"], - ["docBlame", "CategoryTheory.RightSplit.mono"], - ["docBlame", "CategoryTheory.RightSplit.right_split"], - ["docBlame", "CategoryTheory.ShortExact.epi"], - ["docBlame", "CategoryTheory.ShortExact.exact"], - ["docBlame", "CategoryTheory.ShortExact.mono"], - ["docBlame", "CategoryTheory.Simple.mono_isIso_iff_nonzero"], - ["docBlame", "CategoryTheory.Split.split"], - ["docBlame", "CategoryTheory.Splitting.comp_iso_eq_inl"], - ["docBlame", "CategoryTheory.Splitting.iso"], - ["docBlame", "CategoryTheory.Splitting.iso_comp_snd_eq"], ["docBlame", "CategoryTheory.Subgroupoid.arrows"], - ["docBlame", "CategoryTheory.Subgroupoid.inv"], - ["docBlame", "CategoryTheory.Subgroupoid.mul"], - ["docBlame", "CategoryTheory.SymmetricCategory.symmetry"], - ["docBlame", "CategoryTheory.UnbundledHom.hom_comp"], - ["docBlame", "CategoryTheory.UnbundledHom.hom_id"], - ["docBlame", "CategoryTheory.WellPowered.subobject_small"], - ["docBlame", "CategoryTheory.exp.delabPrefunctorObjExp"], - ["docBlame", "CategoryTheory.exp.«term_^^_»"], - ["docBlame", "CategoryTheory.exp.«term_⟹_»"], - ["docBlame", "ChainComplex.MkStruct.X₀"], - ["docBlame", "ChainComplex.MkStruct.X₁"], - ["docBlame", "ChainComplex.MkStruct.X₂"], - ["docBlame", "ChainComplex.MkStruct.d₀"], - ["docBlame", "ChainComplex.MkStruct.d₁"], - ["docBlame", "ChainComplex.MkStruct.s"], ["docBlame", "CliffordAlgebra.EvenHom.bilin"], - ["docBlame", "CliffordAlgebra.EvenHom.contract"], - ["docBlame", "CliffordAlgebra.EvenHom.contract_mid"], ["docBlame", "CochainComplex.MkStruct.X₀"], ["docBlame", "CochainComplex.MkStruct.X₁"], ["docBlame", "CochainComplex.MkStruct.X₂"], ["docBlame", "CochainComplex.MkStruct.d₀"], ["docBlame", "CochainComplex.MkStruct.d₁"], - ["docBlame", "CochainComplex.MkStruct.s"], - ["docBlame", "Complex.IsExpCmpFilter.isBigO_im_pow_re"], - ["docBlame", "Complex.IsExpCmpFilter.tendsto_re"], ["docBlame", "Computability.Encoding.decode"], - ["docBlame", "Computability.Encoding.decode_encode"], ["docBlame", "Computability.Encoding.encode"], ["docBlame", "Computability.Encoding.Γ"], ["docBlame", "Computability.FinEncoding.ΓFin"], ["docBlame", "Computation.parallel.aux1"], ["docBlame", "Computation.parallel.aux2"], ["docBlame", "Configuration.HasLines.mkLine"], - ["docBlame", "Configuration.HasLines.mkLine_ax"], ["docBlame", "Configuration.HasPoints.mkPoint"], - ["docBlame", "Configuration.HasPoints.mkPoint_ax"], - ["docBlame", "Configuration.Nondegenerate.eq_or_eq"], - ["docBlame", "Configuration.Nondegenerate.exists_line"], - ["docBlame", "Configuration.Nondegenerate.exists_point"], - ["docBlame", "Configuration.ProjectivePlane.exists_config"], ["docBlame", "Configuration.ProjectivePlane.mkLine"], - ["docBlame", "Configuration.ProjectivePlane.mkLine_ax"], - ["docBlame", "ContinuousLinearMap.NonlinearRightInverse.bound'"], ["docBlame", "ContinuousLinearMap.NonlinearRightInverse.nnnorm"], - ["docBlame", "ContinuousLinearMap.NonlinearRightInverse.right_inv'"], ["docBlame", "ContinuousLinearMap.NonlinearRightInverse.toFun"], ["docBlame", "ContinuousMap.HomotopyEquiv.invFun"], - ["docBlame", "ContinuousMap.HomotopyEquiv.left_inv"], - ["docBlame", "ContinuousMap.HomotopyEquiv.right_inv"], ["docBlame", "ContinuousMap.HomotopyEquiv.toFun"], ["docBlame", "Ctop.Realizer.F"], - ["docBlame", "Ctop.Realizer.eq"], ["docBlame", "Ctop.Realizer.σ"], ["docBlame", "DirectSum.Decomposition.decompose'"], - ["docBlame", "DirectSum.Decomposition.left_inv"], - ["docBlame", "DirectSum.Decomposition.right_inv"], - ["docBlame", "DirectSum.GAlgebra.commutes"], - ["docBlame", "DirectSum.GAlgebra.map_mul"], - ["docBlame", "DirectSum.GAlgebra.map_one"], - ["docBlame", "DirectSum.GAlgebra.smul_def"], ["docBlame", "DirectSum.GAlgebra.toFun"], - ["docBlame", "DirectSum.GdistribMulAction.smul_add"], - ["docBlame", "DirectSum.GdistribMulAction.smul_zero"], - ["docBlame", "DirectSum.Gmodule.add_smul"], - ["docBlame", "DirectSum.Gmodule.zero_smul"], ["docBlame", "Equiv.Perm.«termC[_,]»"], - ["docBlame", "EuclideanGeometry.Concyclic.Coplanar"], - ["docBlame", "EuclideanGeometry.Concyclic.Cospherical"], ["docBlame", "EuclideanGeometry.Sphere.center"], ["docBlame", "EuclideanGeometry.Sphere.radius"], ["docBlame", "FBinopElab.SRec.args"], ["docBlame", "FBinopElab.SRec.name"], ["docBlame", "Filter.Germ.const"], ["docBlame", "Filter.Germ.ofFun"], - ["docBlame", "Filter.IsMeasurablyGenerated.exists_measurable_subset"], ["docBlame", "Filter.Realizer.F"], - ["docBlame", "Filter.Realizer.eq"], ["docBlame", "Filter.Realizer.σ"], ["docBlame", "FirstOrder.Language.«term_≃ᴸ_»"], ["docBlame", "GeneralizedContinuedFraction.IntFractPair.b"], ["docBlame", "GeneralizedContinuedFraction.IntFractPair.fr"], - ["docBlame", "Geometry.SimplicialComplex.down_closed"], ["docBlame", "Geometry.SimplicialComplex.faces"], - ["docBlame", "Geometry.SimplicialComplex.indep"], - ["docBlame", "Geometry.SimplicialComplex.inter_subset_convexHull"], - ["docBlame", "Geometry.SimplicialComplex.not_empty_mem"], ["docBlame", "GromovHausdorff.AuxGluingStruct.Space"], ["docBlame", "GromovHausdorff.AuxGluingStruct.embed"], - ["docBlame", "GromovHausdorff.AuxGluingStruct.isom"], ["docBlame", "GromovHausdorff.AuxGluingStruct.metric"], - ["docBlame", "Group.FG.out"], - ["docBlame", "Group.IsNilpotent.nilpotent'"], - ["docBlame", "HahnSeries.SummableFamily.finite_co_support'"], - ["docBlame", "HahnSeries.SummableFamily.isPwo_iUnion_support'"], ["docBlame", "HahnSeries.SummableFamily.toFun"], ["docBlame", "HomogeneousLocalization.NumDenSameDeg.deg"], ["docBlame", "HomogeneousLocalization.NumDenSameDeg.den"], - ["docBlame", "HomogeneousLocalization.NumDenSameDeg.den_mem"], ["docBlame", "HomogeneousLocalization.NumDenSameDeg.num"], - ["docBlame", "HomologicalComplex.Hom.comm'"], ["docBlame", "HomologicalComplex.Hom.f"], ["docBlame", "Ideal.Filtration.N"], - ["docBlame", "Ideal.Filtration.mono"], - ["docBlame", "Ideal.Filtration.smul_le"], - ["docBlame", "Ideal.IsJacobson.out'"], ["docBlame", "IntermediateField.delabAdjoinNotation.delabInsertArray"], ["docBlame", "IsDedekindDomain.HeightOneSpectrum.asIdeal"], - ["docBlame", "IsDedekindDomain.HeightOneSpectrum.ne_bot"], - ["docBlame", "Lean.Attr.hintTacticAttr"], ["docBlame", "Lean.Attr.substAttr"], ["docBlame", "Lean.Export.Alloc"], ["docBlame", "Lean.Export.Entry"], @@ -1516,28 +769,12 @@ ["docBlame", "Lean.Expr.modifyRevArg"], ["docBlame", "Lean.MVarId.casesType"], ["docBlame", "Lean.MVarId.congrCore!"], - ["docBlame", "Lean.MVarId.exact"], - ["docBlame", "Lean.Meta.FindOptions"], ["docBlame", "Lean.Meta.checkTypeIsProp"], - ["docBlame", "Lean.Meta.find"], - ["docBlame", "Lean.Meta.findCore"], ["docBlame", "Lean.Meta.mkSimpTheoremCore"], ["docBlame", "Lean.Meta.preprocess"], ["docBlame", "Lean.Meta.shouldPreprocess"], ["docBlame", "Lean.Name.isBlackListed"], ["docBlame", "Lean.PHashSet.toList"], - ["docBlame", "LieAlgebra.IsSemisimple.semisimple"], - ["docBlame", "LieAlgebra.IsSimple.non_abelian"], - ["docBlame", "LieAlgebra.IsSolvable.solvable"], - ["docBlame", "LieModule.IsIrreducible.Irreducible"], - ["docBlame", "LieModule.IsNilpotent.nilpotent"], - ["docBlame", "LieModule.IsTrivial.trivial"], - ["docBlame", "LieSubalgebra.IsCartanSubalgebra.nilpotent"], - ["docBlame", "LieSubalgebra.IsCartanSubalgebra.self_normalizing"], - ["docBlame", "LinearMap.IsProj.map_id"], - ["docBlame", "LinearMap.IsProj.map_mem"], - ["docBlame", "LinearPMap.HasCore.closure_eq"], - ["docBlame", "LinearPMap.HasCore.le_domain"], ["docBlame", "LocallyFinite.Realizer.bas"], ["docBlame", "LocallyFinite.Realizer.sets"], ["docBlame", "MLList.runCmd.put"], @@ -1557,16 +794,12 @@ ["docBlame", "Mathlib.Tactic.assertNoInstance"], ["docBlame", "Mathlib.Tactic.assocRw"], ["docBlame", "Mathlib.Tactic.async"], - ["docBlame", "Mathlib.Tactic.borelize"], ["docBlame", "Mathlib.Tactic.cases'"], ["docBlame", "Mathlib.Tactic.cases''"], ["docBlame", "Mathlib.Tactic.cc"], ["docBlame", "Mathlib.Tactic.clarify"], - ["docBlame", "Mathlib.Tactic.clean"], - ["docBlame", "Mathlib.Tactic.coherence"], ["docBlame", "Mathlib.Tactic.compVal"], ["docBlame", "Mathlib.Tactic.computeDegreeLE"], - ["docBlame", "Mathlib.Tactic.congrM"], ["docBlame", "Mathlib.Tactic.continue"], ["docBlame", "Mathlib.Tactic.decide!"], ["docBlame", "Mathlib.Tactic.defReplacer"], @@ -1581,7 +814,6 @@ ["docBlame", "Mathlib.Tactic.equivRwType"], ["docBlame", "Mathlib.Tactic.evalIntrov"], ["docBlame", "Mathlib.Tactic.expandExists"], - ["docBlame", "Mathlib.Tactic.extractGoal"], ["docBlame", "Mathlib.Tactic.extractGoal!"], ["docBlame", "Mathlib.Tactic.failIfSuccess?"], ["docBlame", "Mathlib.Tactic.field"], @@ -1590,17 +822,11 @@ ["docBlame", "Mathlib.Tactic.generalizes"], ["docBlame", "Mathlib.Tactic.generalizesArg"], ["docBlame", "Mathlib.Tactic.generalizingClause"], - ["docBlame", "Mathlib.Tactic.ghostFunTac"], - ["docBlame", "Mathlib.Tactic.group"], ["docBlame", "Mathlib.Tactic.guardProofTerm"], ["docBlame", "Mathlib.Tactic.guardTags"], ["docBlame", "Mathlib.Tactic.hGeneralize"], ["docBlame", "Mathlib.Tactic.hGeneralize!"], ["docBlame", "Mathlib.Tactic.haveField"], - ["docBlame", "Mathlib.Tactic.hint"], - ["docBlame", "Mathlib.Tactic.hygieneInfo"], - ["docBlame", "Mathlib.Tactic.hygieneInfoFn"], - ["docBlame", "Mathlib.Tactic.hygieneInfoNoAntiquot"], ["docBlame", "Mathlib.Tactic.include"], ["docBlame", "Mathlib.Tactic.induction'"], ["docBlame", "Mathlib.Tactic.induction''"], @@ -1619,25 +845,20 @@ ["docBlame", "Mathlib.Tactic.moveMul"], ["docBlame", "Mathlib.Tactic.moveOp"], ["docBlame", "Mathlib.Tactic.mvBisim"], - ["docBlame", "Mathlib.Tactic.noncommRing"], ["docBlame", "Mathlib.Tactic.notationClass"], ["docBlame", "Mathlib.Tactic.nthRwLHS"], ["docBlame", "Mathlib.Tactic.nthRwRHS"], ["docBlame", "Mathlib.Tactic.obviously"], - ["docBlame", "Mathlib.Tactic.omega"], ["docBlame", "Mathlib.Tactic.omit"], - ["docBlame", "Mathlib.Tactic.optBinderIdent"], ["docBlame", "Mathlib.Tactic.padicIndexSimp"], ["docBlame", "Mathlib.Tactic.parameter"], ["docBlame", "Mathlib.Tactic.piInstance"], ["docBlame", "Mathlib.Tactic.piInstanceDeriveField"], - ["docBlame", "Mathlib.Tactic.ppMVarIds"], ["docBlame", "Mathlib.Tactic.pp_nodot"], ["docBlame", "Mathlib.Tactic.prettyCases"], ["docBlame", "Mathlib.Tactic.printSorryIn"], ["docBlame", "Mathlib.Tactic.propagateTags"], ["docBlame", "Mathlib.Tactic.protectProj"], - ["docBlame", "Mathlib.Tactic.pure_coherence"], ["docBlame", "Mathlib.Tactic.rcases?"], ["docBlame", "Mathlib.Tactic.reassoc"], ["docBlame", "Mathlib.Tactic.reassoc!"], @@ -1660,10 +881,8 @@ ["docBlame", "Mathlib.Tactic.suggest"], ["docBlame", "Mathlib.Tactic.tacticDestruct_"], ["docBlame", "Mathlib.Tactic.tacticHave_"], - ["docBlame", "Mathlib.Tactic.tacticLeft"], ["docBlame", "Mathlib.Tactic.tacticLet_"], ["docBlame", "Mathlib.Tactic.tacticMatch_target_"], - ["docBlame", "Mathlib.Tactic.tacticRight"], ["docBlame", "Mathlib.Tactic.tacticSet!_"], ["docBlame", "Mathlib.Tactic.tacticSuffices_"], ["docBlame", "Mathlib.Tactic.tacticTransitivity___"], @@ -1677,7 +896,6 @@ ["docBlame", "Mathlib.Tactic.unfoldAux"], ["docBlame", "Mathlib.Tactic.unfoldCases"], ["docBlame", "Mathlib.Tactic.unfoldCoes"], - ["docBlame", "Mathlib.Tactic.unfoldProjs"], ["docBlame", "Mathlib.Tactic.unfoldWf"], ["docBlame", "Mathlib.Tactic.uniqueDiffWithinAt_Ici_Iic_univ"], ["docBlame", "Mathlib.Tactic.unitInterval"], @@ -1690,75 +908,21 @@ ["docBlame", "Mathlib.WhatsNew.whatsNew"], ["docBlame", "Mathlib.evalExtractLet.doExtract"], ["docBlame", "Mathlib.evalExtractLet.setupNames"], - ["docBlame", "Matrix.IsAdjMatrix.apply_diag"], - ["docBlame", "Matrix.IsAdjMatrix.symm"], - ["docBlame", "Matrix.IsAdjMatrix.zero_or_one"], ["docBlame", "Matrix.TransvectionStruct.c"], - ["docBlame", "Matrix.TransvectionStruct.hij"], ["docBlame", "Matrix.TransvectionStruct.i"], ["docBlame", "Matrix.TransvectionStruct.j"], - ["docBlame", "MeasurableSpace.CountablyGenerated.isCountablyGenerated"], - ["docBlame", "MeasureTheory.AECover.ae_eventually_mem"], - ["docBlame", "MeasureTheory.AECover.measurableSet"], - ["docBlame", "MeasureTheory.Conservative.exists_mem_image_mem"], - ["docBlame", "MeasureTheory.Content.mono'"], - ["docBlame", "MeasureTheory.Content.sup_disjoint'"], - ["docBlame", "MeasureTheory.Content.sup_le'"], ["docBlame", "MeasureTheory.Content.toFun"], - ["docBlame", "MeasureTheory.Filtration.le'"], - ["docBlame", "MeasureTheory.Filtration.mono'"], ["docBlame", "MeasureTheory.Filtration.seq"], - ["docBlame", "MeasureTheory.HasPDF.pdf'"], - ["docBlame", "MeasureTheory.IsAddFundamentalDomain.ae_covers"], - ["docBlame", "MeasureTheory.IsAddFundamentalDomain.aedisjoint"], - ["docBlame", "MeasureTheory.IsAddFundamentalDomain.nullMeasurableSet"], - ["docBlame", "MeasureTheory.IsFiniteMeasure.measure_univ_lt_top"], - ["docBlame", "MeasureTheory.IsFiniteMeasureOnCompacts.lt_top_of_isCompact"], - ["docBlame", "MeasureTheory.IsFundamentalDomain.ae_covers"], - ["docBlame", "MeasureTheory.IsFundamentalDomain.aedisjoint"], - ["docBlame", "MeasureTheory.IsFundamentalDomain.nullMeasurableSet"], - ["docBlame", "MeasureTheory.IsLocallyFiniteMeasure.finiteAtNhds"], - ["docBlame", "MeasureTheory.IsProbabilityMeasure.measure_univ"], - ["docBlame", "MeasureTheory.JordanDecomposition.mutuallySingular"], ["docBlame", "MeasureTheory.JordanDecomposition.negPart"], ["docBlame", "MeasureTheory.JordanDecomposition.posPart"], ["docBlame", "MeasureTheory.Lp.constL"], - ["docBlame", "MeasureTheory.Measure.m_iUnion"], - ["docBlame", "MeasureTheory.Measure.trimmed"], - ["docBlame", "MeasureTheory.MeasurePreserving.map_eq"], - ["docBlame", "MeasureTheory.MeasurePreserving.measurable"], - ["docBlame", "MeasureTheory.NoAtoms.measure_singleton"], - ["docBlame", "MeasureTheory.OuterMeasure.empty"], - ["docBlame", "MeasureTheory.OuterMeasure.iUnion_nat"], ["docBlame", "MeasureTheory.OuterMeasure.measureOf"], - ["docBlame", "MeasureTheory.OuterMeasure.mono"], - ["docBlame", "MeasureTheory.SMulInvariantMeasure.measure_preimage_smul"], - ["docBlame", "MeasureTheory.SigmaFinite.out'"], - ["docBlame", "MeasureTheory.SigmaFiniteFiltration.SigmaFinite"], - ["docBlame", "MeasureTheory.SimpleFunc.finite_range'"], - ["docBlame", "MeasureTheory.SimpleFunc.measurableSet_fiber'"], ["docBlame", "MeasureTheory.SimpleFunc.toFun"], - ["docBlame", "MeasureTheory.VAddInvariantMeasure.measure_preimage_vadd"], - ["docBlame", "MeasureTheory.VectorMeasure.empty'"], - ["docBlame", "MeasureTheory.VectorMeasure.m_iUnion'"], ["docBlame", "MeasureTheory.VectorMeasure.measureOf'"], - ["docBlame", "MeasureTheory.VectorMeasure.not_measurable'"], - ["docBlame", "Mod_.Hom.act_hom"], ["docBlame", "Mod_.Hom.hom"], - ["docBlame", "ModelWithCorners.Boundaryless.range_eq_univ"], ["docBlame", "Module.Baer.supExtensionOfMaxSingleton"], - ["docBlame", "Module.DualBases.Finite"], - ["docBlame", "Module.DualBases.Total"], - ["docBlame", "Module.DualBases.eval"], - ["docBlame", "Module.Flat.out"], - ["docBlame", "Module.Free.exists_basis"], - ["docBlame", "Module.Injective.out"], - ["docBlame", "Module.Projective.out"], ["docBlame", "Mon_.Hom.hom"], - ["docBlame", "Mon_.Hom.mul_hom"], - ["docBlame", "Mon_.Hom.one_hom"], ["docBlame", "MonadCont.Label.apply"], - ["docBlame", "Monoid.FG.out"], ["docBlame", "Monoid.Foldl.get"], ["docBlame", "Monoid.Foldl.mk"], ["docBlame", "Monoid.Foldl.ofFreeMonoid"], @@ -1771,86 +935,21 @@ ["docBlame", "Monoid.foldrM.get"], ["docBlame", "Monoid.foldrM.mk"], ["docBlame", "Monoid.foldrM.ofFreeMonoid"], - ["docBlame", "MulAction.IsMinimal.dense_orbit"], ["docBlame", "Nat.ArithmeticFunction.termΛ"], - ["docBlame", "Nat.AtLeastTwo.prop"], - ["docBlame", "NormedAddGroupHom.IsQuotient.norm"], - ["docBlame", "NormedAddGroupHom.IsQuotient.surjective"], - ["docBlame", "ONote.NF.out"], ["docBlame", "Order.PFilter.dual"], - ["docBlame", "Ordnode.Valid'.bal"], - ["docBlame", "Ordnode.Valid'.ord"], - ["docBlame", "Ordnode.Valid'.sz"], ["docBlame", "PProd.mk.injArrow"], - ["docBlame", "PicardLindelof.FunSpace.lipschitz'"], - ["docBlame", "PicardLindelof.FunSpace.map_t₀'"], ["docBlame", "PicardLindelof.FunSpace.toFun"], - ["docBlame", "Polynomial.IsEisensteinAt.leading"], - ["docBlame", "Polynomial.IsEisensteinAt.mem"], - ["docBlame", "Polynomial.IsEisensteinAt.not_mem"], - ["docBlame", "Polynomial.IsSplittingField.adjoin_rootSet'"], - ["docBlame", "Polynomial.IsSplittingField.splits'"], - ["docBlame", "Polynomial.IsWeaklyEisensteinAt.mem"], - ["docBlame", "Prefunctor.IsCovering.costar_bijective"], - ["docBlame", "Prefunctor.IsCovering.star_bijective"], ["docBlame", "PresheafOfModules.Hom.hom"], - ["docBlame", "PresheafOfModules.Hom.map_smul"], - ["docBlame", "Pretrivialization.IsLinear.linear"], - ["docBlame", "ProbabilityTheory.HasCondCdf.iInf_rat_gt_eq"], - ["docBlame", "ProbabilityTheory.HasCondCdf.le_one"], - ["docBlame", "ProbabilityTheory.HasCondCdf.mono"], - ["docBlame", "ProbabilityTheory.HasCondCdf.tendsto_atBot_zero"], - ["docBlame", "ProbabilityTheory.HasCondCdf.tendsto_atTop_one"], - ["docBlame", "ProbabilityTheory.IdentDistrib.aemeasurable_fst"], - ["docBlame", "ProbabilityTheory.IdentDistrib.aemeasurable_snd"], - ["docBlame", "ProbabilityTheory.IdentDistrib.map_eq"], - ["docBlame", "ProbabilityTheory.IsFiniteKernel.exists_univ_le"], - ["docBlame", "ProbabilityTheory.IsMarkovKernel.isProbabilityMeasure"], - ["docBlame", "ProbabilityTheory.IsSFiniteKernel.tsum_finite"], ["docBlame", "Prod.mk.injArrow"], - ["docBlame", "QuadraticForm.IsometryEquiv.map_app'"], ["docBlame", "QuaternionAlgebra.Basis.i"], - ["docBlame", "QuaternionAlgebra.Basis.i_mul_i"], - ["docBlame", "QuaternionAlgebra.Basis.i_mul_j"], ["docBlame", "QuaternionAlgebra.Basis.j"], - ["docBlame", "QuaternionAlgebra.Basis.j_mul_i"], - ["docBlame", "QuaternionAlgebra.Basis.j_mul_j"], ["docBlame", "QuaternionAlgebra.Basis.k"], - ["docBlame", "Real.IsConjugateExponent.inv_add_inv_conj"], - ["docBlame", "Real.IsConjugateExponent.one_lt"], - ["docBlame", "Ring.DimensionLEOne.maximalOfPrime"], - ["docBlame", "RingHom.PropertyIsLocal.HoldsForLocalizationAway"], - ["docBlame", "RingHom.PropertyIsLocal.LocalizationPreserves"], - ["docBlame", "RingHom.PropertyIsLocal.OfLocalizationSpanTarget"], - ["docBlame", "RingHom.PropertyIsLocal.StableUnderComposition"], ["docBlame", "Sat.Clause.cons"], ["docBlame", "Sat.Clause.nil"], ["docBlame", "Set.setOf.unexpander"], - ["docBlame", "SetTheory.PGame.Impartial.out"], - ["docBlame", "SetTheory.PGame.State.l"], - ["docBlame", "SetTheory.PGame.State.left_bound"], - ["docBlame", "SetTheory.PGame.State.r"], - ["docBlame", "SetTheory.PGame.State.right_bound"], - ["docBlame", "SetTheory.PGame.State.turnBound"], - ["docBlame", "SimpleGraph.Connected.nonempty"], - ["docBlame", "SimpleGraph.Connected.preconnected"], - ["docBlame", "SimpleGraph.Dart.is_adj"], - ["docBlame", "SimpleGraph.IsNClique.card_eq"], - ["docBlame", "SimpleGraph.IsNClique.clique"], - ["docBlame", "SimpleGraph.IsSRGWith.card"], - ["docBlame", "SimpleGraph.IsSRGWith.of_adj"], - ["docBlame", "SimpleGraph.IsSRGWith.of_not_adj"], - ["docBlame", "SimpleGraph.IsSRGWith.regular"], ["docBlame", "SimpleGraph.Subgraph.Adj"], - ["docBlame", "SimpleGraph.Subgraph.adj_sub"], - ["docBlame", "SimpleGraph.Subgraph.edge_vert"], - ["docBlame", "SimpleGraph.Subgraph.symm"], ["docBlame", "SimpleGraph.Subgraph.verts"], ["docBlame", "SimpleGraph.Walk.notNilRec"], - ["docBlame", "SimplicialObject.Split.X"], - ["docBlame", "SimplicialObject.Split.s"], - ["docBlame", "SimplicialObject.Splitting.N"], - ["docBlame", "SimplicialObject.Splitting.ι"], ["docBlame", "SlimCheck.Configuration.maxSize"], ["docBlame", "SlimCheck.Configuration.numInst"], ["docBlame", "SlimCheck.Configuration.numRetries"], @@ -1878,48 +977,18 @@ ["docBlame", "Std.Priority.max"], ["docBlame", "Stream'.WSeq.«term_~ʷ_»"], ["docBlame", "String.toAsciiByteArray.loop"], - ["docBlame", "StructureGroupoid.LocalInvariantProp.congr_of_forall"], - ["docBlame", "StructureGroupoid.LocalInvariantProp.is_local"], - ["docBlame", "StructureGroupoid.LocalInvariantProp.left_invariance'"], - ["docBlame", "StructureGroupoid.LocalInvariantProp.right_invariance'"], - ["docBlame", "Submodule.IsPrincipal.principal'"], ["docBlame", "Submodule.quotientPi_aux.invFun"], ["docBlame", "Submodule.quotientPi_aux.toFun"], ["docBlame", "Tactic.Elementwise.tacticElementwise!___"], ["docBlame", "Tactic.Elementwise.tacticElementwise___"], - ["docBlame", "Tactic.NormCast.convNormCast"], - ["docBlame", "Tactic.NormCast.evalConvNormCast"], - ["docBlame", "Tactic.NormCast.evalPushCast"], - ["docBlame", "Tactic.NormCast.isCoeOf?"], - ["docBlame", "Tactic.NormCast.isNumeral?"], - ["docBlame", "Tactic.NormCast.mkCoe"], - ["docBlame", "Tactic.NormCast.normCastHyp"], - ["docBlame", "Tactic.NormCast.normCastTarget"], - ["docBlame", "Tactic.NormCast.pushCast"], - ["docBlame", "Tactic.NormCast.tacticNorm_cast0_"], - ["docBlame", "Tactic.NormCast.termMod_cast_"], ["docBlame", "Tactic.NormNum.evalNatGCD"], - ["docBlame", "TensorProduct.CompatibleSMul.smul_tmul"], ["docBlame", "ToAdditive.additiveTestUnsafe.visit"], - ["docBlame", "TopCat.GlueData.f_open"], ["docBlame", "TopologicalSpace.Clopens.carrier"], - ["docBlame", "TopologicalSpace.Clopens.isClopen'"], ["docBlame", "TopologicalSpace.Closeds.carrier"], - ["docBlame", "TopologicalSpace.Closeds.closed'"], - ["docBlame", "TopologicalSpace.CompactOpens.isOpen'"], ["docBlame", "TopologicalSpace.Compacts.carrier"], - ["docBlame", "TopologicalSpace.Compacts.isCompact'"], - ["docBlame", "TopologicalSpace.MetrizableSpace.exists_metric"], - ["docBlame", "TopologicalSpace.NoetherianSpace.wellFounded_opens"], - ["docBlame", "TopologicalSpace.NonemptyCompacts.nonempty'"], - ["docBlame", "TopologicalSpace.PositiveCompacts.interior_nonempty'"], - ["docBlame", "TopologicalSpace.PseudoMetrizableSpace.exists_pseudo_metric"], ["docBlame", "Topology.Homotopy.termΩ"], ["docBlame", "Topology.Homotopy.«termΩ^»"], - ["docBlame", "Trivialization.IsLinear.linear"], - ["docBlame", "Turing.EvalsTo.evals_in_steps"], ["docBlame", "Turing.EvalsTo.steps"], - ["docBlame", "Turing.EvalsToInTime.steps_le_m"], ["docBlame", "Turing.FinTM2.K"], ["docBlame", "Turing.FinTM2.initialState"], ["docBlame", "Turing.FinTM2.kDecidableEq"], @@ -1935,7 +1004,6 @@ ["docBlame", "Turing.FinTM2.σ"], ["docBlame", "Turing.FinTM2.σFin"], ["docBlame", "Turing.PointedMap.f"], - ["docBlame", "Turing.PointedMap.map_pt'"], ["docBlame", "Turing.TM2Computable.outputsFun"], ["docBlame", "Turing.TM2ComputableAux.inputAlphabet"], ["docBlame", "Turing.TM2ComputableAux.outputAlphabet"], @@ -1947,27 +1015,7 @@ ["docBlame", "Turing.Tape.head"], ["docBlame", "Turing.Tape.left"], ["docBlame", "Turing.Tape.right"], - ["docBlame", "Urysohns.CU.C"], - ["docBlame", "Urysohns.CU.U"], - ["docBlame", "Urysohns.CU.closed_C"], - ["docBlame", "Urysohns.CU.open_U"], - ["docBlame", "Urysohns.CU.subset"], - ["docBlame", "Valuation.Integers.exists_of_le_one"], - ["docBlame", "Valuation.Integers.hom_inj"], - ["docBlame", "Valuation.Integers.map_le_one"], - ["docBlame", "VectorBundleCore.IsSmooth.smoothOn_coordChange"], - ["docBlame", "VectorPrebundle.IsSmooth.exists_smoothCoordChange"], - ["docBlame", "WittVector.IsPoly.poly"], - ["docBlame", "WittVector.IsPoly₂.poly"], ["docBlame", "WittVector.Isocrystal.frob"], - ["docBlame", "WittVector.IsocrystalEquiv.frob_equivariant"], - ["docBlame", "WittVector.IsocrystalHom.frob_equivariant"], - ["docBlame", "Zsqrtd.Nonsquare.ns'"], - ["docBlame", "intervalIntegral.FTCFilter.le_nhds"], - ["docBlame", "intervalIntegral.FTCFilter.meas_gen"], - ["docBlame", "intervalIntegral.FTCFilter.pure_le"], - ["docBlame", "lift.SubfieldWithHom.carrier"], - ["docBlame", "lift.SubfieldWithHom.emb"], ["docBlame", "AlgebraicGeometry.PresheafedSpace.Hom.base"], ["docBlame", "AlgebraicGeometry.PresheafedSpace.Hom.c"], ["docBlame", @@ -1976,28 +1024,11 @@ "AlgebraicGeometry.ProjIsoSpecTopComponent.FromSpec.tacticMem_tac_aux"], ["docBlame", "AlgebraicTopology.DoldKan.MorphComponents.a"], ["docBlame", "AlgebraicTopology.DoldKan.MorphComponents.b"], - ["docBlame", "BoxIntegral.IntegrationParams.MemBaseSet.distortion_le"], - ["docBlame", "BoxIntegral.IntegrationParams.MemBaseSet.exists_compl"], - ["docBlame", "BoxIntegral.IntegrationParams.MemBaseSet.isHenstock"], - ["docBlame", "BoxIntegral.IntegrationParams.MemBaseSet.isSubordinate"], - ["docBlame", "CategoryTheory.Center.Hom.comm"], ["docBlame", "CategoryTheory.Center.Hom.f"], - ["docBlame", "CategoryTheory.DifferentialObject.Hom.comm"], ["docBlame", "CategoryTheory.FreeBicategory.Hom₂.mk"], - ["docBlame", "CategoryTheory.Functor.CommShift.add"], ["docBlame", "CategoryTheory.Functor.CommShift.iso"], - ["docBlame", "CategoryTheory.Functor.CommShift.zero"], - ["docBlame", "CategoryTheory.Functor.ReflectsExactSequences.reflects"], ["docBlame", "CategoryTheory.Limits.CoproductDisjoint.isInitialOfIsPullbackOfIsCoproduct"], - ["docBlame", "CategoryTheory.Limits.CoproductDisjoint.mono_inl"], - ["docBlame", "CategoryTheory.Limits.CoproductDisjoint.mono_inr"], - ["docBlame", "CategoryTheory.Limits.DiagramOfCones.comp"], - ["docBlame", "CategoryTheory.Limits.DiagramOfCones.id"], - ["docBlame", "CategoryTheory.Limits.DiagramOfCones.map"], - ["docBlame", "CategoryTheory.Limits.DiagramOfCones.obj"], - ["docBlame", "CategoryTheory.Limits.HasStrictInitialObjects.out"], - ["docBlame", "CategoryTheory.Limits.HasStrictTerminalObjects.out"], ["docBlame", "CategoryTheory.Limits.MulticospanIndex.L"], ["docBlame", "CategoryTheory.Limits.MulticospanIndex.R"], ["docBlame", "CategoryTheory.Limits.MulticospanIndex.fst"], @@ -2015,8 +1046,6 @@ ["docBlame", "CategoryTheory.Limits.MultispanIndex.snd"], ["docBlame", "CategoryTheory.Limits.MultispanIndex.sndFrom"], ["docBlame", "CategoryTheory.Limits.PreservesColimit.preserves"], - ["docBlame", "CategoryTheory.Limits.PreservesFiniteCoproducts.preserves"], - ["docBlame", "CategoryTheory.Limits.PreservesFiniteProducts.preserves"], ["docBlame", "CategoryTheory.Limits.PreservesLimit.preserves"], ["docBlame", "CategoryTheory.Limits.ReflectsColimit.reflects"], ["docBlame", "CategoryTheory.Limits.ReflectsColimitsOfShape.reflectsColimit"], @@ -2026,62 +1055,25 @@ ["docBlame", "CategoryTheory.Limits.ReflectsLimitsOfShape.reflectsLimit"], ["docBlame", "CategoryTheory.Limits.ReflectsLimitsOfSize.reflectsLimitsOfShape"], - ["docBlame", "CategoryTheory.ModuleCat.RestrictionCoextensionAdj.app'"], ["docBlame", "CategoryTheory.Monad.CreatesColimitOfIsSplitPair.out"], - ["docBlame", "CategoryTheory.Monad.HasCoequalizerOfIsSplitPair.out"], ["docBlame", "CategoryTheory.Monad.PreservesColimitOfIsReflexivePair.out"], ["docBlame", "CategoryTheory.Monad.PreservesColimitOfIsSplitPair.out"], ["docBlame", "CategoryTheory.Monad.ReflectsColimitOfIsSplitPair.out"], - ["docBlame", "CategoryTheory.MonoidalCategory.ClosedPredicate.prop_ihom"], - ["docBlame", "CategoryTheory.MonoidalCategory.MonoidalPredicate.prop_id"], - ["docBlame", "CategoryTheory.MonoidalCategory.MonoidalPredicate.prop_tensor"], ["docBlame", "CategoryTheory.Pretriangulated.Triangle.homMk"], ["docBlame", "CategoryTheory.Pretriangulated.Triangle.isoMk"], - ["docBlame", "CategoryTheory.ShortComplex.HasLeftHomology.condition"], - ["docBlame", "CategoryTheory.ShortComplex.HasRightHomology.condition"], - ["docBlame", "CategoryTheory.ShortComplex.HomologyData.comm"], - ["docBlame", "CategoryTheory.ShortComplex.HomologyData.left"], - ["docBlame", "CategoryTheory.ShortComplex.HomologyData.right"], - ["docBlame", "CategoryTheory.Subgroupoid.IsNormal.conj"], - ["docBlame", "CategoryTheory.Subgroupoid.IsWide.wide"], - ["docBlame", "CategoryTheory.Triangulated.Octahedron.comm₁"], - ["docBlame", "CategoryTheory.Triangulated.Octahedron.comm₂"], - ["docBlame", "CategoryTheory.Triangulated.Octahedron.comm₃"], - ["docBlame", "CategoryTheory.Triangulated.Octahedron.comm₄"], - ["docBlame", "CategoryTheory.Triangulated.Octahedron.mem"], ["docBlame", "CategoryTheory.Triangulated.Octahedron.m₁"], ["docBlame", "CategoryTheory.Triangulated.Octahedron.m₃"], - ["docBlame", "FirstOrder.Language.ElementaryEmbedding.map_formula'"], ["docBlame", "FirstOrder.Language.ElementaryEmbedding.toFun"], - ["docBlame", "FirstOrder.Language.ElementarySubstructure.isElementary'"], ["docBlame", "FirstOrder.Language.ElementarySubstructure.toSubstructure"], - ["docBlame", "FirstOrder.Language.IsFraisse.FG"], - ["docBlame", "FirstOrder.Language.IsFraisse.amalgamation"], - ["docBlame", "FirstOrder.Language.IsFraisse.hereditary"], - ["docBlame", "FirstOrder.Language.IsFraisse.is_equiv_invariant"], - ["docBlame", "FirstOrder.Language.IsFraisse.is_essentially_countable"], - ["docBlame", "FirstOrder.Language.IsFraisse.is_nonempty"], - ["docBlame", "FirstOrder.Language.IsFraisse.jointEmbedding"], - ["docBlame", "FirstOrder.Language.IsFraisseLimit.age"], - ["docBlame", "FirstOrder.Language.IsFraisseLimit.ultrahomogeneous"], ["docBlame", "FirstOrder.Language.IsOrdered.leSymb"], ["docBlame", "FirstOrder.Language.LEquiv.invLHom"], - ["docBlame", "FirstOrder.Language.LEquiv.left_inv"], - ["docBlame", "FirstOrder.Language.LEquiv.right_inv"], ["docBlame", "FirstOrder.Language.LEquiv.toLHom"], ["docBlame", "FirstOrder.Language.LHom.onFunction"], ["docBlame", "FirstOrder.Language.LHom.onRelation"], - ["docBlame", "FirstOrder.Language.Prestructure.fun_equiv"], - ["docBlame", "FirstOrder.Language.Prestructure.rel_equiv"], ["docBlame", "FirstOrder.Language.Prestructure.toStructure"], ["docBlame", "FirstOrder.Language.Substructure.carrier"], - ["docBlame", "FirstOrder.Language.Substructure.fun_mem"], ["docBlame", "FirstOrder.Language.Term.relabel"], ["docBlame", "Lean.Elab.Command.irredDefLemma"], - ["docBlame", "Lean.Elab.Command.printPrefix"], - ["docBlame", "Lean.Elab.Tactic.mkDischargeWrapper"], - ["docBlame", "Lean.Environment.findRedundantImports.visit"], - ["docBlame", "Lean.Environment.importGraph.process"], ["docBlame", "Lean.Export.Alloc.map"], ["docBlame", "Lean.Export.Alloc.next"], ["docBlame", "Lean.Export.OfState.get"], @@ -2106,44 +1098,17 @@ ["docBlame", "Lean.MVarId.smartHCongr?.forSide"], ["docBlame", "Lean.MVarId.smartHCongr?.loop"], ["docBlame", "Lean.MVarId.userCongr?.forSide"], - ["docBlame", "Lean.Meta.DiscrTree.getElements"], - ["docBlame", "Lean.Meta.FindOptions.checkPrivate"], - ["docBlame", "Lean.Meta.FindOptions.stage1"], - ["docBlame", "Lean.Meta.Simp.mkCast"], - ["docBlame", "Lean.Meta.Simp.mkEqSymm"], - ["docBlame", "Lean.Meta.findCore.check"], - ["docBlame", "Lean.Meta.mkRichHCongr.doubleTelescope.loop"], - ["docBlame", "Lean.Meta.mkRichHCongr.withNewEqs.loop"], - ["docBlame", "Lean.NameMap.filter.process"], - ["docBlame", "Lean.NameMap.filterMap.process"], - ["docBlame", "Lean.NameMap.transitiveClosure.process"], ["docBlame", "Lean.Parser.Attr.higherOrder"], ["docBlame", "Lean.Parser.Tactic.applyCongr"], ["docBlame", "Mathlib.Command.Variable.completeBinders"], ["docBlame", "Mathlib.Deriving.Fintype.mkFintype"], ["docBlame", "Mathlib.Deriving.Fintype.mkFintypeInstanceHandler"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkAuxFunction"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkInstanceCmds"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkLocalInstanceLetDecls"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkMutualBlock"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkToExprBody"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkToExprHeader"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkToExprInstanceCmds"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkToExprInstanceHandler"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkToTypeExpr"], ["docBlame", "Mathlib.Meta.NormNum.proveNatFibAux"], ["docBlame", "Mathlib.Meta.Positivity.evalBernstein"], ["docBlame", "Mathlib.Meta.Positivity.evalIntCast"], ["docBlame", "Mathlib.Meta.Positivity.evalNatCast"], - ["docBlame", "Mathlib.Notation3.getExplicitArgIndices.collectIdxs"], - ["docBlame", "Mathlib.Notation3.mkExprMatcher.processFn"], - ["docBlame", "Mathlib.Prelude.Rename.addNameAlignment"], - ["docBlame", "Mathlib.Prelude.Rename.getRenameMap"], - ["docBlame", "Mathlib.Prelude.Rename.renameExtension"], ["docBlame", "Mathlib.ProjectionNotation.delabProjectionApp'.walkUp"], ["docBlame", "Mathlib.ProjectionNotation.pp.collapseStructureProjections"], - ["docBlame", "Mathlib.Tactic.CachedData.cache"], - ["docBlame", "Mathlib.Tactic.CachedData.pointer?"], ["docBlame", "Mathlib.Tactic.Conv.convLHS"], ["docBlame", "Mathlib.Tactic.Conv.convRHS"], ["docBlame", "Mathlib.Tactic.Conv.convRun_conv_"], @@ -2155,10 +1120,8 @@ ["docBlame", "Mathlib.Tactic.Find.tacticFind"], ["docBlame", "Mathlib.Tactic.GCongr.exact"], ["docBlame", "Mathlib.Tactic.GCongr.tacticGcongr_discharger"], - ["docBlame", "Mathlib.Tactic.LeftRight.leftRightMeta"], ["docBlame", "Mathlib.Tactic.LibrarySearch.apply?'"], ["docBlame", "Mathlib.Tactic.LibrarySearch.cachePath"], - ["docBlame", "Mathlib.Tactic.LibrarySearch.cachedData"], ["docBlame", "Mathlib.Tactic.LibrarySearch.exact!?"], ["docBlame", "Mathlib.Tactic.LibrarySearch.exact?"], ["docBlame", "Mathlib.Tactic.LibrarySearch.exact?!"], @@ -2167,76 +1130,24 @@ ["docBlame", "Mathlib.Tactic.LibrarySearch.«termExact?%»"], ["docBlame", "Mathlib.Tactic.Propose.proposeLemmas"], ["docBlame", "Mathlib.Tactic.Rewrites.cachePath"], - ["docBlame", "Mathlib.Tactic.Rewrites.cachedData"], - ["docBlame", "Mathlib.Tactic.Says.says"], ["docBlame", "Mathlib.Tactic.Widget.commutativeSquarePresenter"], ["docBlame", "Mathlib.Tactic.Widget.commutativeTrianglePresenter"], - ["docBlame", "Mathlib.Tactic.backtrack.processIndependentGoals"], ["docBlame", "Mathlib.Tactic.evalIntrov.intro1PStep"], ["docBlame", "Mathlib.Tactic.evalIntrov.introsDep"], - ["docBlame", "Mathlib.Tactic.optBinderIdent.name"], - ["docBlame", "MeasureTheory.Measure.FiniteSpanningSetsIn.finite"], ["docBlame", "MeasureTheory.Measure.FiniteSpanningSetsIn.set"], - ["docBlame", "MeasureTheory.Measure.FiniteSpanningSetsIn.set_mem"], - ["docBlame", "MeasureTheory.Measure.FiniteSpanningSetsIn.spanning"], - ["docBlame", - "MeasureTheory.Measure.HaveLebesgueDecomposition.lebesgue_decomposition"], - ["docBlame", "MeasureTheory.Measure.IsAddLeftInvariant.map_add_left_eq_self"], - ["docBlame", - "MeasureTheory.Measure.IsAddRightInvariant.map_add_right_eq_self"], - ["docBlame", "MeasureTheory.Measure.IsComplete.out'"], - ["docBlame", "MeasureTheory.Measure.IsInvInvariant.inv_eq_self"], - ["docBlame", "MeasureTheory.Measure.IsMulLeftInvariant.map_mul_left_eq_self"], - ["docBlame", - "MeasureTheory.Measure.IsMulRightInvariant.map_mul_right_eq_self"], - ["docBlame", "MeasureTheory.Measure.IsNegInvariant.neg_eq_self"], - ["docBlame", "MeasureTheory.Measure.IsOpenPosMeasure.open_pos"], - ["docBlame", "MeasureTheory.Measure.OuterRegular.outerRegular"], - ["docBlame", - "MeasureTheory.Measure.QuasiMeasurePreserving.absolutelyContinuous"], - ["docBlame", "MeasureTheory.Measure.QuasiMeasurePreserving.measurable"], - ["docBlame", "MeasureTheory.Measure.Regular.innerRegular"], - ["docBlame", "MeasureTheory.Measure.WeaklyRegular.innerRegular"], - ["docBlame", "Module.Baer.ExtensionOf.is_extension"], - ["docBlame", "Module.Baer.ExtensionOf.le"], ["docBlame", "Module.End.Eigenvalues.val"], - ["docBlame", "ModuleCat.Colimits.ColimitType.mk"], - ["docBlame", "Order.Ideal.IsPrime.compl_filter"], ["docBlame", "Order.Ideal.PrimePair.F"], ["docBlame", "Order.Ideal.PrimePair.I"], - ["docBlame", "Order.Ideal.PrimePair.isCompl_I_F"], - ["docBlame", "Order.PFilter.IsPrime.compl_ideal"], - ["docBlame", "Sat.Clause.reify.prop"], - ["docBlame", "Sat.Fmla.reify.prop"], - ["docBlame", "Sat.Fmla.subsumes.prop"], - ["docBlame", "Sat.Literal.reify.prop"], - ["docBlame", "Sat.Valuation.satisfies_fmla.prop"], - ["docBlame", "SimpleGraph.Walk.IsCircuit.ne_nil"], - ["docBlame", "SimpleGraph.Walk.IsCycle.support_nodup"], - ["docBlame", "SimpleGraph.Walk.IsPath.support_nodup"], - ["docBlame", "SimpleGraph.Walk.IsTrail.edges_nodup"], + ["docBlame", "SetTheory.PGame.State.l"], + ["docBlame", "SetTheory.PGame.State.r"], + ["docBlame", "SetTheory.PGame.State.turnBound"], ["docBlame", "SimplicialObject.Augmented.ExtraDegeneracy.s"], ["docBlame", "SimplicialObject.Augmented.ExtraDegeneracy.s'"], - ["docBlame", "SimplicialObject.Augmented.ExtraDegeneracy.s'_comp_ε"], - ["docBlame", "SimplicialObject.Augmented.ExtraDegeneracy.s_comp_δ"], - ["docBlame", "SimplicialObject.Augmented.ExtraDegeneracy.s_comp_δ₀"], - ["docBlame", "SimplicialObject.Augmented.ExtraDegeneracy.s_comp_σ"], - ["docBlame", "SimplicialObject.Augmented.ExtraDegeneracy.s₀_comp_δ₁"], - ["docBlame", "SimplicialObject.Split.Hom.F"], - ["docBlame", "SimplicialObject.Split.Hom.comm"], - ["docBlame", "SimplicialObject.Split.Hom.f"], - ["docBlame", "Stream'.WSeq.IsFinite.out"], - ["docBlame", "Stream'.WSeq.Productive.get?_terminates"], ["docBlame", "Tactic.Elementwise.elementwiseExpr.mkHomElementwise"], ["docBlame", "TopCat.GlueData.MkCore.J"], ["docBlame", "TopCat.GlueData.MkCore.U"], ["docBlame", "TopCat.GlueData.MkCore.V"], - ["docBlame", "TopCat.GlueData.MkCore.V_id"], - ["docBlame", "TopCat.GlueData.MkCore.cocycle"], ["docBlame", "TopCat.GlueData.MkCore.t"], - ["docBlame", "TopCat.GlueData.MkCore.t_id"], - ["docBlame", "TopCat.GlueData.MkCore.t_inter"], - ["docBlame", "TopCat.Presheaf.SubmonoidPresheaf.map"], ["docBlame", "TopCat.Presheaf.SubmonoidPresheaf.obj"], ["docBlame", "Turing.TM0.Cfg.Tape"], ["docBlame", "Turing.TM0.Cfg.q"], @@ -2246,25 +1157,15 @@ ["docBlame", "Turing.TM2.Cfg.l"], ["docBlame", "Turing.TM2.Cfg.stk"], ["docBlame", "Turing.TM2.Cfg.var"], - ["docBlame", "UpperHalfPlane.coe'"], - ["docBlame", "FirstOrder.Language.LHom.Injective.onFunction"], - ["docBlame", "FirstOrder.Language.LHom.Injective.onRelation"], - ["docBlame", "FirstOrder.Language.LHom.IsExpansionOn.map_onFunction"], - ["docBlame", "FirstOrder.Language.LHom.IsExpansionOn.map_onRelation"], - ["docBlame", "FirstOrder.Language.Structure.CG.out"], - ["docBlame", "FirstOrder.Language.Structure.FG.out"], - ["docBlame", "FirstOrder.Language.Theory.CompleteType.isMaximal'"], - ["docBlame", "FirstOrder.Language.Theory.CompleteType.subset'"], ["docBlame", "FirstOrder.Language.Theory.CompleteType.toTheory"], - ["docBlame", "FirstOrder.Language.Theory.Model.realize_of_mem"], ["docBlame", "FirstOrder.Language.Theory.ModelType.Carrier"], - ["docBlame", "Lean.Meta.DiscrTree.Trie.getElements"], + ["docBlame", "Lean.Meta.mkRichHCongr.doubleTelescope.loop"], + ["docBlame", "Lean.Meta.mkRichHCongr.withNewEqs.loop"], ["docBlame", "Mathlib.Command.Variable.completeBinders'.isVariableAlias"], ["docBlame", "Mathlib.Command.Variable.elabVariables.extendScope"], ["docBlame", "Mathlib.Command.Variable.elabVariables.process"], ["docBlame", "Mathlib.Command.Variable.variable?.checkRedundant"], ["docBlame", "Mathlib.Command.Variable.variable?.maxSteps"], - ["docBlame", "Mathlib.Deriving.ToExpr.mkToExprBody.mkAlts"], ["docBlame", "Mathlib.Meta.NormNum.evalEq.intArm"], ["docBlame", "Mathlib.Meta.NormNum.evalEq.ratArm"], ["docBlame", "Mathlib.Meta.NormNum.evalLE.intArm"], @@ -2282,15 +1183,9 @@ ["docBlame", "Mathlib.Tactic.GCongr.GCongrLemma.mainSubgoals"], ["docBlame", "Mathlib.Tactic.GCongr.GCongrLemma.varyingArgs"], ["docBlame", "Mathlib.Tactic.Monotonicity.mono.side"], - ["docBlame", "Mathlib.Tactic.Rewrites.RewriteResult.name"], - ["docBlame", "Mathlib.Tactic.Rewrites.RewriteResult.result"], - ["docBlame", "Mathlib.Tactic.Rewrites.RewriteResult.symm"], - ["docBlame", "Mathlib.Tactic.Rewrites.RewriteResult.weight"], ["docBlame", "Mathlib.Tactic.Sat.buildReify.mkPS"], ["docBlame", "Mathlib.Tactic.Says.says.no_verify_in_CI"], ["docBlame", "Mathlib.Tactic.Says.says.verify"], - ["docBlame", "Mathlib.Tactic.SolveByElim.Config.backtracking"], - ["docBlame", "Mathlib.Tactic.SolveByElim.solveByElim.run"], ["docBlame", "Mathlib.Meta.NormNum.evalAdd.core.intArm"], ["docBlame", "Mathlib.Meta.NormNum.evalAdd.core.ratArm"], ["docBlame", "Mathlib.Meta.NormNum.evalMul.core.intArm"], diff --git a/scripts/noshake.json b/scripts/noshake.json new file mode 100644 index 0000000000000..e4e6ac1054eac --- /dev/null +++ b/scripts/noshake.json @@ -0,0 +1,282 @@ +{"ignoreImport": + ["Aesop", + "Init", + "Lean", + "Lean.Elab.ElabRules", + "Lean.Elab.Tactic.Config", + "Mathlib.Algebra.Invertible.Defs", + "Mathlib.AlgebraicGeometry.Restrict", + "Mathlib.AlgebraicTopology.DoldKan.Notations", + "Mathlib.CategoryTheory.Category.Init", + "Mathlib.Combinatorics.SimpleGraph.Init", + "Mathlib.Control.Traversable.Lemmas", + "Mathlib.Data.Matrix.Notation", + "Mathlib.Data.Matroid.Init", + "Mathlib.Data.Rat.Init", + "Mathlib.Data.Set.Basic", + "Mathlib.Data.Sym.Sym2.Init", + "Mathlib.Data.Vector.Basic", + "Mathlib.Geometry.Manifold.Instances.Real", + "Mathlib.Init.Align", + "Mathlib.Init.Data.Int.Basic", + "Mathlib.Init.Data.Nat.Notation", + "Mathlib.LinearAlgebra.AffineSpace.Basic", + "Mathlib.Mathport.Attributes", + "Mathlib.Mathport.Notation", + "Mathlib.Mathport.Rename", + "Mathlib.Probability.Notation", + "Mathlib.Tactic.Abel", + "Mathlib.Tactic.ApplyCongr", + "Mathlib.Tactic.ApplyFun", + "Mathlib.Tactic.ApplyWith", + "Mathlib.Tactic.Attr.Core", + "Mathlib.Tactic.Attr.Register", + "Mathlib.Tactic.Basic", + "Mathlib.Tactic.ByContra", + "Mathlib.Tactic.CancelDenoms", + "Mathlib.Tactic.Cases", + "Mathlib.Tactic.CasesM", + "Mathlib.Tactic.CategoryTheory.Coherence", + "Mathlib.Tactic.CategoryTheory.Elementwise", + "Mathlib.Tactic.CategoryTheory.Slice", + "Mathlib.Tactic.Choose", + "Mathlib.Tactic.Classical", + "Mathlib.Tactic.Clean", + "Mathlib.Tactic.Clear!", + "Mathlib.Tactic.ClearExcept", + "Mathlib.Tactic.Clear_", + "Mathlib.Tactic.Coe", + "Mathlib.Tactic.Common", + "Mathlib.Tactic.Congr!", + "Mathlib.Tactic.Congrm", + "Mathlib.Tactic.Constructor", + "Mathlib.Tactic.Continuity", + "Mathlib.Tactic.Contrapose", + "Mathlib.Tactic.Conv", + "Mathlib.Tactic.Convert", + "Mathlib.Tactic.Core", + "Mathlib.Tactic.DefEqTransformations", + "Mathlib.Tactic.DeriveFintype", + "Mathlib.Tactic.DeriveToExpr", + "Mathlib.Tactic.Eqns", + "Mathlib.Tactic.Existsi", + "Mathlib.Tactic.ExtendDoc", + "Mathlib.Tactic.ExtractGoal", + "Mathlib.Tactic.FBinop", + "Mathlib.Tactic.FailIfNoProgress", + "Mathlib.Tactic.FieldSimp", + "Mathlib.Tactic.FinCases", + "Mathlib.Tactic.Find", + "Mathlib.Tactic.GCongr", + "Mathlib.Tactic.GCongr.Core", + "Mathlib.Tactic.GeneralizeProofs", + "Mathlib.Tactic.Group", + "Mathlib.Tactic.GuardHypNums", + "Mathlib.Tactic.HaveI", + "Mathlib.Tactic.Hint", + "Mathlib.Tactic.InferParam", + "Mathlib.Tactic.Inhabit", + "Mathlib.Tactic.IntervalCases", + "Mathlib.Tactic.IrreducibleDef", + "Mathlib.Tactic.Lemma", + "Mathlib.Tactic.LibrarySearch", + "Mathlib.Tactic.Lift", + "Mathlib.Tactic.LiftLets", + "Mathlib.Tactic.Linarith", + "Mathlib.Tactic.Linarith.Frontend", + "Mathlib.Tactic.Linarith.Lemmas", + "Mathlib.Tactic.LinearCombination", + "Mathlib.Tactic.Measurability", + "Mathlib.Tactic.MkIffOfInductiveProp", + "Mathlib.Tactic.ModCases", + "Mathlib.Tactic.Monotonicity", + "Mathlib.Tactic.Monotonicity.Attr", + "Mathlib.Tactic.NoncommRing", + "Mathlib.Tactic.Nontriviality", + "Mathlib.Tactic.NormNum", + "Mathlib.Tactic.NormNum.Core", + "Mathlib.Tactic.NormNum.Eq", + "Mathlib.Tactic.NormNum.Ineq", + "Mathlib.Tactic.NthRewrite", + "Mathlib.Tactic.PPWithUniv", + "Mathlib.Tactic.Peel", + "Mathlib.Tactic.Polyrith", + "Mathlib.Tactic.Positivity", + "Mathlib.Tactic.Positivity.Basic", + "Mathlib.Tactic.ProjectionNotation", + "Mathlib.Tactic.PushNeg", + "Mathlib.Tactic.Qify", + "Mathlib.Tactic.RSuffices", + "Mathlib.Tactic.Recover", + "Mathlib.Tactic.ReduceModChar.Ext", + "Mathlib.Tactic.Relation.Symm", + "Mathlib.Tactic.Relation.Trans", + "Mathlib.Tactic.Rename", + "Mathlib.Tactic.RenameBVar", + "Mathlib.Tactic.Replace", + "Mathlib.Tactic.Ring", + "Mathlib.Tactic.Ring.Basic", + "Mathlib.Tactic.RunCmd", + "Mathlib.Tactic.Says", + "Mathlib.Tactic.ScopedNS", + "Mathlib.Tactic.Set", + "Mathlib.Tactic.SetLike", + "Mathlib.Tactic.SimpIntro", + "Mathlib.Tactic.SimpRw", + "Mathlib.Tactic.Simps.Basic", + "Mathlib.Tactic.Simps.NotationClass", + "Mathlib.Tactic.SplitIfs", + "Mathlib.Tactic.Spread", + "Mathlib.Tactic.Substs", + "Mathlib.Tactic.SuppressCompilation", + "Mathlib.Tactic.SwapVar", + "Mathlib.Tactic.TFAE", + "Mathlib.Tactic.Tauto", + "Mathlib.Tactic.TermCongr", + "Mathlib.Tactic.ToAdditive", + "Mathlib.Tactic.ToExpr", + "Mathlib.Tactic.ToLevel", + "Mathlib.Tactic.Trace", + "Mathlib.Tactic.TypeCheck", + "Mathlib.Tactic.TypeStar", + "Mathlib.Tactic.Use", + "Mathlib.Tactic.WLOG", + "Mathlib.Tactic.Zify", + "Mathlib.Topology.Sheaves.Init", + "Mathlib.Util.AssertExists", + "Mathlib.Util.CompileInductive", + "Mathlib.Util.Delaborators", + "Mathlib.Util.Syntax", + "Mathlib.Util.Tactic", + "Mathlib.Util.WhatsNew", + "Mathlib.Util.WithWeakNamespace", + "Qq", + "Std.Classes.SetNotation", + "Std.CodeAction", + "Std.Data.Fin.Basic", + "Std.Data.Json", + "Std.Tactic.Alias", + "Std.Tactic.Basic", + "Std.Tactic.Change", + "Std.Tactic.Ext", + "Std.Tactic.Ext.Attr", + "Std.Tactic.GuardMsgs", + "Std.Tactic.HaveI", + "Std.Tactic.LeftRight", + "Std.Tactic.Lint", + "Std.Tactic.Lint.Misc", + "Std.Tactic.NoMatch", + "Std.Tactic.NormCast", + "Std.Tactic.NormCast.Lemmas", + "Std.Tactic.OpenPrivate", + "Std.Tactic.RCases", + "Std.Tactic.Relation.Rfl", + "Std.Tactic.Relation.Symm", + "Std.Tactic.Replace", + "Std.Tactic.Simpa", + "Std.Tactic.SolveByElim", + "Std.Tactic.SolveByElim.Backtrack", + "Std.Util.LibraryNote", + "Std.Util.ProofWanted", + "Std.Util.TermUnsafe"], + "ignoreAll": ["Std.Tactic.Basic", "Mathlib.Mathport.Syntax"], + "ignore": + {"Std.Tactic.OpenPrivate": ["Lean.Parser.Module"], + "Std.Tactic.Omega.OmegaM": ["Std.Tactic.Omega.Int"], + "Std.Tactic.Omega.Frontend": ["Std.Tactic.Omega.Logic"], + "Std.Tactic.NormCast": ["Std.Classes.Cast"], + "Std.Tactic.GuardMsgs": ["Std.CodeAction.Basic"], + "Std.Tactic.ByCases": ["Lean.Parser.Tactic"], + "Std.Linter.UnreachableTactic": ["Std.Tactic.Unreachable"], + "Std.Data.String.Lemmas": ["Std.Data.String.Basic"], + "Std.Data.List.Basic": ["Std.Data.Option.Init.Lemmas"], + "Std.Data.Json": ["Lean.Data.Json.FromToJson"], + "Std.Data.Array.Init.Lemmas": ["Std.Data.Fin.Init.Lemmas"], + "Std.CodeAction.Misc": ["Lean.Elab.BuiltinNotation", "Lean.Elab.BuiltinTerm"], + "Std.CodeAction.Basic": + ["Lean.Elab.BuiltinNotation", "Lean.Elab.BuiltinTerm"], + "Std.Classes.SetNotation": ["Std.Util.ExtendedBinder"], + "Mathlib.Topology.Sheaves.Forget": ["Mathlib.Algebra.Category.Ring.Limits"], + "Mathlib.Topology.Category.UniformSpace": + ["Mathlib.CategoryTheory.Monad.Limits"], + "Mathlib.Topology.Algebra.Nonarchimedean.AdicTopology": + ["Mathlib.Topology.Algebra.UniformRing"], + "Mathlib.Tactic.Widget.SelectPanelUtils": + ["ProofWidgets.Component.OfRpcMethod"], + "Mathlib.Tactic.Widget.CommDiag": ["Mathlib.CategoryTheory.Category.Basic"], + "Mathlib.Tactic.Use": ["Std.Logic"], + "Mathlib.Tactic.TypeStar": ["Std"], + "Mathlib.Tactic.TermCongr": ["Mathlib.Logic.Basic"], + "Mathlib.Tactic.Tauto": ["Mathlib.Logic.Basic"], + "Mathlib.Tactic.TFAE": ["Mathlib.Data.List.TFAE"], + "Mathlib.Tactic.Rewrites": ["Mathlib.Init.Core"], + "Mathlib.Tactic.ReduceModChar": + ["Mathlib.Data.ZMod.Basic", "Mathlib.RingTheory.Polynomial.Basic"], + "Mathlib.Tactic.ProxyType": ["Mathlib.Logic.Equiv.Defs"], + "Mathlib.Tactic.ProdAssoc": ["Mathlib.Logic.Equiv.Defs"], + "Mathlib.Tactic.Positivity.Basic": + ["Mathlib.Algebra.Order.Field.Power", + "Mathlib.Data.Nat.Factorial.Basic", + "Mathlib.Data.Rat.Cast.Order"], + "Mathlib.Tactic.NormNum.Ineq": + ["Mathlib.Algebra.Order.Field.Defs", "Mathlib.Algebra.Order.Monoid.WithTop"], + "Mathlib.Tactic.NormNum.BigOperators": ["Mathlib.Data.List.FinRange"], + "Mathlib.Tactic.Nontriviality.Core": ["Mathlib.Logic.Nontrivial.Basic"], + "Mathlib.Tactic.MoveAdd": + ["Mathlib.Algebra.Group.Basic", "Mathlib.Init.Order.LinearOrder"], + "Mathlib.Tactic.Measurability": ["Mathlib.Tactic.Measurability.Init"], + "Mathlib.Tactic.Lemma": ["Lean.Parser.Command"], + "Mathlib.Tactic.IrreducibleDef": ["Mathlib.Data.Subtype"], + "Mathlib.Tactic.Group": ["Mathlib.Algebra.Group.Commutator"], + "Mathlib.Tactic.GCongr.Core": ["Mathlib.Init.Order.Defs"], + "Mathlib.Tactic.FinCases": ["Mathlib.Data.Fintype.Basic"], + "Mathlib.Tactic.DeriveFintype": + ["Mathlib.Data.Fintype.Basic", + "Mathlib.Data.Fintype.Sigma", + "Mathlib.Data.Fintype.Sum"], + "Mathlib.Tactic.Continuity": ["Mathlib.Tactic.Continuity.Init"], + "Mathlib.Tactic.Choose": ["Mathlib.Logic.Function.Basic"], + "Mathlib.Tactic.CategoryTheory.Slice": + ["Mathlib.CategoryTheory.Category.Basic"], + "Mathlib.Tactic.CategoryTheory.Reassoc": + ["Mathlib.CategoryTheory.Functor.Basic"], + "Mathlib.Tactic.Basic": ["Std"], + "Mathlib.Tactic.Attr.Register": ["Lean.Meta.Tactic.Simp.SimpTheorems"], + "Mathlib.RingTheory.PolynomialAlgebra": ["Mathlib.Data.Matrix.DMatrix"], + "Mathlib.RingTheory.MvPolynomial.Homogeneous": + ["Mathlib.Algebra.DirectSum.Internal"], + "Mathlib.Probability.Notation": + ["Mathlib.MeasureTheory.Decomposition.Lebesgue", + "Mathlib.MeasureTheory.Function.ConditionalExpectation.Basic"], + "Mathlib.Order.Filter.Basic": ["Mathlib.Control.Traversable.Instances"], + "Mathlib.MeasureTheory.Measure.Regular": + ["Mathlib.Topology.Metrizable.Urysohn"], + "Mathlib.Logic.Nontrivial.Defs": ["Mathlib.Init.Logic"], + "Mathlib.Logic.Equiv.Defs": ["Mathlib.Init.Data.Bool.Lemmas"], + "Mathlib.LinearAlgebra.Matrix.Transvection": ["Mathlib.Data.Matrix.DMatrix"], + "Mathlib.LinearAlgebra.AffineSpace.Basic": ["Mathlib.Algebra.AddTorsor"], + "Mathlib.Init.Data.Nat.GCD": ["Std.Data.Nat.Gcd"], + "Mathlib.Init.Core": ["Std.Classes.Dvd"], + "Mathlib.Geometry.Manifold.Sheaf.Smooth": + ["Mathlib.CategoryTheory.Sites.Whiskering"], + "Mathlib.Data.Vector.Basic": ["Mathlib.Control.Applicative"], + "Mathlib.Data.Rat.Init": ["Std.Data.Rat.Basic"], + "Mathlib.Data.Multiset.Bind": ["Mathlib.GroupTheory.GroupAction.Defs"], + "Mathlib.Data.List.EditDistance.Defs": ["Mathlib.Data.Nat.Basic"], + "Mathlib.Data.List.Basic": ["Mathlib.Init.Core"], + "Mathlib.Control.Traversable.Instances": ["Mathlib.Control.Applicative"], + "Mathlib.Control.Monad.Basic": ["Mathlib.Init.Control.Lawful"], + "Mathlib.Control.Basic": ["Mathlib.Init.Function"], + "Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits": + ["Mathlib.CategoryTheory.Limits.Shapes.Pullbacks"], + "Mathlib.Analysis.Complex.UpperHalfPlane.Basic": + ["Mathlib.Data.Fintype.Parity"], + "Mathlib.AlgebraicTopology.DoldKan.Notations": + ["Mathlib.AlgebraicTopology.AlternatingFaceMapComplex"], + "Mathlib.Algebra.Ring.CentroidHom": ["Mathlib.Algebra.Algebra.Basic"], + "Mathlib.Algebra.Order.Ring.Defs": + ["Mathlib.Algebra.Order.Monoid.WithZero.Defs"], + "Mathlib.Algebra.Module.LinearMap": ["Mathlib.Algebra.Star.Basic"], + "Mathlib.Algebra.Homology.ModuleCat": ["Mathlib.Algebra.Homology.Homotopy"], + "Mathlib.Algebra.Category.Ring.Basic": + ["Mathlib.CategoryTheory.ConcreteCategory.ReflectsIso"]}} \ No newline at end of file diff --git a/scripts/style-exceptions.txt b/scripts/style-exceptions.txt index 9334e4a13a11d..cd4c11d47dbfc 100644 --- a/scripts/style-exceptions.txt +++ b/scripts/style-exceptions.txt @@ -1,130 +1,174 @@ -Mathlib/Algebra/Ring/Basic.lean : line 0 : ERR_COP : Malformed or missing copyright header -Mathlib/Algebra/Ring/Basic.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Algebra/Ring/Basic.lean : line 12 : ERR_MOD : Module docstring missing, or too late -Mathlib/Algebra/Ring/Basic.lean : line 2 : ERR_COP : Malformed or missing copyright header -Mathlib/Algebra/Ring/Basic.lean : line 3 : ERR_COP : Malformed or missing copyright header -Mathlib/Algebra/Ring/Basic.lean : line 4 : ERR_COP : Malformed or missing copyright header -Mathlib/Algebra/Ring/Basic.lean : line 5 : ERR_COP : Malformed or missing copyright header -Mathlib/Algebra/Ring/Basic.lean : line 7 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Array/Basic.lean : line 0 : ERR_COP : Malformed or missing copyright header +Mathlib/Algebra/Algebra/Subalgebra/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1511 lines, try to split it up +Mathlib/Algebra/BigOperators/Basic.lean : line 1 : ERR_NUM_LIN : 2800 file contains 2675 lines, try to split it up +Mathlib/Algebra/Lie/Submodule.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1528 lines, try to split it up +Mathlib/Algebra/MonoidAlgebra/Basic.lean : line 1 : ERR_NUM_LIN : 2300 file contains 2158 lines, try to split it up +Mathlib/Algebra/Order/Floor.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1822 lines, try to split it up +Mathlib/Algebra/Order/Monoid/Lemmas.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1709 lines, try to split it up +Mathlib/Algebra/Quaternion.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1509 lines, try to split it up +Mathlib/Analysis/Asymptotics/Asymptotics.lean : line 1 : ERR_NUM_LIN : 2500 file contains 2306 lines, try to split it up +Mathlib/Analysis/Calculus/ContDiff/Basic.lean : line 1 : ERR_NUM_LIN : 2300 file contains 2111 lines, try to split it up +Mathlib/Analysis/Calculus/ContDiff/Defs.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1728 lines, try to split it up +Mathlib/Analysis/Convolution.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1545 lines, try to split it up +Mathlib/Analysis/InnerProductSpace/Basic.lean : line 1 : ERR_NUM_LIN : 2500 file contains 2367 lines, try to split it up +Mathlib/Analysis/Normed/Group/Basic.lean : line 1 : ERR_NUM_LIN : 3000 file contains 2815 lines, try to split it up +Mathlib/Analysis/NormedSpace/OperatorNorm.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2033 lines, try to split it up +Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean : line 1 : ERR_NUM_LIN : 2300 file contains 2118 lines, try to split it up +Mathlib/CategoryTheory/Limits/Shapes/Pullbacks.lean : line 1 : ERR_NUM_LIN : 2900 file contains 2728 lines, try to split it up +Mathlib/Combinatorics/SimpleGraph/Basic.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1625 lines, try to split it up +Mathlib/Combinatorics/SimpleGraph/Connectivity.lean : line 1 : ERR_NUM_LIN : 2800 file contains 2653 lines, try to split it up +Mathlib/Computability/Primrec.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1568 lines, try to split it up +Mathlib/Computability/TMToPartrec.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2069 lines, try to split it up +Mathlib/Computability/TuringMachine.lean : line 1 : ERR_NUM_LIN : 3000 file contains 2821 lines, try to split it up Mathlib/Data/Array/Basic.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Array/Basic.lean : line 2 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Array/Basic.lean : line 4 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Array/Basic.lean : line 4 : ERR_MOD : Module docstring missing, or too late +Mathlib/Data/Array/Basic.lean : line 1 : ERR_COP : Malformed or missing copyright header +Mathlib/Data/Array/Basic.lean : line 3 : ERR_COP : Malformed or missing copyright header +Mathlib/Data/Array/Basic.lean : line 3 : ERR_MOD : Module docstring missing, or too late Mathlib/Data/BinaryHeap.lean : line 8 : ERR_MOD : Module docstring missing, or too late -Mathlib/Data/ByteArray.lean : line 0 : ERR_COP : Malformed or missing copyright header +Mathlib/Data/ByteArray.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Data/ByteArray.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Data/ByteArray.lean : line 2 : ERR_COP : Malformed or missing copyright header Mathlib/Data/ByteArray.lean : line 3 : ERR_COP : Malformed or missing copyright header Mathlib/Data/ByteArray.lean : line 5 : ERR_COP : Malformed or missing copyright header Mathlib/Data/ByteArray.lean : line 5 : ERR_MOD : Module docstring missing, or too late -Mathlib/Data/Fin/Basic.lean : line 0 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Fin/Basic.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Fin/Basic.lean : line 2 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Fin/Basic.lean : line 3 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Fin/Basic.lean : line 4 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Fin/Basic.lean : line 5 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Fin/Basic.lean : line 7 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Fin/Basic.lean : line 7 : ERR_MOD : Module docstring missing, or too late -Mathlib/Data/Int/Basic.lean : line 235 : ERR_LIN : Line has more than 100 characters -Mathlib/Data/Int/Basic.lean : line 263 : ERR_LIN : Line has more than 100 characters -Mathlib/Data/Int/Basic.lean : line 269 : ERR_LIN : Line has more than 100 characters -Mathlib/Data/Int/Basic.lean : line 283 : ERR_LIN : Line has more than 100 characters -Mathlib/Data/Int/Basic.lean : line 286 : ERR_LIN : Line has more than 100 characters -Mathlib/Data/List/Basic.lean : line 0 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 10 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 10 : ERR_MOD : Module docstring missing, or too late -Mathlib/Data/List/Basic.lean : line 2 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 3 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 4 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 5 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 6 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 7 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/List/Basic.lean : line 8 : ERR_COP : Malformed or missing copyright header +Mathlib/Data/Complex/Exponential.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2046 lines, try to split it up +Mathlib/Data/DFinsupp/Basic.lean : line 1 : ERR_NUM_LIN : 2500 file contains 2395 lines, try to split it up +Mathlib/Data/ENNReal/Basic.lean : line 1 : ERR_NUM_LIN : 2900 file contains 2716 lines, try to split it up +Mathlib/Data/Fin/Basic.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2010 lines, try to split it up +Mathlib/Data/Finset/Basic.lean : line 1 : ERR_NUM_LIN : 4100 file contains 3992 lines, try to split it up +Mathlib/Data/Finset/Lattice.lean : line 1 : ERR_NUM_LIN : 2400 file contains 2240 lines, try to split it up +Mathlib/Data/Finset/Pointwise.lean : line 1 : ERR_NUM_LIN : 2700 file contains 2550 lines, try to split it up +Mathlib/Data/Finsupp/Basic.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1956 lines, try to split it up +Mathlib/Data/List/Basic.lean : line 1 : ERR_NUM_LIN : 4600 file contains 4457 lines, try to split it up Mathlib/Data/List/Card.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Data/List/Card.lean : line 12 : ERR_MOD : Module docstring missing, or too late -Mathlib/Data/Nat/Basic.lean : line 0 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Nat/Basic.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Nat/Basic.lean : line 2 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Nat/Basic.lean : line 3 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Nat/Basic.lean : line 4 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Nat/Basic.lean : line 5 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Nat/Basic.lean : line 6 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Nat/Basic.lean : line 8 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/Nat/Basic.lean : line 8 : ERR_MOD : Module docstring missing, or too late +Mathlib/Data/Matrix/Basic.lean : line 1 : ERR_NUM_LIN : 2900 file contains 2715 lines, try to split it up +Mathlib/Data/Multiset/Basic.lean : line 1 : ERR_NUM_LIN : 3300 file contains 3196 lines, try to split it up +Mathlib/Data/MvPolynomial/Basic.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1705 lines, try to split it up +Mathlib/Data/Num/Lemmas.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1771 lines, try to split it up +Mathlib/Data/Ordmap/Ordset.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1795 lines, try to split it up +Mathlib/Data/Polynomial/Degree/Definitions.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1689 lines, try to split it up +Mathlib/Data/Polynomial/RingDivision.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1569 lines, try to split it up Mathlib/Data/QPF/Multivariate/Basic.lean : line 75 : ERR_LIN : Line has more than 100 characters -Mathlib/Data/String/Defs.lean : line 0 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/String/Defs.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/String/Defs.lean : line 3 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/String/Defs.lean : line 3 : ERR_MOD : Module docstring missing, or too late -Mathlib/Data/String/Lemmas.lean : line 0 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/String/Lemmas.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/String/Lemmas.lean : line 2 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/String/Lemmas.lean : line 4 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/String/Lemmas.lean : line 4 : ERR_MOD : Module docstring missing, or too late -Mathlib/Data/UInt.lean : line 0 : ERR_COP : Malformed or missing copyright header +Mathlib/Data/Seq/WSeq.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1825 lines, try to split it up +Mathlib/Data/Set/Basic.lean : line 1 : ERR_NUM_LIN : 3100 file contains 2991 lines, try to split it up +Mathlib/Data/Set/Finite.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1768 lines, try to split it up +Mathlib/Data/Set/Function.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1858 lines, try to split it up +Mathlib/Data/Set/Image.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1613 lines, try to split it up +Mathlib/Data/Set/Intervals/Basic.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1970 lines, try to split it up +Mathlib/Data/Set/Lattice.lean : line 1 : ERR_NUM_LIN : 2500 file contains 2388 lines, try to split it up +Mathlib/Data/String/Lemmas.lean : line 9 : ERR_MOD : Module docstring missing, or too late +Mathlib/Data/UInt.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Data/UInt.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Data/UInt.lean : line 2 : ERR_COP : Malformed or missing copyright header Mathlib/Data/UInt.lean : line 3 : ERR_COP : Malformed or missing copyright header Mathlib/Data/UInt.lean : line 4 : ERR_COP : Malformed or missing copyright header Mathlib/Data/UInt.lean : line 5 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/UInt.lean : line 7 : ERR_COP : Malformed or missing copyright header -Mathlib/Data/UInt.lean : line 7 : ERR_MOD : Module docstring missing, or too late -Mathlib/Data/UnionFind.lean : line 10 : ERR_MOD : Module docstring missing, or too late -Mathlib/Init/Algebra/Functions.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Init/Data/Int/Basic.lean : line 13 : ERR_MOD : Module docstring missing, or too late -Mathlib/Init/Data/Nat/Basic.lean : line 7 : ERR_MOD : Module docstring missing, or too late -Mathlib/Init/Data/Nat/Lemmas.lean : line 10 : ERR_MOD : Module docstring missing, or too late -Mathlib/Init/Function.lean : line 7 : ERR_MOD : Module docstring missing, or too late -Mathlib/Init/Logic.lean : line 16 : ERR_MOD : Module docstring missing, or too late -Mathlib/Init/Meta/WellFoundedTactics.lean : line 11 : ERR_MOD : Module docstring missing, or too late +Mathlib/Data/UInt.lean : line 6 : ERR_COP : Malformed or missing copyright header +Mathlib/Data/UInt.lean : line 8 : ERR_COP : Malformed or missing copyright header +Mathlib/Data/UInt.lean : line 8 : ERR_MOD : Module docstring missing, or too late +Mathlib/Data/UnionFind.lean : line 8 : ERR_MOD : Module docstring missing, or too late +Mathlib/FieldTheory/RatFunc.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1781 lines, try to split it up +Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1607 lines, try to split it up +Mathlib/GroupTheory/MonoidLocalization.lean : line 1 : ERR_NUM_LIN : 2300 file contains 2153 lines, try to split it up +Mathlib/GroupTheory/Perm/Cycle/Basic.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1980 lines, try to split it up +Mathlib/GroupTheory/Subgroup/Basic.lean : line 1 : ERR_NUM_LIN : 4000 file contains 3878 lines, try to split it up +Mathlib/GroupTheory/Submonoid/Operations.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1561 lines, try to split it up +Mathlib/Init/Data/Int/Basic.lean : line 12 : ERR_MOD : Module docstring missing, or too late +Mathlib/Init/Data/Nat/Basic.lean : line 10 : ERR_MOD : Module docstring missing, or too late +Mathlib/Init/Data/Nat/Lemmas.lean : line 12 : ERR_MOD : Module docstring missing, or too late +Mathlib/Init/Logic.lean : line 18 : ERR_MOD : Module docstring missing, or too late +Mathlib/Init/Meta/WellFoundedTactics.lean : line 13 : ERR_MOD : Module docstring missing, or too late Mathlib/Lean/Exception.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Lean/Exception.lean : line 4 : ERR_AUT : Authors line should look like: 'Authors: Jean Dupont, Иван Иванович Иванов' -Mathlib/Lean/Exception.lean : line 7 : ERR_MOD : Module docstring missing, or too late +Mathlib/Lean/Exception.lean : line 8 : ERR_MOD : Module docstring missing, or too late Mathlib/Lean/Expr/ReplaceRec.lean : line 12 : ERR_MOD : Module docstring missing, or too late Mathlib/Lean/LocalContext.lean : line 8 : ERR_MOD : Module docstring missing, or too late -Mathlib/Logic/Equiv/PartialEquiv.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Logic/Equiv/PartialEquiv.lean : line 12 : ERR_MOD : Module docstring missing, or too late -Mathlib/Logic/Equiv/PartialEquiv.lean : line 4 : ERR_AUT : Authors line should look like: 'Authors: Jean Dupont, Иван Иванович Иванов' -Mathlib/Logic/Equiv/MfldSimpsAttr.lean : line 1 : ERR_COP : Malformed or missing copyright header -Mathlib/Logic/Equiv/MfldSimpsAttr.lean : line 4 : ERR_AUT : Authors line should look like: 'Authors: Jean Dupont, Иван Иванович Иванов' -Mathlib/Logic/Equiv/MfldSimpsAttr.lean : line 9 : ERR_MOD : Module docstring missing, or too late +Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1900 lines, try to split it up +Mathlib/LinearAlgebra/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1522 lines, try to split it up +Mathlib/LinearAlgebra/Basis.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1646 lines, try to split it up +Mathlib/LinearAlgebra/Dual.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1847 lines, try to split it up +Mathlib/LinearAlgebra/LinearIndependent.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1537 lines, try to split it up +Mathlib/LinearAlgebra/Multilinear/Basic.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1819 lines, try to split it up +Mathlib/Logic/Equiv/Basic.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2065 lines, try to split it up Mathlib/Mathport/Attributes.lean : line 8 : ERR_MOD : Module docstring missing, or too late Mathlib/Mathport/Rename.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Mathport/Syntax.lean : line 74 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Abstract.lean : line 8 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/ApplyWith.lean : line 0 : ERR_COP : Malformed or missing copyright header +Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean : line 1 : ERR_NUM_LIN : 2500 file contains 2362 lines, try to split it up +Mathlib/MeasureTheory/Function/L1Space.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1549 lines, try to split it up +Mathlib/MeasureTheory/Function/LpSeminorm.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1708 lines, try to split it up +Mathlib/MeasureTheory/Function/LpSpace.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1956 lines, try to split it up +Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean : line 1 : ERR_NUM_LIN : 2300 file contains 2148 lines, try to split it up +Mathlib/MeasureTheory/Integral/Bochner.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2010 lines, try to split it up +Mathlib/MeasureTheory/Integral/FundThmCalculus.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1550 lines, try to split it up +Mathlib/MeasureTheory/Integral/Lebesgue.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1851 lines, try to split it up +Mathlib/MeasureTheory/Integral/SetToL1.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1817 lines, try to split it up +Mathlib/MeasureTheory/MeasurableSpace/Basic.lean : line 1 : ERR_NUM_LIN : 2400 file contains 2250 lines, try to split it up +Mathlib/MeasureTheory/Measure/MeasureSpace.lean : line 1 : ERR_NUM_LIN : 2300 file contains 2191 lines, try to split it up +Mathlib/MeasureTheory/Measure/OuterMeasure.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1785 lines, try to split it up +Mathlib/MeasureTheory/Measure/Typeclasses.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1564 lines, try to split it up +Mathlib/Order/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1547 lines, try to split it up +Mathlib/Order/Bounds/Basic.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1714 lines, try to split it up +Mathlib/Order/CompleteLattice.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2091 lines, try to split it up +Mathlib/Order/ConditionallyCompleteLattice/Basic.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1727 lines, try to split it up +Mathlib/Order/Filter/AtTopBot.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2068 lines, try to split it up +Mathlib/Order/Filter/Basic.lean : line 1 : ERR_NUM_LIN : 3500 file contains 3373 lines, try to split it up +Mathlib/Order/Hom/Lattice.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1840 lines, try to split it up +Mathlib/Order/Lattice.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1541 lines, try to split it up +Mathlib/Order/LiminfLimsup.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1504 lines, try to split it up +Mathlib/Order/LocallyFinite.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1534 lines, try to split it up +Mathlib/Order/SuccPred/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1560 lines, try to split it up +Mathlib/Order/UpperLower/Basic.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2019 lines, try to split it up +Mathlib/RingTheory/FractionalIdeal/Basic.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1691 lines, try to split it up +Mathlib/RingTheory/HahnSeries.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1835 lines, try to split it up +Mathlib/RingTheory/Ideal/Operations.lean : line 1 : ERR_NUM_LIN : 2600 file contains 2414 lines, try to split it up +Mathlib/RingTheory/PowerSeries/Basic.lean : line 1 : ERR_NUM_LIN : 3000 file contains 2865 lines, try to split it up +Mathlib/RingTheory/Subring/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1546 lines, try to split it up +Mathlib/RingTheory/UniqueFactorizationDomain.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2066 lines, try to split it up +Mathlib/SetTheory/Cardinal/Basic.lean : line 1 : ERR_NUM_LIN : 2700 file contains 2551 lines, try to split it up +Mathlib/SetTheory/Cardinal/Ordinal.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1649 lines, try to split it up +Mathlib/SetTheory/Game/PGame.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1926 lines, try to split it up +Mathlib/SetTheory/Ordinal/Arithmetic.lean : line 1 : ERR_NUM_LIN : 2700 file contains 2593 lines, try to split it up +Mathlib/SetTheory/Ordinal/Basic.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1606 lines, try to split it up +Mathlib/SetTheory/ZFC/Basic.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1805 lines, try to split it up +Mathlib/Tactic/ApplyWith.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Tactic/ApplyWith.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Tactic/ApplyWith.lean : line 2 : ERR_COP : Malformed or missing copyright header -Mathlib/Tactic/ApplyWith.lean : line 4 : ERR_COP : Malformed or missing copyright header -Mathlib/Tactic/ApplyWith.lean : line 4 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Basic.lean : line 11 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/ApplyWith.lean : line 3 : ERR_COP : Malformed or missing copyright header +Mathlib/Tactic/ApplyWith.lean : line 5 : ERR_COP : Malformed or missing copyright header +Mathlib/Tactic/ApplyWith.lean : line 5 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/Basic.lean : line 13 : ERR_MOD : Module docstring missing, or too late Mathlib/Tactic/ByContra.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Tactic/ByContra.lean : line 4 : ERR_AUT : Authors line should look like: 'Authors: Jean Dupont, Иван Иванович Иванов' -Mathlib/Tactic/ByContra.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/ClearExcept.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Coe.lean : line 9 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/ByContra.lean : line 8 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/ClearExcept.lean : line 8 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/Coe.lean : line 8 : ERR_MOD : Module docstring missing, or too late Mathlib/Tactic/Constructor.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Core.lean : line 10 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Existsi.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Expect.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Have.lean : line 10 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/LeftRight.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/NormCast/Tactic.lean : line 13 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/PrintPrefix.lean : line 9 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/PushNeg.lean : line 13 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Recover.lean : line 10 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/Rename.lean : line 9 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/Existsi.lean : line 7 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/PushNeg.lean : line 14 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/Recover.lean : line 9 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/Rename.lean : line 8 : ERR_MOD : Module docstring missing, or too late Mathlib/Tactic/RenameBVar.lean : line 10 : ERR_MOD : Module docstring missing, or too late Mathlib/Tactic/Replace.lean : line 9 : ERR_MOD : Module docstring missing, or too late Mathlib/Tactic/Set.lean : line 4 : ERR_AUT : Authors line should look like: 'Authors: Jean Dupont, Иван Иванович Иванов' -Mathlib/Tactic/Set.lean : line 9 : ERR_MOD : Module docstring missing, or too late +Mathlib/Tactic/Set.lean : line 8 : ERR_MOD : Module docstring missing, or too late Mathlib/Tactic/SimpRw.lean : line 9 : ERR_MOD : Module docstring missing, or too late Mathlib/Tactic/Substs.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Tactic/Substs.lean : line 4 : ERR_AUT : Authors line should look like: 'Authors: Jean Dupont, Иван Иванович Иванов' Mathlib/Tactic/Substs.lean : line 8 : ERR_MOD : Module docstring missing, or too late -Mathlib/Tactic/TypeCheck.lean : line 0 : ERR_COP : Malformed or missing copyright header +Mathlib/Tactic/TypeCheck.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Tactic/TypeCheck.lean : line 1 : ERR_COP : Malformed or missing copyright header Mathlib/Tactic/TypeCheck.lean : line 3 : ERR_COP : Malformed or missing copyright header Mathlib/Tactic/TypeCheck.lean : line 3 : ERR_MOD : Module docstring missing, or too late +Mathlib/Topology/Algebra/Group/Basic.lean : line 1 : ERR_NUM_LIN : 2400 file contains 2231 lines, try to split it up +Mathlib/Topology/Algebra/InfiniteSum/Basic.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1665 lines, try to split it up +Mathlib/Topology/Algebra/Module/Basic.lean : line 1 : ERR_NUM_LIN : 2900 file contains 2768 lines, try to split it up +Mathlib/Topology/Basic.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2072 lines, try to split it up +Mathlib/Topology/Category/Profinite/Nobeling.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1831 lines, try to split it up +Mathlib/Topology/Constructions.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1731 lines, try to split it up +Mathlib/Topology/ContinuousFunction/Bounded.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1649 lines, try to split it up +Mathlib/Topology/Instances/ENNReal.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1713 lines, try to split it up +Mathlib/Topology/MetricSpace/HausdorffDistance.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1543 lines, try to split it up +Mathlib/Topology/MetricSpace/PseudoMetric.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2098 lines, try to split it up +Mathlib/Topology/Order/Basic.lean : line 1 : ERR_NUM_LIN : 3100 file contains 2983 lines, try to split it up +Mathlib/Topology/PartialHomeomorph.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1513 lines, try to split it up +Mathlib/Topology/Separation.lean : line 1 : ERR_NUM_LIN : 2500 file contains 2306 lines, try to split it up +Mathlib/Topology/UniformSpace/Basic.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2018 lines, try to split it up diff --git a/test/ApplyAt.lean b/test/ApplyAt.lean index 7240ee54449a5..acfec22dda3de 100644 --- a/test/ApplyAt.lean +++ b/test/ApplyAt.lean @@ -1,6 +1,6 @@ import Mathlib.Tactic.ApplyAt import Mathlib.Algebra.Group.Basic -import Mathlib.Data.Nat.Basic +import Mathlib.Data.Real.Basic import Std.Tactic.GuardExpr example {α β : Type*} (f : α → β) (a : α) : β := by @@ -96,3 +96,13 @@ example {A B : Prop} (h : A ↔ B) : A → B := by intro hA apply h.mp at hA assumption + +example (a : ℝ) (h3: a + 1 = 0) : a = -1 := by + apply (congrArg (fun x => x - 1)) at h3 + simp at h3 + assumption + +example (a b : ℝ) (h : -a * b = 0) : a = 0 ∨ b = 0 := by + apply (congrArg (fun x => x / 1)) at h + simp at h + assumption diff --git a/test/CategoryTheory/Coherence.lean b/test/CategoryTheory/Coherence.lean index db562a9250fb7..f399b28409615 100644 --- a/test/CategoryTheory/Coherence.lean +++ b/test/CategoryTheory/Coherence.lean @@ -1,3 +1,5 @@ +import Mathlib.CategoryTheory.Monoidal.Free.Coherence +import Mathlib.CategoryTheory.Bicategory.Coherence import Mathlib.Tactic.CategoryTheory.Coherence open CategoryTheory diff --git a/test/CategoryTheory/Elementwise.lean b/test/CategoryTheory/Elementwise.lean index 43a8e8a9176ca..3f20709525115 100644 --- a/test/CategoryTheory/Elementwise.lean +++ b/test/CategoryTheory/Elementwise.lean @@ -10,7 +10,7 @@ open CategoryTheory set_option linter.existingAttributeWarning false in attribute [simp] Iso.hom_inv_id Iso.inv_hom_id IsIso.hom_inv_id IsIso.inv_hom_id -attribute [local instance] ConcreteCategory.funLike ConcreteCategory.hasCoeToSort +attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort @[elementwise] theorem ex1 [Category C] [ConcreteCategory C] (X : C) (f g h : X ⟶ X) (h' : g ≫ h = h ≫ g) : diff --git a/test/CommDiag.lean b/test/CommDiag.lean index 94473a468424b..bacdd7ff5daf6 100644 --- a/test/CommDiag.lean +++ b/test/CommDiag.lean @@ -1,4 +1,5 @@ import Mathlib.Tactic.Widget.CommDiag +import ProofWidgets.Component.Panel.SelectionPanel import ProofWidgets.Component.Panel.GoalTypePanel /-! ## Example use of commutative diagram widgets -/ diff --git a/test/Expr.lean b/test/Expr.lean index 43ede46c132f3..779a62164a0d9 100644 --- a/test/Expr.lean +++ b/test/Expr.lean @@ -42,6 +42,6 @@ run_cmd liftTermElabM <| do logInfo m!"new type: {t}" let d ← getConstInfo `bar logInfo m!"after: {d.value!}" - guard $ e == d.value! + guard <| e == d.value! end replaceRec diff --git a/test/ExtractGoal.lean b/test/ExtractGoal.lean index 3b2b5320a2c33..e8c1eab83dfda 100644 --- a/test/ExtractGoal.lean +++ b/test/ExtractGoal.lean @@ -1,5 +1,6 @@ import Mathlib.Tactic.ExtractGoal -import Mathlib.Data.Nat.Basic +import Mathlib.Init.Data.Nat.Lemmas +import Mathlib.Order.Basic set_option pp.unicode.fun true set_option autoImplicit true diff --git a/test/FunLike.lean b/test/FunLike.lean index 7598f24415be3..abc1d15eae413 100644 --- a/test/FunLike.lean +++ b/test/FunLike.lean @@ -1,6 +1,6 @@ import Mathlib.Data.FunLike.Basic -variable {F α β : Sort*} [i : FunLike F α fun _ ↦ β] (f : F) (a : α) +variable {F α β : Sort*} [i : FunLike F α β] (f : F) (a : α) /-- info: f a : β -/ #guard_msgs in #check f a diff --git a/test/ImplicitUniverses.lean b/test/ImplicitUniverses.lean index b7a8b604613a0..01782ba761cfe 100644 --- a/test/ImplicitUniverses.lean +++ b/test/ImplicitUniverses.lean @@ -1,4 +1,4 @@ -import Mathlib.Tactic.Basic +import Mathlib.Tactic.TypeStar import Mathlib.Tactic.SuccessIfFailWithMsg private axiom test_sorry : ∀ {α}, α diff --git a/test/Imports.lean b/test/Imports.lean deleted file mode 100644 index 636266cddb44e..0000000000000 --- a/test/Imports.lean +++ /dev/null @@ -1,21 +0,0 @@ -import Mathlib -import Mathlib.Util.Imports -import Mathlib.Util.WhatsNew - -open Lean Meta - -/-- -info: --/ -#guard_msgs in -#eval show MetaM _ from do - guard <| (← redundantImports).toArray = #[`Mathlib.Util.Imports, `Mathlib.Util.WhatsNew] - -/-- -info: -Found the following transitively redundant imports: -Mathlib.Util.Imports -Mathlib.Util.WhatsNew --/ -#guard_msgs in -#redundant_imports diff --git a/test/LibrarySearch/observe.lean b/test/LibrarySearch/observe.lean index 82da5ceff223a..09e5c74fa0558 100644 --- a/test/LibrarySearch/observe.lean +++ b/test/LibrarySearch/observe.lean @@ -1,6 +1,9 @@ import Mathlib.Tactic.Observe +import Std.Tactic.GuardMsgs +/-- info: Try this: have h : x + y = y + x := Nat.add_comm x y -/ +#guard_msgs in example (x y : Nat) : True := by - observe h : x + y = y + x + observe? h : x + y = y + x guard_hyp h : x + y = y + x trivial diff --git a/test/MLList.lean b/test/MLList.lean index 490d201c7691d..14c6040a87280 100644 --- a/test/MLList.lean +++ b/test/MLList.lean @@ -24,7 +24,7 @@ run_cmd Lean.Elab.Command.liftTermElabM do -- This is different from previous behaviour, where it just terminated the lazy list. -- Hence we must use `.takeAsList 11` here rather than `.force`. let x := ((MLList.fix F 10).takeAsList 11).run [] - guard $ x = some ([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + guard <| x = some ([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) example : ((MLList.fix F 10).takeAsList 4).run [] = some ([10, 9, 8, 7], [8, 9, 10]) := by native_decide @@ -39,7 +39,7 @@ def ll : MLList S Nat := (MLList.ofList [l1, l2]).join run_cmd Lean.Elab.Command.liftTermElabM do let x := ll.force.run [] - guard $ x = some ([0, 1, 2, 3, 4, 5], []) + guard <| x = some ([0, 1, 2, 3, 4, 5], []) def half_or_fail (n : Nat) : MetaM Nat := do guard (n % 2 = 0) @@ -49,7 +49,7 @@ run_cmd Lean.Elab.Command.liftTermElabM do let x : MLList MetaM Nat := MLList.range let y := x.filterMapM fun n => try? <| half_or_fail n let z ← y.takeAsList 10 - guard $ z.length = 10 + guard <| z.length = 10 run_cmd Lean.Elab.Command.liftTermElabM do let R : MLList MetaM Nat := MLList.range @@ -58,12 +58,12 @@ run_cmd Lean.Elab.Command.liftTermElabM do pure n let n ← R.takeAsList 5 let m ← S.head - guard $ n = [0,1,2,3,4] - guard $ m = 0 + guard <| n = [0,1,2,3,4] + guard <| m = 0 run_cmd Lean.Elab.Command.liftTermElabM do let R : MLList MetaM Nat := MLList.range let n ← R.firstM fun n => try? do guard (n = 5) pure n - guard $ n = 5 + guard <| n = 5 diff --git a/test/Monotonicity.lean b/test/Monotonicity.lean index 7bc3b87fb6605..53b3c141073fe 100644 --- a/test/Monotonicity.lean +++ b/test/Monotonicity.lean @@ -419,7 +419,7 @@ example {x y z w : ℕ} : true := by -- example : ∫ x in Icc 0 1, real.exp x ≤ ∫ x in Icc 0 1, real.exp (x+1) := by -- mono -- · exact real.continuous_exp.locally_integrable.integrable_on_is_compact is_compact_Icc --- · exact (real.continuous_exp.comp $ continuous_add_right 1) +-- · exact (real.continuous_exp.comp <| continuous_add_right 1) -- .locally_integrable.integrable_on_is_compact is_compact_Icc -- intro x -- dsimp only diff --git a/test/MoveAdd.lean b/test/MoveAdd.lean index 970f1125b2b1f..39584af348619 100644 --- a/test/MoveAdd.lean +++ b/test/MoveAdd.lean @@ -1,4 +1,5 @@ import Mathlib.Tactic.MoveAdd +import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Data.Nat.Basic universe u @@ -75,9 +76,29 @@ example {R : Type u} [Add R] [CommSemigroup R] {a b c d e f g : R} : move_mul [a, a, b, c, d, e, f] rfl +/- +# Sample usage of `move_oper` +-/ + +example (a b c : Prop) : a ∧ b ∧ c ↔ b ∧ c ∧ a := by + move_oper And [a] + rfl + +example (a b c : Prop) : a ∨ b ∨ c ↔ b ∨ c ∨ a := by + move_oper Or [a] + rfl + +example {R} [LinearOrder R] (a b c : R) : max (max a b) c = max (max b c) a := by + move_oper Max.max [a] + rfl + +example {R} [LinearOrder R] (a b c : R) : min (min a b) c = min (min b c) a := by + move_oper Min.min [a] + rfl end mul section left_assoc + example {a b c d e : Prop} (h : a ∧ b ∧ c ∧ d ∧ e) : a ∧ c ∧ e ∧ b ∧ d := by move_oper And [a, b, c, d, e] exact h diff --git a/test/NoncommRing.lean b/test/NoncommRing.lean index 90f544eec2466..f0b388483a78e 100644 --- a/test/NoncommRing.lean +++ b/test/NoncommRing.lean @@ -1,3 +1,4 @@ +import Mathlib.GroupTheory.GroupAction.Ring import Mathlib.Tactic.NoncommRing local notation (name := commutator) "⁅"a", "b"⁆" => a * b - b * a diff --git a/test/Real.lean b/test/Real.lean index 8548b17d0f2b7..9b4bb3e88c529 100644 --- a/test/Real.lean +++ b/test/Real.lean @@ -14,5 +14,5 @@ run_cmd unsafe testRepr 0 "Real.ofCauchy (sorry /- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, run_cmd unsafe testRepr 1 "Real.ofCauchy (sorry /- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... -/)" run_cmd unsafe testRepr (37 : ℕ) "Real.ofCauchy (sorry /- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, ... -/)" run_cmd unsafe testRepr (2 + 3) "Real.ofCauchy (sorry /- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, ... -/)" -run_cmd unsafe testRepr ⟨CauSeq.Completion.mk $ ⟨fun n ↦ 2^(-n:ℤ), test_sorry⟩⟩ +run_cmd unsafe testRepr ⟨CauSeq.Completion.mk <| ⟨fun n ↦ 2^(-n:ℤ), test_sorry⟩⟩ "Real.ofCauchy (sorry /- 1, (1 : Rat)/2, (1 : Rat)/4, (1 : Rat)/8, (1 : Rat)/16, (1 : Rat)/32, (1 : Rat)/64, (1 : Rat)/128, (1 : Rat)/256, (1 : Rat)/512, ... -/)" diff --git a/test/RewriteSearch/Basic.lean b/test/RewriteSearch/Basic.lean index d06ecc1d270af..8877872148fd3 100644 --- a/test/RewriteSearch/Basic.lean +++ b/test/RewriteSearch/Basic.lean @@ -13,7 +13,9 @@ set_option autoImplicit true example (xs ys : List α) : (xs ++ ys).length = ys.length + xs.length := by rw_search -/-- info: Try this: rw [← @add_assoc, @add_right_comm, @add_assoc, @add_add_add_comm, ← @add_assoc, @add_right_comm] -/ +/-- +info: Try this: rw [← @add_assoc, @add_right_comm, @add_assoc, @add_add_add_comm, ← @add_assoc, @add_right_comm] +-/ #guard_msgs in example [AddCommMonoid α] {a b c d : α} : (a + b) + (c + d) = a + d + c + b := by rw_search @@ -24,7 +26,9 @@ example (xs ys : List α) : (xs ++ ys ++ ys).length = 2 * ys.length + xs.length := by rw_search -/-- info: Try this: rw [@List.length_append, @List.length_append, Nat.two_mul, Nat.add_assoc, @add_rotate', Nat.add_assoc] -/ +/-- +info: Try this: rw [@List.length_append, @List.length_append, Nat.two_mul, Nat.add_assoc, @add_rotate', Nat.add_assoc] +-/ #guard_msgs in example (xs ys : List α) : (xs ++ ys ++ ys).length = 2 * ys.length + xs.length := by diff --git a/test/RewriteSearch/Polynomial.lean b/test/RewriteSearch/Polynomial.lean index 9687eb2e19649..9532c53a5eec8 100644 --- a/test/RewriteSearch/Polynomial.lean +++ b/test/RewriteSearch/Polynomial.lean @@ -1,3 +1,4 @@ +import Mathlib.Init.Core import Mathlib.Data.Polynomial.Eval import Mathlib.Data.Polynomial.Inductions import Mathlib.Tactic.RewriteSearch @@ -6,7 +7,7 @@ set_option autoImplicit true open Polynomial -/-- info: Try this: rw [@sub_eq_neg_add, ← @C_neg, @natDegree_C_add] -/ +/-- info: Try this: rw [@natDegree_sub, @sub_eq_neg_add, @natDegree_add_C, @natDegree_neg] -/ #guard_msgs in example {R : Type*} [Ring R] {p : Polynomial R} {a : R} : natDegree (p - C a) = natDegree p := by diff --git a/test/Simps.lean b/test/Simps.lean index b3a1003685f19..177d14f2070e8 100644 --- a/test/Simps.lean +++ b/test/Simps.lean @@ -181,7 +181,7 @@ def my_equiv := Equiv' namespace CountNested @[simps] -def nested1 : MyProd ℕ $ MyProd ℤ ℕ := +def nested1 : MyProd ℕ <| MyProd ℤ ℕ := ⟨2, -1, 1⟩ @[simps (config := .lemmasOnly)] @@ -205,7 +205,7 @@ run_cmd liftTermElabM <| do guard <| hasSimpAttribute env `CountNested.nested1_fst -- simp attribute is global guard <| not <| hasSimpAttribute env `CountNested.nested2_fst -- lemmas_only doesn't add simp lemma -- todo: maybe test that there are no other lemmas generated - -- guard $ 7 = env.fold 0 + -- guard <| 7 = env.fold 0 -- (λ d n => n + if d.to_name.components.init.ilast = `CountNested then 1 else 0) -- testing with arguments @@ -386,7 +386,7 @@ attribute [local simp] Nat.zero_add Nat.one_mul Nat.mul_one @[simps (config := {simpRhs := true})] def myNatEquiv : ℕ ≃ ℕ := ⟨λ n => 0 + n, λ n => 1 * n * 1, by intro n; simp, by intro n; simp⟩ -example (n : ℕ) : myNatEquiv.toFun (myNatEquiv.toFun $ myNatEquiv.invFun n) = n := by +example (n : ℕ) : myNatEquiv.toFun (myNatEquiv.toFun <| myNatEquiv.invFun n) = n := by { /-successIfFail { rfl },-/ simp only [myNatEquiv_toFun, myNatEquiv_invFun] } @[simps (config := {simpRhs := true})] def succeed_without_simplification_possible : ℕ ≃ ℕ := @@ -762,8 +762,8 @@ initialize_simps_projections Equiv (toFun → coe, as_prefix coe, invFun → sym run_cmd liftTermElabM <| do let data ← getRawProjections .missing `PrefixProjectionNames.Equiv - guard $ data.2.map (·.name) = #[`coe, `symm_apply] - guard $ data.2.map (·.isPrefix) = #[true, false] + guard <| data.2.map (·.name) = #[`coe, `symm_apply] + guard <| data.2.map (·.isPrefix) = #[true, false] @[simps (config := {simpRhs := true})] protected def Equiv.trans (e₁ : α ≃ β) (e₂ : β ≃ γ) : α ≃ γ := ⟨e₂ ∘ (e₁ : α → β), e₁.symm ∘ (e₂.symm : γ → β)⟩ diff --git a/test/Traversable.lean b/test/Traversable.lean index 7c6f72b976138..86c1920163ba7 100644 --- a/test/Traversable.lean +++ b/test/Traversable.lean @@ -74,7 +74,7 @@ def x : MyTree (List Nat) := in each node, traverses each list. For each `ℕ` visited, apply an action `ℕ → StateM (List ℕ) Unit` which adds its argument to the state. -/ def ex : StateM (List ℕ) (MyTree <| List Unit) := do - let xs ← traverse (traverse fun a => modify $ List.cons a) x + let xs ← traverse (traverse fun a => modify <| List.cons a) x return xs example : (ex.run []).1 = node leaf (node (node leaf leaf [(), (), ()]) leaf [(), ()]) [()] := rfl diff --git a/test/abel.lean b/test/abel.lean index 153832f337024..3a191ef22e61f 100644 --- a/test/abel.lean +++ b/test/abel.lean @@ -98,8 +98,11 @@ error: abel_nf made no progress example [AddCommGroup α] (x y z : α) (_w : x = y + z) : False := by abel_nf at * +-- Prior to https://github.com/leanprover/lean4/pull/2917 this would fail +-- (the `at *` would close the goal, +-- and then error when trying to work on the hypotheses because there was no goal.) example [AddCommGroup α] (x y z : α) (_w : x = y + z) : x - x = 0 := by - abel_nf + abel_nf at * /-- error: abel_nf made no progress diff --git a/test/antidiagonal.lean b/test/antidiagonal.lean new file mode 100644 index 0000000000000..b1e35e614797b --- /dev/null +++ b/test/antidiagonal.lean @@ -0,0 +1,36 @@ +import Mathlib.Data.Finset.Sort +import Mathlib.Data.Finset.PiAntidiagonal +import Mathlib.Data.Finsupp.Notation +import Mathlib.Data.Fin.Tuple.NatAntidiagonal + +/-! +# Testing computability (and runtime) of antidiagonal +-/ + +open Finset + +section +-- set_option trace.profiler true + +-- `antidiagonalTuple` is faster than `finAntidiagonal` by a small constant factor +/-- info: 23426 -/ +#guard_msgs in #eval (finAntidiagonal 4 50).card +/-- info: 23426 -/ +#guard_msgs in #eval (Finset.Nat.antidiagonalTuple 4 50).card + +end + +/-- +info: {fun₀ | "C" => 3, + fun₀ | "B" => 1 | "C" => 2, + fun₀ | "B" => 2 | "C" => 1, + fun₀ | "B" => 3, + fun₀ | "A" => 1 | "C" => 2, + fun₀ | "A" => 1 | "B" => 1 | "C" => 1, + fun₀ | "A" => 1 | "B" => 2, + fun₀ | "A" => 2 | "C" => 1, + fun₀ | "A" => 2 | "B" => 1, + fun₀ | "A" => 3} +-/ +#guard_msgs in +#eval piAntidiagonal {"A", "B", "C"} 3 diff --git a/test/apply_fun.lean b/test/apply_fun.lean index 8c2b8c575ebd3..390a20d6ee88c 100644 --- a/test/apply_fun.lean +++ b/test/apply_fun.lean @@ -55,7 +55,7 @@ example (f : ℕ → ℕ → ℕ) (h : f 1 x ≠ f 1 y) : x ≠ y := by case foo => exact 1 assumption -example (X Y Z : Type) (f : X → Y) (g : Y → Z) (H : Injective $ g ∘ f) : Injective f := by +example (X Y Z : Type) (f : X → Y) (g : Y → Z) (H : Injective <| g ∘ f) : Injective f := by intros x x' h apply_fun g at h exact H h diff --git a/test/apply_rules.lean b/test/apply_rules.lean index aa04f6d0f8d46..9cb435a6580ce 100644 --- a/test/apply_rules.lean +++ b/test/apply_rules.lean @@ -7,17 +7,17 @@ open Nat example {a b c d e : Nat} (h1 : a ≤ b) (h2 : c ≤ d) (h3 : 0 ≤ e) : a + c * e + a + c + 0 ≤ b + d * e + b + d + e := Nat.add_le_add (Nat.add_le_add (Nat.add_le_add - (Nat.add_le_add h1 (Nat.mul_le_mul_of_nonneg_right h2)) h1) h2) h3 + (Nat.add_le_add h1 (Nat.mul_le_mul_right _ h2)) h1) h2) h3 example {a b c d e : Nat} (h1 : a ≤ b) (h2 : c ≤ d) (h3 : 0 ≤ e) : a + c * e + a + c + 0 ≤ b + d * e + b + d + e := by - apply_rules [Nat.add_le_add, Nat.mul_le_mul_of_nonneg_right] + apply_rules [Nat.add_le_add, Nat.mul_le_mul_right] -- Check that when we supply an iteration bound, -- `apply_rules` works up to that bound and returns the remaining goals. example {a b c d e : Nat} (h1 : a ≤ b) (h2 : c ≤ d) (h3 : 0 ≤ e) : a + c * e + a + c + 0 ≤ b + d * e + b + d + e := by - apply_rules (config := {maxDepth := 9}) [Nat.add_le_add, Nat.mul_le_mul_of_nonneg_right] + apply_rules (config := {maxDepth := 9}) [Nat.add_le_add, Nat.mul_le_mul_right] guard_target = 0 ≤ e assumption diff --git a/test/byContra.lean b/test/byContra.lean index 6cef8ec43c7b5..46091acbfd82e 100644 --- a/test/byContra.lean +++ b/test/byContra.lean @@ -2,7 +2,8 @@ import Mathlib.Tactic.ByContra import Mathlib.Tactic.Rename import Mathlib.Tactic.Set -import Mathlib.Data.Nat.Basic +import Mathlib.Init.Data.Nat.Lemmas +import Mathlib.Order.Basic set_option autoImplicit true example (a b : ℕ) (foo : False) : a < b := by diff --git a/test/cases.lean b/test/cases.lean index 0bdfe5b32aaf1..c612d293c6e00 100644 --- a/test/cases.lean +++ b/test/cases.lean @@ -1,3 +1,4 @@ +import Std.Tactic.GuardMsgs import Mathlib.Tactic.Cases import Mathlib.Init.Logic import Mathlib.Init.Data.Nat.Notation diff --git a/test/convert2.lean b/test/convert2.lean index babf4963662c8..37d9fc49a8b3a 100644 --- a/test/convert2.lean +++ b/test/convert2.lean @@ -1,5 +1,6 @@ import Mathlib.Data.List.BigOperators.Defs import Mathlib.Data.Nat.Basic +import Mathlib.Tactic.Convert set_option linter.unreachableTactic false diff --git a/test/delaborators.lean b/test/delaborators.lean index 086fe3a9513c1..9a4e7b27b6d6c 100644 --- a/test/delaborators.lean +++ b/test/delaborators.lean @@ -229,7 +229,7 @@ variable (x : ℕ × ℕ) variable (p : (ℕ → ℕ) × (ℕ → ℕ)) -/-- info: p.1 22 : ℕ -/ +/-- info: p.fst 22 : ℕ -/ #guard_msgs in #check p.1 22 diff --git a/test/fin_cases.lean b/test/fin_cases.lean index eda2ef3961a0b..0f7121bea72e0 100644 --- a/test/fin_cases.lean +++ b/test/fin_cases.lean @@ -1,4 +1,5 @@ import Mathlib.Tactic.FinCases +import Mathlib.Tactic.NormNum.Basic import Mathlib.Data.Nat.Interval example {x : Nat} (h : x ∈ [0, 2, 37]) : x ≤ 57 := by diff --git a/test/instance_diamonds.lean b/test/instance_diamonds.lean index b6a5a8549d3e1..1db4b61effd72 100644 --- a/test/instance_diamonds.lean +++ b/test/instance_diamonds.lean @@ -88,19 +88,13 @@ end TensorProduct section Units example (α : Type _) [Monoid α] : - (Units.instMulActionUnitsToMonoidToDivInvMonoidInstGroupUnits : MulAction αˣ (α × α)) = - Prod.mulAction := - rfl + (Units.instMulAction : MulAction αˣ (α × α)) = Prod.mulAction := rfl example (R α : Type _) (β : α → Type _) [Monoid R] [∀ i, MulAction R (β i)] : - (Units.instMulActionUnitsToMonoidToDivInvMonoidInstGroupUnits : MulAction Rˣ (∀ i, β i)) = - Pi.mulAction _ := - rfl + (Units.instMulAction : MulAction Rˣ (∀ i, β i)) = Pi.mulAction _ := rfl example (R α : Type _) [Monoid R] [Semiring α] [DistribMulAction R α] : - (Units.instDistribMulActionUnitsToMonoidToDivInvMonoidInstGroupUnits : DistribMulAction Rˣ α[X]) - = Polynomial.distribMulAction := - rfl + (Units.instDistribMulAction : DistribMulAction Rˣ α[X]) = Polynomial.distribMulAction := rfl /-! TODO: https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/units.2Emul_action'.20diamond/near/246402813 @@ -156,7 +150,7 @@ example {k : Type _} [Semiring k] [Nontrivial k] : (Finsupp.comapSMul : SMul k (k →₀ k)) ≠ Finsupp.smulZeroClass.toSMul := by obtain ⟨u : k, hu⟩ := exists_ne (1 : k) intro h - simp only [SMul.ext_iff, @SMul.smul_eq_hSMul _ _ (_), Function.funext_iff, FunLike.ext_iff] at h + simp only [SMul.ext_iff, @SMul.smul_eq_hSMul _ _ (_), Function.funext_iff, DFunLike.ext_iff] at h replace h := h u (Finsupp.single 1 1) u classical rw [comapSMul_single, smul_apply, smul_eq_mul, mul_one, single_eq_same, smul_eq_mul, @@ -170,7 +164,7 @@ example {k : Type _} [Semiring k] [Nontrivial kˣ] : obtain ⟨u : kˣ, hu⟩ := exists_ne (1 : kˣ) haveI : Nontrivial k := ⟨⟨u, 1, Units.ext.ne hu⟩⟩ intro h - simp only [SMul.ext_iff, @SMul.smul_eq_hSMul _ _ (_), Function.funext_iff, FunLike.ext_iff] at h + simp only [SMul.ext_iff, @SMul.smul_eq_hSMul _ _ (_), Function.funext_iff, DFunLike.ext_iff] at h replace h := h u (Finsupp.single 1 1) u classical rw [comapSMul_single, smul_apply, Units.smul_def, smul_eq_mul, mul_one, single_eq_same, diff --git a/test/matrix.lean b/test/matrix.lean index 5fcf2ebf07e83..9f460ec343931 100644 --- a/test/matrix.lean +++ b/test/matrix.lean @@ -1,3 +1,7 @@ +/- +manually ported from +https://github.com/leanprover-community/mathlib/blob/4f4a1c875d0baa92ab5d92f3fb1bb258ad9f3e5b/test/matrix.lean +-/ import Mathlib.Data.Matrix.Notation import Mathlib.GroupTheory.Perm.Fin import Mathlib.LinearAlgebra.Matrix.Determinant @@ -132,26 +136,27 @@ example {a b c d e f g h : α} : ![a, b, c, d, e, f, g, h] 99 = d := by simp example {α : Type _} [CommRing α] {a b c d : α} : Matrix.det !![a, b; c, d] = a * d - b * c := by simp? [Matrix.det_succ_row_zero, Fin.sum_univ_succ] says - simp only [det_succ_row_zero, of_apply, cons_val', empty_val', - cons_val_fin_one, cons_val_zero, det_unique, Fin.default_eq_zero, submatrix_apply, - Fin.succ_zero_eq_one, cons_val_one, head_fin_const, Fin.sum_univ_succ, Fin.val_zero, - pow_zero, one_mul, Fin.zero_succAbove, head_cons, Finset.univ_unique, - Fin.val_succ, Fin.coe_fin_one, zero_add, pow_one, cons_val_succ, neg_mul, - Fin.succ_succAbove_zero, Finset.sum_const, Finset.card_singleton, smul_neg, one_smul] + simp only [det_succ_row_zero, Fin.isValue, of_apply, cons_val', + empty_val', cons_val_fin_one, cons_val_zero, det_unique, Fin.default_eq_zero, submatrix_apply, + Fin.succ_zero_eq_one, cons_val_one, head_fin_const, Fin.sum_univ_succ, Fin.val_zero, pow_zero, + one_mul, Fin.zero_succAbove, head_cons, Finset.univ_unique, Fin.val_succ, Fin.coe_fin_one, + zero_add, pow_one, cons_val_succ, neg_mul, Fin.succ_succAbove_zero, Finset.sum_const, + Finset.card_singleton, smul_neg, one_smul] ring example {α : Type _} [CommRing α] {a b c d e f g h i : α} : Matrix.det !![a, b, c; d, e, f; g, h, i] = a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g := by simp? [Matrix.det_succ_row_zero, Fin.sum_univ_succ] says - simp only [det_succ_row_zero, of_apply, cons_val', empty_val', - cons_val_fin_one, cons_val_zero, submatrix_apply, Fin.succ_zero_eq_one, cons_val_one, - head_cons, submatrix_submatrix, det_unique, Fin.default_eq_zero, Function.comp_apply, - Fin.succ_one_eq_two, cons_val_two, tail_cons, head_fin_const, Fin.sum_univ_succ, Fin.val_zero, - pow_zero, one_mul, Fin.zero_succAbove, Finset.univ_unique, Fin.val_succ, Fin.coe_fin_one, - zero_add, pow_one, neg_mul, Fin.succ_succAbove_zero, Finset.sum_neg_distrib, - Finset.sum_singleton, cons_val_succ, Fin.succ_succAbove_one, even_add_self, Even.neg_pow, - one_pow, Finset.sum_const, Finset.card_singleton, one_smul] + simp only [det_succ_row_zero, Fin.isValue, of_apply, cons_val', + empty_val', cons_val_fin_one, cons_val_zero, submatrix_apply, Fin.succ_zero_eq_one, + cons_val_one, head_cons, submatrix_submatrix, det_unique, Fin.default_eq_zero, + Function.comp_apply, Fin.succ_one_eq_two, cons_val_two, tail_cons, head_fin_const, + Fin.sum_univ_succ, Fin.val_zero, pow_zero, one_mul, Fin.zero_succAbove, Finset.univ_unique, + Fin.val_succ, Fin.coe_fin_one, zero_add, pow_one, neg_mul, Fin.succ_succAbove_zero, + Finset.sum_neg_distrib, Finset.sum_singleton, cons_val_succ, Fin.succ_succAbove_one, + Nat.reduceAdd, even_two, Even.neg_pow, one_pow, Finset.sum_const, Finset.card_singleton, + one_smul] ring end Matrix diff --git a/test/norm_num.lean b/test/norm_num.lean index f937813327eff..b0103a1b78500 100644 --- a/test/norm_num.lean +++ b/test/norm_num.lean @@ -17,6 +17,10 @@ axiom Real : Type notation "ℝ" => Real @[instance] axiom Real.linearOrderedRing : LinearOrderedField ℝ +axiom NNReal : Type +notation "ℝ≥0" => NNReal +@[instance] axiom NNReal.linearOrderedsemifield : LinearOrderedSemifield ℝ≥0 + axiom Complex : Type notation "ℂ" => Complex @[instance] axiom Complex.field : Field ℂ @@ -38,11 +42,15 @@ example : (7:ℝ)/2 > 3 := by norm_num1 example : (4:ℝ)⁻¹ < 1 := by norm_num1 example : ((1:ℝ) / 2)⁻¹ = 2 := by norm_num1 example : 2 ^ 17 - 1 = 131071 := by norm_num1 --- example : (3 : ℝ) ^ (-2 : ℤ) = 1/9 := by norm_num1 --- example : (3 : ℝ) ^ (-2 : ℤ) = 1/9 := by norm_num1 --- example : (-3 : ℝ) ^ (0 : ℤ) = 1 := by norm_num1 --- example : (-3 : ℝ) ^ (-1 : ℤ) = -1/3 := by norm_num1 --- example : (-3 : ℝ) ^ (2 : ℤ) = 9 := by norm_num1 +example : (3 : ℝ) ^ (-2 : ℤ) = 1/9 := by norm_num1 +example : (-3 : ℝ) ^ (0 : ℤ) = 1 := by norm_num1 +example : (-3 : ℝ) ^ (-1 : ℤ) = -1/3 := by norm_num1 +example : (-3 : ℝ) ^ (1 : ℤ) = -3 := by norm_num1 +example : (-3 : ℝ) ^ (2 : ℤ) = 9 := by norm_num1 +example : (1/3 : ℝ) ^ (2 : ℤ) = 1/9 := by norm_num1 +example : (1/3 : ℝ) ^ (-2 : ℤ) = 9 := by norm_num1 +example : (-1/3 : ℝ) ^ (-1 : ℤ) = -3 := by norm_num1 +example : (3 : ℝ≥0) ^ (2 : ℤ) = 9 := by norm_num1 section InvLit diff --git a/test/norm_num_ext.lean b/test/norm_num_ext.lean index d1984619eb0de..698dd49eddba0 100644 --- a/test/norm_num_ext.lean +++ b/test/norm_num_ext.lean @@ -323,12 +323,6 @@ example : Nat.fib 65 = 17167680177565 := by norm_num1 example : Nat.fib 100 + Nat.fib 101 = Nat.fib 102 := by norm_num1 example : Nat.fib 1000 + Nat.fib 1001 = Nat.fib 1002 := by norm_num1 -/- -example : (2 : ℝ) ^ (3 : ℝ) = 8 := by norm_num -example : (1 : ℝ) ^ (20 : ℝ) = 1 := by norm_num -example : (2 : ℝ) ^ (-3 : ℝ) = 1/8 := by norm_num --/ - section big_operators variable {α : Type _} [CommRing α] diff --git a/test/norm_num_rpow.lean b/test/norm_num_rpow.lean new file mode 100644 index 0000000000000..644120746f08d --- /dev/null +++ b/test/norm_num_rpow.lean @@ -0,0 +1,15 @@ +/- +Copyright (c) 2021 Mario Carneiro All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro, David Renshaw +-/ +import Mathlib.Analysis.SpecialFunctions.Pow.Real + +example : (2 : ℝ) ^ (3 : ℝ) = 8 := by norm_num1 +example : (1 : ℝ) ^ (20 : ℝ) = 1 := by norm_num1 +example : (-2 : ℝ) ^ (3 : ℝ) = -8 := by norm_num1 +example : (1/5 : ℝ) ^ (2 : ℝ) = 1/25 := by norm_num1 +example : (-1/3 : ℝ) ^ (-3 : ℝ) = -27 := by norm_num1 +example : (1/2 : ℝ) ^ (-3 : ℝ) = 8 := by norm_num1 +example : (2 : ℝ) ^ (-3 : ℝ) = 1/8 := by norm_num1 +example : (-2 : ℝ) ^ (-3 : ℝ) = -1/8 := by norm_num1 diff --git a/test/peel.lean b/test/peel.lean index bcb2e64677a2b..f1a18a62b061c 100644 --- a/test/peel.lean +++ b/test/peel.lean @@ -47,24 +47,24 @@ example (p q : Nat → Prop) (h₁ : ∀ x, p x) (h₂ : ∀ x, p x → q x) : exact h₂ _ foo example (p q : Nat → Prop) (h₁ : ∀ x, p x) (h₂ : ∀ x, p x → q x) : ∀ y, q y := by - peel h₁ with foo w + peel h₁ with w foo guard_target =ₐ q w exact h₂ w foo example (p q : Nat → Prop) (h₁ : ∀ x, p x) (h₂ : ∀ x, p x → q x) : ∀ y, q y := by - peel h₁ with foo _ + peel h₁ with _ foo rename_i w guard_target =ₐ q w exact h₂ w foo example (p q : Nat → Prop) (h₁ : ∀ x, p x) (h₂ : ∀ x, p x → q x) : ∀ y, q y := by - peel h₁ with _ w + peel h₁ with w _ guard_target =ₐ q w exact h₂ w this example (p q : Nat → Nat → Prop) (h₁ : ∀ x y, p x y) (h₂ : ∀ x y, p x y → q x y) : ∀ u v, q u v := by - peel h₁ with h_peel s t + peel h₁ with s t h_peel guard_target =ₐ q s t exact h₂ s t h_peel @@ -75,13 +75,13 @@ example (p q : Nat → Prop) (h : ∀ y, p y) (h₁ : ∀ z, p z → q z) : ∀ exact h₁ _ <| by assumption example (p q : Nat → Prop) (h : ∃ y, p y) (h₁ : ∀ z, p z → q z) : ∃ x, q x := by - peel h with h a + peel h with a h guard_target =ₐ q a exact h₁ a h example (x y : ℝ) (h : ∀ ε > 0, ∃ N : ℕ, ∀ n ≥ N, x + n = y + ε) : ∀ ε > 0, ∃ N : ℕ, ∀ n ≥ N, x - ε = y - n := by - peel h with h_peel ε hε N n hn + peel h with ε hε N n hn h_peel guard_target =ₐ x - ε = y - n linarith @@ -96,14 +96,14 @@ example (x y : ℝ) (h : ∀ ε > 0, ∃ N : ℕ, ∀ n ≥ N, x + n = y + ε) : example (p q : ℝ → ℝ → Prop) (h : ∀ ε > 0, ∃ δ > 0, p ε δ) (hpq : ∀ x y, x > 0 → y > 0 → p x y → q x y) : ∀ ε > 0, ∃ δ > 0, q ε δ := by - peel h with h ε hε δ hδ + peel h with ε hε δ hδ h guard_target =ₐ q ε δ exact hpq ε δ hε hδ h example (p q : ℝ → ℝ → Prop) (h : ∀ ε > 0, ∃ δ > 0, p ε δ) (hpq : ∀ x y, x > 0 → y > 0 → p x y → q x y) : ∀ ε > 0, ∃ δ > 0, q ε δ := by - peel h with h ε hε δ hδ using hpq ε δ hε hδ h + peel h with ε hε δ hδ h using hpq ε δ hε hδ h example (x y : ℝ) : (∀ ε > 0, ∃ N : ℕ, ∀ n ≥ N, x + n = y + ε) ↔ ∀ ε > 0, ∃ N : ℕ, ∀ n ≥ N, x - ε = y - n := by @@ -163,12 +163,12 @@ example {f : ℝ → ℝ} (h : ∀ x : ℝ, ∀ᶠ y in 𝓝 x, |f y - f x| ≤ example (α : Type*) (f g : Filter α) (p q : α → α → Prop) (h : ∀ᶠ x in f, ∃ᶠ y in g, p x y) (h₁ : ∀ x y, p x y → q x y) : ∀ᶠ x in f, ∃ᶠ y in g, q x y := by - peel h with h_peel x y + peel h with x y h_peel exact h₁ x y h_peel example (α : Type*) (f : Filter α) (p q : α → Prop) (h : ∀ᶠ x in f, p x) (h₁ : ∀ x, p x → q x) : ∀ᶠ x in f, q x := by - peel h with h_peel x + peel h with x h_peel exact h₁ x h_peel /-! ## Type classes -/ @@ -182,7 +182,7 @@ example {R : Type*} [CommRing R] (h : ∀ x : R, ∃ y : R, x + y = 2) : example {G : Type*} [Group G] [TopologicalSpace G] [TopologicalGroup G] (h : ∀ᶠ x in 𝓝 (1 : G), ∃ᶠ y in 𝓝 x, x * y⁻¹ = 1) : ∀ᶠ x in 𝓝 (1 : G), ∃ᶠ y in 𝓝 x, x ^ 2 = y ^ 2 := by - peel h with h_peel a b + peel h with a b h_peel observe : a = b⁻¹⁻¹ simp [this] @@ -190,14 +190,14 @@ example {G : Type*} [Group G] [TopologicalSpace G] [TopologicalGroup G] example {α β γ : Type*} {f : α → β} {g : β → γ} (h : Function.Injective (g ∘ f)) : Function.Injective f := by - peel 2 h with _ x y + peel 2 h with x y _ intro hf apply this congrm(g $hf) example {α β γ : Type*} {f : α → β} {g : β → γ} (h : Function.Surjective (g ∘ f)) : Function.Surjective g := by - peel 1 h with _ y + peel 1 h with y _ fail_if_success peel this obtain ⟨x, rfl⟩ := this exact ⟨f x, rfl⟩ diff --git a/test/polyrith.lean b/test/polyrith.lean index b8cb441aa0c0a..bc51330562e38 100644 --- a/test/polyrith.lean +++ b/test/polyrith.lean @@ -37,14 +37,14 @@ A full test suite is provided at the bottom of the file. -- fail!"expected final output: {expected_out}\nbut produced: {out}" -- meta def format_string_list (input : list string) : format := --- "[" ++ (format.join $ (input.map (λ s, ("\"" : format) ++ format.of_string s ++ "\"")).intersperse ("," ++ format.line)) ++ "]" +-- "[" ++ (format.join <| (input.map (λ s, ("\"" : format) ++ format.of_string s ++ "\"")).intersperse ("," ++ format.line)) ++ "]" -- setup_tactic_parser -- meta def tactic.interactive.test_polyrith (restr : parse (tk "only")?) -- (hyps : parse pexpr_list?) -- (sage_out : string) (expected_args : list string) (expected_out : string) : tactic unit := do --- some sage_out ← return $ json.parse sage_out, +-- some sage_out ← return <| json.parse sage_out, -- tactic.test_polyrith restr.is_some (hyps.get_or_else []) sage_out expected_args expected_out -- meta def tactic.interactive.test_sage_output (restr : parse (tk "only")?) @@ -86,7 +86,7 @@ A full test suite is provided at the bottom of the file. -- let argstring := format_string_list args, -- let onl := if restr.is_some then "only " else "", -- let hyps := if hyps = [] then "" else to_string hyps, --- let trf := format.nest 2 $ format!"test_polyrith {onl}{hyps} \n\"{sage_out}\"\n{argstring}\n\"{out}\"", +-- let trf := format.nest 2 <| format!"test_polyrith {onl}{hyps} \n\"{sage_out}\"\n{argstring}\n\"{out}\"", -- trace!"Try this: {trf}" diff --git a/test/positivity.lean b/test/positivity.lean index bd5451621f0dd..b777f39f3b997 100644 --- a/test/positivity.lean +++ b/test/positivity.lean @@ -254,7 +254,7 @@ example : 0 ≤ max (-3 : ℤ) 5 := by positivity example (n : ℕ) : 0 < n.succ := by positivity example (n : ℕ) : 0 < n ! := by positivity -example (n k : ℕ) : 0 < n.ascFactorial k := by positivity +example (n k : ℕ) : 0 < (n+1).ascFactorial k := by positivity -- example {α : Type _} (s : Finset α) (hs : s.Nonempty) : 0 < s.card := by positivity -- example {α : Type _} [Fintype α] [Nonempty α] : 0 < Fintype.card α := by positivity diff --git a/test/propose.lean b/test/propose.lean index 4150e87c4305c..118267edacc3c 100644 --- a/test/propose.lean +++ b/test/propose.lean @@ -41,16 +41,15 @@ example (K L M : List α) (w : L.Disjoint M) (m : K ⊆ L) : True := by def bar (n : Nat) (x : String) : Nat × String := (n + x.length, x) --- FIXME notice a bug here: should not generate `let this✝` with an inaccessible name. /-- -info: Try this: let this✝ : ℕ × String := bar p.1 p.2 +info: Try this: let a : ℕ × String := bar p.1 p.2 --- -info: Try this: let this✝ : ℕ × String := bar p.1 p.2 +info: Try this: let _ : ℕ × String := bar p.1 p.2 -/ #guard_msgs in example (p : Nat × String) : True := by fail_if_success have? using p - have? : Nat × String using p.1, p.2 + have? a : Nat × String using p.1, p.2 have? : Nat × _ using p.1, p.2 trivial diff --git a/test/search/DepthFirst.lean b/test/search/DepthFirst.lean index 06ff46cefd5bd..58a92022c761f 100644 --- a/test/search/DepthFirst.lean +++ b/test/search/DepthFirst.lean @@ -1,3 +1,4 @@ +import Std.Tactic.GuardMsgs import Mathlib.Data.MLList.DepthFirst /-- @@ -7,4 +8,4 @@ info: -- We perform a depth first search of the "proper divisors in descending order" tree. #eval show Lean.MetaM Unit from do let r := depthFirstRemovingDuplicates' (fun n => List.range n |>.filter (n % · = 0) |>.reverse) 24 - guard $ r = [24, 12, 6, 3, 1, 2, 4, 8] + guard <| r = [24, 12, 6, 3, 1, 2, 4, 8] diff --git a/test/slim_check.lean b/test/slim_check.lean index 700a099d263cf..7b3f94a50e1d6 100644 --- a/test/slim_check.lean +++ b/test/slim_check.lean @@ -1,7 +1,6 @@ import Mathlib.Tactic.SlimCheck import Mathlib.Tactic.SuccessIfFailWithMsg -import Mathlib.Data.Finsupp.Basic -import Mathlib.Data.DFinsupp.Basic +import Mathlib.Data.Finsupp.Notation import Mathlib.Testing.SlimCheck.Functions -- Porting note: diff --git a/test/toAdditive.lean b/test/toAdditive.lean index a6b2787a35469..85aec546bd8e0 100644 --- a/test/toAdditive.lean +++ b/test/toAdditive.lean @@ -42,7 +42,7 @@ theorem bar1_works : bar1 3 4 = 3 * 4 := by decide infix:80 " ^ " => my_has_pow.pow -instance dummy_pow : my_has_pow ℕ $ PLift ℤ := ⟨fun _ _ => 5⟩ +instance dummy_pow : my_has_pow ℕ <| PLift ℤ := ⟨fun _ _ => 5⟩ @[to_additive bar2] def foo2 {α} [my_has_pow α ℕ] (x : α) (n : ℕ) (m : PLift ℤ) : α := x ^ (n ^ m) @@ -236,7 +236,7 @@ def foo_mul {I J K : Type} (n : ℕ) {f : I → Type} (L : Type) [∀ i, One (f @[to_additive] -instance pi.has_one {I : Type} {f : I → Type} [(i : I) → One $ f i] : One ((i : I) → f i) := +instance pi.has_one {I : Type} {f : I → Type} [(i : I) → One <| f i] : One ((i : I) → f i) := ⟨fun _ => 1⟩ run_cmd do